summaryrefslogtreecommitdiffstats
path: root/libhb/encx264.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/encx264.c')
-rw-r--r--libhb/encx264.c622
1 files changed, 620 insertions, 2 deletions
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 2da886a68..7a3aed270 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -273,7 +273,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
}
/* Apply profile and level settings last, if present. */
- if (job->x264_profile != NULL)
+ if (job->x264_profile != NULL && *job->x264_profile)
{
if (x264_param_apply_profile(&param, job->x264_profile))
{
@@ -282,7 +282,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
return 1;
}
}
- if (job->h264_level != NULL)
+ if (job->h264_level != NULL && *job->h264_level)
{
if (hb_apply_h264_level(&param, job->h264_level,
job->x264_profile, 0) < 0)
@@ -882,6 +882,624 @@ int hb_apply_h264_level(x264_param_t *param, const char *h264_level,
return ret;
}
+char * hb_x264_param_unparse( const char * x264_preset,
+ const char * x264_tune,
+ const char * x264_encopts,
+ const char * x264_profile,
+ const char * h264_level,
+ int width, int height )
+{
+ int i;
+ char buf[32];
+ char * unparsed_opts;
+ hb_dict_t * x264_opts;
+ hb_dict_entry_t * entry;
+ x264_param_t defaults, param;
+
+ /* get the global x264 defaults (what we compare against) */
+ x264_param_default( &defaults );
+
+ /* apply the defaults, preset and tune */
+ if( x264_param_default_preset( &param, x264_preset, x264_tune ) < 0 )
+ {
+ // Note: GUIs should be able to always specifiy valid preset/tunes, so
+ // this code will hopefully never be reached
+ return strdup( "hb_x264_param_unparse: invalid x264 preset/tune" );
+ }
+
+ /* apply the additional advanced x264 options */
+ entry = NULL;
+ x264_opts = hb_encopts_to_dict( x264_encopts, HB_VCODEC_X264 );
+ while( ( entry = hb_dict_next( x264_opts, entry ) ) )
+ {
+ // no need to pollute the log with x264_param_parse return codes
+ x264_param_parse( &param, entry->key, entry->value );
+ }
+
+ /* apply the x264 profile */
+ if( x264_profile && *x264_profile )
+ {
+ if( x264_param_apply_profile( &param, x264_profile ) < 0 )
+ {
+ /* Note: x264_param_apply_profile can bail even when the specified
+ * profile is valid, for example when:
+ * 1) profile is baseline and interlaced is set
+ * 2) profile is not high444 and lossless is set
+ * so this can happen even when calling hb_x264_param_unparse from a
+ * GUI - maybe we should sanitize settings before calling
+ * x264_param_apply_profile? */
+ hb_dict_free( &x264_opts );
+ return strdup( "hb_x264_param_unparse: could not apply x264 profile" );
+ }
+ }
+
+ if (h264_level != NULL && h264_level[0])
+ {
+ /* apply the h264 level */
+ // set width & height to avoid issues in hb_apply_h264_level
+ param.i_width = width;
+ param.i_height = height;
+ hb_apply_h264_level( &param, h264_level, x264_profile, 0 );
+ }
+
+ /* if x264_encopts is NULL, x264_opts wasn't initialized */
+ if( !x264_opts )
+ {
+ // we may have to unparse quite a few options
+ x264_opts = hb_dict_init( 20 );
+ if( !x264_opts )
+ {
+ return strdup( "hb_x264_param_unparse: could not initialize hb_dict_t" );
+ }
+ }
+
+ /* x264 lets you specify some options in multiple ways. For options that we
+ * do unparse, clear the forms that don't match how we unparse said option
+ * from the x264_opts dictionary.
+ *
+ * actual synonyms are already handled by hb_encopts_to_dict().
+ *
+ * "no-deblock" is a special case as it can't be unparsed to "deblock=0"
+ *
+ * also, don't bother with forms that aren't allowed by the x264 CLI, such
+ * as "no-bframes" - there are too many. */
+ hb_dict_unset( &x264_opts, "no-sliced-threads" );
+ hb_dict_unset( &x264_opts, "no-scenecut" );
+ hb_dict_unset( &x264_opts, "no-b-adapt" );
+ hb_dict_unset( &x264_opts, "no-weightb" );
+ hb_dict_unset( &x264_opts, "no-cabac" );
+ hb_dict_unset( &x264_opts, "interlaced" ); // we unparse to tff/bff
+ hb_dict_unset( &x264_opts, "no-interlaced" );
+ hb_dict_unset( &x264_opts, "no-8x8dct" );
+ hb_dict_unset( &x264_opts, "no-mixed-refs" );
+ hb_dict_unset( &x264_opts, "no-fast-pskip" );
+ hb_dict_unset( &x264_opts, "no-dct-decimate" );
+ hb_dict_unset( &x264_opts, "no-psy" );
+ hb_dict_unset( &x264_opts, "no-mbtree" );
+
+ /* compare defaults to param and unparse to the x264_opts dictionary */
+ if( !param.b_sliced_threads != !defaults.b_sliced_threads )
+ {
+ // can be modified by: tune zerolatency
+ sprintf( buf, "%d", !!param.b_sliced_threads );
+ hb_dict_set( &x264_opts, "sliced-threads", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "sliced-threads" );
+ }
+ if( param.i_sync_lookahead != defaults.i_sync_lookahead )
+ {
+ // can be modified by: tune zerolatency
+ sprintf( buf, "%d", param.i_sync_lookahead );
+ hb_dict_set( &x264_opts, "sync-lookahead", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "sync-lookahead" );
+ }
+ if( param.i_level_idc != defaults.i_level_idc )
+ {
+ // can be modified by: level
+ for( i = 0; hb_h264_level_values[i]; i++ )
+ if( param.i_level_idc == hb_h264_level_values[i] )
+ hb_dict_set( &x264_opts, "level", hb_h264_level_names[i] );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "level" );
+ }
+ if( param.i_frame_reference != defaults.i_frame_reference )
+ {
+ // can be modified by: presets, tunes, level
+ sprintf( buf, "%d", param.i_frame_reference );
+ hb_dict_set( &x264_opts, "ref", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "ref" );
+ }
+ if( param.i_scenecut_threshold != defaults.i_scenecut_threshold )
+ {
+ // can be modified by: preset ultrafast
+ sprintf( buf, "%d", param.i_scenecut_threshold );
+ hb_dict_set( &x264_opts, "scenecut", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "scenecut" );
+ }
+ if( param.i_bframe != defaults.i_bframe )
+ {
+ // can be modified by: presets, tunes, profile, level
+ sprintf( buf, "%d", param.i_bframe );
+ hb_dict_set( &x264_opts, "bframes", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "bframes" );
+ }
+ if( param.i_bframe > 0 )
+ {
+ if( param.i_bframe_adaptive != defaults.i_bframe_adaptive )
+ {
+ // can be modified by: presets
+ sprintf( buf, "%d", param.i_bframe_adaptive );
+ hb_dict_set( &x264_opts, "b-adapt", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "b-adapt" );
+ }
+ if( param.i_bframe > 1 &&
+ param.i_bframe_pyramid != defaults.i_bframe_pyramid )
+ {
+ // can be modified by: level
+ if( param.i_bframe_pyramid < X264_B_PYRAMID_NONE )
+ param.i_bframe_pyramid = X264_B_PYRAMID_NONE;
+ if( param.i_bframe_pyramid > X264_B_PYRAMID_NORMAL )
+ param.i_bframe_pyramid = X264_B_PYRAMID_NORMAL;
+ for( i = 0; x264_b_pyramid_names[i]; i++ )
+ if( param.i_bframe_pyramid == i )
+ hb_dict_set( &x264_opts, "b-pyramid", x264_b_pyramid_names[i] );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "b-pyramid" );
+ }
+ if( param.analyse.i_direct_mv_pred != defaults.analyse.i_direct_mv_pred )
+ {
+ // can be modified by: presets
+ if( param.analyse.i_direct_mv_pred < X264_DIRECT_PRED_NONE )
+ param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_NONE;
+ if( param.analyse.i_direct_mv_pred > X264_DIRECT_PRED_AUTO )
+ param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
+ for( i = 0; x264_direct_pred_names[i]; i++ )
+ if( param.analyse.i_direct_mv_pred == i )
+ hb_dict_set( &x264_opts, "direct", x264_direct_pred_names[i] );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "direct" );
+ }
+ if( !param.analyse.b_weighted_bipred != !defaults.analyse.b_weighted_bipred )
+ {
+ // can be modified by: preset ultrafast, tune fastdecode
+ sprintf( buf, "%d", !!param.analyse.b_weighted_bipred );
+ hb_dict_set( &x264_opts, "weightb", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "weightb" );
+ }
+ }
+ else
+ {
+ // no bframes, these options have no effect
+ hb_dict_unset( &x264_opts, "b-adapt" );
+ hb_dict_unset( &x264_opts, "b-pyramid" );
+ hb_dict_unset( &x264_opts, "direct" );
+ hb_dict_unset( &x264_opts, "weightb" );
+ hb_dict_unset( &x264_opts, "b-bias" );
+ hb_dict_unset( &x264_opts, "open-gop" );
+ }
+ if( !param.b_deblocking_filter != !defaults.b_deblocking_filter )
+ {
+ // can be modified by: preset ultrafast, tune fastdecode
+ sprintf( buf, "%d", !param.b_deblocking_filter );
+ hb_dict_set( &x264_opts, "no-deblock", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "no-deblock" );
+ }
+ if( param.b_deblocking_filter &&
+ ( param.i_deblocking_filter_alphac0 != defaults.i_deblocking_filter_alphac0 ||
+ param.i_deblocking_filter_beta != defaults.i_deblocking_filter_beta ) )
+ {
+ // can be modified by: tunes
+ sprintf( buf, "%d,%d", param.i_deblocking_filter_alphac0, param.i_deblocking_filter_beta );
+ hb_dict_set( &x264_opts, "deblock", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "deblock" );
+ }
+ if( !param.b_cabac != !defaults.b_cabac )
+ {
+ // can be modified by: preset ultrafast, tune fastdecode, profile
+ sprintf( buf, "%d", !!param.b_cabac );
+ hb_dict_set( &x264_opts, "cabac", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "cabac" );
+ }
+ if( param.b_interlaced != defaults.b_interlaced )
+ {
+ if( param.b_tff )
+ {
+ hb_dict_set( &x264_opts, "tff", "1" );
+ hb_dict_unset( &x264_opts, "bff" );
+ }
+ else
+ {
+ hb_dict_set( &x264_opts, "bff", "1" );
+ hb_dict_unset( &x264_opts, "tff" );
+ }
+ hb_dict_unset( &x264_opts, "fake-interlaced" );
+ }
+ else if( param.b_fake_interlaced != defaults.b_fake_interlaced )
+ {
+ hb_dict_set( &x264_opts, "fake-interlaced", "1" );
+ hb_dict_unset( &x264_opts, "tff" );
+ hb_dict_unset( &x264_opts, "bff" );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "tff" );
+ hb_dict_unset( &x264_opts, "bff" );
+ hb_dict_unset( &x264_opts, "fake-interlaced" );
+ }
+ if( param.i_cqm_preset == defaults.i_cqm_preset &&
+ param.psz_cqm_file == defaults.psz_cqm_file )
+ {
+ // can be reset to default by: profile
+ hb_dict_unset( &x264_opts, "cqm" );
+ hb_dict_unset( &x264_opts, "cqm4" );
+ hb_dict_unset( &x264_opts, "cqm8" );
+ hb_dict_unset( &x264_opts, "cqm4i" );
+ hb_dict_unset( &x264_opts, "cqm4p" );
+ hb_dict_unset( &x264_opts, "cqm8i" );
+ hb_dict_unset( &x264_opts, "cqm8p" );
+ hb_dict_unset( &x264_opts, "cqm4iy" );
+ hb_dict_unset( &x264_opts, "cqm4ic" );
+ hb_dict_unset( &x264_opts, "cqm4py" );
+ hb_dict_unset( &x264_opts, "cqm4pc" );
+ }
+ if( param.analyse.inter != defaults.analyse.inter )
+ {
+ // can be modified by: presets, tune touhou
+ if( !param.analyse.inter )
+ {
+ hb_dict_set( &x264_opts, "analyse", "none" );
+ }
+ else if( ( param.analyse.inter & X264_ANALYSE_I4x4 ) &&
+ ( param.analyse.inter & X264_ANALYSE_I8x8 ) &&
+ ( param.analyse.inter & X264_ANALYSE_PSUB16x16 ) &&
+ ( param.analyse.inter & X264_ANALYSE_PSUB8x8 ) &&
+ ( param.analyse.inter & X264_ANALYSE_BSUB16x16 ) )
+ {
+ hb_dict_set( &x264_opts, "analyse", "all" );
+ }
+ else
+ {
+ sprintf( buf, "%s", "" );
+ if( param.analyse.inter & X264_ANALYSE_I4x4 )
+ {
+ strcat( buf, "i4x4" );
+ }
+ if( param.analyse.inter & X264_ANALYSE_I8x8 )
+ {
+ if( strlen( buf ) )
+ strcat( buf, "," );
+ strcat( buf, "i8x8" );
+ }
+ if( param.analyse.inter & X264_ANALYSE_PSUB16x16 )
+ {
+ if( strlen( buf ) )
+ strcat( buf, "," );
+ strcat( buf, "p8x8" );
+ }
+ if( param.analyse.inter & X264_ANALYSE_PSUB8x8 )
+ {
+ if( strlen( buf ) )
+ strcat( buf, "," );
+ strcat( buf, "p4x4" );
+ }
+ if( param.analyse.inter & X264_ANALYSE_BSUB16x16 )
+ {
+ if( strlen( buf ) )
+ strcat( buf, "," );
+ strcat( buf, "b8x8" );
+ }
+ hb_dict_set( &x264_opts, "analyse", buf );
+ }
+ // note: param.analyse.intra can only be modified directly or by using
+ // x264 --preset ultrafast, but not via the "analyse" option
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "analyse" );
+ }
+ if( !param.analyse.b_transform_8x8 != !defaults.analyse.b_transform_8x8 )
+ {
+ // can be modified by: preset ultrafast, profile
+ sprintf( buf, "%d", !!param.analyse.b_transform_8x8 );
+ hb_dict_set( &x264_opts, "8x8dct", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "8x8dct" );
+ }
+ if( param.analyse.i_weighted_pred != defaults.analyse.i_weighted_pred )
+ {
+ // can be modified by: presets, tune fastdecode, profile
+ sprintf( buf, "%d", param.analyse.i_weighted_pred );
+ hb_dict_set( &x264_opts, "weightp", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "weightp" );
+ }
+ if( param.analyse.i_me_method != defaults.analyse.i_me_method )
+ {
+ // can be modified by: presets
+ if( param.analyse.i_me_method < X264_ME_DIA )
+ param.analyse.i_me_method = X264_ME_DIA;
+ if( param.analyse.i_me_method > X264_ME_TESA )
+ param.analyse.i_me_method = X264_ME_TESA;
+ for( i = 0; x264_motion_est_names[i]; i++ )
+ if( param.analyse.i_me_method == i )
+ hb_dict_set( &x264_opts, "me", x264_motion_est_names[i] );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "me" );
+ }
+ if( param.analyse.i_me_range != defaults.analyse.i_me_range )
+ {
+ // can be modified by: presets
+ sprintf( buf, "%d", param.analyse.i_me_range );
+ hb_dict_set( &x264_opts, "merange", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "merange" );
+ }
+ if( param.analyse.i_mv_range != defaults.analyse.i_mv_range )
+ {
+ // can be modified by: level
+ sprintf( buf, "%d", param.analyse.i_mv_range );
+ hb_dict_set( &x264_opts, "mvrange", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "mvrange" );
+ }
+ if( param.analyse.i_subpel_refine > 9 &&
+ ( param.analyse.i_trellis < 2 || !param.rc.i_aq_mode ) )
+ {
+ // subme 10 & 11 require AQ and trellis 2
+ param.analyse.i_subpel_refine = 9;
+ }
+ if( param.analyse.i_subpel_refine != defaults.analyse.i_subpel_refine )
+ {
+ // can be modified by: presets
+ sprintf( buf, "%d", param.analyse.i_subpel_refine );
+ hb_dict_set( &x264_opts, "subme", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "subme" );
+ }
+ if( !param.analyse.b_mixed_references != !defaults.analyse.b_mixed_references )
+ {
+ // can be modified by: presets
+ sprintf( buf, "%d", !!param.analyse.b_mixed_references );
+ hb_dict_set( &x264_opts, "mixed-refs", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "mixed-refs" );
+ }
+ if( param.analyse.i_trellis != defaults.analyse.i_trellis )
+ {
+ // can be modified by: presets
+ sprintf( buf, "%d", param.analyse.i_trellis );
+ hb_dict_set( &x264_opts, "trellis", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "trellis" );
+ }
+ if( !param.analyse.b_fast_pskip != !defaults.analyse.b_fast_pskip )
+ {
+ // can be modified by: preset placebo
+ sprintf( buf, "%d", !!param.analyse.b_fast_pskip );
+ hb_dict_set( &x264_opts, "fast-pskip", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "fast-pskip" );
+ }
+ if( !param.analyse.b_dct_decimate != !defaults.analyse.b_dct_decimate )
+ {
+ // can be modified by: tune grain
+ sprintf( buf, "%d", !!param.analyse.b_dct_decimate );
+ hb_dict_set( &x264_opts, "dct-decimate", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "dct-decimate" );
+ }
+ if( !param.analyse.b_psy != !defaults.analyse.b_psy )
+ {
+ // can be modified by: tunes
+ sprintf( buf, "%d", !!param.analyse.b_psy );
+ hb_dict_set( &x264_opts, "psy", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "psy" );
+ }
+ if( param.analyse.b_psy &&
+ ( param.analyse.f_psy_rd != defaults.analyse.f_psy_rd ||
+ param.analyse.f_psy_trellis != defaults.analyse.f_psy_trellis ) )
+ {
+ // can be modified by: tunes
+ sprintf( buf, "%.2f,%.2f", param.analyse.f_psy_rd, param.analyse.f_psy_trellis );
+ hb_dict_set( &x264_opts, "psy-rd", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "psy-rd" );
+ }
+ // note: while deadzone is incompatible with trellis, it still has a slight
+ // effect on the output even when trellis is on, so always unparse it.
+ if( param.analyse.i_luma_deadzone[0] != defaults.analyse.i_luma_deadzone[0] )
+ {
+ // can be modified by: tune grain
+ sprintf( buf, "%d", param.analyse.i_luma_deadzone[0] );
+ hb_dict_set( &x264_opts, "deadzone-inter", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "deadzone-inter" );
+ }
+ if( param.analyse.i_luma_deadzone[1] != defaults.analyse.i_luma_deadzone[1] )
+ {
+ // can be modified by: tune grain
+ sprintf( buf, "%d", param.analyse.i_luma_deadzone[1] );
+ hb_dict_set( &x264_opts, "deadzone-intra", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "deadzone-intra" );
+ }
+ if( param.rc.i_vbv_buffer_size != defaults.rc.i_vbv_buffer_size )
+ {
+ // can be modified by: level
+ sprintf( buf, "%d", param.rc.i_vbv_buffer_size );
+ hb_dict_set( &x264_opts, "vbv-bufsize", buf );
+ if( param.rc.i_vbv_max_bitrate != defaults.rc.i_vbv_max_bitrate )
+ {
+ // can be modified by: level
+ sprintf( buf, "%d", param.rc.i_vbv_max_bitrate );
+ hb_dict_set( &x264_opts, "vbv-bitrate", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "vbv-maxrate" );
+ }
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "vbv-bufsize" );
+ hb_dict_unset( &x264_opts, "vbv-maxrate" );
+ }
+ if( param.rc.f_ip_factor != defaults.rc.f_ip_factor )
+ {
+ // can be modified by: tune grain
+ sprintf( buf, "%.2f", param.rc.f_ip_factor );
+ hb_dict_set( &x264_opts, "ipratio", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "ipratio" );
+ }
+ if( param.i_bframe > 0 && !param.rc.b_mb_tree &&
+ param.rc.f_pb_factor != defaults.rc.f_pb_factor )
+ {
+ // can be modified by: tune grain
+ sprintf( buf, "%.2f", param.rc.f_pb_factor );
+ hb_dict_set( &x264_opts, "pbratio", buf );
+ }
+ else
+ {
+ // pbratio requires bframes and is incomaptible with mbtree
+ hb_dict_unset( &x264_opts, "pbratio" );
+ }
+ if( param.rc.f_qcompress != defaults.rc.f_qcompress )
+ {
+ // can be modified by: tune grain
+ sprintf( buf, "%.2f", param.rc.f_qcompress );
+ hb_dict_set( &x264_opts, "qcomp", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "qcomp" );
+ }
+ if( param.rc.i_aq_mode != defaults.rc.i_aq_mode )
+ {
+ // can be modified by: preset ultrafast, tune psnr
+ sprintf( buf, "%d", param.rc.i_aq_mode );
+ hb_dict_set( &x264_opts, "aq-mode", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "aq-mode" );
+ }
+ if( param.rc.i_aq_mode > 0 &&
+ param.rc.f_aq_strength != defaults.rc.f_aq_strength )
+ {
+ // can be modified by: tunes
+ sprintf( buf, "%.2f", param.rc.f_aq_strength );
+ hb_dict_set( &x264_opts, "aq-strength", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "aq-strength" );
+ }
+ if( !param.rc.b_mb_tree != !defaults.rc.b_mb_tree )
+ {
+ // can be modified by: presets, tune zerolatency
+ sprintf( buf, "%d", !!param.rc.b_mb_tree );
+ hb_dict_set( &x264_opts, "mbtree", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "mbtree" );
+ }
+ if( param.rc.i_lookahead != defaults.rc.i_lookahead )
+ {
+ // can be modified by: presets, tune zerolatency
+ sprintf( buf, "%d", param.rc.i_lookahead );
+ hb_dict_set( &x264_opts, "rc-lookahead", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "rc-lookahead" );
+ }
+ if( !param.b_vfr_input != !defaults.b_vfr_input )
+ {
+ // can be modified by: tune zerolatency
+ sprintf( buf, "%d", !param.b_vfr_input );
+ hb_dict_set( &x264_opts, "force-cfr", buf );
+ }
+ else
+ {
+ hb_dict_unset( &x264_opts, "force-cfr" );
+ }
+
+ /* convert the x264_opts dictionary to an encopts string */
+ unparsed_opts = hb_dict_to_encopts( x264_opts );
+ hb_dict_free( &x264_opts );
+
+ /* we're done */
+ return unparsed_opts;
+}
+
const char * const * hb_x264_presets()
{
return x264_preset_names;