⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swf.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Flash Compatible Streaming Format * Copyright (c) 2000 Fabrice Bellard. * Copyright (c) 2003 Tinic Uro. * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "avformat.h"#include "bitstream.h"#include "riff.h"    /* for CodecTag *//* should have a generic way to indicate probable size */#define DUMMY_FILE_SIZE   (100 * 1024 * 1024)#define DUMMY_DURATION    600 /* in seconds */#define TAG_END           0#define TAG_SHOWFRAME     1#define TAG_DEFINESHAPE   2#define TAG_FREECHARACTER 3#define TAG_PLACEOBJECT   4#define TAG_REMOVEOBJECT  5#define TAG_STREAMHEAD    18#define TAG_STREAMBLOCK   19#define TAG_JPEG2         21#define TAG_PLACEOBJECT2  26#define TAG_STREAMHEAD2   45#define TAG_VIDEOSTREAM   60#define TAG_VIDEOFRAME    61#define TAG_FILEATTRIBUTES 69#define TAG_LONG         0x100/* flags for shape definition */#define FLAG_MOVETO      0x01#define FLAG_SETFILL0    0x02#define FLAG_SETFILL1    0x04#define AUDIO_FIFO_SIZE 65536/* character id used */#define BITMAP_ID 0#define VIDEO_ID 0#define SHAPE_ID  1#undef NDEBUG#include <assert.h>typedef struct {    int audio_stream_index;    offset_t duration_pos;    offset_t tag_pos;    int samples_per_frame;    int sound_samples;    int swf_frame_number;    int video_frame_number;    int frame_rate;    int tag;    uint8_t audio_fifo[AUDIO_FIFO_SIZE];    int audio_in_pos;    int video_type;    int audio_type;} SWFContext;static const AVCodecTag swf_codec_tags[] = {    {CODEC_ID_FLV1, 0x02},    {CODEC_ID_VP6F, 0x04},    {0, 0},};static const AVCodecTag swf_audio_codec_tags[] = {    {CODEC_ID_PCM_S16LE,  0x00},    {CODEC_ID_ADPCM_SWF,  0x01},    {CODEC_ID_MP3,        0x02},    {CODEC_ID_PCM_S16LE,  0x03},  //{CODEC_ID_NELLYMOSER, 0x06},    {0, 0},};#ifdef CONFIG_MUXERSstatic void put_swf_tag(AVFormatContext *s, int tag){    SWFContext *swf = s->priv_data;    ByteIOContext *pb = s->pb;    swf->tag_pos = url_ftell(pb);    swf->tag = tag;    /* reserve some room for the tag */    if (tag & TAG_LONG) {        put_le16(pb, 0);        put_le32(pb, 0);    } else {        put_le16(pb, 0);    }}static void put_swf_end_tag(AVFormatContext *s){    SWFContext *swf = s->priv_data;    ByteIOContext *pb = s->pb;    offset_t pos;    int tag_len, tag;    pos = url_ftell(pb);    tag_len = pos - swf->tag_pos - 2;    tag = swf->tag;    url_fseek(pb, swf->tag_pos, SEEK_SET);    if (tag & TAG_LONG) {        tag &= ~TAG_LONG;        put_le16(pb, (tag << 6) | 0x3f);        put_le32(pb, tag_len - 4);    } else {        assert(tag_len < 0x3f);        put_le16(pb, (tag << 6) | tag_len);    }    url_fseek(pb, pos, SEEK_SET);}static inline void max_nbits(int *nbits_ptr, int val){    int n;    if (val == 0)        return;    val = abs(val);    n = 1;    while (val != 0) {        n++;        val >>= 1;    }    if (n > *nbits_ptr)        *nbits_ptr = n;}static void put_swf_rect(ByteIOContext *pb,                         int xmin, int xmax, int ymin, int ymax){    PutBitContext p;    uint8_t buf[256];    int nbits, mask;    init_put_bits(&p, buf, sizeof(buf));    nbits = 0;    max_nbits(&nbits, xmin);    max_nbits(&nbits, xmax);    max_nbits(&nbits, ymin);    max_nbits(&nbits, ymax);    mask = (1 << nbits) - 1;    /* rectangle info */    put_bits(&p, 5, nbits);    put_bits(&p, nbits, xmin & mask);    put_bits(&p, nbits, xmax & mask);    put_bits(&p, nbits, ymin & mask);    put_bits(&p, nbits, ymax & mask);    flush_put_bits(&p);    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);}static void put_swf_line_edge(PutBitContext *pb, int dx, int dy){    int nbits, mask;    put_bits(pb, 1, 1); /* edge */    put_bits(pb, 1, 1); /* line select */    nbits = 2;    max_nbits(&nbits, dx);    max_nbits(&nbits, dy);    mask = (1 << nbits) - 1;    put_bits(pb, 4, nbits - 2); /* 16 bits precision */    if (dx == 0) {        put_bits(pb, 1, 0);        put_bits(pb, 1, 1);        put_bits(pb, nbits, dy & mask);    } else if (dy == 0) {        put_bits(pb, 1, 0);        put_bits(pb, 1, 0);        put_bits(pb, nbits, dx & mask);    } else {        put_bits(pb, 1, 1);        put_bits(pb, nbits, dx & mask);        put_bits(pb, nbits, dy & mask);    }}#define FRAC_BITS 16/* put matrix */static void put_swf_matrix(ByteIOContext *pb,                           int a, int b, int c, int d, int tx, int ty){    PutBitContext p;    uint8_t buf[256];    int nbits;    init_put_bits(&p, buf, sizeof(buf));    put_bits(&p, 1, 1); /* a, d present */    nbits = 1;    max_nbits(&nbits, a);    max_nbits(&nbits, d);    put_bits(&p, 5, nbits); /* nb bits */    put_bits(&p, nbits, a);    put_bits(&p, nbits, d);    put_bits(&p, 1, 1); /* b, c present */    nbits = 1;    max_nbits(&nbits, c);    max_nbits(&nbits, b);    put_bits(&p, 5, nbits); /* nb bits */    put_bits(&p, nbits, c);    put_bits(&p, nbits, b);    nbits = 1;    max_nbits(&nbits, tx);    max_nbits(&nbits, ty);    put_bits(&p, 5, nbits); /* nb bits */    put_bits(&p, nbits, tx);    put_bits(&p, nbits, ty);    flush_put_bits(&p);    put_buffer(pb, buf, pbBufPtr(&p) - p.buf);}/* */static int swf_write_header(AVFormatContext *s){    SWFContext *swf = s->priv_data;    ByteIOContext *pb = s->pb;    AVCodecContext *enc, *audio_enc, *video_enc;    PutBitContext p;    uint8_t buf1[256];    int i, width, height, rate, rate_base;    int is_avm2;    swf->audio_in_pos = 0;    swf->sound_samples = 0;    swf->swf_frame_number = 0;    swf->video_frame_number = 0;    video_enc = NULL;    audio_enc = NULL;    for(i=0;i<s->nb_streams;i++) {        enc = s->streams[i]->codec;        if (enc->codec_type == CODEC_TYPE_AUDIO) {            if (enc->codec_id == CODEC_ID_MP3) {                if (!enc->frame_size) {                    av_log(s, AV_LOG_ERROR, "audio frame size not set\n");                    return -1;                }                audio_enc = enc;            } else {                av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n");                return -1;            }        } else {            if (enc->codec_id == CODEC_ID_VP6F ||                enc->codec_id == CODEC_ID_FLV1 ||                enc->codec_id == CODEC_ID_MJPEG) {                video_enc = enc;            } else {                av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");                return -1;            }        }    }    if (!video_enc) {        /* currently, cannot work correctly if audio only */        swf->video_type = 0;        width = 320;        height = 200;        rate = 10;        rate_base= 1;    } else {        swf->video_type = video_enc->codec_id;        width = video_enc->width;        height = video_enc->height;        rate = video_enc->time_base.den;        rate_base = video_enc->time_base.num;    }    if (!audio_enc) {        swf->audio_type = 0;        swf->samples_per_frame = (44100. * rate_base) / rate;    } else {        swf->audio_type = audio_enc->codec_id;        swf->samples_per_frame = (audio_enc->sample_rate * rate_base) / rate;    }    is_avm2 = !strcmp("avm2", s->oformat->name);    put_tag(pb, "FWS");    if (is_avm2) {        put_byte(pb, 9);    } else if (video_enc && video_enc->codec_id == CODEC_ID_VP6F) {        put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */    } else if (video_enc && video_enc->codec_id == CODEC_ID_FLV1) {        put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */    } else {        put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */    }    put_le32(pb, DUMMY_FILE_SIZE); /* dummy size                                      (will be patched if not streamed) */    put_swf_rect(pb, 0, width * 20, 0, height * 20);    put_le16(pb, (rate * 256) / rate_base); /* frame rate */    swf->duration_pos = url_ftell(pb);    put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */    /* avm2/swf v9 (also v8?) files require a file attribute tag */    if (is_avm2) {        put_swf_tag(s, TAG_FILEATTRIBUTES);        put_le32(pb, 1<<3); /* set ActionScript v3/AVM2 flag */        put_swf_end_tag(s);    }    /* define a shape with the jpeg inside */    if (video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||                       video_enc->codec_id == CODEC_ID_FLV1)) {    } else if (video_enc && video_enc->codec_id == CODEC_ID_MJPEG) {        put_swf_tag(s, TAG_DEFINESHAPE);        put_le16(pb, SHAPE_ID); /* ID of shape */        /* bounding rectangle */        put_swf_rect(pb, 0, width, 0, height);        /* style info */        put_byte(pb, 1); /* one fill style */        put_byte(pb, 0x41); /* clipped bitmap fill */        put_le16(pb, BITMAP_ID); /* bitmap ID */        /* position of the bitmap */        put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0,                       0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);        put_byte(pb, 0); /* no line style */        /* shape drawing */        init_put_bits(&p, buf1, sizeof(buf1));        put_bits(&p, 4, 1); /* one fill bit */        put_bits(&p, 4, 0); /* zero line bit */        put_bits(&p, 1, 0); /* not an edge */        put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);        put_bits(&p, 5, 1); /* nbits */        put_bits(&p, 1, 0); /* X */        put_bits(&p, 1, 0); /* Y */        put_bits(&p, 1, 1); /* set fill style 1 */        /* draw the rectangle ! */        put_swf_line_edge(&p, width, 0);        put_swf_line_edge(&p, 0, height);        put_swf_line_edge(&p, -width, 0);        put_swf_line_edge(&p, 0, -height);        /* end of shape */        put_bits(&p, 1, 0); /* not an edge */        put_bits(&p, 5, 0);        flush_put_bits(&p);        put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);        put_swf_end_tag(s);    }    if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3) {        int v;        /* start sound */        put_swf_tag(s, TAG_STREAMHEAD2);        v = 0;        switch(audio_enc->sample_rate) {        case 11025:            v |= 1 << 2;            break;        case 22050:            v |= 2 << 2;            break;        case 44100:            v |= 3 << 2;            break;        default:            /* not supported */            av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n");            return -1;        }        v |= 0x02; /* 16 bit playback */        if (audio_enc->channels == 2)            v |= 0x01; /* stereo playback */        put_byte(s->pb, v);        v |= 0x20; /* mp3 compressed */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -