=====================================================
H.264源代码分析文章列表:
【编码 - x264】
x264源代码简单分析:x264命令行工具(x264.exe)
x264源代码简单分析:x264_slice_write()
x264源代码简单分析:宏块分析(Analysis)部分-帧内宏块(Intra)
x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)
x264源代码简单分析:熵编码(Entropy Encoding)部分
【解码 - libavcodec H.264 解码器】
FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分
FFmpeg的H.264解码器源代码简单分析:解码器主干部分
FFmpeg的H.264解码器源代码简单分析:熵解码(EntropyDecoding)部分
FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧内宏块(Intra)
FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)
FFmpeg的H.264解码器源代码简单分析:环路滤波(Loop Filter)部分
=====================================================
本文简单记录一下FFmpeg的libavcodec中与libx264接口部分的源代码。该部分源代码位于“libavcodec/libx264.c”中。正是有了这部分代码,使得FFmpeg可以调用libx264编码H.264视频。
函数调用关系图
FFmpeg的libavcodec中的libx264.c的函数调用关系如下图所示。
从图中可以看出,libx264对应的AVCodec结构体ff_libx264_encoder中设定编码器初始化函数是X264_init(),编码一帧数据的函数是X264_frame(),编码器关闭函数是X264_close()。
X264_init()调用了如下函数:[libx264 API] x264_param_default():设置默认参数。X264_frame()调用了如下函数:
[libx264 API] x264_param_default_preset():设置默认preset。
convert_pix_fmt():将FFmpeg像素格式转换为libx264像素格式。
[libx264 API] x264_param_apply_profile():设置Profile。
[libx264 API] x264_encoder_open():打开编码器。
[libx264 API] x264_encoder_headers():需要全局头的时候,输出头信息。
[libx264 API] x264_encoder_encode():编码一帧数据。X264_close()调用了如下函数:
[libx264 API] x264_encoder_delayed_frames():输出编码器中缓存的数据。
encode_nals():将编码后得到的x264_nal_t转换为AVPacket。
[libx264 API] x264_encoder_close():关闭编码器。
下文将会分别分析X264_init(),X264_frame()和X264_close()这三个函数。
ff_libx264_encoder
ff_libx264_encoder是libx264对应的AVCodec结构体,定义如下所示。//libx264对应的AVCodec结构体AVCodec ff_libx264_encoder = { .name = "libx264", .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .priv_data_size = sizeof(X264Context), .init = X264_init, .encode2 = X264_frame, .close = X264_close, .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, .priv_class = &x264_class, .defaults = x264_defaults, .init_static_data = X264_init_static,};
从ff_libx264_encoder定义中可以看出:init()指向X264_init(),encode2()指向 X264_frame(), close()指向 X264_close()。此外priv_class指向一个x264_class静态结构体,该结构体是libx264对应的AVClass,定义如下。
static const AVClass x264_class = { .class_name = "libx264", .item_name = av_default_item_name, .option = options,//选项 .version = LIBAVUTIL_VERSION_INT,};
x264_class中的option指向一个options[]静态数组,其中包含了libx264支持的AVOption选项,如下所示。
//FFmpeg针对libx264提供的可以通过AVOption设置的选项#define OFFSET(x) offsetof(X264Context, x)#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAMstatic const AVOption options[] = { { "preset", "Set the encoding preset (cf. x264 --fullhelp)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE}, { "tune", "Tune the encoding params (cf. x264 --fullhelp)", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, { "profile", "Set profile restrictions (cf. x264 --fullhelp) ", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, { "fastfirstpass", "Use fast settings when encoding first pass", OFFSET(fastfirstpass), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE}, {
"level", "Specify level (as defined by Annex A)", OFFSET(level), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, {
"passlogfile", "Filename for 2 pass stats", OFFSET(stats), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, {
"wpredp", "Weighted prediction for P-frames", OFFSET(wpredp), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, {
"x264opts", "x264 options", OFFSET(x264opts), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, { "crf", "Select the quality for constant quality mode", OFFSET(crf), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE }, { "crf_max", "In CRF mode, prevents VBV from lowering quality beyond this point.",OFFSET(crf_max), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE }, { "qp", "Constant quantization parameter rate control method",OFFSET(cqp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, { "aq-mode", "AQ method", OFFSET(aq_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "aq_mode"}, { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_NONE}, INT_MIN, INT_MAX, VE, "aq_mode" }, { "variance", "Variance AQ (complexity mask)", 0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_VARIANCE}, INT_MIN, INT_MAX, VE, "aq_mode" }, { "autovariance", "Auto-variance AQ (experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_AUTOVARIANCE}, INT_MIN, INT_MAX, VE, "aq_mode" }, { "aq-strength", "AQ strength. Reduces blocking and blurring in flat and textured areas.", OFFSET(aq_strength), AV_OPT_TYPE_FLOAT, {.dbl = -1}, -1, FLT_MAX, VE}, { "psy", "Use psychovisual optimizations.", OFFSET(psy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, { "psy-rd", "Strength of psychovisual optimization, in <psy-rd>:<psy-trellis> format.", OFFSET(psy_rd), AV_OPT_TYPE_STRING, {
0 }, 0, 0, VE}, { "rc-lookahead", "Number of frames to look ahead for frametype and ratecontrol", OFFSET(rc_lookahead