ffmpeg 的一些数据结构

来源:互联网 发布:javascript 哪些对象 编辑:程序博客网 时间:2024/05/16 04:48


libavcodec目录-------用于存放encode/decode模块。
libavformat目录------用于存放muxer/demuxer模块。
libavutil目录----------用于存放内存操作等模块。

<< muxer/demuxer与encoder/decoder >>
1)数据结构
* muxer   对应的数据结构是AVOutputFormat
* demuxer 对应的数据结构是AVInputFormat
* encoder和decoder 对应的数据结构都是AVCodec

2)muxer/demuxer与encoder/decoder相同之处。
*
二者都是从main()的av_register_all函数初始化。
* 二者都是以链表的形式保存在全局变量中:
    muxer   保存在全局变量AVOutputFormat *first_oformat
    demuxer 保存在全局变量AVInputFormat *first_iformat
    encoder/decoder 都保存在全局变量AVCodec *first_avcodec
* 二者都是用函数指针的方式作为开放的公共接口。

3) muxer/demuxer 的匹配
    在ffmpeg文件转换过程中,是根据输入文件和输出文件的后缀名来匹配合适的demuxer和muxer。

匹配上的demuxer与muxer保存在全局变量first_iformat和first_oformat中。

* demuxer的匹配
    在libavformat\utils.c中的函数av_probe_input_format2()的作用是根据probe data数据,

依次调用每个demuxer的read_probe接口,来判断该demuxer是否和输入文件内容匹配。调用顺序如下:
    · void parse_options()
    · static void opt_input_file()
    · static void opt_input_file()
    · int av_open_input_file()
    · av_probe_input_format()
    · av_probe_input_format2()
    opt_input_file()函数是用于解析argv里的"-i"参数,也就是输入文件名。

* muxer的匹配
     与demuxer的匹配方式不同,muxer的匹配是调用guess_format函数,根据argv里

输出文件的后缀名来进行的。
    ·parse_options()
    ·parse_arg_file()
    ·opt_output_file()
    ·guess_format()

4) encoder/decoder的匹配
     在libavcodec\utils.c中有如下两个函数:
     AVCodec *avcodec_find_encoder(enum CodecID id);
     AVCodec *avcodec_find_decoder(enum CodecID id);
     上述两个函数的功能是根据传入的CodecID,找到匹配的encoder和decoder。

     在av_encode()函数开头,首先初始化各个AVInputStream和AVOutputStream,

然后跟别调用上述两个函数,并将匹配上的encoder与decoder分别保存在如下变量中:
     AVInputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec
     AVOutputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec
    
<< 主要的数据结构 >>
1) AVFormatContext
      AVFormatContext是ffmpeg格式转换过程中实现输入和输出功能、保存相关数据的

主要结构。每一个输入和输出文件,都在如下定义的指针数组全局变量中有对应的实体: 

      static AVFormatContext *output_files[MAX_FILES];
      static AVFormatContext *input_files[MAX_FILES];

      对于输入和输出,因为公用的是同一个结构体,所以需要分别对该结构中成员

iformat和oformat赋值,但是对一个AVFormatContext来说,这两个成员不能同时有值,

即一个AVFormatContext不能同时含有demuxer和muxer。

2) AVCodecContext
    保存AVCodec指针和与codec相关的数据,如video的width、height,audio的sample rate等。

AVCodecContext中的codec_type, codec_id两个变量对于encoder/decoder的匹配来说,最为重要。
    enum CodecType codec_type; /* see CODEC_TYPE_xxx */
    enum CodecID   codec_id;   /* see CODEC_ID_xxx   */
    如上所示,codec_type保存的是CODEC_TYPE_VIDEO, CODEC_TYPE_AUDIO等媒体类型
    codec_id保存的是CODEC_ID_FLV1, CODEC_ID_VPF等编码方式。

   

以支持flv格式为例,在前述的av_open_input_file()函数中,匹配到正确的

AVInputFormat demuxer后,通过av_open_input_stream()函数中调用AVInputFormat的

read_header接口来执行flvdec.c中的flv_read_header()函数。在flv_read_header()

函数内,根据文件头中的数据,创建相应的视频或者音频AVStream,并设置AVStream中

AVCodecContext的正确的codec_type值。codec_id值是在解码过程中flv_read_packet

()函数执行时根据每一个packet头中的数据来设置的。

 

3) AVStream
    AVStream结构保存与数据流相关的编解码器、数据段等信息。比较重要的有如下两

个成员:AVCodecContext *codec; void *priv_data; 其中codec指针保存的就是

encoder或者decoder结构。priv_data指针保存的是和具体编解码流相关的数据。

如ASF解码过程中,priv_data保存的就是ASFStream结构体的数据。

4) AVInputStream/AVOutputStream
    根据输入和输出流的不同,前述的AVStream结构都封装在AVInputStream和

AVOutputStream结构中,在av_encode()函数中使用。
    AVInputStream中还保存的有与时间相关的信息。
    AVOutputStream中还保存有与音视频同步等相关信息。

5) AVPacket
    其用于保存读取的packet数据。
    在av_encode()函数中,调用AVInputFormat的(*read_packet)(struct

AVFormatContext *, AVPacket *pkt);接口,读取输入文件的一帧数据保存在当前输入

AVFormatContext的AVPacket成员中

<< av_encode函数主要流程 >>
    av_encode()函数是ffmepg中最重要的函数,编解码和输出等大部分功能都在此函

数内完成,av_encode的主要流程:
    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

 

原创粉丝点击