FFMPEG流程分析
- 格式:doc
- 大小:148.50 KB
- 文档页数:26
1 FFMPEG架構分析 1. 簡介 FFmpeg是一個集錄製、轉換、音/視頻編碼解碼功能為一體的完整的開源解決方案。 FFmpeg的 開發是基於Linux操作系統,但是可以在大多數操作系統中編譯和使用。 FFmpeg支持MPEG、 DivX、MPEG4、AC3、DV、FLV等40多種編碼,AVI、MPEG、OGG、Matroska、ASF等90多種解碼. TCPMP, VLC, MPlayer等開源播放器都用到了FFmpeg。 FFmpeg主目錄下主要有libavcodec、libavformat和libavutil等子目錄。其中libavcodec用 於存放各個encode/decode模塊,libavformat用於存放muxer/demuxer模塊,libavutil用於 存放內存操作等輔助性模塊。 以flash movie的flv文件格式為例, muxer/demuxer的flvenc.c和flvdec.c文件 在libavformat目錄下,encode/decode的mpegvideo.c和h263de.c在libavcodec目錄下。
2. muxer/demuxer與encoder/decoder定義與初始化
muxer/demuxer和encoder/decoder在FFmpeg中的實現代碼裡,有許多相同的地方,而二者最 大的差別是muxer 和demuxer分別是不同的結構AVOutputFormat與AVInputFormat,而encoder 2
和decoder都是用的AVCodec 結構。
muxer/demuxer和encoder/decoder在FFmpeg中相同的地方有:
二者都是在main()開始的av_register_all()函數內初始化的 二者都是以鍊錶的形式保存在全局變量中的 muxer/demuxer是分別保存在全局變量AVOutputFormat *first_oformat與 AVInputFormat *first_iformat中的。 encoder/decoder都是保存在全局變量AVCodec *first_avcodec中的。 二者都用函數指針的方式作為開放的公共接口
demuxer開放的接口有: int (*read_probe)(AVProbeData *); int (*read_header)(struct AVFormatContext *, AVFormatParameters *ap); int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); int (*read_close)(struct AVFormatContext *); int (*read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags);
muxer開放的接口有: int (*write_header)(struct AVFormatContext *); 3
int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); int (*write_trailer)(struct AVFormatContext *);
encoder/decoder的接口是一樣的,只不過二者分別只實現encoder和decoder函數: int (*init)(AVCodecContext *); int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data); int (*close)(AVCodecContext *); int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, uint8_t *buf, int buf_size);
仍以flv文件為例來說明muxer/demuxer的初始化。
在libavformat\allformats.c文件的av_register_all(void)函數中,通過執行 REGISTER_MUXDEMUX(FLV, flv); 將支持flv 格式的flv_muxer與flv_demuxer變量分別註冊到全局變量first_oformat與first_iformat鍊錶的最後位置。
其中flv_muxer在libavformat\flvenc.c中定義如下: AVOutputFormat flv_muxer = { "flv", "flv format", "video/x-flv", "flv", sizeof(FLVContext), #ifdef CONFIG_LIBMP3LAME CODEC_ID_MP3, #else // CONFIG_LIBMP3LAME CODEC_ID_NONE, 4
CODEC_ID_FLV1, flv_write_header, flv_write_packet, flv_write_trailer, .codec_tag= (const AVCodecTag*[]){flv_video_codec_ids, flv_audio_codec_ids, 0}, }
AVOutputFormat結構的定義如下: typedef struct AVOutputFormat { const char *name; const char *long_name; const char *mime_type; const char *extensions; /**< comma separated filename extensions */ /** size of private data so that it can be allocated in the wrapper */ int priv_data_size; /* output support */ enum CodecID audio_codec; /**< default audio codec */ enum CodecID video_codec; /**< default video codec */
int (*write_header)(struct AVFormatContext *); int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); int (*write_trailer)(struct AVFormatContext *); /** can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER */ int flags; /** currently only used to set pixel format if not YUV420P */ int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *); int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, AVPacket *in, int flush);
/** 5
*list of supported codec_id-codec_tag pairs,ordered by "better choice first" * the arrays are all CODEC_ID_NONE terminated */ const struct AVCodecTag **codec_tag; /* private fields */ struct AVOutputFormat *next; } AVOutputFormat;
由AVOutputFormat結構的定義可知,flv_muxer變量初始化的第一、二個成員分別為該muxer
的名稱與長名稱,第三、第四個成員為所對應MIME Type和後綴名,第五個成員是所對應的 私有結構的大小,第六、第七個成員為所對應的音頻編碼和視頻編碼類型ID,接下來就是三 個重要的接口函數,該muxer的功能也就是通過調用這三個接口實現的。
flv_demuxer在libavformat\flvdec.c中定義如下, 與flv_muxer類似,在這兒主要也是設置
了5個接口函數,其中flv_probe接口用途是測詴傳入的數據段是否是符合當前文件格式,這 個接口在匹配當前demuxer時會用到。 AVInputFormat flv_demuxer = { "flv", "flv format", 0, flv_probe, flv_read_header, flv_read_packet, 6
flv_read_close, flv_read_seek, .extensions = "flv", .value = CODEC_ID_FLV1, };
在上述av_register_all(void)函數中通過執行libavcodec\allcodecs.c文件裡的
avcodec_register_all(void)函數來初始化全部的encoder/decoder。
因為不是每種編碼方式都支持encode和decode,所以有以下三種註冊方式: #define REGISTER_ENCODER(X,x) \ if(ENABLE_##X##_ENCODER) register_avcodec(&x##_encoder) #define REGISTER_DECODER(X,x) \ if(ENABLE_##X##_DECODER) register_avcodec(&x##_decoder) #define REGISTER_ENCDEC(X,x) REGISTER_ENCODER(X,x); REGISTER_DECODER(X,x)
如支持flv的flv_encoder和flv_decoder變量就分別是在libavcodec\mpegvideo.c和libavcodec\h263de.c中創建的。