久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

FFMpeg框架代碼閱讀

 jxwdy123 2010-05-13

FFMpeg框架代碼閱讀
簡介
FFmpeg是一個(gè)集錄制,、轉(zhuǎn)換,、音/視頻編碼解碼功能為一體的完整的開源解決方案。FFmpeg的開發(fā)是基于Linux操作系統(tǒng),,但是可以在大多數(shù)操作系統(tǒng)中編譯和使用,。FFmpeg支持MPEGDivX,、MPEG4,、AC3DV,、FLV40多種編碼,,AVIMPEG,、OGG,、MatroskaASF90多種解碼.
TCPMP, VLC, MPlayer等開源播放器都用到了FFmpeg,。
FFmpeg主目錄下主要有l(wèi)ibavcodec,、libavformat和libavutil等子目錄。其中l(wèi)ibavcodec用于存放各個(gè)encode/decode模塊,,libavformat用于存放muxer/demuxer模塊,,libavutil用于存放內(nèi)存操作等常用模塊,。
以flash movie的flv文件格式為例, muxer/demuxer的flvenc.c和flvdec.c文件在libavformat目錄下,,encode/decode的mpegvideo.c和h263de.c在libavcodec目錄下,。
 
muxer/demuxer與encoder/decoder定義與初始化
muxer/demuxer和encoder/decoder在FFmpeg中的實(shí)現(xiàn)代碼里,有許多相同的地方,,而二者最大的差別是muxer和demuxer分別是不同的結(jié)構(gòu)AVOutputFormat與AVInputFormat,,而encoder和decoder都是用的AVCodec結(jié)構(gòu)。
 
muxer/demuxer和encoder/decoder在FFmpeg中相同的地方有:
l         二者都是在main()開始的av_register_all()函數(shù)內(nèi)初始化的,。
l         二者都是以鏈表的形式保存在全局變量中的,。
muxer/demuxer是分別保存在全局變量AVOutputFormat *first_oformat與AVInputFormat *first_iformat中的。
encoder/decoder都是保存在全局變量AVCodec *first_avcodec中的,。
l         二者都用函數(shù)指針的方式作為開放的公共接口,。
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 *);
                   int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
                int (*write_trailer)(struct AVFormatContext *);
 
