FFmpeg 基本数据结构 AVCodec分析
1、AVCodec 编解码器结构定义
AVCodec 是 FFmpeg 多媒体框架中表示编解码器实现的核心数据结构,它定义了编解码器的能力、操作接口和支持的特性。作为连接编解码算法与上层应用的桥梁,AVCodec 在多媒体处理流水线中扮演着关键角色。
核心能力:
- 算法容器:封装视频/音频编解码算法的具体实现
- 能力定义:声明编解码器支持的分辨率、格式等特性
- 硬件抽象:统一硬件加速接口,支持多平台加速
- 操作接口:提供 init/encode/decode/close 等核心操作
- 性能载体:承载多线程、SIMD 等优化技术
具体结构分析如下:
typedef struct AVCodec {const char *name; // codec的名称const char *long_name; // codec的详细名称enum AVMediaType type; // codec的媒体类型enum AVCodecID id; // codec的IDint capabilities; // codec的 capabilitiesuint8_t max_lowres; // 最大lowres值const AVRational *supported_framerates; // 支持的帧率列表const enum AVPixelFormat *pix_fmts; // 支持的像素格式列表const int *supported_samplerates; // 支持的声音采样率列表const enum AVSampleFormat *sample_fmts; // 支持的声音采样格式列表const AVClass *priv_class; // 私有数据的AVClass结构体const AVProfile *profiles; // 支持的配置文件列表const char *wrapper_name; // 封装器的名称const AVChannelLayout *ch_layouts; // 支持的通道布局列表
} AVCodec;各个成员的含义如下:
- name: 一个字符指针,用于表示AVCodec的名称。
- long_name: 一个字符指针,用于表示AVCodec的详细名称。
- type: 一个枚举类型,用于表示AVCodec的媒体类型。
- id: 一个枚举类型,用于表示AVCodec的ID。
- capabilities: 一个整数,用于表示AVCodec的 capabilities。
- max_lowres: 一个uint8_t类型的整数,用于表示AVCodec的最大lowres值。
- supported_framerates: 一个指向AVRational结构体的指针,用于表示AVCodec支持的帧率列表。
- pix_fmts: 一个指向enum AVPixelFormat结构体的指针,用于表示AVCodec支持的像素格式列表。
- supported_samplerates: 一个指向整数的指针,用于表示AVCodec支持的声音采样率列表。
- sample_fmts: 一个指向enum AVSampleFormat结构体的指针,用于表示AVCodec支持的声音采样格式列表。
- priv_class: 一个指向AVClass结构体的指针,用于表示AVCodec的私有数据类。
- profiles: 一个指向AVProfile结构体的指针,用于表示AVCodec支持的配置文件列表。
- wrapper_name: 一个字符指针,用于表示AVCodec的封装器名称。
- ch_layouts: 一个指向AVChannelLayout结构体的指针,用于表示AVCodec支持的通道布局列表。
2、FFCodec 内部编解码器实现的“描述符”或“包装器”
FFCodec 是 FFmpeg 7.0 中引入的核心数据结构,作为对传统 AVCodec 的扩展和封装,它代表了编解码器的内部实现,提供了更丰富的功能和更好的扩展性。
typedef struct FFCodec {AVCodec p;// 公共API可见部分 (兼容层)unsigned caps_internal:29;unsigned cb_type:3;int priv_data_size; // 默认私有数据int (*update_thread_context)(struct AVCodecContext *dst, const struct AVCodecContext *src);int (*update_thread_context_for_user)(struct AVCodecContext *dst, const struct AVCodecContext *src);const FFCodecDefault *defaults;// 核心功能实现void (*init_static_data)(struct FFCodec *codec);int (*init)(struct AVCodecContext *);// 编解码回调接口union {// 解码器函数集int (*decode)(struct AVCodecContext *avctx, struct AVFrame *frame,int *got_frame_ptr, struct AVPacket *avpkt);int (*decode_sub)(struct AVCodecContext *avctx, struct AVSubtitle *sub,int *got_frame_ptr, const struct AVPacket *avpkt);int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame);// 编码器函数集int (*encode)(struct AVCodecContext *avctx, struct AVPacket *avpkt,const struct AVFrame *frame, int *got_packet_ptr);int (*encode_sub)(struct AVCodecContext *avctx, uint8_t *buf,int buf_size, const struct AVSubtitle *sub);int (*receive_packet)(struct AVCodecContext *avctx, struct AVPacket *avpkt);} cb;// 通用flush和close接口int (*close)(struct AVCodecContext *);void (*flush)(struct AVCodecContext *);const char *bsfs;// 硬件加速支持const struct AVCodecHWConfigInternal *const *hw_configs;const uint32_t *codec_tags;
} FFCodec;
- 新式接口设计:
// 解码器操作流程
static int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame) {FFCodec *const codec = ffcodec(avctx->codec);return codec->cb.dec.receive_frame(avctx, frame);
}// 编码器操作流程
static int ff_encode_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) {FFCodec *const codec = ffcodec(avctx->codec);return codec->cb.enc.receive_packet(avctx, avpkt);
}
- 编解码回调接口 (cb 联合体):

3、FFCodec 解码器定义实例
const FFCodec ff_h264_decoder = {// AVCodec 定义.p.name = "h264",CODEC_LONG_NAME("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),.p.type = AVMEDIA_TYPE_VIDEO,.p.id = AV_CODEC_ID_H264,.priv_data_size = sizeof(H264Context),.init = h264_decode_init,.close = h264_decode_end,FF_CODEC_DECODE_CB(h264_decode_frame),.p.capabilities = AV_CODEC_CAP_DR...,.caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING |FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP,.flush = h264_decode_flush,UPDATE_THREAD_CONTEXT(ff_h264_update_thread_context),UPDATE_THREAD_CONTEXT_FOR_USER(ff_h264_update_thread_context_for_user),.p.profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles),.p.priv_class = &h264_class,
};
