ffmpeg 框架

 
当前muxer/demuxer的匹配
在FFmpeg的文件转换过程中,首先要做的就是根据传入文件和传出文件的后缀名匹配合适的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)函数用途是根据传入的probe data数据,依次调用每个demuxer的read_probe接口,来进行该demuxer是否和传入的文件内容匹配的判断。其调用顺序如下:
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函数是在保存在 const OptionDef options[]数组中,用于 void parse_options(int argc, char **argv, const OptionDef *options)中解析argv里的“-i” 参数,也就是输入文件名时调用的。
2.         muxer匹配
与demuxer的匹配不同,muxer的匹配是调用 guess_format函数,根据 main( ) 函数的argv里的输出文件后缀名来进行的。
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)
当前encoder/decoder的匹配
main( )函数中除了解析传入参数并初始化demuxer与muxer的 parse_options( )函数以外,其他的功能都是在 av_encode( )函数里完成的。
在libavcodec\utils.c中有如下二个函数。
              AVCodec *avcodec_find_encoder(enum CodecID id)
                   AVCodec *avcodec_find_decoder(enum CodecID id)
他们的功能就是根据传入的CodecID,找到匹配的encoder和decoder。
av_encode( )函数的开头,首先初始化各个 AVInputStreamAVOutputStream,然后分别调用上述二个函数,并将匹配上的encoder与decoder分别保存在 AVInputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codecAVOutputStream->AVStream *st->AVCodecContext *codec->struct AVCodec *codec变量中。
其他主要数据结构
1.        AVFormatContext
AVFormatContext是FFMpeg格式转换过程中实现输入和输出功能、保存相关数据的主要结构。每一个输入和输出文件,都在如下定义的指针数组全局变量中有对应的实体。
static AVFormatContext *output_files[MAX_FILES];
static AVFormatContext *input_files[MAX_FILES];
对于输入和输出,因为共用的是同一个结构体,所以需要分别对该结构中如下定义的 iformatoformat成员赋值。
   struct AVInputFormat *iformat;
    struct AVOutputFormat *oformat;
对一个 AVFormatContext来说,二个成员不能同时有值,即一个 AVFormatContext不能同时含有demuxer和muxer。
main( )函数开头的 parse_options( )函数中找到了匹配的muxer和demuxer之后,根据传入的argv参数,初始化每个输入和输出的 AVFormatContext结构,并保存在相应的 output_filesinput_files指针数组中。
av_encode( )函数中, output_filesinput_files是作为函数参数传入后,在其他地方就没有用到了。
2.         AVCodecContext
保存 AVCodec指针和与codec相关的数据,如video的width、height,audio的sample rate等。 AVCodecContext中的 codec_typecodec_id二个变量对于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_FLV1CODEC_ID_VP6F等编码方式。
以支持flv格式为例,在前述的 av_open_input_file(…… ) 函数中,匹配到正确的 AVInputFormat demuxer后,通过 av_open_input_stream( )函数中调用 AVInputFormatread_header接口来执行flvdec.c中的 flv_read_header( )函数。在 flv_read_header( )函数内,根据文件头中的数据,创建相应的视频或音频 AVStream,并设置 AVStreamAVCodecContext的正确的 codec_type值。 codec_id值是在解码过程中 flv_read_packet( )函数执行时根据每一个packet头中的数据来设置的。
3.         AVStream
AVStream结构保存与数据流相关的编解码器,数据段等信息。比较重要的有如下二个成员:
           AVCodecContext *codec; /**< codec context */
void *priv_data;
其中 codec指针保存的就是上节所述的encoder或decoder结构。 priv_data指针保存的是和具体编解码流相关的数据,如下代码所示,在ASF的解码过程中, priv_data保存的就是 ASFStream结构的数据。
    AVStream *st;
ASFStream *asf_st;   
     … …
st->priv_data = asf_st;
4.         AVInputStream/ AVOutputStream
根据输入和输出流的不同,前述的 AVStream结构都是封装在 AVInputStreamAVOutputStream结构中,在 av_encode( )函数中使用。 AVInputStream中还保存的有与时间有关的信息。 AVOutputStream中还保存有与音视频同步等相关的信息。
5.         AVPacket
AVPacket结构定义如下,其是用于保存读取的packet数据。
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( )函数中,调用 AVInputFormat(*read_packet)(struct AVFormatContext *, AVPacket *pkt);接口,读取输入文件的一帧数据保存在当前输入 AVFormatContextAVPacket成员中。
av_encode函数主要流程
av_encode( )函数是FFMpeg中最重要的函数,编解码和输出等大部分功能都在此函数内完成,因此有必要详细描述一下这个函数的主要流程。
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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值