encoder/decoder的接口都是一樣的,只不過二者分別只實(shí)現(xiàn)encoder和decoder函數(shù):
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)函數(shù)中,,通過執(zhí)行
REGISTER_MUXDEMUX(FLV, flv);
將支持flv 格式的flv_muxerflv_demuxer變量分別注冊(cè)到全局變量first_oformatfirst_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,
    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結(jié)構(gòu)的定義如下:
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);
 
    /**
     * 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結(jié)構(gòu)的定義可知,,flv_muxer變量初始化的第一,、第二個(gè)成員分別為該muxer的名稱與長名稱,第三,、第四個(gè)成員為所對(duì)應(yīng)MIMIE Type和后綴名,,第五個(gè)成員是所對(duì)應(yīng)的私有結(jié)構(gòu)的大小,第六,、第七個(gè)成員為所對(duì)應(yīng)的音頻編碼和視頻編碼類型ID,,接下來就是三個(gè)重要的接口函數(shù),該muxer的功能也就是通過調(diào)用這三個(gè)接口實(shí)現(xiàn)的,。
 
flv_demuxer在libavformat\flvdec.c中定義如下, 與flv_muxer類似,,在這兒主要也是設(shè)置了5個(gè)接口函數(shù),其中flv_probe接口用途是測試傳入的數(shù)據(jù)段是否是符合當(dāng)前文件格式,,這個(gè)接口在匹配當(dāng)前demuxer的時(shí)候會(huì)用到,。
AVInputFormat flv_demuxer = {
    "flv",
    "flv format",
    0,
    flv_probe,
    flv_read_header,
    flv_read_packet,
    flv_read_close,
    flv_read_seek,
    .extensions = "flv",
    .value = CODEC_ID_FLV1,
};
 
在上述av_register_all(void)函數(shù)中通過執(zhí)行l(wèi)ibavcodec\allcodecs.c文件里的avcodec_register_all(void)函數(shù)來初始化全部的encoder/decoder。
 
因?yàn)椴皇敲糠N編碼方式都支持encode和decode,,所以有以下三種注冊(cè)方式:
#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_encoderflv_decoder變量就分別是在libavcodec\mpegvideo.c和libavcodec\h263de.c中創(chuàng)建的,。
 
當(dāng)前muxer/demuxer的匹配
在FFmpeg的文件轉(zhuǎn)換過程中,首先要做的就是根據(jù)傳入文件和傳出文件的后綴名匹配合適的demuxer和muxer,。
匹配上的demuxer和muxer都保存在如下所示,,定義在ffmpeg.c里的全局變量file_iformatfile_oformat中:
static AVInputFormat *file_iformat;
static AVOutputFormat *file_oformat;
 
1.         demuxer匹配
在libavformat\utils.c中的static AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)函數(shù)用途是根據(jù)傳入的probe data數(shù)據(jù),依次調(diào)用每個(gè)demuxer的read_probe接口,來進(jìn)行該demuxer是否和傳入的文件內(nèi)容匹配的判斷,。其調(diào)用順序如下:
void parse_options(int argc, char **argv, const OptionDef *options)   
static void opt_input_file(const char *filename)
static void opt_input_file(const char *filename)
                     int av_open_input_file(…… )
                                     AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)
static AVInputFormat *av_probe_input_format2(……)
                                                
opt_input_file函數(shù)是在保存在const OptionDef options[]數(shù)組中,,用于void parse_options(int argc, char **argv, const OptionDef *options)中解析argv里的“-i” 參數(shù),也就是輸入文件名時(shí)調(diào)用的,。
 
2.         muxer匹配
與demuxer的匹配不同,,muxer的匹配是調(diào)用guess_format函數(shù),根據(jù)main( ) 函數(shù)的argv里的輸出文件后綴名來進(jìn)行的,。
void parse_options(int argc, char **argv, const OptionDef *options)
void parse_arg_file(const char *filename)
static void opt_output_file(const char *filename)
AVOutputFormat *guess_format(const char *short_name, const char *filename,
                             const char *mime_type)
 
當(dāng)前encoder/decoder的匹配
main( )函數(shù)中除了解析傳入?yún)?shù)并初始化demuxer與muxer的parse_options( )函數(shù)以外,,其他的功能都是在av_encode( )函數(shù)里完成的。
在libavcodec\utils.c中有如下二個(gè)函數(shù),。
              AVCodec *avcodec_find_encoder(enum CodecID id)
                   AVCodec *avcodec_find_decoder(enum CodecID id)
他們的功能就是根據(jù)傳入的CodecID,,找到匹配的encoder和decoder。
 
av_encode( )函數(shù)的開頭,,首先初始化各個(gè)AVInputStreamAVOutputStream,,然后分別調(diào)用上述二個(gè)函數(shù),并將匹配上的encoder與decoder分別保存在AVInputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codecAVOutputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec變量中,。
 
 
 
 
其他主要數(shù)據(jù)結(jié)構(gòu)
1.        AVFormatContext
AVFormatContext是FFMpeg格式轉(zhuǎn)換過程中實(shí)現(xiàn)輸入和輸出功能,、保存相關(guān)數(shù)據(jù)的主要結(jié)構(gòu)。每一個(gè)輸入和輸出文件,,都在如下定義的指針數(shù)組全局變量中有對(duì)應(yīng)的實(shí)體,。
static AVFormatContext *output_files[MAX_FILES];
static AVFormatContext *input_files[MAX_FILES];
對(duì)于輸入和輸出,因?yàn)楣灿玫氖峭粋€(gè)結(jié)構(gòu)體,,所以需要分別對(duì)該結(jié)構(gòu)中如下定義的iformatoformat成員賦值。
   struct AVInputFormat *iformat;
    struct AVOutputFormat *oformat;
對(duì)一個(gè)AVFormatContext來說,,二個(gè)成員不能同時(shí)有值,,即一個(gè)AVFormatContext不能同時(shí)含有demuxer和muxer。
main( )函數(shù)開頭的parse_options( )函數(shù)中找到了匹配的muxer和demuxer之后,,根據(jù)傳入的argv參數(shù),,初始化每個(gè)輸入和輸出的AVFormatContext結(jié)構(gòu),并保存在相應(yīng)的output_filesinput_files指針數(shù)組中,。
av_encode( )函數(shù)中,,output_filesinput_files是作為函數(shù)參數(shù)傳入后,在其他地方就沒有用到了,。
 
2.         AVCodecContext
保存AVCodec指針和與codec相關(guān)的數(shù)據(jù),,如video的width、height,,audio的sample rate等,。AVCodecContext中的codec_typecodec_id二個(gè)變量對(duì)于encoder/decoder的匹配來說,最為重要,。
          enum CodecType codec_type; /* see CODEC_TYPE_xxx */
                enum CodecID codec_id; /* see CODEC_ID_xxx */
 
