summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
Diffstat (limited to 'libhb')
-rw-r--r--libhb/encx264.c93
-rw-r--r--libhb/encx264.h2
2 files changed, 69 insertions, 26 deletions
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 29037b636..d20447bb1 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -291,7 +291,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
}
if( job->h264_level )
{
- hb_apply_h264_level( &param, job->h264_level );
+ hb_apply_h264_level( &param, job->h264_level, job->x264_profile );
}
/* B-frames are on by default.*/
@@ -634,33 +634,67 @@ int encx264Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
* Does not modify resolution/framerate but warns when they exceed level limits.
* No return value: an error or warning does not cause libhb to exit.
* Based on x264_param_apply_level and other x264 code. */
-void hb_apply_h264_level( x264_param_t * param, const char * level )
+void hb_apply_h264_level( x264_param_t * param, const char * level, const char * x264_profile )
{
int i, h264_profile, i_mb_width, i_mb_height, mbs, max_frame_side;
x264_level_t * h264_level = NULL;
+ /* H.264 profile */
+ h264_profile = -1; // Auto
+ if( x264_profile && *x264_profile )
+ {
+ // if the user explicitly specified a profile, don't guess it
+ if( !strcasecmp( x264_profile, "high444" ) )
+ {
+ h264_profile = 2; // High 4:4:4 Predictive
+ }
+ else if( !strcasecmp( x264_profile, "high" ) )
+ {
+ h264_profile = 1; // High
+ }
+ else if( !strcasecmp( x264_profile, "main" ) ||
+ !strcasecmp( x264_profile, "baseline" ) )
+ {
+ h264_profile = 0; // less than High
+ }
+ else
+ {
+ hb_log( "hb_apply_h264_level [warning]: unsupported x264 profile %s, ignoring", x264_profile );
+ }
+ }
+
/* find the x264_level_t corresponding to the requested level */
- for( i = 0; h264_level_names[i]; i++ )
+ if( level && *level )
{
- if( !strcmp( h264_level_names[i], level ) )
+ for( i = 0; h264_level_names[i]; i++ )
{
- int val = h264_level_values[i];
- for( i = 0; x264_levels[i].level_idc; i++ )
+ if( !strcmp( h264_level_names[i], level ) )
{
- if( x264_levels[i].level_idc == val )
+ int val = h264_level_values[i];
+ for( i = 0; x264_levels[i].level_idc; i++ )
{
- h264_level = (x264_level_t *)(x264_levels + i);
- break;
+ if( x264_levels[i].level_idc == val )
+ {
+ h264_level = (x264_level_t *)(x264_levels + i);
+ break;
+ }
}
+ break;
}
- break;
+ }
+ if( !h264_level )
+ {
+ // error (invalid or unsupported level), abort
+ // this is not a failure (encoding continues)
+ hb_log( "hb_apply_h264_level [ERROR]: invalid level %s, ignoring", level );
+ return;
}
}
- if( !h264_level )
+ else
{
- // error (invalid or unsupported level), abort
+ // error (level not a string), abort
// this is not a failure (encoding continues)
- hb_log( "hb_apply_h264_level [ERROR]: invalid level %s, ignoring", level );
+ hb_log( "hb_apply_h264_level [ERROR]: no level specified, ignoring" );
return;
}
@@ -676,9 +710,11 @@ void hb_apply_h264_level( x264_param_t * param, const char * level )
/* frame dimensions & rate (in macroblocks) */
i_mb_width = ( param->i_width + 15 ) / 16;
i_mb_height = ( param->i_height + 15 ) / 16;
- // interlaced: i_mb_height*16 must be mod 32
if( param->b_interlaced || param->b_fake_interlaced )
+ {
+ // interlaced: i_mb_height * 16 must be mod 32
i_mb_height = ( i_mb_height + 1 ) & ~1;
+ }
mbs = i_mb_width * i_mb_height;
/* sanitize ref/frameref */
@@ -689,23 +725,30 @@ void hb_apply_h264_level( x264_param_t * param, const char * level )
// some level/resolution combinations may require as little as 1 reference
// B-frames & B-pyramid are not compatible with this scenario
if( i_max_dec_frame_buffering < 2 )
+ {
param->i_bframe = 0;
+ }
else if( i_max_dec_frame_buffering < 4 )
+ {
param->i_bframe_pyramid = X264_B_PYRAMID_NONE;
+ }
}
- /* H.264 profile */
- if( param->rc.i_rc_method == X264_RC_CRF && param->rc.f_rf_constant < 1 )
- {
- h264_profile = 2; // High 4:4:4 Predictive
- }
- else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT )
- {
- h264_profile = 1; // High
- }
- else
+ /* guess the H.264 profile if the user didn't request one */
+ if( h264_profile == -1 )
{
- h264_profile = 0; // less than High
+ if( param->rc.i_rc_method == X264_RC_CRF && param->rc.f_rf_constant < 1 )
+ {
+ h264_profile = 2; // High 4:4:4 Predictive
+ }
+ else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT )
+ {
+ h264_profile = 1; // High
+ }
+ else
+ {
+ h264_profile = 0; // less than High
+ }
}
/* set and/or sanitize the VBV (if not lossless) */
diff --git a/libhb/encx264.h b/libhb/encx264.h
index f825028eb..263e18890 100644
--- a/libhb/encx264.h
+++ b/libhb/encx264.h
@@ -7,4 +7,4 @@
static const char * const h264_level_names[] = { "1.0", "1b", "1.1", "1.2", "1.3", "2.0", "2.1", "2.2", "3.0", "3.1", "3.2", "4.0", "4.1", "4.2", "5.0", "5.1", 0 };
static const int const h264_level_values[] = { 10, 9, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, 0 };
-void hb_apply_h264_level( x264_param_t * param, const char * level );
+void hb_apply_h264_level( x264_param_t * param, const char * level, const char * x264_profile );