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

📄 swf.c

📁 FFmpeg is an audio/video conversion tool. It includes libavcodec, the leading open source codec libr
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Flash Compatible Streaming Format * Copyright (c) 2000 Fabrice Bellard. * Copyright (c) 2003 Tinic Uro. * * This library 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 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "avformat.h"/* 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    45#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_LONG         0x100/* flags for shape definition */#define FLAG_MOVETO      0x01#define FLAG_SETFILL0    0x02#define FLAG_SETFILL1    0x04#define SWF_VIDEO_CODEC_FLV1	0x02#define AUDIO_FIFO_SIZE 65536/* character id used */#define BITMAP_ID 0#define VIDEO_ID 0#define SHAPE_ID  1typedef struct SWFFrame_s {    void *data;    int size;    struct SWFFrame_s *prev;    struct SWFFrame_s *next;} SWFFrame;typedef struct {    offset_t duration_pos;    offset_t tag_pos;        int samples_per_frame;    int sound_samples;    int video_samples;    int skip_samples;    int swf_frame_number;    int video_frame_number;    int ms_per_frame;    int ch_id;    int tag;    uint8_t *audio_fifo;    int audio_in_pos;    int audio_out_pos;    int audio_size;    int video_type;    int audio_type;        SWFFrame *frame_head;    SWFFrame *frame_tail;} SWFContext;static const int sSampleRates[3][4] = {    {44100, 48000, 32000, 0},    {22050, 24000, 16000, 0},    {11025, 12000,  8000, 0},};static const int sBitRates[2][3][15] = {    {   {  0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},        {  0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},        {  0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}    },    {   {  0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},        {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}    },};static const int sSamplesPerFrame[3][3] ={    {  384,     1152,    1152 },    {  384,     1152,     576 },    {  384,     1152,     576 }};static const int sBitsPerSlot[3] = {    32,    8,    8};static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono ){    uint8_t *dataTmp = (uint8_t *)data;    uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];    int layerID = 3 - ((header >> 17) & 0x03);    int bitRateID = ((header >> 12) & 0x0f);    int sampleRateID = ((header >> 10) & 0x03);    int bitRate = 0;    int bitsPerSlot = sBitsPerSlot[layerID];    int isPadded = ((header >> 9) & 0x01);        if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {        return 0;    }    *isMono = ((header >>  6) & 0x03) == 0x03;    if ( (header >> 19 ) & 0x01 ) {        *sampleRate = sSampleRates[0][sampleRateID];        bitRate = sBitRates[0][layerID][bitRateID] * 1000;        *samplesPerFrame = sSamplesPerFrame[0][layerID];    } else {        if ( (header >> 20) & 0x01 ) {            *sampleRate = sSampleRates[1][sampleRateID];            bitRate = sBitRates[1][layerID][bitRateID] * 1000;            *samplesPerFrame = sSamplesPerFrame[1][layerID];        } else {            *sampleRate = sSampleRates[2][sampleRateID];            bitRate = sBitRates[1][layerID][bitRateID] * 1000;            *samplesPerFrame = sSamplesPerFrame[2][layerID];        }    }    *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );    return 1;}#ifdef CONFIG_ENCODERSstatic 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;    ByteIOContext *pb = &s->pb;    AVCodecContext *enc, *audio_enc, *video_enc;    PutBitContext p;    uint8_t buf1[256];    int i, width, height, rate, rate_base;    swf = av_malloc(sizeof(SWFContext));    if (!swf)        return -1;    s->priv_data = swf;    swf->ch_id = -1;    swf->audio_in_pos = 0;    swf->audio_out_pos = 0;    swf->audio_size = 0;    swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);    swf->frame_head = 0;    swf->frame_tail = 0;    swf->sound_samples = 0;    swf->video_samples = 0;    swf->swf_frame_number = 0;    swf->video_frame_number = 0;    swf->skip_samples = 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)            audio_enc = enc;        else {            if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {                video_enc = enc;            } else {                av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");                return -1;            }        }    }    if (!video_enc) {        /* currenty, 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->frame_rate;        rate_base = video_enc->frame_rate_base;    }    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;    }    put_tag(pb, "FWS");    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 */        /* define a shape with the jpeg inside */    if ( video_enc && 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_free(swf->audio_fifo);            av_free(swf);            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 */        put_byte(&s->pb, v);        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */        put_le16(&s->pb, 0);                put_swf_end_tag(s);    }    put_flush_packet(&s->pb);    return 0;}static int swf_write_video(AVFormatContext *s,                            AVCodecContext *enc, const uint8_t *buf, int size){    SWFContext *swf = s->priv_data;    ByteIOContext *pb = &s->pb;    int c = 0;    int outSize = 0;    int outSamples = 0;        /* Flash Player limit */    if ( swf->swf_frame_number == 16000 ) {        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");    }    /* Store video data in queue */    if ( enc->codec_type == CODEC_TYPE_VIDEO ) {        SWFFrame *new_frame = av_malloc(sizeof(SWFFrame));        new_frame->prev = 0;        new_frame->next = swf->frame_head;        new_frame->data = av_malloc(size);

⌨️ 快捷键说明

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