如上所示,,codec_type保存的是CODEC_TYPE_VIDEOCODEC_TYPE_AUDIO等媒體類型,,
codec_id保存的是CODEC_ID_FLV1,,CODEC_ID_VP6F等編碼方式。
 
以支持flv格式為例,,在前述的av_open_input_file(…… ) 函數(shù)中,,匹配到正確的AVInputFormat demuxer后,通過av_open_input_stream( )函數(shù)中調(diào)用AVInputFormatread_header接口來執(zhí)行flvdec.c中的flv_read_header( )函數(shù),。在flv_read_header( )函數(shù)內(nèi),,根據(jù)文件頭中的數(shù)據(jù),創(chuàng)建相應(yīng)的視頻或音頻AVStream,,并設(shè)置AVStreamAVCodecContext的正確的codec_type值,。codec_id值是在解碼過程中flv_read_packet( )函數(shù)執(zhí)行時(shí)根據(jù)每一個(gè)packet頭中的數(shù)據(jù)來設(shè)置的。
 
3.         AVStream
AVStream結(jié)構(gòu)保存與數(shù)據(jù)流相關(guān)的編解碼器,,數(shù)據(jù)段等信息,。比較重要的有如下二個(gè)成員:
            AVCodecContext *codec; /**< codec context */
void *priv_data;
其中codec指針保存的就是上節(jié)所述的encoder或decoder結(jié)構(gòu)。priv_data指針保存的是和具體編解碼流相關(guān)的數(shù)據(jù),,如下代碼所示,,在ASF的解碼過程中,priv_data保存的就是ASFStream結(jié)構(gòu)的數(shù)據(jù),。
    AVStream *st;
ASFStream *asf_st;   
     … …
st->priv_data = asf_st;
 
 
4.         AVInputStream/ AVOutputStream
根據(jù)輸入和輸出流的不同,,前述的AVStream結(jié)構(gòu)都是封裝在AVInputStreamAVOutputStream結(jié)構(gòu)中,在av_encode( )函數(shù)中使用,。
AVInputStream中還保存的有與時(shí)間有關(guān)的信息,。
AVOutputStream中還保存有與音視頻同步等相關(guān)的信息。
 
5.         AVPacket
AVPacket結(jié)構(gòu)定義如下,,其是用于保存讀取的packet數(shù)據(jù),。
typedef struct AVPacket {
    int64_t pts;            ///< presentation time stamp in time_base units
    int64_t dts;            ///< decompression time stamp in time_base units
    uint8_t *data;
    int   size;
    int   stream_index;
    int   flags;
    int   duration;        ///< presentation duration in time_base units (0 if not available)
    void (*destruct)(struct AVPacket *);
    void *priv;
    int64_t pos;           ///< byte position in stream, -1 if unknown
} AVPacket;
 
av_encode( )函數(shù)中,調(diào)用AVInputFormat(*read_packet)(struct AVFormatContext *, AVPacket *pkt);接口,,讀取輸入文件的一幀數(shù)據(jù)保存在當(dāng)前輸入AVFormatContextAVPacket成員中,。
 
av_encode函數(shù)主要流程
av_encode( )函數(shù)是FFMpeg中最重要的函數(shù),編解碼和輸出等大部分功能都在此函數(shù)內(nèi)完成,,因此有必要詳細(xì)描述一下這個(gè)函數(shù)的主要流程,。
1.         input streams initializing
2.         output streams initializing
3.         encoders and decoders initializing
4.         set meta data information from input file if required.
5.         write output files header
6.         loop of handling each frame
a.       read frame from input file:
b.       decode frame data
c.       encode new frame data
d.       write new frame to output file
7.         write output files trailer
8.         close each encoder and decoder
 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多