ffmpeg 几个主要数据结构

本文详细解读了FFMpeg中AVFormatContext、AVCodecContext、AVStream等关键结构的作用,以及AVPacket的使用。重点介绍了AVMpeg编解码流程的主要步骤,包括输入流初始化、输出流初始化、编码器/解码器初始化、元数据信息读取、文件头写入、帧处理循环、文件尾部写入以及编码器/解码器关闭等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ffplay.c

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_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_VIDEOCODEC_TYPE_AUDIO等媒体类型,

codec_id保存的是CODEC_ID_FLV1CODEC_ID_VP6F等编码方式。

以支持flv格式为例,在前述的av_open_input_file(…… ) 函数中,匹配到正确的AVInputFormatdemuxer后,通过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结构都是封装在AVInputStream和 AVOutputStream结构中,在av_encode( )函数中使用。

AVInputStream中还保存的有与时间有关的信息。

AVOutputStream中还保存有与音视频同步等相关的信息。

5. AVPacket

AVPacket结构定义如下,其是用于保存读取的packet数据。

typedef struct AVPacket {

int64_t pts; ///< presentation time stamp in time_baseunits

int64_t dts; ///< decompression time stamp intime_base units

uint8_t *data;

int size;

int stream_index;

int flags;

int duration; ///< presentation duration in time_baseunits (0 if not available)

void (*destruct)(struct AVPacket *);

void *priv;

int64_t pos; ///< byte position in stream, -1 ifunknown

} 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

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的接口都是一样的,只不过二者分别只实现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);

http://www.dranger.com/ffmpeg/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值