📄 encoder.c
字号:
if( h->param.rc.i_rc_method < 0 || h->param.rc.i_rc_method > 2 ) { x264_log( h, X264_LOG_ERROR, "no ratecontrol method specified\n" ); return -1; } h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, 0, 51 ); h->param.rc.i_qp_constant = x264_clip3( h->param.rc.i_qp_constant, 0, 51 ); if( h->param.rc.i_rc_method == X264_RC_CRF ) h->param.rc.i_qp_constant = h->param.rc.f_rf_constant; if( (h->param.rc.i_rc_method == X264_RC_CQP || h->param.rc.i_rc_method == X264_RC_CRF) && h->param.rc.i_qp_constant == 0 ) { h->mb.b_lossless = 1; h->param.i_cqm_preset = X264_CQM_FLAT; h->param.psz_cqm_file = NULL; h->param.rc.i_rc_method = X264_RC_CQP; h->param.rc.f_ip_factor = 1; h->param.rc.f_pb_factor = 1; h->param.analyse.b_transform_8x8 = 0; h->param.analyse.b_psnr = 0; h->param.analyse.b_ssim = 0; h->param.analyse.i_chroma_qp_offset = 0; h->param.analyse.i_trellis = 0; h->param.analyse.b_fast_pskip = 0; h->param.analyse.i_noise_reduction = 0; h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 6 ); } if( h->param.rc.i_rc_method == X264_RC_CQP ) { float qp_p = h->param.rc.i_qp_constant; float qp_i = qp_p - 6*log(h->param.rc.f_ip_factor)/log(2); float qp_b = qp_p + 6*log(h->param.rc.f_pb_factor)/log(2); h->param.rc.i_qp_min = x264_clip3( (int)(X264_MIN3( qp_p, qp_i, qp_b )), 0, 51 ); h->param.rc.i_qp_max = x264_clip3( (int)(X264_MAX3( qp_p, qp_i, qp_b ) + .999), 0, 51 ); } if( ( h->param.i_width % 16 || h->param.i_height % 16 ) && h->param.i_height != 1080 && !h->mb.b_lossless ) { // There's nothing special about 1080 in that the warning still applies to it, // but chances are the user can't help it if his content is already 1080p, // so there's no point in warning in that case. x264_log( h, X264_LOG_WARNING, "width or height not divisible by 16 (%dx%d), compression will suffer.\n", h->param.i_width, h->param.i_height ); } h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, 16 ); if( h->param.i_keyint_max <= 0 ) h->param.i_keyint_max = 1; h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 ); h->param.i_bframe = x264_clip3( h->param.i_bframe, 0, X264_BFRAME_MAX ); h->param.i_bframe_bias = x264_clip3( h->param.i_bframe_bias, -90, 100 ); h->param.b_bframe_pyramid = h->param.b_bframe_pyramid && h->param.i_bframe > 1; h->param.b_bframe_adaptive = h->param.b_bframe_adaptive && h->param.i_bframe > 0; h->param.analyse.b_weighted_bipred = h->param.analyse.b_weighted_bipred && h->param.i_bframe > 0; h->mb.b_direct_auto_write = h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO && h->param.i_bframe && ( h->param.rc.b_stat_write || !h->param.rc.b_stat_read ); if( h->param.i_scenecut_threshold < 0 ) h->param.b_pre_scenecut = 0; h->param.i_deblocking_filter_alphac0 = x264_clip3( h->param.i_deblocking_filter_alphac0, -6, 6 ); h->param.i_deblocking_filter_beta = x264_clip3( h->param.i_deblocking_filter_beta, -6, 6 ); h->param.analyse.i_luma_deadzone[0] = x264_clip3( h->param.analyse.i_luma_deadzone[0], 0, 32 ); h->param.analyse.i_luma_deadzone[1] = x264_clip3( h->param.analyse.i_luma_deadzone[1], 0, 32 ); h->param.i_cabac_init_idc = x264_clip3( h->param.i_cabac_init_idc, 0, 2 ); if( h->param.i_cqm_preset < X264_CQM_FLAT || h->param.i_cqm_preset > X264_CQM_CUSTOM ) h->param.i_cqm_preset = X264_CQM_FLAT; if( h->param.analyse.i_me_method < X264_ME_DIA || h->param.analyse.i_me_method > X264_ME_ESA ) h->param.analyse.i_me_method = X264_ME_HEX; if( h->param.analyse.i_me_range < 4 ) h->param.analyse.i_me_range = 4; if( h->param.analyse.i_me_range > 16 && h->param.analyse.i_me_method <= X264_ME_HEX ) h->param.analyse.i_me_range = 16; h->param.analyse.i_subpel_refine = x264_clip3( h->param.analyse.i_subpel_refine, 1, 7 ); h->param.analyse.b_bframe_rdo = h->param.analyse.b_bframe_rdo && h->param.analyse.i_subpel_refine >= 6; h->param.analyse.b_mixed_references = h->param.analyse.b_mixed_references && h->param.i_frame_reference > 1; h->param.analyse.inter &= X264_ANALYSE_PSUB16x16|X264_ANALYSE_PSUB8x8|X264_ANALYSE_BSUB16x16| X264_ANALYSE_I4x4|X264_ANALYSE_I8x8; h->param.analyse.intra &= X264_ANALYSE_I4x4|X264_ANALYSE_I8x8; if( !(h->param.analyse.inter & X264_ANALYSE_PSUB16x16) ) h->param.analyse.inter &= ~X264_ANALYSE_PSUB8x8; if( !h->param.analyse.b_transform_8x8 ) { h->param.analyse.inter &= ~X264_ANALYSE_I8x8; h->param.analyse.intra &= ~X264_ANALYSE_I8x8; } h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -12, 12); if( !h->param.b_cabac ) h->param.analyse.i_trellis = 0; h->param.analyse.i_trellis = x264_clip3( h->param.analyse.i_trellis, 0, 2 ); h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 ); { const x264_level_t *l = x264_levels; while( l->level_idc != 0 && l->level_idc != h->param.i_level_idc ) l++; if( l->level_idc == 0 ) { x264_log( h, X264_LOG_ERROR, "invalid level_idc: %d\n", h->param.i_level_idc ); return -1; } if( h->param.analyse.i_mv_range <= 0 ) h->param.analyse.i_mv_range = l->mv_range; else h->param.analyse.i_mv_range = x264_clip3(h->param.analyse.i_mv_range, 32, 512); if( h->param.analyse.i_direct_8x8_inference < 0 ) h->param.analyse.i_direct_8x8_inference = l->direct8x8; } if( h->param.i_threads > 1 ) { int r = h->param.analyse.i_mv_range_thread; int r2; if( r <= 0 ) { // half of the available space is reserved and divided evenly among the threads, // the rest is allocated to whichever thread is far enough ahead to use it. // reserving more space increases quality for some videos, but costs more time // in thread synchronization. int max_range = (h->param.i_height + X264_THREAD_HEIGHT) / h->param.i_threads - X264_THREAD_HEIGHT; r = max_range / 2; } r = X264_MAX( r, h->param.analyse.i_me_range ); r = X264_MIN( r, h->param.analyse.i_mv_range ); // round up to use the whole mb row r2 = (r & ~15) + ((-X264_THREAD_HEIGHT) & 15); if( r2 < r ) r2 += 16; x264_log( h, X264_LOG_DEBUG, "using mv_range_thread = %d\n", r2 ); h->param.analyse.i_mv_range_thread = r2; } if( h->param.rc.f_qblur < 0 ) h->param.rc.f_qblur = 0; if( h->param.rc.f_complexity_blur < 0 ) h->param.rc.f_complexity_blur = 0; h->param.i_sps_id &= 31; if( h->param.i_log_level < X264_LOG_INFO ) { h->param.analyse.b_psnr = 0; h->param.analyse.b_ssim = 0; } /* ensure the booleans are 0 or 1 so they can be used in math */#define BOOLIFY(x) h->param.x = !!h->param.x BOOLIFY( b_cabac ); BOOLIFY( b_deblocking_filter ); BOOLIFY( b_interlaced ); BOOLIFY( analyse.b_transform_8x8 ); BOOLIFY( analyse.i_direct_8x8_inference ); BOOLIFY( analyse.b_bidir_me ); BOOLIFY( analyse.b_chroma_me ); BOOLIFY( analyse.b_fast_pskip ); BOOLIFY( rc.b_stat_write ); BOOLIFY( rc.b_stat_read );#undef BOOLIFY return 0;}static void mbcmp_init( x264_t *h ){ memcpy( h->pixf.mbcmp, ( h->mb.b_lossless || h->param.analyse.i_subpel_refine <= 1 ) ? h->pixf.sad : h->pixf.satd, sizeof(h->pixf.mbcmp) );}/**************************************************************************** * x264_encoder_open: ****************************************************************************/x264_t *x264_encoder_open ( x264_param_t *param ){ x264_t *h = x264_malloc( sizeof( x264_t ) ); int i; memset( h, 0, sizeof( x264_t ) ); /* Create a copy of param */ memcpy( &h->param, param, sizeof( x264_param_t ) ); if( x264_validate_parameters( h ) < 0 ) { x264_free( h ); return NULL; } if( h->param.psz_cqm_file ) if( x264_cqm_parse_file( h, h->param.psz_cqm_file ) < 0 ) { x264_free( h ); return NULL; } if( h->param.rc.psz_stat_out ) h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out ); if( h->param.rc.psz_stat_in ) h->param.rc.psz_stat_in = strdup( h->param.rc.psz_stat_in ); if( h->param.rc.psz_rc_eq ) h->param.rc.psz_rc_eq = strdup( h->param.rc.psz_rc_eq ); /* VUI */ if( h->param.vui.i_sar_width > 0 && h->param.vui.i_sar_height > 0 ) { int i_w = param->vui.i_sar_width; int i_h = param->vui.i_sar_height; x264_reduce_fraction( &i_w, &i_h ); while( i_w > 65535 || i_h > 65535 ) { i_w /= 2; i_h /= 2; } h->param.vui.i_sar_width = 0; h->param.vui.i_sar_height = 0; if( i_w == 0 || i_h == 0 ) { x264_log( h, X264_LOG_WARNING, "cannot create valid sample aspect ratio\n" ); } else { x264_log( h, X264_LOG_INFO, "using SAR=%d/%d\n", i_w, i_h ); h->param.vui.i_sar_width = i_w; h->param.vui.i_sar_height = i_h; } } x264_reduce_fraction( &h->param.i_fps_num, &h->param.i_fps_den ); /* Init x264_t */ h->i_frame = 0; h->i_frame_num = 0; h->i_idr_pic_id = 0; h->sps = &h->sps_array[0]; x264_sps_init( h->sps, h->param.i_sps_id, &h->param ); h->pps = &h->pps_array[0]; x264_pps_init( h->pps, h->param.i_sps_id, &h->param, h->sps); x264_validate_levels( h ); if( x264_cqm_init( h ) < 0 ) { x264_free( h ); return NULL; } h->mb.i_mb_count = h->sps->i_mb_width * h->sps->i_mb_height; /* Init frames. */ h->frames.i_delay = h->param.i_bframe + h->param.i_threads - 1; h->frames.i_max_ref0 = h->param.i_frame_reference; h->frames.i_max_ref1 = h->sps->vui.i_num_reorder_frames; h->frames.i_max_dpb = h->sps->vui.i_max_dec_frame_buffering; h->frames.b_have_lowres = !h->param.rc.b_stat_read && ( h->param.rc.i_rc_method == X264_RC_ABR || h->param.rc.i_rc_method == X264_RC_CRF || h->param.b_bframe_adaptive || h->param.b_pre_scenecut ); h->frames.i_last_idr = - h->param.i_keyint_max; h->frames.i_input = 0; h->frames.last_nonb = NULL; h->i_ref0 = 0; h->i_ref1 = 0; x264_rdo_init( ); /* init CPU functions */ x264_predict_16x16_init( h->param.cpu, h->predict_16x16 ); x264_predict_8x8c_init( h->param.cpu, h->predict_8x8c ); x264_predict_8x8_init( h->param.cpu, h->predict_8x8 ); x264_predict_4x4_init( h->param.cpu, h->predict_4x4 ); x264_pixel_init( h->param.cpu, &h->pixf ); x264_dct_init( h->param.cpu, &h->dctf ); x264_zigzag_init( h->param.cpu, &h->zigzagf, h->param.b_interlaced ); x264_mc_init( h->param.cpu, &h->mc ); x264_csp_init( h->param.cpu, h->param.i_csp, &h->csp ); x264_quant_init( h, h->param.cpu, &h->quantf ); x264_deblock_init( h->param.cpu, &h->loopf ); x264_dct_init_weights(); mbcmp_init( h ); x264_log( h, X264_LOG_INFO, "using cpu capabilities: %s%s%s%s%s%s%s%s\n", param->cpu&X264_CPU_MMX ? "MMX " : "", param->cpu&X264_CPU_MMXEXT ? "MMXEXT " : "", param->cpu&X264_CPU_SSE ? "SSE " : "", param->cpu&X264_CPU_SSE2 ? "SSE2 " : "", param->cpu&X264_CPU_SSSE3 ? "SSSE3 " : "", param->cpu&X264_CPU_3DNOW ? "3DNow! " : "", param->cpu&X264_CPU_ALTIVEC ? "Altivec " : "", param->cpu ? "" : "none!" ); h->out.i_nal = 0; h->out.i_bitstream = X264_MAX( 1000000, h->param.i_width * h->param.i_height * 4 * ( h->param.rc.i_rc_method == X264_RC_ABR ? pow( 0.95, h->param.rc.i_qp_min ) : pow( 0.95, h->param.rc.i_qp_constant ) * X264_MAX( 1, h->param.rc.f_ip_factor ))); h->thread[0] = h; h->i_thread_num = 0; for( i = 1; i < h->param.i_threads; i++ ) h->thread[i] = x264_malloc( sizeof(x264_t) ); for( i = 0; i < h->param.i_threads; i++ ) { if( i > 0 ) *h->thread[i] = *h; h->thread[i]->fdec = x264_frame_pop_unused( h ); h->thread[i]->out.p_bitstream = x264_malloc( h->out.i_bitstream ); if( x264_macroblock_cache_init( h->thread[i] ) < 0 ) return NULL; } if( x264_ratecontrol_new( h ) < 0 ) return NULL;#ifdef DEBUG_DUMP_FRAME { /* create or truncate the reconstructed video file */ FILE *f = fopen( "fdec.yuv", "w" ); if( f ) fclose( f ); else { x264_log( h, X264_LOG_ERROR, "can't write to fdec.yuv\n" ); x264_free( h ); return NULL; } }#endif return h;}/**************************************************************************** * x264_encoder_reconfig: ****************************************************************************/int x264_encoder_reconfig( x264_t *h, x264_param_t *param ){#define COPY(var) h->param.var = param->var COPY( i_frame_reference ); // but never uses more refs than initially specified COPY( i_bframe_bias ); if( h->param.i_scenecut_threshold >= 0 && param->i_scenecut_threshold >= 0 ) COPY( i_scenecut_threshold ); // can't turn it on or off, only vary the threshold COPY( b_deblocking_filter ); COPY( i_deblocking_filter_alphac0 ); COPY( i_deblocking_filter_beta ); COPY( analyse.intra ); COPY( analyse.inter ); COPY( analyse.i_direct_mv_pred ); COPY( analyse.i_me_method ); COPY( analyse.i_me_range ); COPY( analyse.i_noise_reduction ); COPY( analyse.i_subpel_refine ); COPY( analyse.i_trellis ); COPY( analyse.b_bidir_me ); COPY( analyse.b_bframe_rdo ); COPY( analyse.b_chroma_me ); COPY( analyse.b_dct_decimate ); COPY( analyse.b_fast_pskip ); COPY( analyse.b_mixed_references );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -