@TOC
常用结构体
FFMPEG中结构体很多。最关键的结构体可以分成以下几类:
解协议(http,rtsp,rtmp,mms)
AVIOContext,URLProtocol,URLContext主要存储视音频使用的协议的类型以及状态。URLProtocol存储输入视音频使用的封装格式。每种协议都对应一个URLProtocol结构。(注意:FFMPEG中文件也被当做一种协议“file”)解封装(flv,avi,rmvb,mp4)
AVFormatContext主要存储视音频封装格式中包含的信息;AVInputFormat存储输入视音频使用的封装格式。每种视音频封装格式都对应一个AVInputFormat 结构。解码(h264,mpeg2,aac,mp3)
每个AVStream存储一个视频/音频流的相关数据;每个AVStream对应一个AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个AVCodecContext中对应一个AVCodec,包含该视频/音频对应的解码器。每种解码器都对应一个AVCodec结构。存数据
视频的话,每个结构一般是存一帧;音频可能有好几帧
解码前数据:AVPacket
解码后数据:AVFrame
结构图如下:
AVIOContext
AVIOContext中有以下几个变量比较重要:
unsigned char *buffer:缓存开始位置
int buffer_size:缓存大小(默认32768)
unsigned char *buf_ptr:当前指针读取到的位置
unsigned char *buf_end:缓存结束的位置
void *opaque:URLContext结构体
在解码的情况下,buffer用于存储ffmpeg读入的数据。例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。
其中opaque指向了URLContext。
在avformat_open_input()中进行初始化。
AVFrame
该结构体在Frame.h中,AVFrame结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV,RGB,对音频来说是PCM),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表,QP表,运动矢量表等数据。编码的时候也存储了相关的数据。因此在使用FFMPEG进行码流分析的时候,AVFrame是一个很重要的结构体。由av_frame_alloc()或av_image_fill_arrays()初始化,由av_frame_free()销毁。
源码定义如下:
typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
uint8_t *data[AV_NUM_DATA_POINTERS]; //解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)
int linesize[AV_NUM_DATA_POINTERS]; //data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。
uint8_t **extended_data; //视频帧宽和高(1920x1080,1280x720...)
int width, height;
int nb_samples; //音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个
int format; //解码后原始数据类型(YUV420,YUV422,RGB24...)
int key_frame; //是否是关键帧
enum AVPictureType pict_type; //帧类型(I,B,P...)
#if FF_API_AVFRAME_LAVC
attribute_deprecated
uint8_t *base[AV_NUM_DATA_POINTERS];
#endif
AVRational sample_aspect_ratio; //宽高比(16:9,4:3...)
int64_t pts; //显示时间戳
int64_t pkt_pts;
int64_t pkt_dts;
int coded_picture_number; //编码帧序号
int display_picture_number; //显示帧序号
int quality;
#if FF_API_AVFRAME_LAVC
attribute_deprecated
int reference;
attribute_deprecated
int8_t *qscale_table; //QP表
attribute_deprecated
int qstride;
attribute_deprecated
int qscale_type;
attribute_deprecated
uint8_t *mbskip_table; //跳过宏块表
int16_t (*motion_val[2])[2]; //运动矢量表
attribute_deprecated
uint32_t *mb_type; //宏块类型表
attribute_deprecated
short *dct_coeff; //DCT系数
attribute_deprecated
int8_t *ref_index[2]; //运动估计参考帧列表(貌似H.264这种比较新的标准才会涉及到多参考帧)
#endif
void *opaque;
uint64_t error[AV_NUM_DATA_POINTERS];
#if FF_API_AVFRAME_LAVC
attribute_deprecated
int type;
#endif
int repeat_pict;
int interlaced_frame; //是否是隔行扫描
int top_field_first;
int palette_has_changed;
#if FF_API_AVFRAME_LAVC
attribute_deprecated
int buffer_hints;
attribute_deprecated
struct AVPanScan *pan_scan;
#endif
int64_t reordered_opaque;
#if FF_API_AVFRAME_LAVC
attribute_deprecated void *hwaccel_picture_private;
attribute_deprecated
struct AVCodecContext *owner;
attribute_deprecated
void *thread_opaque;
uint8_t motion_subsample_log2; //一个宏块中的运动矢量采样个数,取log的
#endif
int sample_rate;
uint64_t channel_layout;
AVBufferRef *buf[AV_NUM_DATA_POINTERS];
AVBufferRef **extended_buf;
int nb_extended_buf;
AVFrameSideData **side_data;
int nb_side_data;
#define AV_FRAME_FLAG_CORRUPT (1 << 0)
int flags;
enum AVColorRange color_range;
enum AVColorPrimaries color_primaries;
enum AVColorTransferCharacteristic color_trc;
enum AVColorSpace colorspace;
enum AVChromaLocation chroma_location;
int64_t best_effort_timestamp;
int64_t pkt_pos;
int64_t pkt_duration;
AVDictionary *metadata;
int decode_error_flags;
#define FF_DECODE_ERROR_INVALID_BITSTREAM 1
#define FF_DECODE_ERROR_MISSING_REFERENCE 2
int channels;
int pkt_size;
AVBufferRef *qp_table_buf;
} AVFrame;
AVFormatContext
是一个贯穿始终的数据结构,它是解封装(flv、mp4、rmvb、avi)功能的结构体。
该结构体在avformat.h中,AVFormatContext主要存储视音频封装格式中包含的信息,包含编解码码流丰富的信息,统领全局的基本结构体,主要用于处理封装格式(FLV/MKV/RMVB等),由avformat_alloc_context()初始化,由avformat_free_context()销毁。
在使用FFMPEG进行开发的时候,AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。它是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体。下面看几个主要变量的作用(在这里考虑解码的情况):
struct AVInputFormat *iformat:输入数据的封装格式
AVIOContext *pb:输入数据的缓存
unsigned int nb_streams:视音频流的个数
AVStream **streams:视音频流
char filename[1024]:文件名
int64_t duration:时长(单位:微秒us,转换为秒需要除以1000000)
int bit_rate:比特率(单位bps,转换为kbps需要除以1000)
AVDictionary *metadata:元数据
具体定义源码如下:
typedef struct AVFormatContext {
const AVClass *av_class;
struct AVInputFormat *iformat; //输入数据的封装格式
struct AVOutputFormat *oformat;
void *priv_data;
AVIOContext *pb; //输入数据的缓存
int ctx_flags;
unsigned int nb_streams;
AVStream **streams; //视音频流
char filename[1024]; //文件名
int64_t start_time;
int64_t duration; //时长(单位:微秒us,转换为秒需要除以1000000)
int bit_rate; //比特率(单位bps,转换为kbps需要除以1000)
unsigned int packet_size;
int max_delay;
int flags;
#if FF_API_PROBESIZE_32
unsigned int probesize;
attribute_deprecated
int max_analyze_duration;
#endif
const uint8_t *key;
int keylen;
unsigned int nb_programs;
AVProgram **programs;
enum AVCodecID video_codec_id;
enum AVCodecID audio_codec_id;
enum AVCodecID subtitle_codec_id;
unsigned int max_index_size;
unsigned int max_picture_buffer;
unsigned int nb_chapters;
AVChapter **chapters;
AVDictionary *metadata; //元数据
int64_t start_time_realtime;
int fps_probe_size;
int error_recognition;
AVIOInterruptCB interrupt_callback;
int debug;
#define FF_FDEBUG_TS 0x0001
int64_t max_interleave_delta;
int strict_std_compliance;
int event_flags;
int max_ts_probe;
int avoid_negative_ts;
int ts_id;
int audio_preload;
int max_chunk_duration;
int max_chunk_size;
int use_wallclock_as_timestamps;
int avio_flags;
enum AVDurationEstimationMethod duration_estimation_method;
int64_t skip_initial_bytes;
unsigned int correct_ts_overflow;
int seek2any;
int flush_packets;
int probe_score;
int format_probesize;
char *codec_whitelist;
char *format_whitelist;
AVFormatInternal *internal;
int io_repositioned;
AVCodec *video_codec;
AVCodec *audio_codec;
AVCodec *subtitle_codec;
AVCodec *data_codec;
int metadata_header_padding;
void *opaque;
av_format_control_message control_message_cb;
int64_t output_ts_offset;
#if FF_API_PROBESIZE_32
int64_t max_analyze_duration2;
#else
int64_t max_analyze_duration;
#endif
#if FF_API_PROBESIZE_32
int64_t probesize2;
#else
int64_t probesize;
#endif
uint8_t *dump_separator;
enum AVCodecID data_codec_id;
int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
} AVFormatContext;
AVStream
是存储每一个视频/音频流信息的结构体。
AVStream重要的变量如下所示:
int index:标识该视频/音频流
AVCodecContext codec:指向该视频/音频流的AVCodecContext(它们是一一对应的关系)
AVRational time_base:时基。通过该值可以把PTS,DTS转化为真正的时间。FFMPEG其他结构体中也有这个字段,但是根据我的经验,只有AVStream中的time_base是可用的。PTStime_base=真正的时间
int64_t duration:该视频/音频流长度
AVDictionary *metadata:元数据信息
AVRational avg_frame_rate:帧率(注:对视频来说,这个挺重要的)
AVPacket attached_pic:附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。
AVCodecParameters *codecpar:编解码器的参数(音频、视频、字幕解码器)
AVCodecContext
挑一些关键的变量来看看(这里只考虑解码)。
enum AVMediaType codec_type:编解码器的类型(视频,音频…)
struct AVCodec *codec:采用的解码器AVCodec(H.264,MPEG2…)
int bit_rate:平均比特率
uint8_t *extradata; int extradata_size:针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)
AVRational time_base:根据该参数,可以把PTS转化为实际的时间(单位为秒s)
int width, height:如果是视频的话,代表宽和高
int refs:运动估计参考帧的个数(H.264的话会有多帧,MPEG2这类的一般就没有了)
int sample_rate:采样率(音频)
int channels:声道数(音频)
enum AVSampleFormat sample_fmt:采样格式
int profile:型(H.264里面就有,其他编码标准应该也有)
int level:级(和profile差不太多)
在这里需要注意:AVCodecContext中很多的参数是编码的时候使用的,而不是解码的时候使用的。
AVPacket
用于暂存解复用之后、解码之前的媒体数据(比如一个视频帧)及附加信息(dts、pts)。
在AVPacket结构体中,重要的变量有以下几个:
uint8_t *data:压缩编码的数据。
例如对于H.264来说。1个AVPacket的data通常对应一个NAL。
注意:在这里只是对应,而不是一模一样。他们之间有微小的差别:使用FFMPEG类库分离出多媒体文件中的H.264码流
因此在使用FFMPEG进行视音频处理的时候,常常可以将得到的AVPacket的data数据直接写成文件,从而得到视音频的码流文件。
int size:data的大小
int64_t pts:显示时间戳
int64_t dts:解码时间戳
int stream_index:标识该AVPacket所属的视频/音频流。
这个结构体虽然比较简单,但是非常的常用。