X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=common%2Fcommon.c;h=59c2f05188c75870610ae1f1c9857d6014382ead;hb=d026397b0bf4c87e96b19c9fff7f43be6c4d9def;hp=1ed983fb18471df186e69789d676387452ac75e3;hpb=669cc1def2034a7ef55946df9f6e1ae13963eb8a;p=x264 diff --git a/common/common.c b/common/common.c index 1ed983fb..59c2f051 100644 --- a/common/common.c +++ b/common/common.c @@ -1,7 +1,7 @@ /***************************************************************************** - * common.c: h264 library + * common.c: misc common functions ***************************************************************************** - * Copyright (C) 2003-2008 x264 project + * Copyright (C) 2003-2012 x264 project * * Authors: Loren Merritt * Laurent Aimar @@ -19,6 +19,9 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + * + * This program is also available under a commercial proprietary license. + * For more information, contact us at licensing@x264.com. *****************************************************************************/ #include "common.h" @@ -30,6 +33,10 @@ #include #endif +const int x264_bit_depth = BIT_DEPTH; + +const int x264_chroma_format = X264_CHROMA_FORMAT; + static void x264_log_default( void *, int, const char *, va_list ); /**************************************************************************** @@ -43,21 +50,22 @@ void x264_param_default( x264_param_t *param ) /* CPU autodetect */ param->cpu = x264_cpu_detect(); param->i_threads = X264_THREADS_AUTO; + param->i_lookahead_threads = X264_THREADS_AUTO; param->b_deterministic = 1; param->i_sync_lookahead = X264_SYNC_LOOKAHEAD_AUTO; /* Video properties */ - param->i_csp = X264_CSP_I420; + param->i_csp = X264_CHROMA_FORMAT ? X264_CHROMA_FORMAT : X264_CSP_I420; param->i_width = 0; param->i_height = 0; param->vui.i_sar_width = 0; param->vui.i_sar_height= 0; param->vui.i_overscan = 0; /* undef */ param->vui.i_vidformat = 5; /* undef */ - param->vui.b_fullrange = 0; /* off */ + param->vui.b_fullrange = -1; /* default depends on input */ param->vui.i_colorprim = 2; /* undef */ param->vui.i_transfer = 2; /* undef */ - param->vui.i_colmatrix = 2; /* undef */ + param->vui.i_colmatrix = -1; /* default depends on input */ param->vui.i_chroma_loc= 0; /* left center */ param->i_fps_num = 25; param->i_fps_den = 1; @@ -91,10 +99,10 @@ void x264_param_default( x264_param_t *param ) param->rc.i_vbv_max_bitrate = 0; param->rc.i_vbv_buffer_size = 0; param->rc.f_vbv_buffer_init = 0.9; - param->rc.i_qp_constant = 23; + param->rc.i_qp_constant = 23 + QP_BD_OFFSET; param->rc.f_rf_constant = 23; - param->rc.i_qp_min = 10; - param->rc.i_qp_max = 51; + param->rc.i_qp_min = 0; + param->rc.i_qp_max = QP_MAX; param->rc.i_qp_step = 4; param->rc.f_ip_factor = 1.4; param->rc.f_pb_factor = 1.3; @@ -146,25 +154,32 @@ void x264_param_default( x264_param_t *param ) param->i_cqm_preset = X264_CQM_FLAT; memset( param->cqm_4iy, 16, sizeof( param->cqm_4iy ) ); - memset( param->cqm_4ic, 16, sizeof( param->cqm_4ic ) ); memset( param->cqm_4py, 16, sizeof( param->cqm_4py ) ); + memset( param->cqm_4ic, 16, sizeof( param->cqm_4ic ) ); memset( param->cqm_4pc, 16, sizeof( param->cqm_4pc ) ); memset( param->cqm_8iy, 16, sizeof( param->cqm_8iy ) ); memset( param->cqm_8py, 16, sizeof( param->cqm_8py ) ); + memset( param->cqm_8ic, 16, sizeof( param->cqm_8ic ) ); + memset( param->cqm_8pc, 16, sizeof( param->cqm_8pc ) ); param->b_repeat_headers = 1; param->b_annexb = 1; param->b_aud = 0; param->b_vfr_input = 1; - param->b_dts_compress = 0; param->i_nal_hrd = X264_NAL_HRD_NONE; param->b_tff = 1; param->b_pic_struct = 0; param->b_fake_interlaced = 0; + param->i_frame_packing = -1; } static int x264_param_apply_preset( x264_param_t *param, const char *preset ) { + char *end; + int i = strtol( preset, &end, 10 ); + if( *end == 0 && i >= 0 && i < sizeof(x264_preset_names)/sizeof(*x264_preset_names)-1 ) + preset = x264_preset_names[i]; + if( !strcasecmp( preset, "ultrafast" ) ) { param->i_frame_reference = 1; @@ -195,7 +210,7 @@ static int x264_param_apply_preset( x264_param_t *param, const char *preset ) param->analyse.b_mixed_references = 0; param->analyse.i_trellis = 0; param->rc.b_mb_tree = 0; - param->analyse.i_weighted_pred = X264_WEIGHTP_NONE; + param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE; param->rc.i_lookahead = 0; } else if( !strcasecmp( preset, "veryfast" ) ) @@ -205,7 +220,7 @@ static int x264_param_apply_preset( x264_param_t *param, const char *preset ) param->i_frame_reference = 1; param->analyse.b_mixed_references = 0; param->analyse.i_trellis = 0; - param->analyse.i_weighted_pred = X264_WEIGHTP_NONE; + param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE; param->rc.i_lookahead = 10; } else if( !strcasecmp( preset, "faster" ) ) @@ -213,13 +228,14 @@ static int x264_param_apply_preset( x264_param_t *param, const char *preset ) param->analyse.b_mixed_references = 0; param->i_frame_reference = 2; param->analyse.i_subpel_refine = 4; - param->analyse.i_weighted_pred = X264_WEIGHTP_BLIND; + param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE; param->rc.i_lookahead = 20; } else if( !strcasecmp( preset, "fast" ) ) { param->i_frame_reference = 2; param->analyse.i_subpel_refine = 6; + param->analyse.i_weighted_pred = X264_WEIGHTP_SIMPLE; param->rc.i_lookahead = 30; } else if( !strcasecmp( preset, "medium" ) ) @@ -262,7 +278,7 @@ static int x264_param_apply_preset( x264_param_t *param, const char *preset ) else if( !strcasecmp( preset, "placebo" ) ) { param->analyse.i_me_method = X264_ME_TESA; - param->analyse.i_subpel_refine = 10; + param->analyse.i_subpel_refine = 11; param->analyse.i_me_range = 24; param->i_frame_reference = 16; param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS; @@ -413,16 +429,62 @@ void x264_param_apply_fastfirstpass( x264_param_t *param ) } } +static int profile_string_to_int( const char *str ) +{ + if( !strcasecmp( str, "baseline" ) ) + return PROFILE_BASELINE; + if( !strcasecmp( str, "main" ) ) + return PROFILE_MAIN; + if( !strcasecmp( str, "high" ) ) + return PROFILE_HIGH; + if( !strcasecmp( str, "high10" ) ) + return PROFILE_HIGH10; + if( !strcasecmp( str, "high422" ) ) + return PROFILE_HIGH422; + if( !strcasecmp( str, "high444" ) ) + return PROFILE_HIGH444_PREDICTIVE; + return -1; +} + int x264_param_apply_profile( x264_param_t *param, const char *profile ) { if( !profile ) return 0; - if( !strcasecmp( profile, "baseline" ) ) + int p = profile_string_to_int( profile ); + if( p < 0 ) + { + x264_log( NULL, X264_LOG_ERROR, "invalid profile: %s\n", profile ); + return -1; + } + if( p < PROFILE_HIGH444_PREDICTIVE && ((param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant <= 0) || + (param->rc.i_rc_method == X264_RC_CRF && (int)(param->rc.f_rf_constant + QP_BD_OFFSET) <= 0)) ) + { + x264_log( NULL, X264_LOG_ERROR, "%s profile doesn't support lossless\n", profile ); + return -1; + } + if( p < PROFILE_HIGH444_PREDICTIVE && (param->i_csp & X264_CSP_MASK) >= X264_CSP_I444 ) + { + x264_log( NULL, X264_LOG_ERROR, "%s profile doesn't support 4:4:4\n", profile ); + return -1; + } + if( p < PROFILE_HIGH422 && (param->i_csp & X264_CSP_MASK) >= X264_CSP_I422 ) + { + x264_log( NULL, X264_LOG_ERROR, "%s profile doesn't support 4:2:2\n", profile ); + return -1; + } + if( p < PROFILE_HIGH10 && BIT_DEPTH > 8 ) + { + x264_log( NULL, X264_LOG_ERROR, "%s profile doesn't support a bit depth of %d\n", profile, BIT_DEPTH ); + return -1; + } + + if( p == PROFILE_BASELINE ) { param->analyse.b_transform_8x8 = 0; param->b_cabac = 0; param->i_cqm_preset = X264_CQM_FLAT; + param->psz_cqm_file = NULL; param->i_bframe = 0; param->analyse.i_weighted_pred = X264_WEIGHTP_NONE; if( param->b_interlaced ) @@ -436,25 +498,11 @@ int x264_param_apply_profile( x264_param_t *param, const char *profile ) return -1; } } - else if( !strcasecmp( profile, "main" ) ) + else if( p == PROFILE_MAIN ) { param->analyse.b_transform_8x8 = 0; param->i_cqm_preset = X264_CQM_FLAT; - } - else if( !strcasecmp( profile, "high" ) ) - { - /* Default */ - } - else - { - x264_log( NULL, X264_LOG_ERROR, "invalid profile: %s\n", profile ); - return -1; - } - if( (param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0) || - (param->rc.i_rc_method == X264_RC_CRF && param->rc.f_rf_constant == 0) ) - { - x264_log( NULL, X264_LOG_ERROR, "%s profile doesn't support lossless\n", profile ); - return -1; + param->psz_cqm_file = NULL; } return 0; } @@ -572,6 +620,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) b_error = 1; } free( buf ); + if( p->cpu & X264_CPU_SSSE3 ) + p->cpu |= X264_CPU_SSE2_IS_FAST; + if( p->cpu & X264_CPU_SSE4 ) + p->cpu |= X264_CPU_SHUFFLE_IS_FAST; } } OPT("threads") @@ -581,6 +633,13 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) else p->i_threads = atoi(value); } + OPT("lookahead-threads") + { + if( !strcmp(value, "auto") ) + p->i_lookahead_threads = X264_THREADS_AUTO; + else + p->i_lookahead_threads = atoi(value); + } OPT("sliced-threads") p->b_sliced_threads = atobool(value); OPT("sync-lookahead") @@ -592,13 +651,19 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) } OPT2("deterministic", "n-deterministic") p->b_deterministic = atobool(value); + OPT("cpu-independent") + p->b_cpu_independent = atobool(value); OPT2("level", "level-idc") { - if( atof(value) < 6 ) + if( !strcmp(value, "1b") ) + p->i_level_idc = 9; + else if( atof(value) < 6 ) p->i_level_idc = (int)(10*atof(value)+.5); else p->i_level_idc = atoi(value); } + OPT("bluray-compat") + p->b_bluray_compat = atobool(value); OPT("sar") { b_error = ( 2 != sscanf( value, "%d:%d", &p->vui.i_sar_width, &p->vui.i_sar_height ) && @@ -628,17 +693,28 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) else { float fps = atof(value); - p->i_fps_num = (int)(fps * 1000 + .5); - p->i_fps_den = 1000; + if( fps > 0 && fps <= INT_MAX/1000 ) + { + p->i_fps_num = (int)(fps * 1000 + .5); + p->i_fps_den = 1000; + } + else + { + p->i_fps_num = atoi(value); + p->i_fps_den = 1; + } } } OPT2("ref", "frameref") p->i_frame_reference = atoi(value); + OPT("dpb-size") + p->i_dpb_size = atoi(value); OPT("keyint") { - p->i_keyint_max = atoi(value); - if( p->i_keyint_min > p->i_keyint_max ) - p->i_keyint_min = p->i_keyint_max; + if( strstr( value, "infinite" ) ) + p->i_keyint_max = X264_KEYINT_MAX_INFINITE; + else + p->i_keyint_max = atoi(value); } OPT2("min-keyint", "keyint-min") { @@ -680,14 +756,7 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) } } OPT("open-gop") - { - b_error |= parse_enum( value, x264_open_gop_names, &p->i_open_gop ); - if( b_error ) - { - b_error = 0; - p->i_open_gop = atoi(value); - } - } + p->b_open_gop = atobool(value); OPT("nf") p->b_deblocking_filter = !atobool(value); OPT2("filter", "deblock") @@ -741,8 +810,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) { p->i_cqm_preset = X264_CQM_CUSTOM; b_error |= parse_cqm( value, p->cqm_4iy, 16 ); - b_error |= parse_cqm( value, p->cqm_4ic, 16 ); b_error |= parse_cqm( value, p->cqm_4py, 16 ); + b_error |= parse_cqm( value, p->cqm_4ic, 16 ); b_error |= parse_cqm( value, p->cqm_4pc, 16 ); } OPT("cqm8") @@ -750,6 +819,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) p->i_cqm_preset = X264_CQM_CUSTOM; b_error |= parse_cqm( value, p->cqm_8iy, 64 ); b_error |= parse_cqm( value, p->cqm_8py, 64 ); + b_error |= parse_cqm( value, p->cqm_8ic, 64 ); + b_error |= parse_cqm( value, p->cqm_8pc, 64 ); } OPT("cqm4i") { @@ -787,11 +858,13 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) { p->i_cqm_preset = X264_CQM_CUSTOM; b_error |= parse_cqm( value, p->cqm_8iy, 64 ); + b_error |= parse_cqm( value, p->cqm_8ic, 64 ); } OPT("cqm8p") { p->i_cqm_preset = X264_CQM_CUSTOM; b_error |= parse_cqm( value, p->cqm_8py, 64 ); + b_error |= parse_cqm( value, p->cqm_8pc, 64 ); } OPT("log") p->i_log_level = atoi(value); @@ -929,6 +1002,9 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) p->rc.f_complexity_blur = atof(value); OPT("zones") p->rc.psz_zones = strdup(value); + OPT("crop-rect") + b_error |= sscanf( value, "%u,%u,%u,%u", &p->crop_rect.i_left, &p->crop_rect.i_top, + &p->crop_rect.i_right, &p->crop_rect.i_bottom ) != 4; OPT("psnr") p->analyse.b_psnr = atobool(value); OPT("ssim") @@ -951,6 +1027,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) p->b_pic_struct = atobool(value); OPT("fake-interlaced") p->b_fake_interlaced = atobool(value); + OPT("frame-packing") + p->i_frame_packing = atoi(value); else return X264_PARAM_BAD_NAME; #undef OPT @@ -1015,7 +1093,7 @@ void x264_picture_init( x264_picture_t *pic ) { memset( pic, 0, sizeof( x264_picture_t ) ); pic->i_type = X264_TYPE_AUTO; - pic->i_qpplus1 = 0; + pic->i_qpplus1 = X264_QP_AUTO; pic->i_pic_struct = PIC_STRUCT_AUTO; } @@ -1024,17 +1102,50 @@ void x264_picture_init( x264_picture_t *pic ) ****************************************************************************/ int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height ) { + typedef struct + { + int planes; + int width_fix8[3]; + int height_fix8[3]; + } x264_csp_tab_t; + + static const x264_csp_tab_t x264_csp_tab[] = + { + [X264_CSP_I420] = { 3, { 256*1, 256/2, 256/2 }, { 256*1, 256/2, 256/2 } }, + [X264_CSP_YV12] = { 3, { 256*1, 256/2, 256/2 }, { 256*1, 256/2, 256/2 } }, + [X264_CSP_NV12] = { 2, { 256*1, 256*1 }, { 256*1, 256/2 }, }, + [X264_CSP_I422] = { 3, { 256*1, 256/2, 256/2 }, { 256*1, 256*1, 256*1 } }, + [X264_CSP_YV16] = { 3, { 256*1, 256/2, 256/2 }, { 256*1, 256*1, 256*1 } }, + [X264_CSP_NV16] = { 2, { 256*1, 256*1 }, { 256*1, 256*1 }, }, + [X264_CSP_I444] = { 3, { 256*1, 256*1, 256*1 }, { 256*1, 256*1, 256*1 } }, + [X264_CSP_YV24] = { 3, { 256*1, 256*1, 256*1 }, { 256*1, 256*1, 256*1 } }, + [X264_CSP_BGR] = { 1, { 256*3 }, { 256*1 }, }, + [X264_CSP_BGRA] = { 1, { 256*4 }, { 256*1 }, }, + [X264_CSP_RGB] = { 1, { 256*3 }, { 256*1 }, }, + }; + + int csp = i_csp & X264_CSP_MASK; + if( csp <= X264_CSP_NONE || csp >= X264_CSP_MAX ) + return -1; x264_picture_init( pic ); pic->img.i_csp = i_csp; - pic->img.i_plane = 3; - pic->img.plane[0] = x264_malloc( 3 * i_width * i_height / 2 ); + pic->img.i_plane = x264_csp_tab[csp].planes; + int depth_factor = i_csp & X264_CSP_HIGH_DEPTH ? 2 : 1; + int plane_offset[3] = {0}; + int frame_size = 0; + for( int i = 0; i < pic->img.i_plane; i++ ) + { + int stride = (((int64_t)i_width * x264_csp_tab[csp].width_fix8[i]) >> 8) * depth_factor; + int plane_size = (((int64_t)i_height * x264_csp_tab[csp].height_fix8[i]) >> 8) * stride; + pic->img.i_stride[i] = stride; + plane_offset[i] = frame_size; + frame_size += plane_size; + } + pic->img.plane[0] = x264_malloc( frame_size ); if( !pic->img.plane[0] ) return -1; - pic->img.plane[1] = pic->img.plane[0] + i_width * i_height; - pic->img.plane[2] = pic->img.plane[1] + i_width * i_height / 4; - pic->img.i_stride[0] = i_width; - pic->img.i_stride[1] = i_width / 2; - pic->img.i_stride[2] = i_width / 2; + for( int i = 1; i < pic->img.i_plane; i++ ) + pic->img.plane[i] = pic->img.plane[0] + plane_offset[i]; return 0; } @@ -1055,7 +1166,7 @@ void x264_picture_clean( x264_picture_t *pic ) void *x264_malloc( int i_size ) { uint8_t *align_buf = NULL; -#if SYS_MACOSX || (SYS_MINGW && ARCH_X86_64) +#if SYS_MACOSX || (SYS_WINDOWS && ARCH_X86_64) /* Mac OS X and Win x64 always returns 16 byte aligned memory */ align_buf = malloc( i_size ); #elif HAVE_MALLOC_H @@ -1081,7 +1192,7 @@ void x264_free( void *p ) { if( p ) { -#if HAVE_MALLOC_H || SYS_MACOSX || (SYS_MINGW && ARCH_X86_64) +#if HAVE_MALLOC_H || SYS_MACOSX || (SYS_WINDOWS && ARCH_X86_64) free( p ); #else free( *( ( ( void **) p ) - 1 ) ); @@ -1120,7 +1231,7 @@ REDUCE_FRACTION( x264_reduce_fraction64, uint64_t ) char *x264_slurp_file( const char *filename ) { int b_error = 0; - int i_size; + size_t i_size; char *buf; FILE *fh = fopen( filename, "rb" ); if( !fh ) @@ -1129,10 +1240,10 @@ char *x264_slurp_file( const char *filename ) b_error |= ( i_size = ftell( fh ) ) <= 0; b_error |= fseek( fh, 0, SEEK_SET ) < 0; if( b_error ) - return NULL; + goto error; buf = x264_malloc( i_size+2 ); - if( buf == NULL ) - return NULL; + if( !buf ) + goto error; b_error |= fread( buf, 1, i_size, fh ) != i_size; if( buf[i_size-1] != '\n' ) buf[i_size++] = '\n'; @@ -1144,6 +1255,9 @@ char *x264_slurp_file( const char *filename ) return NULL; } return buf; +error: + fclose( fh ); + return NULL; } /**************************************************************************** @@ -1164,6 +1278,7 @@ char *x264_param2string( x264_param_t *p, int b_res ) s += sprintf( s, "%dx%d ", p->i_width, p->i_height ); s += sprintf( s, "fps=%u/%u ", p->i_fps_num, p->i_fps_den ); s += sprintf( s, "timebase=%u/%u ", p->i_timebase_num, p->i_timebase_den ); + s += sprintf( s, "bitdepth=%d ", BIT_DEPTH ); } s += sprintf( s, "cabac=%d", p->b_cabac ); @@ -1186,6 +1301,7 @@ char *x264_param2string( x264_param_t *p, int b_res ) s += sprintf( s, " fast_pskip=%d", p->analyse.b_fast_pskip ); s += sprintf( s, " chroma_qp_offset=%d", p->analyse.i_chroma_qp_offset ); s += sprintf( s, " threads=%d", p->i_threads ); + s += sprintf( s, " lookahead_threads=%d", p->i_lookahead_threads ); s += sprintf( s, " sliced_threads=%d", p->b_sliced_threads ); if( p->i_slice_count ) s += sprintf( s, " slices=%d", p->i_slice_count ); @@ -1196,6 +1312,7 @@ char *x264_param2string( x264_param_t *p, int b_res ) s += sprintf( s, " nr=%d", p->analyse.i_noise_reduction ); s += sprintf( s, " decimate=%d", p->analyse.b_dct_decimate ); s += sprintf( s, " interlaced=%s", p->b_interlaced ? p->b_tff ? "tff" : "bff" : p->b_fake_interlaced ? "fake" : "0" ); + s += sprintf( s, " bluray_compat=%d", p->b_bluray_compat ); s += sprintf( s, " constrained_intra=%d", p->b_constrained_intra ); @@ -1204,12 +1321,16 @@ char *x264_param2string( x264_param_t *p, int b_res ) { s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d weightb=%d open_gop=%d", p->i_bframe_pyramid, p->i_bframe_adaptive, p->i_bframe_bias, - p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred, p->i_open_gop ); + p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred, p->b_open_gop ); } s += sprintf( s, " weightp=%d", p->analyse.i_weighted_pred > 0 ? p->analyse.i_weighted_pred : 0 ); - s += sprintf( s, " keyint=%d keyint_min=%d scenecut=%d intra_refresh=%d", - p->i_keyint_max, p->i_keyint_min, p->i_scenecut_threshold, p->b_intra_refresh ); + if( p->i_keyint_max == X264_KEYINT_MAX_INFINITE ) + s += sprintf( s, " keyint=infinite" ); + else + s += sprintf( s, " keyint=%d", p->i_keyint_max ); + s += sprintf( s, " keyint_min=%d scenecut=%d intra_refresh=%d", + p->i_keyint_min, p->i_scenecut_threshold, p->b_intra_refresh ); if( p->rc.b_mb_tree || p->rc.i_vbv_buffer_size ) s += sprintf( s, " rc_lookahead=%d", p->rc.i_lookahead ); @@ -1239,6 +1360,15 @@ char *x264_param2string( x264_param_t *p, int b_res ) } else if( p->rc.i_rc_method == X264_RC_CQP ) s += sprintf( s, " qp=%d", p->rc.i_qp_constant ); + + if( p->rc.i_vbv_buffer_size ) + s += sprintf( s, " nal_hrd=%s", x264_nal_hrd_names[p->i_nal_hrd] ); + if( p->crop_rect.i_left | p->crop_rect.i_top | p->crop_rect.i_right | p->crop_rect.i_bottom ) + s += sprintf( s, " crop_rect=%u,%u,%u,%u", p->crop_rect.i_left, p->crop_rect.i_top, + p->crop_rect.i_right, p->crop_rect.i_bottom ); + if( p->i_frame_packing >= 0 ) + s += sprintf( s, " frame-packing=%d", p->i_frame_packing ); + if( !(p->rc.i_rc_method == X264_RC_CQP && p->rc.i_qp_constant == 0) ) { s += sprintf( s, " ip_ratio=%.2f", p->rc.f_ip_factor ); @@ -1253,8 +1383,6 @@ char *x264_param2string( x264_param_t *p, int b_res ) s += sprintf( s, " zones" ); } - if( p->rc.i_vbv_buffer_size ) - s += sprintf( s, " nal_hrd=%s", x264_nal_hrd_names[p->i_nal_hrd] ); return buf; }