AVFormatContext
AVFormatContext是一个描述编解码格式上下文的数据结构。
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;//元数据
AVStream
AVStream是存储每一个视频/音频流信息的结构体。
结构体参数来自:这里
int index; //在AVFormatContext中的索引,这个数字是自动生成的,可以通过这个数字从AVFormatContext::streams表中索引到该流。
int id;//流的标识,依赖于具体的容器格式。解码:由libavformat设置。编码:由用户设置,如果未设置则由libavformat替换。
AVCodecContext *codec;//指向该流对应的AVCodecContext结构,调用avformat_open_input时生成。
AVRational time_base;//这是表示帧时间戳的基本时间单位(以秒为单位)。该流中媒体数据的pts和dts都将以这个时间基准为粒度。
int64_t start_time;//流的起始时间,以流的时间基准为单位。如需设置,100%确保你设置它的值真的是第一帧的pts。
int64_t duration;//解码流的持续时间。如果源文件未指定持续时间,但指定了比特率,则将根据比特率和文件大小估计该值。
int64_t nb_frames; //此流中的帧数(如果已知)或0。
enum AVDiscard discard;//选择哪些数据包可以随意丢弃,不需要去demux。
AVRational sample_aspect_ratio;//样本长宽比(如果未知,则为0)。
AVDictionary *metadata;//元数据信息。
AVRational avg_frame_rate;//平均帧速率。解封装:可以在创建流时设置为libavformat,也可以在avformat_find_stream_info()中设置。
//封装:可以由调用者在avformat_write_header()之前设置。
AVPacket attached_pic;//附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。
int probe_packets;//编解码器用于probe的包的个数。
int codec_info_nb_frames;//在av_find_stream_info()期间已经解封装的帧数。
int request_probe;//流探测状态,1表示探测完成,0表示没有探测请求,rest 执行探测。
int skip_to_keyframe;//表示应丢弃直到下一个关键帧的所有内容。
int skip_samples;//在从下一个数据包解码的帧开始时要跳过的采样数。
int64_t start_skip_samples;//如果不是0,则应该从流的开始跳过的采样的数目。
int64_t first_discard_sample;//如果不是0,则应该从流中丢弃第一个音频样本。
int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];//内部数据,从pts生成dts。
int64_t last_dts_for_order_check;
uint8_t dts_ordered;
uint8_t dts_misordered;//内部数据,用于分析dts和检测故障mpeg流。
AVRational display_aspect_ratio;//显示宽高比。
AVIOContext
AVIOContext是FFMPEG管理输入输出数据的结构体。
unsigned char *buffer;//缓存开始位置
int buffer_size;//缓存大小(默认32768)
unsigned char *buf_ptr;//当前指针读取到的位置
unsigned char *buf_end;//缓存结束的位置
void *opaque;//URLContext结构体
AVCodecContext
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差不太多)
AVCodec
解码器。结构来自:这里
/**
* AVCodec.
* H.264的解码器对象: ff_h264_decoder
*/
typedef struct AVCodec
{
// 解码器名字
const char *name;
// 解码器完整名
const char *long_name;
// 媒体类型
// AVMEDIA_TYPE_VIDEO
// AVMEDIA_TYPE_AUDIO
// AVMEDIA_TYPE_DATA
enum AVMediaType type;
// 解码器ID(AV_CODEC_ID_H264)
enum AVCodecID id;
// 能力集
// H264: CODEC_CAP_DR1|CODEC_CAP_DELAY|CODEC_CAP_SLICE_THREADS|CODEC_CAP_FRAME_THREADS
int capabilities;
// 支持的帧率(V)
const AVRational *supported_framerates;
// 支持的像素格式(V)
// AV_PIX_FMT_YUV420P
// AV_PIX_FMT_RGB24
const enum AVPixelFormat *pix_fmts;
// 支持的采样率(A)
const int *supported_samplerates;
// 支持的采样格式(A)
const enum AVSampleFormat *sample_fmts;
// 支持的声道数(A)
const uint64_t *channel_layouts;
// (这里的3条感觉就是打补丁打出来的字段)
// 由解码器支持低分辨率的最大值,不能直接访问,使用av_codec_get_max_lowres()
uint8_t max_lowres;
// AVClass针对私有上下文
const AVClass *priv_class;
// 公认的配置文件数组,如果未知则为NULL,数组由FF_PROFILE_UNKNOWN表示终止
const AVProfile *profiles;
// 私有数据总长度
int priv_data_size;
// 下一个链接对象
struct AVCodec *next;
// 假如被定义了, 那么当他们被创建时则被线程上下文调用。
// 假如编解码器在调用init()时分配了可写表, 那么在这里重新分配.
// priv_data将被设置为原件的副本
int (*init_thread_copy)(AVCodecContext *);
/**
* 将必要的上下文变量从上一个线程复制到当前线程的上下文,(跨线程拷贝)。
* 假如没有被定义, 下一个线程将自动启动; 否则, 编解码器必须调用call ff_thread_finish_setup().
*
* 目标和源很少指向相同的上下文, 在这种情况下应该跳过memcpy()的调用。
*/
int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src);
// 私有的指定的编解码器默认值.
const AVCodecDefault *defaults;
// 初始化编解码器的静态数据, 由avcodec_register()来调用.
void (*init_static_data)(struct AVCodec *codec);
// 根据AVCodecContext来初始化
int (*init)(AVCodecContext *);
int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, const struct AVSubtitle *sub);
// 编码数据到AVPacket.
// @参数 avctx: 编解码上下文
// @参数 avpkt: 输出的AVPacket,(可能包含上层调用者提供的缓冲区)
// @参数[in] frame: AVFrame包含了未加工的数据来编码
// @参数[out] got_packet_ptr: 设置为0或1来表示一个非空的AVPacket返回值avpkt
// @返回值 0表示成功,其他错误代码表示错误
int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr);
// 执行解码,从数据包AVPacket中进行解码转为outdata和outdata_size,提供AVCodecContext来定义编解码上下文信息
int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt);
// 关闭编解码器对象
int (*close)(AVCodecContext *);
// 编码+解码的API函数, 用来解耦packet/frame数据流(就是提供自己玩的接口,而不是打包操作).
// 这些API和avcodec_ prefixed的API差不多,除了下面这些:
// - 如果编解码器关闭或者是错误类型,那么就不要使用。
// - 在调用AVCodec->send_packet()之前,改变了AVPacket参数数据
// - 假如AV_CODEC_CAP_DELAY没有被设置、漏包或者帧压根没有被发送
// 发送帧
int (*send_frame)(AVCodecContext *avctx, const AVFrame *frame);
// 发送包
int (*send_packet)(AVCodecContext *avctx, const AVPacket *avpkt);
// 接受帧
int (*receive_frame)(AVCodecContext *avctx, AVFrame *frame);
// 接受包
int (*receive_packet)(AVCodecContext *avctx, AVPacket *avpkt);
// 刷新缓冲区
void (*flush)(AVCodecContext *);
// 内部的编解码能力.
// 可以查看FF_CODEC_CAP_*系列宏,在头文件internal.h中
int caps_internal;
}
AVPacket
AVPacket是FFmpeg中很重要的一个数据结构,它保存了解复用(demuxer)之后,解码(decode)之前的数据(仍然是压缩后的数据)和关于这些数据的一些附加的信息,如显示时间戳(pts),解码时间戳(dts),数据时长(duration),所在流媒体的索引(stream_index)等等。详情看这里
pts: (int64_t)显示时间,结合AVStream->time_base转换成时间戳
dts: (int64_t)解码时间,结合AVStream->time_base转换成时间戳
size: (int)data的大小
stream_index: (int)packet在stream的index位置
flags: (int)标示,结合AV_PKT_FLAG使用,其中最低为1表示该数据是一个关键帧。
#define AV_PKT_FLAG_KEY 0x0001 //关键帧
#define AV_PKT_FLAG_CORRUPT 0x0002 //损坏的数据
#define AV_PKT_FLAG_DISCARD 0x0004 /丢弃的数据
side_data_elems: (int)边缘数据元数个数
duration: (int64_t)数据的时长,以所属媒体流的时间基准为单位,未知则值为默认值0
pos: (int64_t )数据在流媒体中的位置,未知则值为默认值-1
convergence_duration:该字段已deprecated,不在使用
关于数据缓存,AVPacket本身只是个容器,不直接的包含数据,而是通过数据缓存的指针引用数据。
uint8_t *data:指向保存压缩数据的指针,这就是AVPacket的实际数据。
AVPacketSideData *side_data:容器提供的一些附加数据
AVBufferRef *buf:用来管理data指针引用的数据缓存,其使用在后面介绍。
AVFrame
AVFrame用来存储解码后的(或原始)音频或视频数据,位于avcodec.h文件中。
AVFrame必须由av_frame_alloc()分配内存,同时必须由av_frame_free()释放。
AVFrame分配内存后能够被多次用来存储不同的数据(例如:decoder解码后的帧)。av_frame_unref释放任何持帧的引用,并结构体还原到未被使用的状态。来自这里
一个AVPacket包含一个视频帧(AVFrame),也可以包含多个音频帧。
一帧音频的数据量 = channel数 * nb_samples样本数 * 每个样本占用的字节数。
uint8_t * data [AV_NUM_DATA_POINTERS];//解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)。
int linesize[AV_NUM_DATA_POINTERS];//在视频中,表示图片一行数据的大小。
uint8_t **extended_data;//指向数据平面/通道。
int width, height;//一个视频帧的宽度和高度。
int nb_samples;//这个AVFrame中的每个音频声道的样本数。
int format;//表示解码后的数据类型或格式,-1表示未被设置或不能识别的类型。
int key_frame;//是否为关键帧,1->关键帧,0->非关键帧。
enum AVPictureType pict_type;//帧的类型。
AVRational sample_aspect_ratio;//视频帧的宽高比,0表示未知。
int64_t pts;//显示时间戳,表示该什么时候被显示。
int64_t pkt_dts;//从AVPacket中拷贝的值。
int coded_picture_number;//编码帧序号。
int display_picture_number;//显示帧需要。
void *opaque;//用户私有信息。
int repeat_pict;//解码时,每帧图片延迟的时间,extra_delay = repeat_pict / (2*fps)。
int interlaced_frame;//是否是隔行扫描
int sample_rate;//音频的采样率。
uint64_t channel_layout;//音频的布局方式。
enum AVColorRange color_range;
enum AVColorPrimaries color_primaries;
enum AVColorTransferCharacteristic color_trc;
enum AVColorSpace colorspace;
enum AVChromaLocation chroma_location;
int64_t best_effort_timestamp;//大多数情况下AVFrame的pts和best_effort_timestamp值是一样的
int64_t pkt_pos;//记录最后一个进入解码器的packet在输入文件中的位置偏移量。
int64_t pkt_duration;//对应packet的时长,单位是AVStream->time_base。
AVDictionary *metadata;
int decode_error_flags;
int channels;//音频通道个数
int pkt_size;//对应packet的大小。
int8_t *qscale_table;
int qstride;
int qscale_type;
AVBufferRef *qp_table_buf;
AVBufferRef *hw_frames_ctx;
AVBufferRef *opaque_ref;
AVSampleFormat
音频数据格式。名称尾有p表示分片,如音频有两个声道,分片左声道存linesize[0],右声道存linesize[1],不分片都存linesize[0],左右左右...的顺序依次存储。
enum AVSampleFormat {
AV_SAMPLE_FMT_NONE = -1,
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
AV_SAMPLE_FMT_S16, ///< signed 16 bits
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double
AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP, ///< float, planar
AV_SAMPLE_FMT_DBLP, ///< double, planar
AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
};
AVPictureType
视频帧类型。
enum AVPictureType {
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
AV_PICTURE_TYPE_I, ///< Intra
AV_PICTURE_TYPE_P, ///< Predicted
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4
AV_PICTURE_TYPE_SI, ///< Switching Intra
AV_PICTURE_TYPE_SP, ///< Switching Predicted
AV_PICTURE_TYPE_BI, ///< BI type
};