毕设网站和系统的区别,全媒体网站的建设,网站建设图片大小,信息化推进与网站建设参考链接
FFmpeg源代码简单分析#xff1a;avcodec_open2()_雷霄骅的博客-CSDN博客
avcodec_open2()
该函数用于初始化一个音视频编解码器的AVCodecContextavcodec_open2()的声明位于libavcodec\avcodec.h#xff0c;如下所示。
/*** Initialize the AVCodecContext to use…参考链接
FFmpeg源代码简单分析avcodec_open2()_雷霄骅的博客-CSDN博客
avcodec_open2()
该函数用于初始化一个音视频编解码器的AVCodecContextavcodec_open2()的声明位于libavcodec\avcodec.h如下所示。
/*** Initialize the AVCodecContext to use the given AVCodec. Prior to using this* function the context has to be allocated with avcodec_alloc_context3().* 初始化 AVCodecContext 以使用给定的 AVCodec* 在使用此函数之前必须使用 avcodec_alloc_context3() 分配上下文** The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),* avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for* retrieving a codec.* 函数 avcodec_find_decoder_by_name()、avcodec_find_encoder_by_name()、avcodec_find_decoder() * avcodec_find_encoder() 为检索编解码器提供了一种简单的方法** note Always call this function before using decoding routines (such as* ref avcodec_receive_frame()).** code* av_dict_set(opts, b, 2.5M, 0);* codec avcodec_find_decoder(AV_CODEC_ID_H264);* if (!codec)* exit(1);** context avcodec_alloc_context3(codec);** if (avcodec_open2(context, codec, opts) 0)* exit(1);* endcode** param avctx The context to initialize.* param codec The codec to open this context for. If a non-NULL codec has been* previously passed to avcodec_alloc_context3() or* for this context, then this parameter MUST be either NULL or* equal to the previously passed codec.* param options A dictionary filled with AVCodecContext and codec-private options.* On return this object will be filled with options that were not found.** return zero on success, a negative value on error* see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),* av_dict_set(), av_opt_find().*/
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
用中文简单转述一下avcodec_open2()各个参数的含义avctx需要初始化的AVCodecContext。codec输入的AVCodecoptions一些选项。例如使用libx264编码的时候“preset”“tune”等都可以通过该参数设置。
函数调用关系图 int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
{int ret 0;AVCodecInternal *avci;const FFCodec *codec2;//如果已经打开直接返回if (avcodec_is_open(avctx))return 0;if (!codec !avctx-codec) {av_log(avctx, AV_LOG_ERROR, No codec provided to avcodec_open2()\n);return AVERROR(EINVAL);}if (codec avctx-codec codec ! avctx-codec) {av_log(avctx, AV_LOG_ERROR, This AVCodecContext was allocated for %s, but %s passed to avcodec_open2()\n, avctx-codec-name, codec-name);return AVERROR(EINVAL);}if (!codec)codec avctx-codec;codec2 ffcodec(codec);if ((avctx-codec_type ! AVMEDIA_TYPE_UNKNOWN avctx-codec_type ! codec-type) ||(avctx-codec_id ! AV_CODEC_ID_NONE avctx-codec_id ! codec-id)) {av_log(avctx, AV_LOG_ERROR, Codec type or id mismatches\n);return AVERROR(EINVAL);}avctx-codec_type codec-type;avctx-codec_id codec-id;avctx-codec codec;if (avctx-extradata_size 0 || avctx-extradata_size FF_MAX_EXTRADATA_SIZE)return AVERROR(EINVAL);avci av_mallocz(sizeof(*avci));if (!avci) {ret AVERROR(ENOMEM);goto end;}avctx-internal avci;avci-buffer_frame av_frame_alloc();avci-buffer_pkt av_packet_alloc();if (!avci-buffer_frame || !avci-buffer_pkt) {ret AVERROR(ENOMEM);goto free_and_end;}avci-skip_samples_multiplier 1;if (codec2-priv_data_size 0) {if (!avctx-priv_data) {avctx-priv_data av_mallocz(codec2-priv_data_size);if (!avctx-priv_data) {ret AVERROR(ENOMEM);goto free_and_end;}if (codec-priv_class) {*(const AVClass **)avctx-priv_data codec-priv_class;av_opt_set_defaults(avctx-priv_data);}}if (codec-priv_class (ret av_opt_set_dict(avctx-priv_data, options)) 0)goto free_and_end;} else {avctx-priv_data NULL;}//将输入的AVDictionary形式的选项设置到AVCodecContextif ((ret av_opt_set_dict(avctx, options)) 0)goto free_and_end;if (avctx-codec_whitelist av_match_list(codec-name, avctx-codec_whitelist, ,) 0) {av_log(avctx, AV_LOG_ERROR, Codec (%s) not on whitelist \%s\\n, codec-name, avctx-codec_whitelist);ret AVERROR(EINVAL);goto free_and_end;}// only call ff_set_dimensions() for non H.264/VP6F/DXV codecs so as not to overwrite previously setup dimensionsif (!(avctx-coded_width avctx-coded_height avctx-width avctx-height (avctx-codec_id AV_CODEC_ID_H264 || avctx-codec_id AV_CODEC_ID_VP6F || avctx-codec_id AV_CODEC_ID_DXV))) {if (avctx-coded_width avctx-coded_height)ret ff_set_dimensions(avctx, avctx-coded_width, avctx-coded_height);else if (avctx-width avctx-height)ret ff_set_dimensions(avctx, avctx-width, avctx-height);if (ret 0)goto free_and_end;}//检查宽和高if ((avctx-coded_width || avctx-coded_height || avctx-width || avctx-height) ( av_image_check_size2(avctx-coded_width, avctx-coded_height, avctx-max_pixels, AV_PIX_FMT_NONE, 0, avctx) 0|| av_image_check_size2(avctx-width, avctx-height, avctx-max_pixels, AV_PIX_FMT_NONE, 0, avctx) 0)) {av_log(avctx, AV_LOG_WARNING, Ignoring invalid width/height values\n);ff_set_dimensions(avctx, 0, 0);}//检查宽高比if (avctx-width 0 avctx-height 0) {if (av_image_check_sar(avctx-width, avctx-height,avctx-sample_aspect_ratio) 0) {av_log(avctx, AV_LOG_WARNING, ignoring invalid SAR: %u/%u\n,avctx-sample_aspect_ratio.num,avctx-sample_aspect_ratio.den);avctx-sample_aspect_ratio (AVRational){ 0, 1 };}}if (avctx-sample_rate 0) {av_log(avctx, AV_LOG_ERROR, Invalid sample rate: %d\n, avctx-sample_rate);ret AVERROR(EINVAL);goto free_and_end;}if (avctx-block_align 0) {av_log(avctx, AV_LOG_ERROR, Invalid block align: %d\n, avctx-block_align);ret AVERROR(EINVAL);goto free_and_end;}#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS/* compat wrapper for old-style callers */if (avctx-channel_layout !avctx-channels)avctx-channels av_popcount64(avctx-channel_layout);if ((avctx-channels 0 avctx-ch_layout.nb_channels ! avctx-channels) ||(avctx-channel_layout (avctx-ch_layout.order ! AV_CHANNEL_ORDER_NATIVE ||avctx-ch_layout.u.mask ! avctx-channel_layout))) {if (avctx-channel_layout) {av_channel_layout_from_mask(avctx-ch_layout, avctx-channel_layout);} else {avctx-ch_layout.order AV_CHANNEL_ORDER_UNSPEC;avctx-ch_layout.nb_channels avctx-channels;}}
FF_ENABLE_DEPRECATION_WARNINGS
#endifif (avctx-ch_layout.nb_channels FF_SANE_NB_CHANNELS) {av_log(avctx, AV_LOG_ERROR, Too many channels: %d\n, avctx-ch_layout.nb_channels);ret AVERROR(EINVAL);goto free_and_end;}avctx-frame_number 0;avctx-codec_descriptor avcodec_descriptor_get(avctx-codec_id);//检查编码器是否出于“实验”阶段if ((avctx-codec-capabilities AV_CODEC_CAP_EXPERIMENTAL) avctx-strict_std_compliance FF_COMPLIANCE_EXPERIMENTAL) {const char *codec_string av_codec_is_encoder(codec) ? encoder : decoder;const AVCodec *codec2;av_log(avctx, AV_LOG_ERROR,The %s %s is experimental but experimental codecs are not enabled, add -strict %d if you want to use it.\n,codec_string, codec-name, FF_COMPLIANCE_EXPERIMENTAL);codec2 av_codec_is_encoder(codec) ? avcodec_find_encoder(codec-id) : avcodec_find_decoder(codec-id);if (!(codec2-capabilities AV_CODEC_CAP_EXPERIMENTAL))av_log(avctx, AV_LOG_ERROR, Alternatively use the non experimental %s %s.\n,codec_string, codec2-name);ret AVERROR_EXPERIMENTAL;goto free_and_end;}if (avctx-codec_type AVMEDIA_TYPE_AUDIO (!avctx-time_base.num || !avctx-time_base.den)) {avctx-time_base.num 1;avctx-time_base.den avctx-sample_rate;}//检查输入参数是否符合【编码器】要求if (av_codec_is_encoder(avctx-codec))ret ff_encode_preinit(avctx);elseret ff_decode_preinit(avctx);if (ret 0)goto free_and_end;if (CONFIG_FRAME_THREAD_ENCODER av_codec_is_encoder(avctx-codec)) {ret ff_frame_thread_encoder_init(avctx);if (ret 0)goto free_and_end;}if (HAVE_THREADS !(avci-frame_thread_encoder (avctx-active_thread_typeFF_THREAD_FRAME))) {/* Frame-threaded decoders call FFCodec.init for their child contexts. */lock_avcodec(codec2);ret ff_thread_init(avctx);unlock_avcodec(codec2);if (ret 0) {goto free_and_end;}}if (!HAVE_THREADS !(codec2-caps_internal FF_CODEC_CAP_AUTO_THREADS))avctx-thread_count 1;if (!(avctx-active_thread_type FF_THREAD_FRAME) ||avci-frame_thread_encoder) {if (codec2-init) {lock_avcodec(codec2);ret codec2-init(avctx);unlock_avcodec(codec2);if (ret 0) {avci-needs_close codec2-caps_internal FF_CODEC_CAP_INIT_CLEANUP;goto free_and_end;}}avci-needs_close 1;}ret0;if (av_codec_is_decoder(avctx-codec)) {if (!avctx-bit_rate)avctx-bit_rate get_bit_rate(avctx);#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS/* update the deprecated fields for old-style callers */avctx-channels avctx-ch_layout.nb_channels;avctx-channel_layout avctx-ch_layout.order AV_CHANNEL_ORDER_NATIVE ?avctx-ch_layout.u.mask : 0;/* validate channel layout from the decoder */if (avctx-channel_layout) {int channels av_get_channel_layout_nb_channels(avctx-channel_layout);if (!avctx-channels)avctx-channels channels;else if (channels ! avctx-channels) {char buf[512];av_get_channel_layout_string(buf, sizeof(buf), -1, avctx-channel_layout);av_log(avctx, AV_LOG_WARNING,Channel layout %s with %d channels does not match specified number of channels %d: ignoring specified channel layout\n,buf, channels, avctx-channels);avctx-channel_layout 0;}}if (avctx-channels avctx-channels 0 ||avctx-channels FF_SANE_NB_CHANNELS) {ret AVERROR(EINVAL);goto free_and_end;}if (avctx-bits_per_coded_sample 0) {ret AVERROR(EINVAL);goto free_and_end;}
FF_ENABLE_DEPRECATION_WARNINGS
#endif#if FF_API_AVCTX_TIMEBASEif (avctx-framerate.num 0 avctx-framerate.den 0)avctx-time_base av_inv_q(av_mul_q(avctx-framerate, (AVRational){avctx-ticks_per_frame, 1}));
#endif}if (codec-priv_class)av_assert0(*(const AVClass **)avctx-priv_data codec-priv_class);end:return ret;
free_and_end:avcodec_close(avctx);goto end;
}
avcodec_open2()的源代码量是非常长的但是它的调用关系非常简单——它只调用了一个关键的函数即AVCodec的init()后文将会对这个函数进行分析。我们可以简单梳理一下avcodec_open2()所做的工作如下所列 1为各种结构体分配内存通过各种av_malloc()实现。2将输入的AVDictionary形式的选项设置到AVCodecContext。3其他一些零零碎碎的检查比如说检查编解码器是否处于“实验”阶段。4如果是编码器检查输入参数是否符合编码器的要求5调用AVCodec的init()初始化具体的解码器。
AVCodec-init()
avcodec_open2()中最关键的一步就是调用AVCodec的init()方法初始化具体的编码器。AVCodec的init()是一个函数指针指向具体编解码器中的初始化函数。这里我们以libx264为例看一下它对应的AVCodec的定义。libx264对应的AVCodec的定义位于libavcodec\libx264.c如下所示。
#if X264_BUILD 153
const
#endif
FFCodec ff_libx264_encoder {.p.name libx264,.p.long_name NULL_IF_CONFIG_SMALL(libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10),.p.type AVMEDIA_TYPE_VIDEO,.p.id AV_CODEC_ID_H264,.p.capabilities AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |AV_CODEC_CAP_OTHER_THREADS |AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,.p.priv_class x264_class,.p.wrapper_name libx264,.priv_data_size sizeof(X264Context),.init X264_init,FF_CODEC_ENCODE_CB(X264_frame),.close X264_close,.defaults x264_defaults,
#if X264_BUILD 153.init_static_data X264_init_static,
#else.p.pix_fmts pix_fmts_all,
#endif.caps_internal FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS
#if X264_BUILD 158| FF_CODEC_CAP_INIT_THREADSAFE
#endif,
};
#endif
可以看出在ff_libx264_encoder中init()指向X264_init()。X264_init()的定义同样位于libavcodec\libx264.c如下所示。
static av_cold int X264_init(AVCodecContext *avctx)
{X264Context *x4 avctx-priv_data;AVCPBProperties *cpb_props;int sw,sh;int ret;if (avctx-global_quality 0)av_log(avctx, AV_LOG_WARNING, -qscale is ignored, -crf is recommended.\n);#if CONFIG_LIBX262_ENCODERif (avctx-codec_id AV_CODEC_ID_MPEG2VIDEO) {x4-params.b_mpeg2 1;x264_param_default_mpeg2(x4-params);} else
#endifx264_param_default(x4-params);x4-params.b_deblocking_filter avctx-flags AV_CODEC_FLAG_LOOP_FILTER;if (x4-preset || x4-tune)if (x264_param_default_preset(x4-params, x4-preset, x4-tune) 0) {int i;av_log(avctx, AV_LOG_ERROR, Error setting preset/tune %s/%s.\n, x4-preset, x4-tune);av_log(avctx, AV_LOG_INFO, Possible presets:);for (i 0; x264_preset_names[i]; i)av_log(avctx, AV_LOG_INFO, %s, x264_preset_names[i]);av_log(avctx, AV_LOG_INFO, \n);av_log(avctx, AV_LOG_INFO, Possible tunes:);for (i 0; x264_tune_names[i]; i)av_log(avctx, AV_LOG_INFO, %s, x264_tune_names[i]);av_log(avctx, AV_LOG_INFO, \n);return AVERROR(EINVAL);}if (avctx-level 0)x4-params.i_level_idc avctx-level;x4-params.pf_log X264_log;x4-params.p_log_private avctx;x4-params.i_log_level X264_LOG_DEBUG;x4-params.i_csp convert_pix_fmt(avctx-pix_fmt);
#if X264_BUILD 153x4-params.i_bitdepth av_pix_fmt_desc_get(avctx-pix_fmt)-comp[0].depth;
#endifPARSE_X264_OPT(weightp, wpredp);if (avctx-bit_rate) {if (avctx-bit_rate / 1000 INT_MAX || avctx-rc_max_rate / 1000 INT_MAX) {av_log(avctx, AV_LOG_ERROR, bit_rate and rc_max_rate %d000 not supported by libx264\n, INT_MAX);return AVERROR(EINVAL);}x4-params.rc.i_bitrate avctx-bit_rate / 1000;x4-params.rc.i_rc_method X264_RC_ABR;}x4-params.rc.i_vbv_buffer_size avctx-rc_buffer_size / 1000;x4-params.rc.i_vbv_max_bitrate avctx-rc_max_rate / 1000;x4-params.rc.b_stat_write avctx-flags AV_CODEC_FLAG_PASS1;if (avctx-flags AV_CODEC_FLAG_PASS2) {x4-params.rc.b_stat_read 1;} else {if (x4-crf 0) {x4-params.rc.i_rc_method X264_RC_CRF;x4-params.rc.f_rf_constant x4-crf;} else if (x4-cqp 0) {x4-params.rc.i_rc_method X264_RC_CQP;x4-params.rc.i_qp_constant x4-cqp;}if (x4-crf_max 0)x4-params.rc.f_rf_constant_max x4-crf_max;}if (avctx-rc_buffer_size avctx-rc_initial_buffer_occupancy 0 (avctx-rc_initial_buffer_occupancy avctx-rc_buffer_size)) {x4-params.rc.f_vbv_buffer_init (float)avctx-rc_initial_buffer_occupancy / avctx-rc_buffer_size;}PARSE_X264_OPT(level, level);if (avctx-i_quant_factor 0)x4-params.rc.f_ip_factor 1 / fabs(avctx-i_quant_factor);if (avctx-b_quant_factor 0)x4-params.rc.f_pb_factor avctx-b_quant_factor;if (x4-chroma_offset)x4-params.analyse.i_chroma_qp_offset x4-chroma_offset;if (avctx-gop_size 0)x4-params.i_keyint_max avctx-gop_size;if (avctx-max_b_frames 0)x4-params.i_bframe avctx-max_b_frames;if (x4-scenechange_threshold 0)x4-params.i_scenecut_threshold x4-scenechange_threshold;if (avctx-qmin 0)x4-params.rc.i_qp_min avctx-qmin;if (avctx-qmax 0)x4-params.rc.i_qp_max avctx-qmax;if (avctx-max_qdiff 0)x4-params.rc.i_qp_step avctx-max_qdiff;if (avctx-qblur 0)x4-params.rc.f_qblur avctx-qblur; /* temporally blur quants */if (avctx-qcompress 0)x4-params.rc.f_qcompress avctx-qcompress; /* 0.0 cbr, 1.0 constant qp */if (avctx-refs 0)x4-params.i_frame_reference avctx-refs;else if (x4-params.i_level_idc 0) {int i;int mbn AV_CEIL_RSHIFT(avctx-width, 4) * AV_CEIL_RSHIFT(avctx-height, 4);int scale X264_BUILD 129 ? 384 : 1;for (i 0; ix264_levels[i].level_idc; i)if (x264_levels[i].level_idc x4-params.i_level_idc)x4-params.i_frame_reference av_clip(x264_levels[i].dpb / mbn / scale, 1, x4-params.i_frame_reference);}if (avctx-trellis 0)x4-params.analyse.i_trellis avctx-trellis;if (avctx-me_range 0)x4-params.analyse.i_me_range avctx-me_range;if (x4-noise_reduction 0)x4-params.analyse.i_noise_reduction x4-noise_reduction;if (avctx-me_subpel_quality 0)x4-params.analyse.i_subpel_refine avctx-me_subpel_quality;if (avctx-keyint_min 0)x4-params.i_keyint_min avctx-keyint_min;if (avctx-me_cmp 0)x4-params.analyse.b_chroma_me avctx-me_cmp FF_CMP_CHROMA;if (x4-aq_mode 0)x4-params.rc.i_aq_mode x4-aq_mode;if (x4-aq_strength 0)x4-params.rc.f_aq_strength x4-aq_strength;PARSE_X264_OPT(psy-rd, psy_rd);PARSE_X264_OPT(deblock, deblock);PARSE_X264_OPT(partitions, partitions);PARSE_X264_OPT(stats, stats);if (x4-psy 0)x4-params.analyse.b_psy x4-psy;if (x4-rc_lookahead 0)x4-params.rc.i_lookahead x4-rc_lookahead;if (x4-weightp 0)x4-params.analyse.i_weighted_pred x4-weightp;if (x4-weightb 0)x4-params.analyse.b_weighted_bipred x4-weightb;if (x4-cplxblur 0)x4-params.rc.f_complexity_blur x4-cplxblur;if (x4-ssim 0)x4-params.analyse.b_ssim x4-ssim;if (x4-intra_refresh 0)x4-params.b_intra_refresh x4-intra_refresh;if (x4-bluray_compat 0) {x4-params.b_bluray_compat x4-bluray_compat;x4-params.b_vfr_input 0;}if (x4-avcintra_class 0)
#if X264_BUILD 142x4-params.i_avcintra_class x4-avcintra_class;
#elseav_log(avctx, AV_LOG_ERROR,x264 too old for AVC Intra, at least version 142 needed\n);
#endifif (x4-avcintra_class 200) {
#if X264_BUILD 164av_log(avctx, AV_LOG_ERROR,x264 too old for AVC Intra 300/480, at least version 164 needed\n);return AVERROR(EINVAL);
#else/* AVC-Intra 300/480 only supported by Sony XAVC flavor */x4-params.i_avcintra_flavor X264_AVCINTRA_FLAVOR_SONY;
#endif}if (x4-b_bias ! INT_MIN)x4-params.i_bframe_bias x4-b_bias;if (x4-b_pyramid 0)x4-params.i_bframe_pyramid x4-b_pyramid;if (x4-mixed_refs 0)x4-params.analyse.b_mixed_references x4-mixed_refs;if (x4-dct8x8 0)x4-params.analyse.b_transform_8x8 x4-dct8x8;if (x4-fast_pskip 0)x4-params.analyse.b_fast_pskip x4-fast_pskip;if (x4-aud 0)x4-params.b_aud x4-aud;if (x4-mbtree 0)x4-params.rc.b_mb_tree x4-mbtree;if (x4-direct_pred 0)x4-params.analyse.i_direct_mv_pred x4-direct_pred;if (x4-slice_max_size 0)x4-params.i_slice_max_size x4-slice_max_size;if (x4-fastfirstpass)x264_param_apply_fastfirstpass(x4-params);/* Allow specifying the x264 profile through AVCodecContext. */if (!x4-profile)switch (avctx-profile) {case FF_PROFILE_H264_BASELINE:x4-profile av_strdup(baseline);break;case FF_PROFILE_H264_HIGH:x4-profile av_strdup(high);break;case FF_PROFILE_H264_HIGH_10:x4-profile av_strdup(high10);break;case FF_PROFILE_H264_HIGH_422:x4-profile av_strdup(high422);break;case FF_PROFILE_H264_HIGH_444:x4-profile av_strdup(high444);break;case FF_PROFILE_H264_MAIN:x4-profile av_strdup(main);break;default:break;}if (x4-nal_hrd 0)x4-params.i_nal_hrd x4-nal_hrd;if (x4-motion_est 0)x4-params.analyse.i_me_method x4-motion_est;if (x4-coder 0)x4-params.b_cabac x4-coder;if (x4-b_frame_strategy 0)x4-params.i_bframe_adaptive x4-b_frame_strategy;if (x4-profile)if (x264_param_apply_profile(x4-params, x4-profile) 0) {int i;av_log(avctx, AV_LOG_ERROR, Error setting profile %s.\n, x4-profile);av_log(avctx, AV_LOG_INFO, Possible profiles:);for (i 0; x264_profile_names[i]; i)av_log(avctx, AV_LOG_INFO, %s, x264_profile_names[i]);av_log(avctx, AV_LOG_INFO, \n);return AVERROR(EINVAL);}x4-params.i_width avctx-width;x4-params.i_height avctx-height;av_reduce(sw, sh, avctx-sample_aspect_ratio.num, avctx-sample_aspect_ratio.den, 4096);x4-params.vui.i_sar_width sw;x4-params.vui.i_sar_height sh;x4-params.i_timebase_den avctx-time_base.den;x4-params.i_timebase_num avctx-time_base.num;if (avctx-framerate.num 0 avctx-framerate.den 0) {x4-params.i_fps_num avctx-framerate.num;x4-params.i_fps_den avctx-framerate.den;} else {x4-params.i_fps_num avctx-time_base.den;x4-params.i_fps_den avctx-time_base.num * avctx-ticks_per_frame;}x4-params.analyse.b_psnr avctx-flags AV_CODEC_FLAG_PSNR;x4-params.i_threads avctx-thread_count;if (avctx-thread_type)x4-params.b_sliced_threads avctx-thread_type FF_THREAD_SLICE;x4-params.b_interlaced avctx-flags AV_CODEC_FLAG_INTERLACED_DCT;x4-params.b_open_gop !(avctx-flags AV_CODEC_FLAG_CLOSED_GOP);x4-params.i_slice_count avctx-slices;if (avctx-color_range ! AVCOL_RANGE_UNSPECIFIED)x4-params.vui.b_fullrange avctx-color_range AVCOL_RANGE_JPEG;else if (avctx-pix_fmt AV_PIX_FMT_YUVJ420P ||avctx-pix_fmt AV_PIX_FMT_YUVJ422P ||avctx-pix_fmt AV_PIX_FMT_YUVJ444P)x4-params.vui.b_fullrange 1;if (avctx-colorspace ! AVCOL_SPC_UNSPECIFIED)x4-params.vui.i_colmatrix avctx-colorspace;if (avctx-color_primaries ! AVCOL_PRI_UNSPECIFIED)x4-params.vui.i_colorprim avctx-color_primaries;if (avctx-color_trc ! AVCOL_TRC_UNSPECIFIED)x4-params.vui.i_transfer avctx-color_trc;if (avctx-chroma_sample_location ! AVCHROMA_LOC_UNSPECIFIED)x4-params.vui.i_chroma_loc avctx-chroma_sample_location - 1;if (avctx-flags AV_CODEC_FLAG_GLOBAL_HEADER)x4-params.b_repeat_headers 0;if(x4-x264opts){const char *p x4-x264opts;while(p){char param[4096]{0}, val[4096]{0};if(sscanf(p, %4095[^:]%4095[^:], param, val) 1){ret parse_opts(avctx, param, 1);if (ret 0)return ret;} else {ret parse_opts(avctx, param, val);if (ret 0)return ret;}p strchr(p, :);p!!p;}}#if X264_BUILD 142/* Separate headers not supported in AVC-Intra mode */if (x4-avcintra_class 0)x4-params.b_repeat_headers 1;
#endif{AVDictionaryEntry *en NULL;while (en av_dict_get(x4-x264_params, , en, AV_DICT_IGNORE_SUFFIX)) {if ((ret x264_param_parse(x4-params, en-key, en-value)) 0) {av_log(avctx, AV_LOG_WARNING,Error parsing option %s %s.\n,en-key, en-value);
#if X264_BUILD 161if (ret X264_PARAM_ALLOC_FAILED)return AVERROR(ENOMEM);
#endif}}}// update AVCodecContext with x264 parametersavctx-has_b_frames x4-params.i_bframe ?x4-params.i_bframe_pyramid ? 2 : 1 : 0;if (avctx-max_b_frames 0)avctx-max_b_frames 0;avctx-bit_rate x4-params.rc.i_bitrate*1000LL;x4-enc x264_encoder_open(x4-params);if (!x4-enc)return AVERROR_EXTERNAL;if (avctx-flags AV_CODEC_FLAG_GLOBAL_HEADER) {x264_nal_t *nal;uint8_t *p;int nnal, s, i;s x264_encoder_headers(x4-enc, nal, nnal);avctx-extradata p av_mallocz(s AV_INPUT_BUFFER_PADDING_SIZE);if (!p)return AVERROR(ENOMEM);for (i 0; i nnal; i) {/* Dont put the SEI in extradata. */if (nal[i].i_type NAL_SEI) {av_log(avctx, AV_LOG_INFO, %s\n, nal[i].p_payload25);x4-sei_size nal[i].i_payload;x4-sei av_malloc(x4-sei_size);if (!x4-sei)return AVERROR(ENOMEM);memcpy(x4-sei, nal[i].p_payload, nal[i].i_payload);continue;}memcpy(p, nal[i].p_payload, nal[i].i_payload);p nal[i].i_payload;}avctx-extradata_size p - avctx-extradata;}cpb_props ff_add_cpb_side_data(avctx);if (!cpb_props)return AVERROR(ENOMEM);cpb_props-buffer_size x4-params.rc.i_vbv_buffer_size * 1000;cpb_props-max_bitrate x4-params.rc.i_vbv_max_bitrate * 1000LL;cpb_props-avg_bitrate x4-params.rc.i_bitrate * 1000LL;// Overestimate the reordered opaque buffer size, in case a runtime// reconfigure would increase the delay (which it shouldnt).x4-nb_reordered_opaque x264_encoder_maximum_delayed_frames(x4-enc) 17;x4-reordered_opaque av_malloc_array(x4-nb_reordered_opaque,sizeof(*x4-reordered_opaque));if (!x4-reordered_opaque)return AVERROR(ENOMEM);return 0;
}
X264_init()的代码的两项工作1设置X264Context的参数。X264Context主要完成了libx264和FFmpeg对接的功能。可以看出代码主要在设置一个params结构体变量该变量的类型即是x264中存储参数的结构体x264_param_t。2调用libx264的API进行编码器的初始化工作。例如调用x264_param_default()设置默认参数调用x264_param_apply_profile()设置profile调用x264_encoder_open()打开编码器等等。最后附上X264Context的定义位于libavcodec\libx264.c如下所示。typedef struct X264Context {AVClass *class;x264_param_t params;x264_t *enc;x264_picture_t pic;uint8_t *sei;int sei_size;char *preset;char *tune;char *profile;char *level;int fastfirstpass;char *wpredp;char *x264opts;float crf;float crf_max;int cqp;int aq_mode;float aq_strength;char *psy_rd;int psy;int rc_lookahead;int weightp;int weightb;int ssim;int intra_refresh;int bluray_compat;int b_bias;int b_pyramid;int mixed_refs;int dct8x8;int fast_pskip;int aud;int mbtree;char *deblock;float cplxblur;char *partitions;int direct_pred;int slice_max_size;char *stats;int nal_hrd;int avcintra_class;int motion_est;int forced_idr;int coder;int a53_cc;int b_frame_strategy;int chroma_offset;int scenechange_threshold;int noise_reduction;int udu_sei;AVDictionary *x264_params;int nb_reordered_opaque, next_reordered_opaque;X264Opaque *reordered_opaque;/*** If the encoder does not support ROI then warn the first time we* encounter a frame with ROI side data.*/int roi_warned;
} X264Context;