diff options
-rw-r--r-- | libhb/common.h | 8 | ||||
-rw-r--r-- | libhb/encx264.c | 78 | ||||
-rw-r--r-- | libhb/work.c | 15 | ||||
-rw-r--r-- | test/test.c | 94 |
4 files changed, 171 insertions, 24 deletions
diff --git a/libhb/common.h b/libhb/common.h index 41272b93f..2d275978f 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -257,6 +257,9 @@ struct hb_job_s int cfr; int pass; char *advanced_opts; + char *x264_profile; + char *x264_preset; + char *x264_tune; int areBframes; int color_matrix_code; int color_prim; @@ -871,4 +874,9 @@ int hb_rgb2yuv(int rgb); const char * hb_subsource_name( int source ); +// x264 preset/tune/profile helpers +const char * const * hb_x264_presets(); +const char * const * hb_x264_tunes(); +const char * const * hb_x264_profiles(); + #endif diff --git a/libhb/encx264.c b/libhb/encx264.c index 3d55c2ee3..9af954d97 100644 --- a/libhb/encx264.c +++ b/libhb/encx264.c @@ -83,7 +83,12 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) memset( pv->filename, 0, 1024 ); hb_get_tempory_filename( job->h, pv->filename, "x264.log" ); - x264_param_default( ¶m ); + if( x264_param_default_preset( ¶m, job->x264_preset, job->x264_tune ) < 0 ) + { + free( pv ); + pv = NULL; + return 1; + } /* Enable metrics */ param.analyse.b_psnr = 1; @@ -209,7 +214,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) } free(x264opts_start); } - + /* Reload colorimetry settings in case custom values were set * in the advanced_opts string */ job->color_matrix_code = 3; @@ -217,26 +222,6 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) job->color_transfer = param.vui.i_transfer; job->color_matrix = param.vui.i_colmatrix; - /* B-frames are on by default.*/ - job->areBframes = 1; - - if( param.i_bframe && param.i_bframe_pyramid ) - { - /* Note b-pyramid here, so the initial delay can be doubled */ - job->areBframes = 2; - } - else if( !param.i_bframe ) - { - /* - When B-frames are enabled, the max frame count increments - by 1 (regardless of the number of B-frames). If you don't - change the duration of the video track when you mux, libmp4 - barfs. So, check if the x264opts aren't using B-frames, and - when they aren't, set the boolean job->areBframes as false. - */ - job->areBframes = 0; - } - /* For 25 fps sources, HandBrake's explicit keyints will match the x264 defaults: min-keyint 25 (same as auto), keyint 250 */ if( param.i_keyint_min != 25 || param.i_keyint_max != 250 ) @@ -295,11 +280,44 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) } } + /* Apply profile settings after explicit settings, if present. */ + if( job->x264_profile ) + { + if( x264_param_apply_profile( ¶m, job->x264_profile ) < 0 ) + { + free( pv ); + pv = NULL; + return 1; + } + } + + /* B-frames are on by default.*/ + job->areBframes = 1; + + if( param.i_bframe && param.i_bframe_pyramid ) + { + /* Note b-pyramid here, so the initial delay can be doubled */ + job->areBframes = 2; + } + else if( !param.i_bframe ) + { + /* + When B-frames are enabled, the max frame count increments + by 1 (regardless of the number of B-frames). If you don't + change the duration of the video track when you mux, libmp4 + barfs. So, check if the x264opts aren't using B-frames, and + when they aren't, set the boolean job->areBframes as false. + */ + job->areBframes = 0; + } + hb_deep_log( 2, "encx264: opening libx264 (pass %d)", job->pass ); pv->x264 = x264_encoder_open( ¶m ); if ( pv->x264 == NULL ) { hb_error("encx264: x264_encoder_open failed."); + free( pv ); + pv = NULL; return 1; } @@ -608,3 +626,19 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in, *buf_out = x264_encode( w, in ); return HB_WORK_OK; } + +const char * const * hb_x264_presets() +{ + return x264_preset_names; +} + +const char * const * hb_x264_tunes() +{ + return x264_tune_names; +} + +const char * const * hb_x264_profiles() +{ + return x264_profile_names; +} + diff --git a/libhb/work.c b/libhb/work.c index c9e5ee205..d8cb7b919 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -288,12 +288,27 @@ void hb_display_job_info( hb_job_t * job ) } } + if( job->x264_preset && *job->x264_preset && + job->vcodec == HB_VCODEC_X264 ) + { + hb_log( " + x264 preset: %s", job->x264_preset); + } + if( job->x264_tune && *job->x264_tune && + job->vcodec == HB_VCODEC_X264 ) + { + hb_log( " + x264 tune: %s", job->x264_tune); + } if( job->advanced_opts && *job->advanced_opts && ( ( job->vcodec & HB_VCODEC_FFMPEG_MASK ) || ( job->vcodec == HB_VCODEC_X264 ) ) ) { hb_log( " + options: %s", job->advanced_opts); } + if( job->x264_profile && *job->x264_profile && + job->vcodec == HB_VCODEC_X264 ) + { + hb_log( " + x264 profile: %s", job->x264_profile); + } if( job->vquality >= 0 ) { diff --git a/test/test.c b/test/test.c index c91b59b30..fac25e8bc 100644 --- a/test/test.c +++ b/test/test.c @@ -114,6 +114,9 @@ static int chapter_markers = 0; static char * marker_file = NULL; static char *advanced_opts = NULL; static char *advanced_opts2 = NULL; +static char *x264_profile = NULL; +static char *x264_preset = NULL; +static char *x264_tune = NULL; static int maxHeight = 0; static int maxWidth = 0; static int turbo_opts_enabled = 0; @@ -361,6 +364,9 @@ int main( int argc, char ** argv ) if (preset_name) free (preset_name); if( stop_at_string ) free( stop_at_string ); if( start_at_string ) free( start_at_string ); + free( x264_profile ); + free( x264_preset ); + free( x264_tune ); // write a carriage return to stdout - avoids overlap / line wrapping when stderr is redirected fprintf( stdout, "\n" ); @@ -2319,6 +2325,9 @@ static int HandleEvents( hb_handle_t * h ) { job->advanced_opts = NULL; } + job->x264_profile = x264_profile; + job->x264_preset = x264_preset; + job->x264_tune = x264_tune; if (maxWidth) job->maxWidth = maxWidth; if (maxHeight) @@ -2541,8 +2550,10 @@ void SigHandler( int i_signal ) ****************************************************************************/ static void ShowHelp() { - int i, j; + int i, j, len; FILE* const out = stdout; + const char * const *x264_opts; + char tmp[80]; fprintf( out, "Syntax: HandBrakeCLI [options] -i <device> -o <file>\n" @@ -2614,9 +2625,73 @@ static void ShowHelp() } } fprintf( out, + " --x264-preset When using x264, selects the x264 preset:\n" + " <string> "); + x264_opts = hb_x264_presets(); + tmp[0] = 0; + len = 0; + while( x264_opts && *x264_opts ) + { + strncat( tmp, *x264_opts++, 79 - len ); + if( *x264_opts ) + strcat( tmp, "/" ); + len = strlen( tmp ); + if( len > 40 && *x264_opts ) + { + fprintf( out, "%s\n ", tmp ); + len = 0; + tmp[0] = 0; + } + } + if( len ) + fprintf( out, "%s\n", tmp ); + fprintf( out, + " --x264-tune When using x264, selects the x264 tuning:\n" + " <string> "); + x264_opts = hb_x264_tunes(); + tmp[0] = 0; + len = 0; + while( x264_opts && *x264_opts ) + { + strncat( tmp, *x264_opts++, 79 - len ); + if( *x264_opts ) + strcat( tmp, "/" ); + len = strlen( tmp ); + if( len > 40 && *x264_opts ) + { + fprintf( out, "%s\n ", tmp ); + len = 0; + tmp[0] = 0; + } + } + if( len ) + fprintf( out, "%s\n", tmp ); + fprintf( out, " -x, --encopts <string> Specify advanced encoder options in the\n" " same style as mencoder (x264 and ffmpeg only):\n" " option1=value1:option2=value2\n" + " --x264-profile When using x264, ensures compliance with the\n" + " <string> specified h.264 profile:\n" + " "); + x264_opts = hb_x264_profiles(); + tmp[0] = 0; + len = 0; + while( x264_opts && *x264_opts ) + { + strncat( tmp, *x264_opts++, 79 - len ); + if( *x264_opts ) + strcat( tmp, "/" ); + len = strlen( tmp ); + if( len > 40 && *x264_opts ) + { + fprintf( out, "%s\n ", tmp ); + len = 0; + tmp[0] = 0; + } + } + if( len ) + fprintf( out, "%s\n", tmp ); + fprintf( out, " -q, --quality <number> Set video quality\n" " -b, --vb <kb/s> Set video bitrate (default: 1000)\n" " -2, --two-pass Use two-pass mode\n" @@ -2974,7 +3049,10 @@ static int ParseOptions( int argc, char ** argv ) #define ALLOWED_AUDIO_COPY 280 #define AUDIO_FALLBACK 281 #define LOOSE_CROP 282 - + #define X264_PROFILE 283 + #define X264_PRESET 284 + #define X264_TUNE 285 + for( ;; ) { static struct option long_options[] = @@ -3042,6 +3120,9 @@ static int ParseOptions( int argc, char ** argv ) { "rate", required_argument, NULL, 'r' }, { "arate", required_argument, NULL, 'R' }, { "encopts", required_argument, NULL, 'x' }, + { "x264-profile", required_argument, NULL, X264_PROFILE }, + { "x264-preset", required_argument, NULL, X264_PRESET }, + { "x264-tune", required_argument, NULL, X264_TUNE }, { "turbo", no_argument, NULL, 'T' }, { "maxHeight", required_argument, NULL, 'Y' }, { "maxWidth", required_argument, NULL, 'X' }, @@ -3451,6 +3532,15 @@ static int ParseOptions( int argc, char ** argv ) case 'x': advanced_opts = strdup( optarg ); break; + case X264_PROFILE: + x264_profile = strdup( optarg ); + break; + case X264_PRESET: + x264_preset = strdup( optarg ); + break; + case X264_TUNE: + x264_tune = strdup( optarg ); + break; case 'T': turbo_opts_enabled = 1; break; |