Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git common/common.c common/common.c
- index 69941de..5769b45 100644
- --- common/common.c
- +++ common/common.c
- @@ -24,6 +24,7 @@
- * For more information, contact us at licensing@x264.com.
- *****************************************************************************/
- +#include <string.h>
- #include "common.h"
- #include <stdarg.h>
- @@ -70,6 +71,7 @@ void x264_param_default( x264_param_t *param )
- param->i_slice_max_size = 0;
- param->i_slice_max_mbs = 0;
- param->i_slice_count = 0;
- + param->b_mvc = 0;
- /* Encoder parameters */
- param->i_frame_reference = 3;
- @@ -137,6 +139,7 @@ void x264_param_default( x264_param_t *param )
- param->analyse.b_chroma_me = 1;
- param->analyse.i_mv_range_thread = -1;
- param->analyse.i_mv_range = -1; // set from level_idc
- + param->analyse.i_original_chroma_qp_offset =
- param->analyse.i_chroma_qp_offset = 0;
- param->analyse.b_fast_pskip = 1;
- param->analyse.b_weighted_bipred = 1;
- @@ -545,6 +548,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- int name_was_bool;
- int value_was_null = !value;
- int i;
- + int view = 0;
- + int total_bitrate = 0;
- if( !name )
- return X264_PARAM_BAD_NAME;
- @@ -825,7 +830,7 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- p->b_visualize = atobool(value);
- #endif
- OPT("dump-yuv")
- - p->psz_dump_yuv = strdup(value);
- + p->psz_dump_yuv[0] = strdup(value);
- OPT2("analyse", "partitions")
- {
- p->analyse.inter = 0;
- @@ -847,7 +852,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- OPT2("direct", "direct-pred")
- b_error |= parse_enum( value, x264_direct_pred_names, &p->analyse.i_direct_mv_pred );
- OPT("chroma-qp-offset")
- + {
- + p->analyse.i_original_chroma_qp_offset =
- p->analyse.i_chroma_qp_offset = atoi(value);
- + }
- OPT("me")
- b_error |= parse_enum( value, x264_motion_est_names, &p->analyse.i_me_method );
- OPT2("merange", "me-range")
- @@ -894,8 +902,36 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- p->analyse.i_noise_reduction = atoi(value);
- OPT("bitrate")
- {
- - p->rc.i_bitrate = atoi(value);
- - p->rc.i_rc_method = X264_RC_ABR;
- + int sub_rate_sum = 0;
- + char *bitrate_buf = (char*)x264_malloc(strlen(value) + 1);
- + char *ptr, *save_ptr;
- + if (!bitrate_buf)
- + b_error |= 1;
- + else {
- + strcpy(bitrate_buf, value);
- + for (ptr = strtok_r(bitrate_buf, ":", &save_ptr); view < MAX_DEP_STREAM + 1 && ptr != NULL; ptr = strtok_r(NULL, ":", &save_ptr)) {
- + if (view == 0) total_bitrate = atoi(ptr);
- + else {
- + p->rc.i_bitrate_dep[view-1] = atoi(ptr);
- + sub_rate_sum += p->rc.i_bitrate_dep[view-1];
- + }
- + view++;
- + }
- + x264_free(bitrate_buf);
- + b_error |= sub_rate_sum >= total_bitrate;
- + p->rc.i_bitrate = total_bitrate - sub_rate_sum;
- + p->rc.i_rc_method = X264_RC_ABR;
- +
- + if (view > 1) {
- + int total_maxrate = p->rc.i_vbv_max_bitrate;
- + if (total_maxrate > 0) {
- + p->rc.i_vbv_max_bitrate = (int)((float)total_maxrate * (float)p->rc.i_bitrate / (float)total_bitrate);
- + for (int view_id = 0; view_id<view-1; view_id++) {
- + p->rc.i_vbv_max_bitrate_dep[view_id] = (int)((float)total_maxrate * (float)p->rc.i_bitrate_dep[view_id] / (float)total_bitrate);
- + }
- + }
- + }
- + }
- }
- OPT2("qp", "qp_constant")
- {
- @@ -920,7 +956,21 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- OPT("ratetol")
- p->rc.f_rate_tolerance = !strncmp("inf", value, 3) ? 1e9 : atof(value);
- OPT("vbv-maxrate")
- - p->rc.i_vbv_max_bitrate = atoi(value);
- + {
- + int total_maxrate = atoi(value);
- + int total_rate = p->rc.i_bitrate;
- + for (int view_id = 0; view_id < MAX_DEP_STREAM; view_id++) {
- + total_rate += p->rc.i_bitrate_dep[view_id];
- + }
- + if (total_rate > 0) {
- + p->rc.i_vbv_max_bitrate = (int)((float)total_maxrate * (float)p->rc.i_bitrate / (float)total_rate);
- + for (int view_id = 0; view_id < MAX_DEP_STREAM; view_id++) {
- + p->rc.i_vbv_max_bitrate_dep[view_id] = total_maxrate * p->rc.i_bitrate_dep[view_id] / total_rate;
- + }
- + } else {
- + p->rc.i_vbv_max_bitrate = total_maxrate;
- + }
- + }
- OPT("vbv-bufsize")
- p->rc.i_vbv_buffer_size = atoi(value);
- OPT("vbv-init")
- @@ -981,6 +1031,18 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- p->b_fake_interlaced = atobool(value);
- OPT("frame-packing")
- p->i_frame_packing = atoi(value);
- + OPT("timecode-offset")
- + {
- + int hour, minute, second, frame;
- + int field_num = sscanf(value, "%2d:%2d:%2d:%2d", &hour, &minute, &second, &frame);
- + if (field_num != 4) b_error |= -1;
- + else {
- + p->timecode_offset.hour = hour;
- + p->timecode_offset.minute = minute;
- + p->timecode_offset.second = second;
- + p->timecode_offset.frame = frame;
- + }
- + }
- else
- return X264_PARAM_BAD_NAME;
- #undef OPT
- @@ -1100,6 +1162,7 @@ void *x264_malloc( int i_size )
- align_buf = malloc( i_size );
- #elif HAVE_MALLOC_H
- align_buf = memalign( 16, i_size );
- +// x264_log( NULL, X264_LOG_INFO, "memalign : %p\n", align_buf);
- #else
- uint8_t *buf = malloc( i_size + 15 + sizeof(void **) );
- if( buf )
- @@ -1192,7 +1255,7 @@ error:
- /****************************************************************************
- * x264_param2string:
- ****************************************************************************/
- -char *x264_param2string( x264_param_t *p, int b_res )
- +char *x264_param2string( x264_param_t *p, int b_res, int view )
- {
- int len = 1000;
- char *buf, *s;
- @@ -1271,7 +1334,7 @@ char *x264_param2string( x264_param_t *p, int b_res )
- s += sprintf( s, " crf=%.1f", p->rc.f_rf_constant );
- else
- s += sprintf( s, " bitrate=%d ratetol=%.1f",
- - p->rc.i_bitrate, p->rc.f_rate_tolerance );
- + view == 0 ? p->rc.i_bitrate : p->rc.i_bitrate_dep[view-1], p->rc.f_rate_tolerance );
- s += sprintf( s, " qcomp=%.2f qpmin=%d qpmax=%d qpstep=%d",
- p->rc.f_qcompress, p->rc.i_qp_min, p->rc.i_qp_max, p->rc.i_qp_step );
- if( p->rc.b_stat_read )
- @@ -1280,7 +1343,7 @@ char *x264_param2string( x264_param_t *p, int b_res )
- if( p->rc.i_vbv_buffer_size )
- {
- s += sprintf( s, " vbv_maxrate=%d vbv_bufsize=%d",
- - p->rc.i_vbv_max_bitrate, p->rc.i_vbv_buffer_size );
- + view == 0 ? p->rc.i_vbv_max_bitrate : p->rc.i_vbv_max_bitrate_dep[view-1], p->rc.i_vbv_buffer_size );
- if( p->rc.i_rc_method == X264_RC_CRF )
- s += sprintf( s, " crf_max=%.1f", p->rc.f_rf_constant_max );
- }
- @@ -1313,3 +1376,34 @@ char *x264_param2string( x264_param_t *p, int b_res )
- return buf;
- }
- +
- +// Here is utilities to show about encoding frames
- +void log_ref_list( x264_t *h )
- +{
- +#if 0
- + int i, j;
- + static char frame_type_name[] = {
- + 'P', 'B', 'I'
- + };
- + static int count = 0;
- + x264_log( h, X264_LOG_INFO, "Start log_ref_list() (called %d time(s)).\n", ++count );
- + if( h->fenc != NULL )
- + x264_log( h, X264_LOG_INFO, "Start log_ref_list(%d ,%c-FRAME).\n", h->fenc->i_frame, frame_type_name[h->sh.i_type] );
- + //if (h->param.b_interlaced == 1) {
- + // x264_log( h, X264_LOG_INFO, "Interlaced.\n" );
- + //} else {
- + // x264_log( h, X264_LOG_INFO, "Progressive.\n" );
- + //}
- + for (i = 0; i < 2; ++i) {
- + x264_log( h, X264_LOG_INFO, "i_ref[%d]: %d\n", i, h->i_ref[i] );
- + for (j = 0; j < h->i_ref[i]; ++j) {
- + x264_frame_t *fref = h->fref[i][j];
- + x264_log( h, X264_LOG_INFO, "fref[%d][%d]: %d/%d\n", i, j, fref->i_frame, fref->i_coded );
- + }
- + //x264_log( h, X264_LOG_INFO, "fref_nearest[%d]: %d/%d\n", i, h->fref_nearest[i]->i_frame, h->fref_nearest[i]->i_coded );
- + //x264_log( h, X264_LOG_INFO, "b_ref_reorder[%d]: %d/%d\n", i, h->b_ref_reorder[i], h->b_ref_reorder[i] );
- + }
- + x264_log( h, X264_LOG_INFO, "End log_ref_list().\n\n", i, h->i_ref[i] );
- +#endif
- +}
- +
- diff --git common/common.h common/common.h
- index f2021b6..cb7446a 100644
- --- common/common.h
- +++ common/common.h
- @@ -27,6 +27,8 @@
- #ifndef X264_COMMON_H
- #define X264_COMMON_H
- +//#define _DEBUG
- +
- /****************************************************************************
- * Macros
- ****************************************************************************/
- @@ -81,6 +83,14 @@ do {\
- #define NALU_OVERHEAD 5 // startcode + NAL type costs 5 bytes per frame
- #define FILLER_OVERHEAD (NALU_OVERHEAD+1)
- +#define MAX_MVC_VIEW 2
- +
- +#define IS_SLICE_TYPE_P(type) ((type) % 5 == SLICE_TYPE_P)
- +#define IS_SLICE_TYPE_B(type) ((type) % 5 == SLICE_TYPE_B)
- +#define IS_SLICE_TYPE_I(type) ((type) % 5 == SLICE_TYPE_I)
- +#define IS_SLICE_TYPE_SP(type) ((type) % 5 == SLICE_TYPE_SP)
- +#define IS_SLICE_TYPE_SI(type) ((type) % 5 == SLICE_TYPE_SI)
- +
- /****************************************************************************
- * Includes
- ****************************************************************************/
- @@ -198,7 +208,7 @@ int64_t x264_mdate( void );
- /* x264_param2string: return a (malloced) string containing most of
- * the encoding options */
- -char *x264_param2string( x264_param_t *p, int b_res );
- +char *x264_param2string( x264_param_t *p, int b_res, int view );
- /* log */
- void x264_log( x264_t *h, int i_level, const char *psz_fmt, ... );
- @@ -297,6 +307,8 @@ enum slice_type_e
- SLICE_TYPE_P = 0,
- SLICE_TYPE_B = 1,
- SLICE_TYPE_I = 2,
- + SLICE_TYPE_SP = 3,
- + SLICE_TYPE_SI = 4,
- };
- static const char slice_type_to_char[] = { 'P', 'B', 'I' };
- @@ -318,7 +330,11 @@ typedef struct
- x264_sps_t *sps;
- x264_pps_t *pps;
- + x264_sps_t *subset_sps;
- + x264_pps_t *subset_pps;
- +
- int i_type;
- + int b_anchor;
- int i_first_mb;
- int i_last_mb;
- @@ -349,7 +365,7 @@ typedef struct
- {
- int idc;
- int arg;
- - } ref_pic_list_order[2][X264_REF_MAX];
- + } ref_pic_list_order[2][X264_REF_MAX + 1]; /* "+ 1" is for inter-view prediction. */
- /* P-frame weighting */
- x264_weight_t weight[X264_REF_MAX*2][3];
- @@ -374,6 +390,15 @@ typedef struct
- int i_alpha_c0_offset;
- int i_beta_offset;
- + /* MVC slice layer extension */
- + int b_svc_extension_flag;
- + int b_non_idr_flag;
- + int i_priority_id;
- + int i_view_id;
- + int i_temporal_id;
- + int b_anchor_pic_flag;
- + int b_inter_view_flag;
- + int b_reserved_one_bit;
- } x264_slice_header_t;
- typedef struct x264_lookahead_t
- @@ -384,9 +409,11 @@ typedef struct x264_lookahead_t
- int i_last_keyframe;
- int i_slicetype_length;
- x264_frame_t *last_nonb;
- + x264_frame_t *last_nonb_dependent;
- x264_pthread_t thread_handle;
- x264_sync_frame_list_t ifbuf;
- x264_sync_frame_list_t next;
- + x264_sync_frame_list_t next_dependent;
- x264_sync_frame_list_t ofbuf;
- } x264_lookahead_t;
- @@ -421,11 +448,20 @@ struct x264_t
- x264_sps_t *sps;
- x264_pps_t *pps;
- + x264_sps_t *subset_sps;
- + x264_pps_t *subset_pps;
- +
- + int64_t offset_frame; /* start frame calculated from x264_param_t::timecode_offset */
- +
- /**** thread synchronization starts here ****/
- /* frame number/poc */
- int i_frame;
- int i_frame_num;
- +
- + int b_once_buffer_filled;
- +
- + int b_dependent;
- int i_thread_frames; /* Number of different frames being encoded by threads;
- * 1 when sliced-threads is on. */
- @@ -442,18 +478,22 @@ struct x264_t
- int64_t i_cpb_delay_lookahead;
- int64_t i_cpb_delay_pir_offset;
- + int64_t i_cpb_delay_pir_offset_dep;
- int b_queued_intra_refresh;
- int64_t i_last_idr_pts;
- + int i_last_idr_frame;
- /* We use only one SPS and one PPS */
- - x264_sps_t sps_array[1];
- - x264_pps_t pps_array[1];
- + x264_sps_t sps_array[2];
- + x264_pps_t pps_array[2];
- int i_idr_pic_id;
- /* quantization matrix for decoding, [cqm][qp%6][coef] */
- - int (*dequant4_mf[4])[16]; /* [4][6][16] */
- - int (*dequant8_mf[2])[64]; /* [2][6][64] */
- + //int (*dequant4_mf[4])[16]; /* [4][6][16] */
- + //int (*dequant8_mf[2])[64]; /* [2][6][64] */
- + int dequant4_mf[4][6][16];
- + int dequant8_mf[2][6][64];
- /* quantization matrix for trellis, [cqm][qp][coef] */
- int (*unquant4_mf[4])[16]; /* [4][52][16] */
- int (*unquant8_mf[2])[64]; /* [2][52][64] */
- @@ -487,7 +527,7 @@ struct x264_t
- x264_frame_t **blank_unused;
- /* frames used for reference + sentinels */
- - x264_frame_t *reference[X264_REF_MAX+2];
- + x264_frame_t *reference[(X264_REF_MAX*2)+3];
- int i_last_keyframe; /* Frame number of the last keyframe */
- int i_last_idr; /* Frame number of the last IDR (not RP)*/
- @@ -526,6 +566,8 @@ struct x264_t
- /* hrd */
- int initial_cpb_removal_delay;
- int initial_cpb_removal_delay_offset;
- + int initial_cpb_removal_delay_dep;
- + int initial_cpb_removal_delay_offset_dep;
- int64_t i_reordered_pts_delay;
- /* Current MB DCT coeffs */
- @@ -754,6 +796,7 @@ struct x264_t
- /* rate control encoding only */
- x264_ratecontrol_t *rc;
- + x264_ratecontrol_t *rc_mvc[1+MAX_DEP_STREAM];
- /* stats */
- struct
- @@ -812,6 +855,10 @@ struct x264_t
- /* num p-frames weighted */
- int i_wpred[2];
- + /* for MVC rc */
- + int i_frame_dep_count[3];
- + int64_t i_frame_dep_size[3];
- + double f_frame_dep_qp[3];
- } stat;
- /* 0 = luma 4x4, 1 = luma 8x8, 2 = chroma 4x4 */
- @@ -857,5 +904,8 @@ struct x264_t
- #include "x86/util.h"
- #endif
- +// Here is utilities to learn x264. Do not commit this source.
- +void log_ref_list( x264_t * );
- +
- #endif
- diff --git common/frame.h common/frame.h
- index 38d0bf2..7dbe566 100644
- --- common/frame.h
- +++ common/frame.h
- @@ -38,6 +38,7 @@ typedef struct x264_frame
- int i_poc;
- int i_delta_poc[2];
- int i_type;
- + int i_last_type; /* save last type of base view for MVC */
- int i_qpplus1;
- int64_t i_pts;
- int64_t i_dts;
- @@ -156,6 +157,10 @@ typedef struct x264_frame
- /* user sei */
- x264_sei_t extra_sei;
- +
- + /* for MVV */
- + int is_dependent;
- + int b_inter_view_only;
- } x264_frame_t;
- /* synchronized frame list */
- diff --git common/macroblock.c common/macroblock.c
- index 24c2af9..f1777da 100644
- --- common/macroblock.c
- +++ common/macroblock.c
- @@ -236,7 +236,7 @@ int x264_macroblock_cache_allocate( x264_t *h )
- for( int i = 0; i < 2; i++ )
- {
- - int i_refs = X264_MIN(X264_REF_MAX, (i ? 1 + !!h->param.i_bframe_pyramid : h->param.i_frame_reference) ) << h->param.b_interlaced;
- + int i_refs = X264_MIN(X264_REF_MAX, (i ? 1 + !!h->param.i_bframe_pyramid : h->param.i_frame_reference + h->param.b_mvc) ) << h->param.b_interlaced;
- if( h->param.analyse.i_weighted_pred == X264_WEIGHTP_SMART )
- i_refs = X264_MIN(X264_REF_MAX, i_refs + 1 + (BIT_DEPTH == 8)); //smart weights add two duplicate frames, one in >8-bit
- diff --git common/quant.c common/quant.c
- index 8ae20a0..1078c09 100644
- --- common/quant.c
- +++ common/quant.c
- @@ -439,11 +439,13 @@ void x264_quant_init( x264_t *h, int cpu, x264_quant_function_t *pf )
- pf->dequant_4x4 = x264_dequant_4x4_mmx;
- pf->dequant_4x4_dc = x264_dequant_4x4dc_mmxext;
- pf->dequant_8x8 = x264_dequant_8x8_mmx;
- +#ifdef ENABLE_FAST_QUANT
- if( h->param.i_cqm_preset == X264_CQM_FLAT )
- {
- pf->dequant_4x4 = x264_dequant_4x4_flat16_mmx;
- pf->dequant_8x8 = x264_dequant_8x8_flat16_mmx;
- }
- +#endif
- pf->denoise_dct = x264_denoise_dct_mmx;
- #endif
- }
- @@ -484,11 +486,13 @@ void x264_quant_init( x264_t *h, int cpu, x264_quant_function_t *pf )
- pf->dequant_4x4 = x264_dequant_4x4_sse2;
- pf->dequant_4x4_dc = x264_dequant_4x4dc_sse2;
- pf->dequant_8x8 = x264_dequant_8x8_sse2;
- +#ifdef ENABLE_FAST_QUANT
- if( h->param.i_cqm_preset == X264_CQM_FLAT )
- {
- pf->dequant_4x4 = x264_dequant_4x4_flat16_sse2;
- pf->dequant_8x8 = x264_dequant_8x8_flat16_sse2;
- }
- +#endif
- pf->optimize_chroma_dc = x264_optimize_chroma_dc_sse2;
- pf->denoise_dct = x264_denoise_dct_sse2;
- pf->decimate_score15 = x264_decimate_score15_sse2;
- diff --git common/set.c common/set.c
- index f8f6a11..b2a6a2b 100644
- --- common/set.c
- +++ common/set.c
- @@ -93,27 +93,31 @@ int x264_cqm_init( x264_t *h )
- for( j = (i<4 ? 0 : 4); j < i; j++ )
- if( !memcmp( h->pps->scaling_list[i], h->pps->scaling_list[j], size*sizeof(uint8_t) ) )
- break;
- - if( j < i )
- + if( 0 ) // all parameters have to be different to change matrix while encoding.
- {
- h-> quant4_mf[i] = h-> quant4_mf[j];
- - h->dequant4_mf[i] = h->dequant4_mf[j];
- + //h->dequant4_mf[i] = h->dequant4_mf[j];
- h->unquant4_mf[i] = h->unquant4_mf[j];
- }
- else
- {
- - CHECKED_MALLOC( h-> quant4_mf[i], (QP_MAX+1)*size*sizeof(udctcoef) );
- - CHECKED_MALLOC( h->dequant4_mf[i], 6*size*sizeof(int) );
- - CHECKED_MALLOC( h->unquant4_mf[i], (QP_MAX+1)*size*sizeof(int) );
- + if (!h-> quant4_mf[i])
- + CHECKED_MALLOC( h-> quant4_mf[i], (QP_MAX+1)*size*sizeof(udctcoef) );
- + //if (!h->dequant4_mf[i])
- + // CHECKED_MALLOC( h->dequant4_mf[i], 6*size*sizeof(int) );
- + if (!h->unquant4_mf[i])
- + CHECKED_MALLOC( h->unquant4_mf[i], (QP_MAX+1)*size*sizeof(int) );
- }
- for( j = (i<4 ? 0 : 4); j < i; j++ )
- if( deadzone[j&3] == deadzone[i&3] &&
- !memcmp( h->pps->scaling_list[i], h->pps->scaling_list[j], size*sizeof(uint8_t) ) )
- break;
- - if( j < i )
- + if(0) // all parameters have to be different to change matrix while encoding.
- h->quant4_bias[i] = h->quant4_bias[j];
- else
- - CHECKED_MALLOC( h->quant4_bias[i], (QP_MAX+1)*size*sizeof(udctcoef) );
- + if (!h->quant4_bias[i])
- + CHECKED_MALLOC( h->quant4_bias[i], (QP_MAX+1)*size*sizeof(udctcoef) );
- }
- for( int q = 0; q < 6; q++ )
- @@ -188,7 +192,8 @@ int x264_cqm_init( x264_t *h )
- /* Emergency mode denoising. */
- x264_emms();
- - CHECKED_MALLOC( h->nr_offset_emergency, sizeof(*h->nr_offset_emergency)*(QP_MAX-QP_MAX_SPEC) );
- + if (!h->nr_offset_emergency)
- + CHECKED_MALLOC( h->nr_offset_emergency, sizeof(*h->nr_offset_emergency)*(QP_MAX-QP_MAX_SPEC) );
- for( int q = 0; q < QP_MAX - QP_MAX_SPEC; q++ )
- for( int cat = 0; cat <= 2; cat++ )
- {
- @@ -262,7 +267,7 @@ fail:
- if( j == i )\
- {\
- x264_free( h-> quant##n##_mf[i] );\
- - x264_free( h->dequant##n##_mf[i] );\
- + /*x264_free( h->dequant##n##_mf[i] );*/\
- x264_free( h->unquant##n##_mf[i] );\
- }\
- for( j = 0; j < i; j++ )\
- diff --git common/set.h common/set.h
- index fb81c1a..b94c546 100644
- --- common/set.h
- +++ common/set.h
- @@ -35,6 +35,7 @@ enum profile_e
- PROFILE_HIGH = 100,
- PROFILE_HIGH10 = 110,
- PROFILE_HIGH422 = 122,
- + PROFILE_STEREO_HIGH = 128,
- PROFILE_HIGH444 = 144,
- PROFILE_HIGH444_PREDICTIVE = 244,
- };
- diff --git encoder/analyse.c encoder/analyse.c
- index 29597eb..eb09e6f 100644
- --- encoder/analyse.c
- +++ encoder/analyse.c
- @@ -3576,6 +3576,7 @@ static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a )
- default:
- x264_log( h, X264_LOG_ERROR, "internal error P_L0 and partition=%d\n", h->mb.i_partition );
- + // exit(1);
- break;
- }
- break;
- diff --git encoder/encoder.c encoder/encoder.c
- index d42ca31..7460c96 100644
- --- encoder/encoder.c
- +++ encoder/encoder.c
- @@ -37,11 +37,13 @@
- #include "common/visualize.h"
- #endif
- +//#define __DEBUG
- //#define DEBUG_MB_TYPE
- #define bs_write_ue bs_write_ue_big
- static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
- + x264_t *thread_next,
- x264_nal_t **pp_nal, int *pi_nal,
- x264_picture_t *pic_out );
- @@ -66,11 +68,23 @@ static double x264_ssim( double ssim )
- static void x264_frame_dump( x264_t *h )
- {
- - FILE *f = fopen( h->param.psz_dump_yuv, "r+b" );
- + int view_id;
- + char *name;
- + if( h->param.b_mvc && (h->fdec->i_frame % 2) )
- + view_id = 1;
- + else
- + view_id = 0;
- +
- + FILE *f = fopen( h->param.psz_dump_yuv[view_id], "r+b" );
- if( !f )
- + {
- + x264_log(h, X264_LOG_ERROR, "Failed to open %s\n", h->param.psz_dump_yuv[view_id]);
- return;
- + }
- +
- /* Write the frame in display order */
- - fseek( f, (uint64_t)h->fdec->i_frame * h->param.i_height * h->param.i_width * 3/2 * sizeof(pixel), SEEK_SET );
- + uint64_t offset = ((uint64_t)h->fdec->i_frame / ( h->param.b_mvc + 1 )) * h->param.i_height * h->param.i_width * 3/2 * sizeof(pixel);
- + fseek( f, offset, SEEK_SET );
- for( int y = 0; y < h->param.i_height; y++ )
- fwrite( &h->fdec->plane[0][y*h->fdec->i_stride[0]], sizeof(pixel), h->param.i_width, f );
- int cw = h->param.i_width>>1;
- @@ -84,6 +98,32 @@ static void x264_frame_dump( x264_t *h )
- fclose( f );
- }
- +/* Fill ref_pic_list_reordering and ref_pic_list_order field in slice header. */
- +static void create_reordering_inst( x264_t *h, x264_slice_header_t *sh, int list, int pred_frame_num )
- +{
- + sh->b_ref_pic_list_reordering[list] = 1;
- + //printf(" RefPicListL%d of the frame %d (frame_num=%d) is\n", list, h->i_frame, h->i_frame_num);
- + for( int i = 0; i < h->i_ref[list]; i++ )
- + {
- + if( !h->b_dependent || h->fref[list][i]->i_frame_num != sh->i_frame_num )
- + {
- + //printf(" h->fref[%d][%d]->i_frame=%d (frame_num=%d) (intra view)\n", list, i, h->fref[list][i]->i_frame, h->fref[list][i]->i_frame_num);
- + int diff = h->fref[list][i]->i_frame_num - pred_frame_num;
- + //printf(" Order inst: idc=%d, arg=%d\n", ( diff > 0 ), (abs(diff) - 1) & ((1 << sh->sps->i_log2_max_frame_num) - 1));
- + sh->ref_pic_list_order[list][i].idc = ( diff > 0 );
- + sh->ref_pic_list_order[list][i].arg = (abs(diff) - 1) & ((1 << sh->sps->i_log2_max_frame_num) - 1);
- + pred_frame_num = h->fref[list][i]->i_frame_num;
- + }
- + else
- + {
- + //printf(" h->fref[%d][%d]->i_frame=%d (frame_num=%d) (inter view)\n", list, i, h->fref[list][i]->i_frame, h->fref[list][i]->i_frame_num);
- + //printf(" Order inst: idc=%d, arg=%d\n", 5, 0);
- + sh->b_ref_pic_list_reordering[list] = 1;
- + sh->ref_pic_list_order[list][i].idc = 5;
- + sh->ref_pic_list_order[list][i].arg = 0;
- + }
- + }
- +}
- /* Fill "default" values */
- static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
- @@ -92,15 +132,27 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
- {
- x264_param_t *param = &h->param;
- + int is_mvc = param->b_mvc;
- +
- /* First we fill all fields */
- sh->sps = sps;
- sh->pps = pps;
- + // for MVC slice header extension
- + sh->b_svc_extension_flag = 0;
- + sh->b_non_idr_flag = (i_idr_pic_id < 0);
- + sh->i_priority_id = 0;
- + sh->i_view_id = h->b_dependent;
- + sh->i_temporal_id = 0;
- + sh->b_anchor_pic_flag = (i_idr_pic_id < 0) ? 0 : 1;
- + sh->b_inter_view_flag = 0;
- + sh->b_reserved_one_bit = 1;
- +
- sh->i_first_mb = 0;
- sh->i_last_mb = h->mb.i_mb_count - 1;
- sh->i_pps_id = pps->i_id;
- - sh->i_frame_num = i_frame;
- + sh->i_frame_num = is_mvc ? i_frame / 2 : i_frame;
- sh->b_mbaff = h->param.b_interlaced;
- sh->b_field_pic = 0; /* no field support for now */
- @@ -141,21 +193,42 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
- sh->i_num_ref_idx_l0_active = 1;
- sh->i_num_ref_idx_l1_active = 1;
- - sh->b_ref_pic_list_reordering[0] = h->b_ref_reorder[0];
- - sh->b_ref_pic_list_reordering[1] = h->b_ref_reorder[1];
- + sh->b_ref_pic_list_reordering[0] = 0;//h->b_ref_reorder[0];
- + sh->b_ref_pic_list_reordering[1] = 0;//h->b_ref_reorder[1];
- + //printf("\nEncoding frame %d. (idr_pic_id=%d frame_num=%d type=%d)\n", h->i_frame, sh->i_idr_pic_id, sh->i_frame_num, h->fenc->i_type);
- + //if( h->sps != sps ) printf(" This frame has a subset sps/pps.\n");
- + //if( sh->b_non_idr_flag && h->b_dependent ) printf(" This frame is not IDR.\n");
- +
- /* If the ref list isn't in the default order, construct reordering header */
- for( int list = 0; list < 2; list++ )
- {
- if( sh->b_ref_pic_list_reordering[list] )
- {
- - int pred_frame_num = i_frame;
- + create_reordering_inst( h, sh, list, i_frame );
- + }
- + else if( h->b_dependent )
- + {
- + for( int i = 0; i < h->i_ref[list]; i++ )
- + if( h->fref[list][i]->i_frame_num == sh->i_frame_num )
- + {
- + create_reordering_inst( h, sh, list, i_frame / 2 );
- + break;
- + }
- + }
- + else
- + {
- + //printf(" RefPicListL%d (with no reordering) of the frame %d is\n", list, h->i_frame);
- for( int i = 0; i < h->i_ref[list]; i++ )
- {
- - int diff = h->fref[list][i]->i_frame_num - pred_frame_num;
- - sh->ref_pic_list_order[list][i].idc = ( diff > 0 );
- - sh->ref_pic_list_order[list][i].arg = (abs(diff) - 1) & ((1 << sps->i_log2_max_frame_num) - 1);
- - pred_frame_num = h->fref[list][i]->i_frame_num;
- + if( !h->b_dependent || h->fref[list][i]->i_frame_num != h->i_frame_num - 1 )
- + {
- + //printf(" h->fref[list][i]->i_frame=%d (intra view)\n", h->fref[list][i]->i_frame);
- + }
- + else
- + {
- + //printf(" h->fref[list][i]->i_frame=%d (inter view)\n", h->fref[list][i]->i_frame);
- + }
- }
- }
- }
- @@ -177,8 +250,19 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
- sh->i_beta_offset = param->i_deblocking_filter_beta << 1;
- }
- -static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal_ref_idc )
- +static void x264_slice_header_write(x264_t *h, bs_t *s, x264_slice_header_t *sh, int i_nal_ref_idc )
- {
- + if (sh->b_svc_extension_flag) { // write svc_extension_flag and nal_unit_header_mvc_extension()
- + bs_write1( s, 0 ); // svc_extension_flag -> mvc
- + bs_write1( s, sh->b_non_idr_flag );
- + bs_write( s, 6, sh->i_priority_id );
- + bs_write( s, 10, sh->i_view_id );
- + bs_write( s, 3, sh->i_temporal_id );
- + bs_write1( s, sh->b_anchor_pic_flag );
- + bs_write1( s, sh->b_inter_view_flag );
- + bs_write1( s, sh->b_reserved_one_bit );
- + }
- +
- if( sh->b_mbaff )
- {
- assert( sh->i_first_mb % (2*sh->sps->i_mb_width) == 0 );
- @@ -188,7 +272,13 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
- bs_write_ue( s, sh->i_first_mb );
- bs_write_ue( s, sh->i_type + 5 ); /* same type things */
- - bs_write_ue( s, sh->i_pps_id );
- +
- + if (!sh->b_svc_extension_flag) {
- + bs_write_ue( s, sh->i_pps_id );
- + } else { // for MVC dependent view
- + bs_write_ue( s, 1 );
- + }
- +
- bs_write( s, sh->sps->i_log2_max_frame_num, sh->i_frame_num & ((1<<sh->sps->i_log2_max_frame_num)-1) );
- if( !sh->sps->b_frame_mbs_only )
- @@ -199,11 +289,22 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
- }
- if( sh->i_idr_pic_id >= 0 ) /* NAL IDR */
- + {
- bs_write_ue( s, sh->i_idr_pic_id );
- + }
- - if( sh->sps->i_poc_type == 0 )
- + if( sh->sps->i_poc_type == 0 ) // always 0
- {
- + if (!h->param.b_mvc) {
- bs_write( s, sh->sps->i_log2_max_poc_lsb, sh->i_poc & ((1<<sh->sps->i_log2_max_poc_lsb)-1) );
- + } else { // mvc case
- + //if (!sh->b_svc_extension_flag) { // base view
- + bs_write( s, sh->sps->i_log2_max_poc_lsb, (sh->i_poc & ((1<<sh->sps->i_log2_max_poc_lsb)-1)) >> 1 );
- + //} else { // dependent view
- + // bs_write( s, sh->sps->i_log2_max_poc_lsb, (sh->i_poc & (((1<<sh->sps->i_log2_max_poc_lsb)-1)) - 2) >> 1);
- + //}
- + }
- +
- if( sh->pps->b_pic_order && !sh->b_field_pic )
- bs_write_se( s, sh->i_delta_poc_bottom );
- }
- @@ -220,7 +321,7 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
- if( sh->i_type == SLICE_TYPE_B )
- bs_write1( s, sh->b_direct_spatial_mv_pred );
- - if( sh->i_type == SLICE_TYPE_P || sh->i_type == SLICE_TYPE_B )
- + if( IS_SLICE_TYPE_P(sh->i_type) || IS_SLICE_TYPE_B(sh->i_type) )
- {
- bs_write1( s, sh->b_num_ref_idx_override );
- if( sh->b_num_ref_idx_override )
- @@ -232,20 +333,22 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
- }
- /* ref pic list reordering */
- - if( sh->i_type != SLICE_TYPE_I )
- + if( !IS_SLICE_TYPE_I(sh->i_type) )
- {
- bs_write1( s, sh->b_ref_pic_list_reordering[0] );
- if( sh->b_ref_pic_list_reordering[0] )
- {
- + //printf("Reordering %d frame(s).\n", sh->i_num_ref_idx_l0_active);
- for( int i = 0; i < sh->i_num_ref_idx_l0_active; i++ )
- {
- + //printf("Write command idc=%d, arg=%d\n", sh->ref_pic_list_order[0][i].idc, sh->ref_pic_list_order[0][i].arg );
- bs_write_ue( s, sh->ref_pic_list_order[0][i].idc );
- bs_write_ue( s, sh->ref_pic_list_order[0][i].arg );
- }
- bs_write_ue( s, 3 );
- }
- }
- - if( sh->i_type == SLICE_TYPE_B )
- + if( IS_SLICE_TYPE_B(sh->i_type) )
- {
- bs_write1( s, sh->b_ref_pic_list_reordering[1] );
- if( sh->b_ref_pic_list_reordering[1] )
- @@ -259,6 +362,55 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
- }
- }
- + /* FIXME! most be parameterized */
- + int ref_pic_list_modification_flag_l0 = 1; // always 1
- + int ref_pic_list_modification_flag_l1 = 0; // always 0?
- + int num_modification_of_pic_nums_idc = 4; // num of nums idc
- +
- + int modification_of_pic_nums_idc[4] = { 0, 3, 3, 3 };
- +
- + int abs_diff_pic_num_minus1 = 1;
- + int abs_diff_view_idx_minus1 = 1;
- +
- + // for MVC ref_pic_list_mvc_modification()
- +#if 0
- + if (sh->b_svc_extension_flag) {
- + if ((sh->i_type % 5 != 2) && (sh->i_type % 5 != 4)) { /* if type is neither I nor SI */
- + // ref_pic_list_modification_flag_l0
- + bs_write1( s, ref_pic_list_modification_flag_l0);
- +
- + if (ref_pic_list_modification_flag_l0) {
- + for (int i = 0; i < num_modification_of_pic_nums_idc; i++) {
- + // modification_of_pic_nums_idc_l0
- + bs_write_ue( s, modification_of_pic_nums_idc[i] );
- +
- + if ((modification_of_pic_nums_idc[i] == 0) || (modification_of_pic_nums_idc[i] == 1)) {
- + // abs_diff_pic_num_minus1
- + bs_write_ue( s, abs_diff_pic_num_minus1 );
- + } else if (modification_of_pic_nums_idc[i] == 2) {
- + // long_term_pic_num
- + bs_write_ue( s, 0 ); // maybe not used
- + } else if ((modification_of_pic_nums_idc[i] == 4) || (modification_of_pic_nums_idc[i] == 5)) {
- + // abs_diff_view_idx_minus1
- + bs_write_ue( s, abs_diff_view_idx_minus1 );
- + } else if (modification_of_pic_nums_idc[i] == 3) {
- + break;
- + }
- + // modification_of_pic_nums_idc_l0
- + }
- + }
- + }
- +
- + if (sh->i_type % 5 == 1) { /* if type is B */
- + // ref_pic_list_modification_flag_l1
- + bs_write1( s, ref_pic_list_modification_flag_l1);
- + if (ref_pic_list_modification_flag_l1) { // always 0
- + // none
- + }
- + }
- + }
- +#endif
- +
- if( sh->pps->b_weighted_pred && sh->i_type == SLICE_TYPE_P )
- {
- /* pred_weight_table() */
- @@ -517,7 +669,7 @@ static int x264_validate_parameters( x264_t *h )
- h->param.rc.f_pb_factor = 1;
- h->param.analyse.b_psnr = 0;
- h->param.analyse.b_ssim = 0;
- - h->param.analyse.i_chroma_qp_offset = 0;
- + h->param.analyse.i_original_chroma_qp_offset = 0;
- h->param.analyse.i_trellis = 0;
- h->param.analyse.b_fast_pskip = 0;
- h->param.analyse.i_noise_reduction = 0;
- @@ -563,7 +715,7 @@ static int x264_validate_parameters( x264_t *h )
- else if( h->param.rc.i_vbv_max_bitrate < h->param.rc.i_bitrate &&
- h->param.rc.i_rc_method == X264_RC_ABR )
- {
- - x264_log( h, X264_LOG_WARNING, "max bitrate less than average bitrate, assuming CBR\n" );
- + x264_log( h, X264_LOG_WARNING, "max bitrate(%d) less than average bitrate(%d), assuming CBR\n", h->param.rc.i_vbv_max_bitrate, h->param.rc.i_bitrate );
- h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
- }
- }
- @@ -703,7 +855,7 @@ static int x264_validate_parameters( x264_t *h )
- 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);
- + h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_original_chroma_qp_offset, -12, 12);
- h->param.analyse.i_trellis = x264_clip3( h->param.analyse.i_trellis, 0, 2 );
- if( !h->param.analyse.b_psy )
- {
- @@ -827,6 +979,17 @@ static int x264_validate_parameters( x264_t *h )
- h->param.i_nal_hrd = X264_NAL_HRD_VBR;
- }
- + /* timecode offset */
- + if (h->param.timecode_offset.frame < 0 || h->param.timecode_offset.frame >= (int)(fps+0.5f)) h->param.timecode_offset.frame = 0;
- + if (h->param.timecode_offset.second < 0 || h->param.timecode_offset.second > 59) h->param.timecode_offset.second = 0;
- + if (h->param.timecode_offset.minute < 0 || h->param.timecode_offset.minute > 59) h->param.timecode_offset.minute = 0;
- + if (h->param.timecode_offset.hour < 0 || h->param.timecode_offset.hour > 23) h->param.timecode_offset.hour = 0;
- + if (h->param.i_fps_den == 1001 &&
- + h->param.timecode_offset.b_drop &&
- + h->param.timecode_offset.frame < 2 &&
- + h->param.timecode_offset.second == 0 &&
- + (h->param.timecode_offset.minute % 10)) h->param.timecode_offset.frame = 2;
- +
- /* 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 );
- @@ -912,6 +1075,28 @@ static void x264_set_aspect_ratio( x264_t *h, x264_param_t *param, int initial )
- }
- }
- +static int64_t calculate_frame_from_timecode( uint32_t num, uint32_t denom, struct timecode time)
- +{
- + int64_t frame, second, minute;
- + if (denom == 0) return 0;
- + minute = (time.hour * 60) + time.minute;
- + second = minute * 60 + time.second;
- + if (denom == 1001) {
- + frame = second * num / 1000;
- + if (time.b_drop) {
- + // drop frame is only effective at 30000/1001
- + int64_t minute10 = minute / 10;
- + int64_t drop_count = (minute - minute10) * 2; /* drop 2frames each minute, except each 10 minutes. */
- + frame -= drop_count;
- + }
- + } else {
- + frame = second * num / denom;
- + }
- + frame += time.frame;
- +
- + return frame;
- +}
- +
- /****************************************************************************
- * x264_encoder_open:
- ****************************************************************************/
- @@ -923,6 +1108,163 @@ x264_t *x264_encoder_open( x264_param_t *param )
- CHECKED_MALLOCZERO( h, sizeof(x264_t) );
- +#ifdef __PARAM_DEBUG
- +#define PARAM_PRINT(x) printf("%s = %08x\n", #x, param->x);
- +#define PARAM_PRINT_F(x) printf("%s = %7.4f\n", #x, param->x);
- +#define PARAM_PRINT_P(x) printf("%s = %p\n", #x, param->x);
- +#else
- +#define PARAM_PRINT(x);
- +#define PARAM_PRINT_F(x);
- +#define PARAM_PRINT_P(x);
- +#endif
- +
- + PARAM_PRINT(cpu);
- + PARAM_PRINT(i_threads);
- + PARAM_PRINT(b_sliced_threads);
- + PARAM_PRINT(b_deterministic);
- + PARAM_PRINT(i_sync_lookahead);
- + PARAM_PRINT(i_width);
- + PARAM_PRINT(i_height);
- + PARAM_PRINT(i_csp);
- + PARAM_PRINT(i_level_idc);
- + PARAM_PRINT(i_frame_total);
- + PARAM_PRINT(i_nal_hrd);
- + PARAM_PRINT(vui.i_sar_height);
- + PARAM_PRINT(vui.i_sar_width);
- + PARAM_PRINT(vui.i_overscan);
- + PARAM_PRINT(vui.i_vidformat);
- + PARAM_PRINT(vui.b_fullrange);
- + PARAM_PRINT(vui.i_colorprim);
- + PARAM_PRINT(vui.i_transfer);
- + PARAM_PRINT(vui.i_colmatrix);
- + PARAM_PRINT(vui.i_chroma_loc);
- +
- + PARAM_PRINT(i_frame_reference); /* Maximum number of reference frames */
- + PARAM_PRINT(i_dpb_size); /* Force a DPB size larger than that implied by B-frames and reference frames.
- + * Useful in combination with interactive error resilience. */
- + PARAM_PRINT(i_keyint_max); /* Force an IDR keyframe at this interval */
- + PARAM_PRINT(i_keyint_min); /* Scenecuts closer together than this are coded as I, not IDR. */
- + PARAM_PRINT(i_scenecut_threshold); /* how aggressively to insert extra I frames */
- + PARAM_PRINT(b_intra_refresh); /* Whether or not to use periodic intra refresh instead of IDR frames. */
- +
- + PARAM_PRINT(i_bframe); /* how many b-frame between 2 references pictures */
- + PARAM_PRINT(i_bframe_adaptive);
- + PARAM_PRINT(i_bframe_bias);
- + PARAM_PRINT(i_bframe_pyramid); /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */
- + PARAM_PRINT(i_open_gop); /* Open gop: 1=display order, 2=bluray compatibility braindamage mode */
- +
- + PARAM_PRINT(b_deblocking_filter);
- + PARAM_PRINT(i_deblocking_filter_alphac0); /* [-6, 6] -6 light filter, 6 strong */
- + PARAM_PRINT(i_deblocking_filter_beta); /* [-6, 6] idem */
- +
- + PARAM_PRINT(b_cabac);
- + PARAM_PRINT(i_cabac_init_idc);
- +
- + PARAM_PRINT(b_interlaced);
- + PARAM_PRINT(b_constrained_intra);
- +
- + PARAM_PRINT(i_cqm_preset);
- + PARAM_PRINT_P(psz_cqm_file);
- +
- + PARAM_PRINT(b_mvc);
- +
- + PARAM_PRINT(analyse.intra); /* intra partitions */
- + PARAM_PRINT(analyse.inter); /* inter partitions */
- +
- + PARAM_PRINT(analyse.b_transform_8x8);
- + PARAM_PRINT(analyse.i_weighted_pred); /* weighting for P-frames */
- + PARAM_PRINT(analyse.b_weighted_bipred); /* implicit weighting for B-frames */
- + PARAM_PRINT(analyse.i_direct_mv_pred); /* spatial vs temporal mv prediction */
- + PARAM_PRINT(analyse.i_chroma_qp_offset);
- +
- + PARAM_PRINT(analyse.i_me_method); /* motion estimation algorithm to use (X264_ME_*) */
- + PARAM_PRINT(analyse.i_me_range); /* integer pixel motion estimation search range (from predicted mv) */
- + PARAM_PRINT(analyse.i_mv_range); /* maximum length of a mv (in pixels). -1 = auto, based on level */
- + PARAM_PRINT(analyse.i_mv_range_thread); /* minimum space between threads. -1 = auto, based on number of threads. */
- + PARAM_PRINT(analyse.i_subpel_refine); /* subpixel motion estimation quality */
- + PARAM_PRINT(analyse.b_chroma_me); /* chroma ME for subpel and mode decision in P-frames */
- + PARAM_PRINT(analyse.b_mixed_references); /* allow each mb partition to have its own reference number */
- + PARAM_PRINT(analyse.i_trellis); /* trellis RD quantization */
- + PARAM_PRINT(analyse.b_fast_pskip); /* early SKIP detection on P-frames */
- + PARAM_PRINT(analyse.b_dct_decimate); /* transform coefficient thresholding on P-frames */
- + PARAM_PRINT(analyse.i_noise_reduction); /* adaptive pseudo-deadzone */
- + PARAM_PRINT_F(analyse.f_psy_rd); /* Psy RD strength */
- + PARAM_PRINT_F(analyse.f_psy_trellis); /* Psy trellis strength */
- + PARAM_PRINT(analyse.b_psy); /* Toggle all psy optimizations */
- +
- + PARAM_PRINT(analyse.i_luma_deadzone[0]); /* {inter, intra} */
- + PARAM_PRINT(analyse.i_luma_deadzone[1]); /* {inter, intra} */
- + PARAM_PRINT(analyse.b_psnr); /* compute and print PSNR stats */
- + PARAM_PRINT(analyse.b_ssim); /* compute and print SSIM stats */
- +
- + PARAM_PRINT(rc.i_rc_method); /* X264_RC_* */
- +
- + PARAM_PRINT(rc.i_qp_constant); /* 0 to (51 + 6*(x264_bit_depth-8)). 0=lossless */
- + PARAM_PRINT(rc.i_qp_min); /* min allowed QP value */
- + PARAM_PRINT(rc.i_qp_max); /* max allowed QP value */
- + PARAM_PRINT(rc.i_qp_step); /* max QP step between frames */
- +
- + PARAM_PRINT(rc.i_bitrate);
- + PARAM_PRINT_F(rc.f_rf_constant); /* 1pass VBR, nominal QP */
- + PARAM_PRINT_F(rc.f_rf_constant_max); /* In CRF mode, maximum CRF as caused by VBV */
- + PARAM_PRINT_F(rc.f_rate_tolerance);
- + PARAM_PRINT(rc.i_vbv_max_bitrate);
- + PARAM_PRINT(rc.i_vbv_buffer_size);
- + PARAM_PRINT_F(rc.f_vbv_buffer_init); /* <=1: fraction of buffer_size. >1: kbit */
- + PARAM_PRINT_F(rc.f_ip_factor);
- + PARAM_PRINT_F(rc.f_pb_factor);
- +
- + PARAM_PRINT(rc.i_aq_mode); /* psy adaptive QP. (X264_AQ_*) */
- + PARAM_PRINT_F(rc.f_aq_strength);
- + PARAM_PRINT(rc.b_mb_tree); /* Macroblock-tree ratecontrol. */
- + PARAM_PRINT(rc.i_lookahead);
- +
- + PARAM_PRINT(rc.b_stat_write); /* Enable stat writing in psz_stat_out */
- + PARAM_PRINT_P(rc.psz_stat_out);
- + PARAM_PRINT(rc.b_stat_read); /* Read stat from psz_stat_in and use it */
- + PARAM_PRINT_P(rc.psz_stat_in);
- +
- + PARAM_PRINT_F(rc.f_qcompress); /* 0.0 => cbr, 1.0 => constant qp */
- + PARAM_PRINT_F(rc.f_qblur); /* temporally blur quants */
- + PARAM_PRINT_F(rc.f_complexity_blur); /* temporally blur complexity */
- + PARAM_PRINT_P(rc.zones); /* ratecontrol overrides */
- + PARAM_PRINT(rc.i_zones); /* number of zone_t's */
- + PARAM_PRINT_P(rc.psz_zones); /* alternate method of specifying zones */
- +
- + PARAM_PRINT(rc.i_bitrate_dep[0]);
- + PARAM_PRINT(rc.i_vbv_max_bitrate_dep[0]);
- +
- + PARAM_PRINT(crop_rect.i_left);
- + PARAM_PRINT(crop_rect.i_top);
- + PARAM_PRINT(crop_rect.i_right);
- + PARAM_PRINT(crop_rect.i_bottom);
- +
- + PARAM_PRINT(timecode_offset.b_drop);
- + PARAM_PRINT(timecode_offset.hour);
- + PARAM_PRINT(timecode_offset.minute);
- + PARAM_PRINT(timecode_offset.second);
- + PARAM_PRINT(timecode_offset.frame);
- +
- + PARAM_PRINT(i_frame_packing);
- + PARAM_PRINT(b_aud);
- + PARAM_PRINT(b_repeat_headers);
- + PARAM_PRINT(b_repeat_pps_all_frames);
- + PARAM_PRINT(b_annexb);
- + PARAM_PRINT(i_sps_id);
- + PARAM_PRINT(b_vfr_input);
- + PARAM_PRINT(b_pulldown);
- + PARAM_PRINT(i_fps_num);
- + PARAM_PRINT(i_fps_den);
- + PARAM_PRINT(i_timebase_num);
- + PARAM_PRINT(i_timebase_den);
- +
- + PARAM_PRINT(b_tff);
- + PARAM_PRINT(b_pic_struct);
- + PARAM_PRINT(b_fake_interlaced);
- + PARAM_PRINT(i_slice_max_size);
- + PARAM_PRINT(i_slice_max_mbs);
- + PARAM_PRINT(i_slice_count);
- +
- /* Create a copy of param */
- memcpy( &h->param, param, sizeof(x264_param_t) );
- @@ -964,9 +1306,17 @@ x264_t *x264_encoder_open( x264_param_t *param )
- h->sps = &h->sps_array[0];
- x264_sps_init( h->sps, h->param.i_sps_id, &h->param );
- + h->subset_sps = &h->sps_array[1];
- + x264_sps_init( h->subset_sps, 1, &h->param );
- +
- h->pps = &h->pps_array[0];
- x264_pps_init( h->pps, h->param.i_sps_id, &h->param, h->sps );
- + h->subset_pps = &h->pps_array[1];
- + x264_pps_init( h->subset_pps, 1, &h->param, h->subset_sps );
- + if( h->subset_pps->i_num_ref_idx_l0_default_active > 2 )
- + h->subset_pps->i_num_ref_idx_l0_default_active--;
- +
- x264_set_aspect_ratio( h, &h->param, 1 );
- x264_validate_levels( h, 1 );
- @@ -992,6 +1342,8 @@ x264_t *x264_encoder_open( x264_param_t *param )
- h->frames.i_delay += h->param.i_sync_lookahead;
- h->frames.i_delay += h->param.b_vfr_input;
- h->frames.i_bframe_delay = h->param.i_bframe ? (h->param.i_bframe_pyramid ? 2 : 1) : 0;
- + if( h->param.b_mvc )
- + h->frames.i_bframe_delay *= 2;
- h->frames.i_max_ref0 = h->param.i_frame_reference;
- h->frames.i_max_ref1 = X264_MIN( h->sps->vui.i_num_reorder_frames, h->param.i_frame_reference );
- @@ -1012,7 +1364,13 @@ x264_t *x264_encoder_open( x264_param_t *param )
- h->frames.i_largest_pts = h->frames.i_second_largest_pts = -1;
- h->frames.i_poc_last_open_gop = -1;
- - CHECKED_MALLOCZERO( h->frames.unused[0], (h->frames.i_delay + 3) * sizeof(x264_frame_t *) );
- + h->offset_frame = calculate_frame_from_timecode(h->param.i_fps_num, h->param.i_fps_den, h->param.timecode_offset);
- + if (h->param.b_mvc) {
- + h->offset_frame *= 2;
- + }
- +
- + CHECKED_MALLOCZERO( h->frames.unused[0], (h->frames.i_delay + 3) * sizeof(x264_frame_t *) * ((h->param.b_mvc) ? 2 : 1));
- +
- /* Allocate room for max refs plus a few extra just in case. */
- CHECKED_MALLOCZERO( h->frames.unused[1], (h->i_thread_frames + X264_REF_MAX + 4) * sizeof(x264_frame_t *) );
- CHECKED_MALLOCZERO( h->frames.current, (h->param.i_sync_lookahead + h->param.i_bframe
- @@ -1149,21 +1507,36 @@ x264_t *x264_encoder_open( x264_param_t *param )
- x264_log( h, X264_LOG_DEBUG, "CPB size: %i bits\n", h->sps->vui.hrd.i_cpb_size_unscaled );
- }
- - if( h->param.psz_dump_yuv )
- + if( h->param.psz_dump_yuv[0] )
- {
- - /* create or truncate the reconstructed video file */
- - FILE *f = fopen( h->param.psz_dump_yuv, "w" );
- - if( !f )
- + if( h->param.b_mvc )
- {
- - x264_log( h, X264_LOG_ERROR, "dump_yuv: can't write to %s\n", h->param.psz_dump_yuv );
- - goto fail;
- + static const char *dep_suffix = "_dep";
- + size_t namelen = strlen(h->param.psz_dump_yuv[0]),
- + sufflen = strlen(dep_suffix);
- + h->param.psz_dump_yuv[1] = calloc( namelen + sufflen + 1, sizeof(char) );
- + memcpy( h->param.psz_dump_yuv[1], h->param.psz_dump_yuv[0], namelen - 4 ); /* without extension */
- + h->param.psz_dump_yuv[1][namelen - 4] = '\0';
- + strcat( h->param.psz_dump_yuv[1], dep_suffix);
- + strcat( h->param.psz_dump_yuv[1], h->param.psz_dump_yuv[0] + namelen - 4);
- }
- - else if( !x264_is_regular_file( f ) )
- +
- + /* create or truncate the reconstructed video file */
- + for( int i = 0; i < 2 && h->param.psz_dump_yuv[i] != NULL ; i++ )
- {
- - x264_log( h, X264_LOG_ERROR, "dump_yuv: incompatible with non-regular file %s\n", h->param.psz_dump_yuv );
- - goto fail;
- + FILE *f = fopen( h->param.psz_dump_yuv[i], "w" );
- + if( !f )
- + {
- + x264_log( h, X264_LOG_ERROR, "dump_yuv: can't write to %s\n", h->param.psz_dump_yuv[i] );
- + goto fail;
- + }
- + else if( !x264_is_regular_file( f ) )
- + {
- + x264_log( h, X264_LOG_ERROR, "dump_yuv: incompatible with non-regular file %s\n", h->param.psz_dump_yuv[i] );
- + goto fail;
- + }
- + fclose( f );
- }
- - fclose( f );
- }
- const char *profile = h->sps->i_profile_idc == PROFILE_BASELINE ? "Constrained Baseline" :
- @@ -1242,6 +1615,23 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
- COPY( i_slice_count );
- COPY( b_tff );
- + if (param->i_cqm_preset >= X264_CQM_FLAT && param->i_cqm_preset <= X264_CQM_CUSTOM) {
- + COPY( i_cqm_preset );
- + if (param->i_cqm_preset == X264_CQM_CUSTOM) {
- + memcpy(h->param.cqm_4iy, param->cqm_4iy, 16);
- + memcpy(h->param.cqm_4ic, param->cqm_4ic, 16);
- + memcpy(h->param.cqm_8iy, param->cqm_8iy, 64);
- + memcpy(h->param.cqm_4py, param->cqm_4py, 16);
- + memcpy(h->param.cqm_4pc, param->cqm_4pc, 16);
- + memcpy(h->param.cqm_8py, param->cqm_8py, 64);
- + }
- +
- + x264_pps_init ( h->pps, h->pps->i_id, &h->param, h->sps );
- + if (h->subset_sps && h->subset_pps) x264_pps_init ( h->subset_pps, h->subset_pps->i_id, &h->param, h->subset_sps );
- +
- + if (x264_cqm_init( h ) < 0) return -1;
- + }
- +
- /* VBV can't be turned on if it wasn't on to begin with */
- if( h->param.rc.i_vbv_max_bitrate > 0 && h->param.rc.i_vbv_buffer_size > 0 &&
- param->rc.i_vbv_max_bitrate > 0 && param->rc.i_vbv_buffer_size > 0 )
- @@ -1291,7 +1681,7 @@ void x264_encoder_parameters( x264_t *h, x264_param_t *param )
- static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc )
- {
- x264_nal_t *nal = &h->out.nal[h->out.i_nal];
- -
- +
- nal->i_ref_idc = i_ref_idc;
- nal->i_type = i_type;
- nal->b_long_startcode = 1;
- @@ -1572,28 +1962,99 @@ static inline int x264_reference_distance( x264_t *h, x264_frame_t *frame )
- static inline void x264_reference_build_list( x264_t *h, int i_poc )
- {
- - int b_ok;
- +#ifdef _DEBUG
- + x264_log(h, X264_LOG_INFO, "Start x264_reference_build_list(). (Frame number: %d)\n", h->fenc->i_frame );
- +#endif
- +
- + int b_ok;
- + int remove_num = h->sh.i_mmco_remove_from_end;
- +
- /* build ref list 0/1 */
- h->mb.pic.i_fref[0] = h->i_ref[0] = 0;
- h->mb.pic.i_fref[1] = h->i_ref[1] = 0;
- if( h->sh.i_type == SLICE_TYPE_I )
- return;
- + //for( int i = 0; h->frames.reference[i]; i++ )
- + // printf( "Reference frame is %d.\n", h->frames.reference[i]->i_frame );
- + x264_frame_t *base_view = NULL;
- + if ( h->param.b_mvc )
- + {
- + for( int i = 0; h->frames.reference[i]; i++ )
- + {
- +
- +#ifdef _DEBUG
- + x264_log(h, X264_LOG_INFO, "h->frames.reference[%d]->i_frame %d\n", i, h->frames.reference[i]->i_frame);
- + x264_log(h, X264_LOG_INFO, "h->fenc->i_frame - 1 = %d\n", h->fenc->i_frame - 1);
- +#endif
- +
- + if ( h->frames.reference[i]->i_frame == h->fenc->i_frame - 1 )
- + {
- + //assert( base_view == NULL );
- + if ( base_view != NULL )
- + x264_log( h, X264_LOG_WARNING, "A duplicated base view frame found. (Frame number: %d)\n", h->fenc->i_frame );
- +
- + base_view = h->frames.reference[i];
- + }
- + }
- +
- + /* Insert an inter-view reference frame to L0. */
- + if ( h->b_dependent ) /* The frame being encoded is dependent view. */
- + {
- + if (base_view != NULL)
- + h->fref[0][h->i_ref[0]++] = base_view;
- + else
- + x264_log( h, X264_LOG_WARNING, "No base view frame found. (Frame number: %d)\n", h->fenc->i_frame );
- + }
- + }
- +
- for( int i = 0; h->frames.reference[i]; i++ )
- {
- - if( h->frames.reference[i]->b_corrupt )
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "h->frames.reference[%d]->i_frame %d\n", i, h->frames.reference[i]->i_frame);
- +#endif
- +
- + if( h->frames.reference[i]->b_corrupt ) {
- +#ifdef __DEBUG
- + x264_log( h, X264_LOG_INFO, "b_corrupt : ref frame %d : poc=%d\n",
- + h->frames.reference[i]->i_frame, h->frames.reference[i]->i_poc);
- +#endif
- continue;
- - if( h->frames.reference[i]->i_poc < i_poc )
- - h->fref[0][h->i_ref[0]++] = h->frames.reference[i];
- - else if( h->frames.reference[i]->i_poc > i_poc )
- - h->fref[1][h->i_ref[1]++] = h->frames.reference[i];
- + }
- + if( !h->param.b_mvc || h->frames.reference[i]->i_frame % 2 == h->fenc->i_frame % 2 )
- + {
- +#ifdef __DEBUG
- + x264_log( h, X264_LOG_INFO, "ref frame %d : poc=%d (Frame number: %d)\n",
- + h->frames.reference[i]->i_frame, h->frames.reference[i]->i_poc,
- + h->fenc->i_frame );
- +#endif
- + if( h->frames.reference[i]->i_poc < i_poc )
- + {
- +#ifdef __DEBUG
- + x264_log( h, X264_LOG_INFO, "Set base view frame(%d) to L0 at %d. (Frame number: %d)\n", h->frames.reference[i]->i_frame, h->i_ref[0], h->fenc->i_frame );
- +#endif
- + h->fref[0][h->i_ref[0]++] = h->frames.reference[i];
- + }
- + else if( h->frames.reference[i]->i_poc > i_poc )
- + {
- +#ifdef __DEBUG
- + x264_log( h, X264_LOG_INFO, "Set base view frame(%d) to L1 at %d. (Frame number: %d)\n", h->frames.reference[i]->i_frame, h->i_ref[0], h->fenc->i_frame );
- +#endif
- + h->fref[1][h->i_ref[1]++] = h->frames.reference[i];
- + }
- + }
- }
- /* Order reference lists by distance from the current frame. */
- for( int list = 0; list < 2; list++ )
- {
- - h->fref_nearest[list] = h->fref[list][0];
- + int pos = 0;
- + do {
- + h->fref_nearest[list] = h->fref[list][pos];
- + pos++;
- + } while (h->param.b_mvc && pos < h->i_ref[list] && (h->fref_nearest[list]->i_poc & (~2)) == (h->fenc->i_poc & (~2)));
- do
- {
- b_ok = 1;
- @@ -1612,8 +2073,12 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
- } while( !b_ok );
- }
- - if( h->sh.i_mmco_remove_from_end )
- - for( int i = h->i_ref[0]-1; i >= h->i_ref[0] - h->sh.i_mmco_remove_from_end; i-- )
- + if ( h->param.b_mvc )
- + {
- + remove_num /= 2;
- + }
- + if( remove_num )
- + for( int i = h->i_ref[0]-1; i >= h->i_ref[0] - remove_num; i-- )
- {
- int diff = h->i_frame_num - h->fref[0][i]->i_frame_num;
- h->sh.mmco[h->sh.i_mmco_command_count].i_poc = h->fref[0][i]->i_poc;
- @@ -1623,11 +2088,13 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
- x264_reference_check_reorder( h );
- h->i_ref[1] = X264_MIN( h->i_ref[1], h->frames.i_max_ref1 );
- - h->i_ref[0] = X264_MIN( h->i_ref[0], h->frames.i_max_ref0 );
- - h->i_ref[0] = X264_MIN( h->i_ref[0], h->param.i_frame_reference ); // if reconfig() has lowered the limit
- + //h->i_ref[0] = X264_MIN( h->i_ref[0], h->frames.i_max_ref0 );
- + //h->i_ref[0] = X264_MIN( h->i_ref[0], h->param.i_frame_reference ); // if reconfig() has lowered the limit
- + h->i_ref[0] = X264_MIN( h->i_ref[0], h->frames.i_max_ref0 + h->b_dependent );
- + h->i_ref[0] = X264_MIN( h->i_ref[0], h->param.i_frame_reference + h->b_dependent ); // if reconfig() has lowered the limit
- /* add duplicates */
- - if( h->fenc->i_type == X264_TYPE_P )
- + if( h->fenc->i_type == X264_TYPE_P || h->fenc->i_type == X264_TYPE_ANCHOR)
- {
- int idx = -1;
- if( h->param.analyse.i_weighted_pred >= X264_WEIGHTP_SIMPLE )
- @@ -1665,6 +2132,18 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
- assert( h->i_ref[0] + h->i_ref[1] <= X264_REF_MAX );
- h->mb.pic.i_fref[0] = h->i_ref[0];
- h->mb.pic.i_fref[1] = h->i_ref[1];
- +
- +#ifdef __DEBUG
- + for (int j = 0; j < 2; j++) {
- + x264_log(h, X264_LOG_INFO, "i_ref%d=%d\n", j, h->i_ref[j]);
- + for (int i = 0; i < h->i_ref[j]; ++i) {
- + x264_log(h, X264_LOG_INFO, "ref%d[%2d] : no = %4d, poc = %2d\n",
- + j, i,
- + h->fref[j][i] ? h->fref[j][i]->i_frame : 9999,
- + h->fref[j][i] ? h->fref[j][i]->i_poc : -1);
- + }
- + }
- +#endif
- }
- static void x264_fdec_filter_row( x264_t *h, int mb_y, int b_inloop )
- @@ -1677,7 +2156,7 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y, int b_inloop )
- int min_y = mb_y - (1 << h->sh.b_mbaff);
- int b_start = min_y == h->i_threadslice_start;
- int max_y = b_end ? h->i_threadslice_end : mb_y;
- - b_deblock &= b_hpel || h->param.psz_dump_yuv;
- + b_deblock &= b_hpel || h->param.psz_dump_yuv[0];
- if( h->param.b_sliced_threads && b_start && min_y && !b_inloop )
- {
- b_deblock = 0; /* We already deblocked on the inloop pass. */
- @@ -1744,6 +2223,38 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y, int b_inloop )
- static inline int x264_reference_update( x264_t *h )
- {
- + x264_sps_t * sps = h->b_dependent ? h->subset_sps : h->sps;
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "x264_reference_update called h->fdec->i_frame %d, (%s), frame=%d\n", h->fdec->i_frame, h->b_dependent ? "d" : "m", h->i_frame);
- +#endif
- +
- + /* Delete all inter-view only frames. */
- + /* h->i_frame is not updated in this timing. */
- + if( (h->i_frame % 2) == 1 )
- + for( int i = 0; h->frames.reference[i]; i++ ) {
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "ref frame %d\n", h->frames.reference[i]->i_frame);
- +#endif
- + if( h->frames.reference[i]->b_inter_view_only && h->frames.reference[i]->i_type == X264_TYPE_B )
- + {
- + //printf("Delete an inter view only frame.\n");
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "Delete an inter view only frame %d(type=%d) at %d\n", h->frames.reference[i]->i_frame, h->frames.reference[i]->i_type, h->fdec->i_frame);
- +#endif
- + x264_frame_push_unused( h, x264_frame_shift( &h->frames.reference[i] ) );
- + }
- + }
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "num_ref[view=%d] = %d\n", h->b_dependent, sps->i_num_ref_frames);
- + for( int j = 0; h->frames.reference[j]; j++ )
- + x264_log(h, X264_LOG_INFO, "ref[%2d]: no=%5d, poc=%3d\n",
- + j, h->frames.reference[j]->i_frame, h->frames.reference[j]->i_poc);
- + for( int i = 0; i < h->sh.i_mmco_command_count; i++ )
- + x264_log(h, X264_LOG_INFO, "sh_mmco[%2d]: poc=%3d\n",
- + i, h->sh.mmco[i].i_poc);
- +#endif
- +
- if( !h->fdec->b_kept_as_ref )
- {
- if( h->i_thread_frames > 1 )
- @@ -1764,9 +2275,22 @@ static inline int x264_reference_update( x264_t *h )
- /* move frame in the buffer */
- x264_frame_push( h->frames.reference, h->fdec );
- - if( h->frames.reference[h->sps->i_num_ref_frames] )
- +
- + int ivo_add = h->param.b_mvc && IS_X264_TYPE_B(h->fdec->i_type) ? 1 : 0;
- + if( h->frames.reference[sps->i_num_ref_frames * (h->param.b_mvc ? 2 : 1) + ivo_add] ) {
- +#ifdef __DEBUG
- + for( int i = 0; i < sps->i_num_ref_frames * (h->param.b_mvc ? 2 : 1) + ivo_add + (h->param.b_mvc && h->i_frame % 2); i++ )
- + {
- + if( !h->frames.reference[i] )
- + x264_log(h, X264_LOG_ERROR, "There is a NULL frame on the reference list.");
- + }
- + x264_log(h, X264_LOG_INFO, "Delete frame %d, last frame %d, dec type %d\n", h->frames.reference[0]->i_frame, h->frames.reference[sps->i_num_ref_frames * (h->param.b_mvc ? 2 : 1)]->i_frame, h->fdec->i_type);
- +#endif
- x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) );
- + }
- +
- h->fdec = x264_frame_pop_unused( h, 1 );
- +
- if( !h->fdec )
- return -1;
- return 0;
- @@ -1789,7 +2313,7 @@ static inline void x264_reference_hierarchy_reset( x264_t *h )
- for( int i = 0; h->frames.current[i] && IS_DISPOSABLE( h->frames.current[i]->i_type ); i++ )
- b_hasdelayframe |= h->frames.current[i]->i_coded
- != h->frames.current[i]->i_frame + h->sps->vui.i_num_reorder_frames;
- -
- +
- /* This function must handle b-pyramid and clear frames for open-gop */
- if( h->param.i_bframe_pyramid != X264_B_PYRAMID_STRICT && !b_hasdelayframe && h->frames.i_poc_last_open_gop == -1 )
- return;
- @@ -1817,7 +2341,7 @@ static inline void x264_reference_hierarchy_reset( x264_t *h )
- h->sh.i_mmco_remove_from_end = X264_MAX( ref + 2 - h->frames.i_max_dpb, 0 );
- }
- -static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
- +static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp, int i_nal_ref_idc )
- {
- /* ------------------------ Create slice header ----------------------- */
- if( i_nal_type == NAL_SLICE_IDR )
- @@ -1827,6 +2351,38 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
- /* alternate id */
- h->i_idr_pic_id ^= 1;
- }
- + else if (i_nal_type == NAL_SLICE_LAYER_EXTENSION) {
- + if (0/*i_nal_ref_idc == NAL_PRIORITY_HIGHEST*/) {
- + // this means anchor picture
- +
- + } else {
- + // only works on mvc dependent view.
- + int idr_pic_id;
- + if( h->i_last_idr_frame == h->i_frame - 1 )
- + idr_pic_id = h->i_idr_pic_id;
- + else
- + idr_pic_id = -1;
- +
- + x264_slice_header_init( h, &h->sh, h->subset_sps, h->subset_pps,
- + idr_pic_id, h->i_frame_num, i_global_qp );
- + // TODO: Integrate with the else statement below.
- + h->sh.i_num_ref_idx_l0_active = h->i_ref[0] <= 0 ? 1 : h->i_ref[0];
- + h->sh.i_num_ref_idx_l1_active = h->i_ref[1] <= 0 ? 1 : h->i_ref[1];
- + if( h->sh.i_num_ref_idx_l0_active != h->subset_pps->i_num_ref_idx_l0_default_active ||
- + (h->sh.i_type == SLICE_TYPE_B && h->sh.i_num_ref_idx_l1_active != h->subset_pps->i_num_ref_idx_l1_default_active) )
- + {
- + h->sh.b_num_ref_idx_override = 1;
- + }
- +#if 0
- + if( h->sh.i_num_ref_idx_l0_active > 0 )
- + h->sh.i_num_ref_idx_l0_active--;
- +
- + if( h->sh.i_num_ref_idx_l1_active > 0 )
- + h->sh.i_num_ref_idx_l1_active--;
- +#endif
- + //h->sh.b_num_ref_idx_override = 1;
- + }
- + }
- else
- {
- x264_slice_header_init( h, &h->sh, h->sps, h->pps, -1, h->i_frame_num, i_global_qp );
- @@ -1845,6 +2401,8 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
- if( h->sps->i_poc_type == 0 )
- {
- h->sh.i_poc = h->fdec->i_poc;
- + if ( h->param.b_mvc )
- + h->sh.i_poc = h->sh.i_poc / 2 & ~1;
- if( h->param.b_interlaced )
- {
- h->sh.i_delta_poc_bottom = h->param.b_tff ? 1 : -1;
- @@ -1888,11 +2446,15 @@ static int x264_slice_write( x264_t *h )
- int b_deblock = h->sh.i_disable_deblocking_filter_idc != 1;
- int b_hpel = h->fdec->b_kept_as_ref;
- uint8_t *last_emu_check;
- - b_deblock &= b_hpel || h->param.psz_dump_yuv;
- + b_deblock &= b_hpel || h->param.psz_dump_yuv[0];
- bs_realign( &h->out.bs );
- -
- +
- /* Slice */
- - x264_nal_start( h, h->i_nal_type, h->i_nal_ref_idc );
- + if (!h->sh.b_svc_extension_flag) {
- + x264_nal_start( h, h->i_nal_type, h->i_nal_ref_idc );
- + } else {
- + x264_nal_start( h, NAL_SLICE_LAYER_EXTENSION, h->i_nal_ref_idc );
- + }
- h->out.nal[h->out.i_nal].i_first_mb = h->sh.i_first_mb;
- /* Slice header */
- @@ -1907,7 +2469,7 @@ static int x264_slice_write( x264_t *h )
- h->sh.i_qp_delta = h->sh.i_qp - h->pps->i_pic_init_qp;
- }
- - x264_slice_header_write( &h->out.bs, &h->sh, h->i_nal_ref_idc );
- + x264_slice_header_write( h, &h->out.bs, &h->sh, h->i_nal_ref_idc );
- if( h->param.b_cabac )
- {
- /* alignment needed */
- @@ -2160,6 +2722,7 @@ reencode:
- bs_rbsp_trailing( &h->out.bs );
- bs_flush( &h->out.bs );
- }
- +
- if( x264_nal_end( h ) )
- return -1;
- @@ -2206,6 +2769,10 @@ static void *x264_slices_write( x264_t *h )
- int i_slice_num = 0;
- int last_thread_mb = h->sh.i_last_mb;
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[slices_write] %d \n", h->sh.i_type);
- +#endif
- +
- #if HAVE_VISUALIZE
- if( h->param.b_visualize )
- if( x264_visualize_init( h ) )
- @@ -2232,7 +2799,7 @@ static void *x264_slices_write( x264_t *h )
- return (void *)-1;
- h->sh.i_first_mb = h->sh.i_last_mb + 1;
- }
- -
- +
- #if HAVE_VISUALIZE
- if( h->param.b_visualize )
- {
- @@ -2357,16 +2924,17 @@ int x264_encoder_encode( x264_t *h,
- x264_picture_t *pic_in,
- x264_picture_t *pic_out )
- {
- - x264_t *thread_current, *thread_prev, *thread_oldest;
- + x264_t *thread_current, *thread_prev, *thread_oldest, *thread_next_oldest;
- int i_nal_type, i_nal_ref_idc, i_global_qp;
- int overhead = NALU_OVERHEAD;
- -
- +
- if( h->i_thread_frames > 1 )
- {
- thread_prev = h->thread[ h->i_thread_phase ];
- h->i_thread_phase = (h->i_thread_phase + 1) % h->i_thread_frames;
- thread_current = h->thread[ h->i_thread_phase ];
- thread_oldest = h->thread[ (h->i_thread_phase + 1) % h->i_thread_frames ];
- + thread_next_oldest = h->thread[ (h->i_thread_phase + 2) % h->i_thread_frames ];
- x264_thread_sync_context( thread_current, thread_prev );
- x264_thread_sync_ratecontrol( thread_current, thread_prev, thread_oldest );
- h = thread_current;
- @@ -2381,22 +2949,33 @@ int x264_encoder_encode( x264_t *h,
- x264_cpu_mask_misalign_sse();
- #endif
- - // ok to call this before encoding any frames, since the initial values of fdec have b_kept_as_ref=0
- - if( x264_reference_update( h ) )
- - return -1;
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "pic_in: %d frame\n", pic_in ? pic_in->i_pts: -1);
- +#endif
- + if( h->b_once_buffer_filled )
- + if( x264_reference_update( h ) )
- + return -1;
- + h->b_once_buffer_filled = 1; /* will reset below if the buffer has not filled yet. */
- h->fdec->i_lines_completed = -1;
- /* no data out */
- *pi_nal = 0;
- *pp_nal = NULL;
- +
- +#ifdef __DEBUG
- + x264_log( h, X264_LOG_INFO, "i_delay %d\n", h->frames.i_delay);
- +#endif
- +
- /* ------------------- Setup new frame from picture -------------------- */
- if( pic_in != NULL )
- {
- /* 1: Copy the picture to a frame and move it to a buffer */
- x264_frame_t *fenc = x264_frame_pop_unused( h, 0 );
- - if( !fenc )
- + if( !fenc ) {
- + x264_log(h, X264_LOG_ERROR, "[encoder_encode] cannot pop frame unused \n");
- return -1;
- + }
- if( x264_frame_copy_picture( h, fenc, pic_in ) < 0 )
- return -1;
- @@ -2405,6 +2984,10 @@ int x264_encoder_encode( x264_t *h,
- h->param.i_height != 16 * h->mb.i_mb_height )
- x264_frame_expand_border_mod16( h, fenc );
- +#ifdef _DEBUG
- + x264_log(h, X264_LOG_INFO, "[encoder_encode] fenc->i_frame will be frames.i_input %d\n", h->frames.i_input + 1);
- +#endif
- +
- fenc->i_frame = h->frames.i_input++;
- if( fenc->i_frame == 0 )
- @@ -2450,12 +3033,15 @@ int x264_encoder_encode( x264_t *h,
- /* 2: Place the frame into the queue for its slice type decision */
- x264_lookahead_put_frame( h, fenc );
- - if( h->frames.i_input <= h->frames.i_delay + 1 - h->i_thread_frames )
- - {
- - /* Nothing yet to encode, waiting for filling of buffers */
- - pic_out->i_type = X264_TYPE_AUTO;
- - return 0;
- - }
- + if ((!h->param.b_mvc && ( h->frames.i_input <= h->frames.i_delay + 1 - h->i_thread_frames )) ||
- + (h->param.b_mvc && ( (h->frames.i_input / 2) <= h->frames.i_delay + 1 - h->i_thread_frames ))
- + )
- + {
- + /* Nothing yet to encode, waiting for filling of buffers */
- + h->b_once_buffer_filled = 0;
- + pic_out->i_type = X264_TYPE_AUTO;
- + return 0;
- + }
- }
- else
- {
- @@ -2468,22 +3054,62 @@ int x264_encoder_encode( x264_t *h,
- h->i_frame++;
- /* 3: The picture is analyzed in the lookahead */
- - if( !h->frames.current[0] )
- + if( !h->frames.current[0] ) {
- x264_lookahead_get_frames( h );
- +#ifdef _DEBUG
- + if ( h->frames.current[0] ) {
- + x264_log(h, X264_LOG_INFO, "[encoder_encode] get frame h->frames.current[0].i_frame %d type %d\n", h->frames.current[0]->i_frame, h->frames.current[0]->i_type);
- + }
- + if ( h->frames.current[1] ) {
- + x264_log(h, X264_LOG_INFO, "[encoder_encode] get frame h->frames.current[1].i_frame %d type %d\n", h->frames.current[1]->i_frame, h->frames.current[1]->i_type);
- + }
- + if ( h->frames.current[2] ) {
- + x264_log(h, X264_LOG_INFO, "[encoder_encode] get frame h->frames.current[2].i_frame %d type %d\n", h->frames.current[2]->i_frame, h->frames.current[2]->i_type);
- + }
- + if ( h->frames.current[3] ) {
- + x264_log(h, X264_LOG_INFO, "[encoder_encode] get frame h->frames.current[3].i_frame %d type %d\n", h->frames.current[3]->i_frame, h->frames.current[3]->i_type);
- + }
- + if ( h->frames.current[4] ) {
- + x264_log(h, X264_LOG_INFO, "[encoder_encode] get frame h->frames.current[4].i_frame %d type %d\n", h->frames.current[4]->i_frame, h->frames.current[4]->i_type);
- + }
- + if ( h->frames.current[5] ) {
- + x264_log(h, X264_LOG_INFO, "[encoder_encode] get frame h->frames.current[5].i_frame %d type %d\n", h->frames.current[5]->i_frame, h->frames.current[5]->i_type);
- + }
- +#endif
- + }
- +
- if( !h->frames.current[0] && x264_lookahead_is_empty( h ) )
- - return x264_encoder_frame_end( thread_oldest, thread_current, pp_nal, pi_nal, pic_out );
- + return x264_encoder_frame_end( thread_oldest, thread_current, thread_next_oldest, pp_nal, pi_nal, pic_out );
- /* ------------------- Get frame to be encoded ------------------------- */
- /* 4: get picture to encode */
- - h->fenc = x264_frame_shift( h->frames.current );
- +
- + if (h->frames.current[0]) {
- + h->fenc = x264_frame_shift( h->frames.current );
- + } else {
- + // in mvc case, frames.current[0] is null when odd frame
- +
- +#ifdef _DEBUG
- + x264_log(h, X264_LOG_INFO, "frames.current[0] is null\n");
- +#endif
- +
- + return 0;
- + }
- +
- + h->b_dependent = (h->param.b_mvc && h->fenc->i_frame % 2);
- if( h->i_frame == h->i_thread_frames - 1 )
- h->i_reordered_pts_delay = h->fenc->i_reordered_pts;
- if( h->fenc->param )
- {
- - x264_encoder_reconfig( h, h->fenc->param );
- + if (h->fenc->i_type != X264_TYPE_IDR) {
- + h->fenc->param->i_cqm_preset = -1; // invalid
- + }
- + int reconfig_ret = x264_encoder_reconfig( h, h->fenc->param );
- if( h->fenc->param->param_free )
- h->fenc->param->param_free( h->fenc->param );
- +
- + if (reconfig_ret < 0) return -1;
- }
- if( !IS_X264_TYPE_I( h->fenc->i_type ) )
- @@ -2513,55 +3139,76 @@ int x264_encoder_encode( x264_t *h,
- h->sh.i_mmco_remove_from_end = 0;
- h->b_ref_reorder[0] =
- h->b_ref_reorder[1] = 0;
- +
- h->fdec->i_poc =
- h->fenc->i_poc = 2 * ( h->fenc->i_frame - X264_MAX( h->frames.i_last_idr, 0 ) );
- /* ------------------- Setup frame context ----------------------------- */
- /* 5: Init data dependent of frame type */
- - if( h->fenc->i_type == X264_TYPE_IDR )
- + if( h->fenc->i_type == X264_TYPE_IDR || (h->fenc->i_type == X264_TYPE_I && h->param.i_open_gop == X264_OPEN_GOP_NONE))
- {
- /* reset ref pictures */
- i_nal_type = NAL_SLICE_IDR;
- i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
- h->sh.i_type = SLICE_TYPE_I;
- + h->sh.b_anchor = 1;
- x264_reference_reset( h );
- h->frames.i_poc_last_open_gop = -1;
- }
- else if( h->fenc->i_type == X264_TYPE_I )
- {
- - i_nal_type = NAL_SLICE;
- + i_nal_type = h->b_dependent ? NAL_SLICE_LAYER_EXTENSION : NAL_SLICE;
- i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
- h->sh.i_type = SLICE_TYPE_I;
- + h->sh.b_anchor = 1;
- x264_reference_hierarchy_reset( h );
- if( h->param.i_open_gop )
- h->frames.i_poc_last_open_gop = h->fenc->b_keyframe ? h->fenc->i_poc : -1;
- }
- + else if( h->fenc->i_type == X264_TYPE_ANCHOR )
- + {
- + /* reset ref pictures */
- + i_nal_type = NAL_SLICE_LAYER_EXTENSION;
- + i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
- + h->sh.i_type = SLICE_TYPE_P;
- + h->sh.b_anchor = 1;
- + x264_reference_hierarchy_reset( h );
- + h->frames.i_poc_last_open_gop = -1;
- + }
- else if( h->fenc->i_type == X264_TYPE_P )
- {
- - i_nal_type = NAL_SLICE;
- + i_nal_type = h->b_dependent ? NAL_SLICE_LAYER_EXTENSION : NAL_SLICE;
- i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
- h->sh.i_type = SLICE_TYPE_P;
- + h->sh.b_anchor = 0;
- x264_reference_hierarchy_reset( h );
- h->frames.i_poc_last_open_gop = -1;
- }
- else if( h->fenc->i_type == X264_TYPE_BREF )
- {
- - i_nal_type = NAL_SLICE;
- + i_nal_type = h->b_dependent ? NAL_SLICE_LAYER_EXTENSION : NAL_SLICE;
- i_nal_ref_idc = h->param.i_bframe_pyramid == X264_B_PYRAMID_STRICT ? NAL_PRIORITY_LOW : NAL_PRIORITY_HIGH;
- h->sh.i_type = SLICE_TYPE_B;
- + h->sh.b_anchor = 0;
- x264_reference_hierarchy_reset( h );
- }
- else /* B frame */
- {
- - i_nal_type = NAL_SLICE;
- + i_nal_type = h->b_dependent ? NAL_SLICE_LAYER_EXTENSION : NAL_SLICE;
- i_nal_ref_idc = NAL_PRIORITY_DISPOSABLE;
- h->sh.i_type = SLICE_TYPE_B;
- + h->sh.b_anchor = 0;
- }
- h->fdec->i_type = h->fenc->i_type;
- h->fdec->i_frame = h->fenc->i_frame;
- + h->fdec->b_inter_view_only = h->fenc->b_inter_view_only;
- h->fenc->b_kept_as_ref =
- - h->fdec->b_kept_as_ref = i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE && h->param.i_keyint_max > 1;
- + h->fdec->b_kept_as_ref = ( h->param.b_mvc && !h->b_dependent ) ||
- + (i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE && h->param.i_keyint_max > 1);
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[%4d]: kept as ref = %d\n", h->fenc->i_frame, h->fenc->b_kept_as_ref);
- +#endif
- h->fdec->i_pts = h->fenc->i_pts;
- if( h->frames.i_bframe_delay )
- @@ -2575,7 +3222,14 @@ int x264_encoder_encode( x264_t *h,
- else
- h->fdec->i_dts = h->fenc->i_reordered_pts;
- if( h->fenc->i_type == X264_TYPE_IDR )
- + {
- h->i_last_idr_pts = h->fdec->i_pts;
- + h->i_last_idr_frame = h->fdec->i_frame;
- + }
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[%4d]: pts=%d, bframe_delay=%d, reordered_pts=%d, i_dts=%d\n",
- + h->fenc->i_frame, h->fenc->i_pts, h->frames.i_bframe_delay, h->fenc->i_reordered_pts, h->fdec->i_dts);
- +#endif
- /* ------------------- Init ----------------------------- */
- /* build ref list 0/1 */
- @@ -2631,7 +3285,7 @@ int x264_encoder_encode( x264_t *h,
- * the whole frame and counts as an intra refresh. */
- h->fdec->f_pir_position = h->mb.i_mb_width;
- }
- - else if( h->fenc->i_type == X264_TYPE_P )
- + else if( h->fenc->i_type == X264_TYPE_P || h->fenc->i_type == X264_TYPE_ANCHOR)
- {
- int pocdiff = (h->fdec->i_poc - h->fref[0][0]->i_poc)/2;
- float increment = X264_MAX( ((float)h->mb.i_mb_width-1) / h->param.i_keyint_max, 1 );
- @@ -2654,7 +3308,7 @@ int x264_encoder_encode( x264_t *h,
- }
- }
- - if( h->fenc->b_keyframe )
- + if( h->fenc->b_keyframe || (h->fenc->i_type == X264_TYPE_I && h->param.b_repeat_headers_all_gop))
- {
- /* Write SPS and PPS */
- if( h->param.b_repeat_headers )
- @@ -2676,6 +3330,45 @@ int x264_encoder_encode( x264_t *h,
- /* buffering period sei is written in x264_encoder_frame_end */
- }
- + else if( (h->b_dependent && h->frames.i_last_keyframe == h->fenc->i_frame - 1) ||
- + (h->fenc->i_type == X264_TYPE_ANCHOR && h->param.b_repeat_headers_all_gop) )
- + {
- + // for MVC subset SPS and subset PPS
- + /* Write SPS and PPS */
- + if( h->param.b_repeat_headers )
- + {
- + // printf("Writing subset SPS. (i_frame=%d)\n", h->fenc->i_frame);
- + /* generate sequence parameters */
- + x264_nal_start( h, NAL_SUBSET_SPS, NAL_PRIORITY_HIGHEST );
- + // x264_sps_write( &h->out.bs, h->subset_sps );
- + x264_subset_sps_write( &h->out.bs, h->subset_sps );
- + if( x264_nal_end( h ) )
- + return -1;
- + overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
- +
- + /* generate picture parameters */
- + x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
- + x264_pps_write( &h->out.bs, h->subset_pps );
- + if( x264_nal_end( h ) )
- + return -1;
- + overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
- + }
- +
- + /* buffering period sei is written in x264_encoder_frame_end */
- + }
- + else
- + {
- + /* Write PPS */
- + if( h->param.b_repeat_pps_all_frames )
- + {
- + /* generate picture parameters */
- + x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
- + x264_pps_write( &h->out.bs, h->pps );
- + if( x264_nal_end( h ) )
- + return -1;
- + overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
- + }
- + }
- /* write extra sei */
- for( int i = 0; i < h->fenc->extra_sei.num_payloads; i++ )
- @@ -2693,7 +3386,7 @@ int x264_encoder_encode( x264_t *h,
- if( h->fenc->extra_sei.sei_free && h->fenc->extra_sei.payloads )
- h->fenc->extra_sei.sei_free( h->fenc->extra_sei.payloads );
- - if( h->fenc->b_keyframe )
- + if( h->fenc->b_keyframe || h->sh.b_anchor)
- {
- if( h->param.b_repeat_headers && h->fenc->i_frame == 0 )
- {
- @@ -2706,7 +3399,7 @@ int x264_encoder_encode( x264_t *h,
- overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
- }
- - if( h->fenc->i_type != X264_TYPE_IDR )
- + if( h->fenc->i_type != X264_TYPE_IDR && h->fenc->i_type != X264_TYPE_ANCHOR)
- {
- int time_to_recovery = h->param.i_open_gop ? 0 : X264_MIN( h->mb.i_mb_width - 1, h->param.i_keyint_max ) + h->param.i_bframe - 1;
- x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- @@ -2715,15 +3408,6 @@ int x264_encoder_encode( x264_t *h,
- return -1;
- overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
- }
- -
- - if ( h->param.i_frame_packing >= 0 )
- - {
- - x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- - x264_sei_frame_packing_write( h, &h->out.bs );
- - if( x264_nal_end( h ) )
- - return -1;
- - overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
- - }
- }
- /* generate sei pic timing */
- @@ -2736,12 +3420,32 @@ int x264_encoder_encode( x264_t *h,
- overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
- }
- - if( h->fenc->b_keyframe && h->param.b_intra_refresh )
- + if (h->param.b_mvc) {
- + h->i_cpb_delay_pir_offset_dep = h->i_cpb_delay_pir_offset;
- + }
- + if( h->fenc->b_keyframe && h->param.b_intra_refresh ) {
- h->i_cpb_delay_pir_offset = h->fenc->i_cpb_delay;
- + }
- +
- + if( h->fenc->b_keyframe || h->sh.b_anchor)
- + {
- + if ( h->param.i_frame_packing >= 0 )
- + {
- + x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- + x264_sei_frame_packing_write( h, &h->out.bs );
- + if( x264_nal_end( h ) )
- + return -1;
- + overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
- + }
- + }
- /* Init the rate control */
- /* FIXME: Include slice header bit cost. */
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[%4d]: ratecontrol_start\n", h->fenc->i_frame);
- +#endif
- x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );
- +
- i_global_qp = x264_ratecontrol_qp( h );
- pic_out->i_qpplus1 =
- @@ -2752,12 +3456,17 @@ int x264_encoder_encode( x264_t *h,
- x264_reference_build_list_optimal( h );
- x264_reference_check_reorder( h );
- }
- + else if ( h->b_dependent )
- + {
- + x264_reference_build_list_mvc( h );
- + }
- + log_ref_list( h );
- if( h->i_ref[0] )
- h->fdec->i_poc_l0ref0 = h->fref[0][0]->i_poc;
- /* ------------------------ Create slice header ----------------------- */
- - x264_slice_init( h, i_nal_type, i_global_qp );
- + x264_slice_init( h, i_nal_type, i_global_qp, i_nal_ref_idc );
- /*------------------------- Weights -------------------------------------*/
- if( h->sh.i_type == SLICE_TYPE_B )
- @@ -2769,30 +3478,58 @@ int x264_encoder_encode( x264_t *h,
- h->i_frame_num++;
- /* Write frame */
- - h->i_threadslice_start = 0;
- - h->i_threadslice_end = h->mb.i_mb_height;
- - if( h->i_thread_frames > 1 )
- - {
- + if (!h->b_dependent) {
- + h->i_threadslice_start = 0;
- + h->i_threadslice_end = h->mb.i_mb_height;
- + if( h->i_thread_frames > 1 )
- + {
- x264_threadpool_run( h->threadpool, (void*)x264_slices_write, h );
- h->b_thread_active = 1;
- - }
- - else if( h->param.b_sliced_threads )
- - {
- + }
- + else if( h->param.b_sliced_threads )
- + {
- if( x264_threaded_slices_write( h ) )
- - return -1;
- - }
- - else
- + return -1;
- + }
- + else
- if( (intptr_t)x264_slices_write( h ) )
- - return -1;
- + return -1;
- + } else {
- + /* for dependent view(copy from upper) */
- + /* Write frame */
- + h->i_threadslice_start = 0;
- + h->i_threadslice_end = h->mb.i_mb_height;
- +
- + h->sh.b_svc_extension_flag = 1;
- +
- + if( h->i_thread_frames > 1 )
- + {
- + // printf("Writing coded slice extension. (frame id: %d)\n", h->i_frame);
- + x264_threadpool_run( h->threadpool, (void*)x264_slices_write, h );
- + h->b_thread_active = 1;
- + }
- + else if( h->param.b_sliced_threads )
- + {
- + if( x264_threaded_slices_write( h ) )
- + return -1;
- + }
- + else
- + {
- + if( (intptr_t)x264_slices_write( h ) )
- + return -1;
- + }
- + }
- - return x264_encoder_frame_end( thread_oldest, thread_current, pp_nal, pi_nal, pic_out );
- + return x264_encoder_frame_end( thread_oldest, thread_current, thread_next_oldest, pp_nal, pi_nal, pic_out );
- }
- static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
- + x264_t *thread_next,
- x264_nal_t **pp_nal, int *pi_nal,
- x264_picture_t *pic_out )
- {
- char psz_message[80];
- + x264_sps_t *sps = h->b_dependent ? h->subset_sps : h->sps;
- if( h->b_thread_active )
- {
- @@ -2808,9 +3545,13 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
- x264_emms();
- /* generate sei buffering period and insert it into place */
- - if( h->fenc->b_keyframe && h->sps->vui.b_nal_hrd_parameters_present )
- + if( (h->fenc->b_keyframe || h->fenc->i_type == X264_TYPE_ANCHOR || h->fenc->i_type == X264_TYPE_I) &&
- + sps->vui.b_nal_hrd_parameters_present )
- {
- x264_hrd_fullness( h );
- + if (h->param.b_mvc && !h->b_dependent) {
- + x264_hrd_copy_to_dependent(h, thread_next);
- + }
- x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- x264_sei_buffering_period_write( h, &h->out.bs );
- if( x264_nal_end( h ) )
- @@ -2819,6 +3560,7 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
- int idx = 0;
- while( h->out.nal[idx].i_type == NAL_AUD ||
- h->out.nal[idx].i_type == NAL_SPS ||
- + h->out.nal[idx].i_type == NAL_SUBSET_SPS ||
- h->out.nal[idx].i_type == NAL_PPS )
- idx++;
- x264_nal_t nal_tmp = h->out.nal[h->out.i_nal-1];
- @@ -2837,9 +3579,9 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
- pic_out->i_pts = h->fdec->i_pts;
- pic_out->i_dts = h->fdec->i_dts;
- - if( pic_out->i_pts < pic_out->i_dts )
- - x264_log( h, X264_LOG_WARNING, "invalid DTS: PTS is less than DTS\n" );
- -
- + if( pic_out->i_pts < pic_out->i_dts ) {
- + x264_log( h, X264_LOG_WARNING, "invalid DTS: PTS(%lld) is less than DTS(%lld)\n", pic_out->i_pts, pic_out->i_dts );
- + }
- pic_out->img.i_csp = X264_CSP_NV12;
- #if HIGH_BIT_DEPTH
- pic_out->img.i_csp |= X264_CSP_HIGH_DEPTH;
- @@ -2896,10 +3638,15 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
- x264_thread_sync_stat( h, h->thread[0] );
- /* Slice stat */
- - h->stat.i_frame_count[h->sh.i_type]++;
- - h->stat.i_frame_size[h->sh.i_type] += frame_size;
- - h->stat.f_frame_qp[h->sh.i_type] += h->fdec->f_qp_avg_aq;
- -
- + if (h->b_dependent) {
- + h->stat.i_frame_dep_count[h->sh.i_type]++;
- + h->stat.i_frame_dep_size[h->sh.i_type] += frame_size;
- + h->stat.f_frame_dep_qp[h->sh.i_type] += h->fdec->f_qp_avg_aq;
- + } else {
- + h->stat.i_frame_count[h->sh.i_type]++;
- + h->stat.i_frame_size[h->sh.i_type] += frame_size;
- + h->stat.f_frame_qp[h->sh.i_type] += h->fdec->f_qp_avg_aq;
- + }
- for( int i = 0; i < X264_MBTYPE_MAX; i++ )
- h->stat.i_mb_count[h->sh.i_type][i] += h->stat.frame.i_mb_count[i];
- for( int i = 0; i < X264_PARTTYPE_MAX; i++ )
- @@ -3014,7 +3761,7 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
- h->fref[0][i] = 0;
- }
- - if( h->param.psz_dump_yuv )
- + if( h->param.psz_dump_yuv[0] )
- x264_frame_dump( h );
- x264_emms();
- @@ -3311,6 +4058,12 @@ void x264_encoder_close ( x264_t *h )
- /* rc */
- x264_ratecontrol_delete( h );
- +
- + if( h->param.psz_dump_yuv[1] )
- + {
- + free(h->param.psz_dump_yuv[1]);
- + h->param.psz_dump_yuv[1] = NULL;
- + }
- /* param */
- if( h->param.rc.psz_stat_out )
- @@ -3380,13 +4133,20 @@ int x264_encoder_delayed_frames( x264_t *h )
- }
- for( int i = 0; h->frames.current[i]; i++ )
- delayed_frames++;
- +
- x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );
- x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex );
- x264_pthread_mutex_lock( &h->lookahead->next.mutex );
- + x264_pthread_mutex_lock( &h->lookahead->next_dependent.mutex );
- +
- delayed_frames += h->lookahead->ifbuf.i_size + h->lookahead->next.i_size + h->lookahead->ofbuf.i_size;
- + delayed_frames += h->lookahead->next_dependent.i_size;
- +
- + x264_pthread_mutex_unlock( &h->lookahead->next_dependent.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->next.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->ofbuf.mutex );
- +
- return delayed_frames;
- }
- diff --git encoder/lookahead.c encoder/lookahead.c
- index 7e04864..b53a200 100644
- --- encoder/lookahead.c
- +++ encoder/lookahead.c
- @@ -39,9 +39,12 @@
- #include "common/common.h"
- #include "analyse.h"
- +//#define __DEBUG
- +
- static void x264_lookahead_shift( x264_sync_frame_list_t *dst, x264_sync_frame_list_t *src, int count )
- {
- int i = count;
- +
- while( i-- )
- {
- assert( dst->i_size < dst->i_max_size );
- @@ -64,20 +67,122 @@ static void x264_lookahead_update_last_nonb( x264_t *h, x264_frame_t *new_nonb )
- new_nonb->i_reference_count++;
- }
- +static void x264_lookahead_update_last_nonb_dep( x264_t *h, x264_frame_t *new_nonb )
- +{
- + if( h->lookahead->last_nonb_dependent )
- + x264_frame_push_unused( h, h->lookahead->last_nonb_dependent );
- + h->lookahead->last_nonb_dependent = new_nonb;
- + new_nonb->i_reference_count++;
- +}
- +
- #if HAVE_THREAD
- static void x264_lookahead_slicetype_decide( x264_t *h )
- {
- - x264_stack_align( x264_slicetype_decide, h );
- + static int frameNum = 0;
- + int b_mvc = h->param.b_mvc;
- +
- + // if (!h->param.b_mvc ||
- + // (h->param.b_mvc && !(frameNum & 0x1))) {
- + x264_stack_align( x264_slicetype_decide, h );
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[update last_nonb 0]: frame %d\n", h->lookahead->next.list[0]->i_frame);
- +#endif
- x264_lookahead_update_last_nonb( h, h->lookahead->next.list[0] );
- + if (b_mvc) x264_lookahead_update_last_nonb_dep( h, h->lookahead->next_dependent.list[0] );
- + // }
- +
- + int shift = h->lookahead->next.list[0]->i_bframes + 1;
- x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );
- - while( h->lookahead->ofbuf.i_size == h->lookahead->ofbuf.i_max_size )
- +
- + if (!h->param.b_mvc) {
- + while( h->lookahead->ofbuf.i_size == h->lookahead->ofbuf.i_max_size ) {
- x264_pthread_cond_wait( &h->lookahead->ofbuf.cv_empty, &h->lookahead->ofbuf.mutex );
- + }
- + } else { // mvc case
- + while( h->lookahead->ofbuf.i_max_size - h->lookahead->ofbuf.i_size < (shift * 2)) {
- + x264_pthread_cond_wait( &h->lookahead->ofbuf.cv_empty, &h->lookahead->ofbuf.mutex );
- + }
- + }
- x264_pthread_mutex_lock( &h->lookahead->next.mutex );
- - x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, h->lookahead->next.list[0]->i_bframes + 1 );
- + x264_pthread_mutex_lock( &h->lookahead->next_dependent.mutex );
- +
- + if (!h->param.b_mvc) {
- + x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, shift );
- + } else { // for MVC
- + for (int i = 0; i < shift; i++) {
- + int base_i_type = h->lookahead->next.list[0]->i_type;
- + for (int j = 0; j < X264_BFRAME_MAX + 2; j++) {
- + for (int k = 0; k < X264_BFRAME_MAX + 2; k++) {
- + h->lookahead->next_dependent.list[0]->i_cost_est[j][k] = h->lookahead->next.list[0]->i_cost_est[j][k];
- + h->lookahead->next_dependent.list[0]->i_cost_est_aq[j][k] = h->lookahead->next.list[0]->i_cost_est_aq[j][k];
- +
- + h->lookahead->next_dependent.list[0]->i_cpb_duration = h->lookahead->next.list[0]->i_cpb_duration;
- + h->lookahead->next_dependent.list[0]->i_cpb_delay = h->lookahead->next.list[0]->i_cpb_delay;
- + h->lookahead->next_dependent.list[0]->i_dpb_output_delay = h->lookahead->next.list[0]->i_dpb_output_delay;
- +
- +#ifdef __DEBUG
- + if ( h->lookahead->next.list[0]->i_cost_est[j][k] >= 0) {
- + x264_log(h, X264_LOG_INFO, "i_cost_est[%d][%d] = %d\n", j, k, h->lookahead->next.list[0]->i_cost_est[j][k]);
- + }
- +#endif
- + }
- + }
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "base_i_type %d\n", base_i_type);
- +#endif
- +
- + int dep_i_type;
- + int b_anchor = 0;
- + switch(base_i_type) {
- + case X264_TYPE_I :
- + case X264_TYPE_IDR :
- + case X264_TYPE_KEYFRAME :
- + dep_i_type = X264_TYPE_ANCHOR;
- + b_anchor = 1;
- + break;
- + case X264_TYPE_P :
- + dep_i_type = X264_TYPE_P;
- + break;
- + case X264_TYPE_B :
- + dep_i_type = X264_TYPE_B;
- + break;
- + case X264_TYPE_BREF :
- + dep_i_type = X264_TYPE_BREF;
- + break;
- + default :
- + dep_i_type = X264_TYPE_P;
- + break;
- + }
- + h->lookahead->next_dependent.list[0]->i_type = dep_i_type;
- + //h->lookahead->next_dependent.list[0]->b_anchor = b_anchor;
- +
- + x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, 1 );
- +
- + //x264_log(h, X264_LOG_INFO, "lookahead_shift [next] i_frame %d\n", h->lookahead->next.i_size);
- +
- +#if 0
- + while( h->lookahead->ofbuf.i_size == h->lookahead->ofbuf.i_max_size ) {
- + x264_pthread_cond_wait( &h->lookahead->ofbuf.cv_empty, &h->lookahead->ofbuf.mutex );
- + }
- +#endif
- +
- +
- + x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next_dependent, 1 );
- + //x264_log(h, X264_LOG_INFO, "lookahead_shift [next_dep] i_frame %d\n", h->lookahead->next_dependent.i_size);
- +
- + //x264_log(h, X264_LOG_INFO, "ofbuf size %d\n", h->lookahead->ofbuf.i_size);
- +
- + }
- + }
- +
- x264_pthread_mutex_unlock( &h->lookahead->next.mutex );
- + x264_pthread_mutex_unlock( &h->lookahead->next_dependent.mutex );
- +
- + frameNum++;
- /* For MB-tree and VBV lookahead, we have to perform propagation analysis on I-frames too. */
- if( h->lookahead->b_analyse_keyframe && IS_X264_TYPE_I( h->lookahead->last_nonb->i_type ) )
- @@ -89,6 +194,12 @@ static void x264_lookahead_slicetype_decide( x264_t *h )
- static void x264_lookahead_thread( x264_t *h )
- {
- int shift;
- + int shift_dependent;
- +
- + int b_mvc = h->param.b_mvc;
- +
- + x264_log( h, X264_LOG_INFO, "b_mvc %d\n", b_mvc);
- +
- #if HAVE_MMX
- if( h->param.cpu&X264_CPU_SSE_MISALIGN )
- x264_cpu_mask_misalign_sse();
- @@ -97,28 +208,100 @@ static void x264_lookahead_thread( x264_t *h )
- {
- x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex );
- x264_pthread_mutex_lock( &h->lookahead->next.mutex );
- - shift = X264_MIN( h->lookahead->next.i_max_size - h->lookahead->next.i_size, h->lookahead->ifbuf.i_size );
- - x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, shift );
- + x264_pthread_mutex_lock( &h->lookahead->next_dependent.mutex );
- +
- + if (!b_mvc) {
- + shift = X264_MIN( h->lookahead->next.i_max_size - h->lookahead->next.i_size, h->lookahead->ifbuf.i_size );
- + // base and dependent will be divided to the other buffer
- + x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, shift);
- + } else {
- + shift = X264_MIN( h->lookahead->next.i_max_size - h->lookahead->next.i_size, h->lookahead->ifbuf.i_size / 2);
- + shift_dependent = X264_MIN( h->lookahead->next_dependent.i_max_size - h->lookahead->next_dependent.i_size,
- + h->lookahead->ifbuf.i_size / 2);
- + shift = X264_MIN(shift, shift_dependent);
- + shift_dependent = shift;
- +#ifdef __DEBUG
- + if (h->lookahead->ifbuf.i_size > 1) {
- + x264_log( h, X264_LOG_INFO, "i_size %d\n", h->lookahead->ifbuf.i_size);
- + }
- +#endif
- +#ifdef __DEBUG
- + if ((shift > 0) || (shift_dependent > 0)) {
- + x264_log( h, X264_LOG_INFO, "shift %d shift_dep %d\n", shift, shift_dependent);
- + }
- +#endif
- + // base and dependent will be divided to the other buffer
- + while (shift > 0 || shift_dependent > 0) {
- + if (shift) {
- + x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, 1);
- + shift--;
- + }
- + if (shift_dependent) {
- + x264_lookahead_shift( &h->lookahead->next_dependent, &h->lookahead->ifbuf, 1 );
- + shift_dependent--;
- + }
- + }
- + }
- +
- + x264_pthread_mutex_unlock( &h->lookahead->next_dependent.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->next.mutex );
- - if( h->lookahead->next.i_size <= h->lookahead->i_slicetype_length + h->param.b_vfr_input )
- +
- +
- +#ifdef __DEBUG____
- +
- + if (h->lookahead->ifbuf.i_size > 0) {
- + x264_log( h, X264_LOG_INFO, "ibuf %d ", h->lookahead->ifbuf.i_size);
- + x264_log( h, X264_LOG_INFO, "next.i_size %d next_dep.i_size %d \n", h->lookahead->next.i_size,
- + h->lookahead->next_dependent.i_size);
- + x264_log( h, X264_LOG_INFO, "slice_type_length %d b_vfr %d", h->lookahead->i_slicetype_length,
- + h->param.b_vfr_input);
- +
- + }
- +#endif
- +
- + if ( (!b_mvc && (h->lookahead->next.i_size <= h->lookahead->i_slicetype_length + h->param.b_vfr_input)) ||
- + (b_mvc && ((h->lookahead->next.i_size <= h->lookahead->i_slicetype_length + h->param.b_vfr_input )
- + || (h->lookahead->next_dependent.i_size <= h->lookahead->i_slicetype_length + h->param.b_vfr_input) ) ) )
- {
- - while( !h->lookahead->ifbuf.i_size && !h->lookahead->b_exit_thread )
- - x264_pthread_cond_wait( &h->lookahead->ifbuf.cv_fill, &h->lookahead->ifbuf.mutex );
- + while( !h->lookahead->ifbuf.i_size && !h->lookahead->b_exit_thread ) {
- + x264_pthread_cond_wait( &h->lookahead->ifbuf.cv_fill, &h->lookahead->ifbuf.mutex );
- + }
- x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex );
- }
- else
- {
- x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex );
- + // x264_log( h, X264_LOG_INFO, "buffer is filled enough\n");
- + // for base view, slice_type is decided here
- +
- x264_lookahead_slicetype_decide( h );
- +
- }
- } /* end of input frames */
- +
- +
- x264_pthread_mutex_lock( &h->lookahead->ifbuf.mutex );
- x264_pthread_mutex_lock( &h->lookahead->next.mutex );
- - x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, h->lookahead->ifbuf.i_size );
- + x264_pthread_mutex_lock( &h->lookahead->next_dependent.mutex );
- +
- + if (!h->param.b_mvc) { // not mvc
- + x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, h->lookahead->ifbuf.i_size );
- + } else { // mvc
- + for (int i = 0; i < (h->lookahead->ifbuf.i_size / 2); i++) {
- + x264_lookahead_shift( &h->lookahead->next, &h->lookahead->ifbuf, 1);
- + x264_lookahead_shift( &h->lookahead->next_dependent, &h->lookahead->ifbuf, 1);
- + }
- + }
- +
- + x264_pthread_mutex_unlock( &h->lookahead->next_dependent.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->next.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->ifbuf.mutex );
- - while( h->lookahead->next.i_size )
- +
- +
- + while( h->lookahead->next.i_size ) {
- x264_lookahead_slicetype_decide( h );
- + }
- +
- x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );
- h->lookahead->b_thread_active = 0;
- x264_pthread_cond_broadcast( &h->lookahead->ofbuf.cv_fill );
- @@ -141,9 +324,13 @@ int x264_lookahead_init( x264_t *h, int i_slicetype_length )
- /* init frame lists */
- if( x264_sync_frame_list_init( &look->ifbuf, h->param.i_sync_lookahead+3 ) ||
- x264_sync_frame_list_init( &look->next, h->frames.i_delay+3 ) ||
- - x264_sync_frame_list_init( &look->ofbuf, h->frames.i_delay+3 ) )
- + x264_sync_frame_list_init( &look->ofbuf, (h->frames.i_delay+3) * (h->param.b_mvc ? 2 : 1) ) )
- goto fail;
- + /* for MVC lookahead */
- + if (x264_sync_frame_list_init( &look->next_dependent, h->frames.i_delay + 3))
- + goto fail;
- +
- if( !h->param.i_sync_lookahead )
- return 0;
- @@ -180,25 +367,53 @@ void x264_lookahead_delete( x264_t *h )
- }
- x264_sync_frame_list_delete( &h->lookahead->ifbuf );
- x264_sync_frame_list_delete( &h->lookahead->next );
- + x264_sync_frame_list_delete( &h->lookahead->next_dependent);
- +
- if( h->lookahead->last_nonb )
- x264_frame_push_unused( h, h->lookahead->last_nonb );
- + if( h->param.b_mvc && h->lookahead->last_nonb_dependent )
- + x264_frame_push_unused( h, h->lookahead->last_nonb_dependent );
- x264_sync_frame_list_delete( &h->lookahead->ofbuf );
- x264_free( h->lookahead );
- }
- void x264_lookahead_put_frame( x264_t *h, x264_frame_t *frame )
- {
- - if( h->param.i_sync_lookahead )
- - x264_sync_frame_list_push( &h->lookahead->ifbuf, frame );
- - else
- + static int frame_num = 0;
- + if( h->param.i_sync_lookahead ) { // if lookahead is enabled, base and dependent is divided at the next function
- + x264_sync_frame_list_push( &h->lookahead->ifbuf, frame );
- + } else { // if lookahead is disabled, base and dependent is divided here
- +
- + if (!h->param.b_mvc) {
- + x264_sync_frame_list_push( &h->lookahead->next, frame );
- + } else { // mvc case
- + if (frame_num & 0x1) {
- + x264_sync_frame_list_push( &h->lookahead->next_dependent, frame );
- + } else {
- + x264_sync_frame_list_push( &h->lookahead->next, frame );
- + }
- + }
- +
- + /*
- + if (h->param.b_mvc && ((frame_num & 0x1) != 0)) {
- + x264_sync_frame_list_push( &h->lookahead->next_dependent, frame );
- + } else {
- x264_sync_frame_list_push( &h->lookahead->next, frame );
- + }
- + */
- + }
- + frame_num++;
- +
- }
- int x264_lookahead_is_empty( x264_t *h )
- {
- x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );
- x264_pthread_mutex_lock( &h->lookahead->next.mutex );
- - int b_empty = !h->lookahead->next.i_size && !h->lookahead->ofbuf.i_size;
- + x264_pthread_mutex_lock( &h->lookahead->next_dependent.mutex );
- + // int b_empty = !h->lookahead->next.i_size && !h->lookahead->ofbuf.i_size;
- + int b_empty = !h->lookahead->next.i_size && !h->lookahead->ofbuf.i_size && !h->lookahead->next_dependent.i_size;
- + x264_pthread_mutex_unlock( &h->lookahead->next_dependent.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->next.mutex );
- x264_pthread_mutex_unlock( &h->lookahead->ofbuf.mutex );
- return b_empty;
- @@ -206,26 +421,64 @@ int x264_lookahead_is_empty( x264_t *h )
- static void x264_lookahead_encoder_shift( x264_t *h )
- {
- +#ifdef _DEBUG
- + x264_log(h, X264_LOG_INFO, "encoder_shift ofbuf.i_size %d\n", h->lookahead->ofbuf.i_size);
- +#endif
- +
- if( !h->lookahead->ofbuf.i_size )
- return;
- - int i_frames = h->lookahead->ofbuf.list[0]->i_bframes + 1;
- +
- + int i_frames;
- + if (!h->param.b_mvc) {
- + i_frames = h->lookahead->ofbuf.list[0]->i_bframes + 1;
- + } else {
- + i_frames = (h->lookahead->ofbuf.list[0]->i_bframes + 1) * 2;
- + }
- +
- +#ifdef _DEBUG
- + x264_log(h, X264_LOG_INFO, "encoder_shift i_frames %d\n", i_frames);
- +#endif
- +
- while( i_frames-- )
- {
- x264_frame_push( h->frames.current, x264_frame_shift( h->lookahead->ofbuf.list ) );
- h->lookahead->ofbuf.i_size--;
- }
- x264_pthread_cond_broadcast( &h->lookahead->ofbuf.cv_empty );
- +
- }
- void x264_lookahead_get_frames( x264_t *h )
- {
- + static int frameNum = 0;
- +
- if( h->param.i_sync_lookahead )
- { /* We have a lookahead thread, so get frames from there */
- x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );
- - while( !h->lookahead->ofbuf.i_size && h->lookahead->b_thread_active )
- +
- + if (!h->param.b_mvc) {
- + while( !h->lookahead->ofbuf.i_size && h->lookahead->b_thread_active ) {
- x264_pthread_cond_wait( &h->lookahead->ofbuf.cv_fill, &h->lookahead->ofbuf.mutex );
- - x264_lookahead_encoder_shift( h );
- + }
- +
- + x264_lookahead_encoder_shift( h );
- + } else { // mvc case
- +
- + if ((h->lookahead->next.i_size + h->lookahead->next_dependent.i_size
- + + h->lookahead->ifbuf.i_size + h->lookahead->ofbuf.i_size) >= 2) {
- +
- + while( (h->lookahead->ofbuf.i_size < 2) && h->lookahead->b_thread_active ) {
- + x264_pthread_cond_wait( &h->lookahead->ofbuf.cv_fill, &h->lookahead->ofbuf.mutex );
- + }
- +
- + x264_lookahead_encoder_shift( h );
- + } else { // put frame is only 1. wait for next put frame
- + return;
- + }
- + }
- x264_pthread_mutex_unlock( &h->lookahead->ofbuf.mutex );
- +
- + frameNum++;
- }
- else
- { /* We are not running a lookahead thread, so perform all the slicetype decide on the fly */
- @@ -233,14 +486,149 @@ void x264_lookahead_get_frames( x264_t *h )
- if( h->frames.current[0] || !h->lookahead->next.i_size )
- return;
- - x264_stack_align( x264_slicetype_decide, h );
- - x264_lookahead_update_last_nonb( h, h->lookahead->next.list[0] );
- - x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, h->lookahead->next.list[0]->i_bframes + 1 );
- + if (h->param.b_mvc && !h->lookahead->next_dependent.i_size) {
- + return;
- + }
- +
- + int b_frame_pair_exists = 0;
- + if ((h->lookahead->next.i_size == h->lookahead->next_dependent.i_size) && h->lookahead->next.i_size && h->lookahead->next_dependent.i_size) {
- + b_frame_pair_exists = 1;
- + }
- + // x264_log(h, X264_LOG_INFO, "lookahead_shift [next] i_frame %d\n", h->lookahead->next.i_size);
- + // x264_log(h, X264_LOG_INFO, "lookahead_shift [next_dep] i_frame %d\n", h->lookahead->next_dependent.i_size);
- +
- + //x264_log(h, X264_LOG_INFO, "i_bframes %d\n", h->lookahead->next.list[0]->i_bframes);
- + //x264_log(h, X264_LOG_INFO, "i_reference_count %d\n", h->lookahead->next.list[0]->i_reference_count);
- + //x264_log(h, X264_LOG_INFO, "frameNum %d\n", frameNum);
- +
- + if (!h->param.b_mvc) {
- + x264_stack_align( x264_slicetype_decide, h );
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[update last_nonb 1]: frame %d\n", h->lookahead->next.list[0]->i_frame);
- +#endif
- + x264_lookahead_update_last_nonb( h, h->lookahead->next.list[0] );
- + } else { // mvc case
- + // if (!(frameNum & 0x1)) { // if even frame, slicetype_decide is executed
- + if (b_frame_pair_exists) {
- + // x264_log(h, X264_LOG_INFO, "slicetype_decide\n");
- + x264_stack_align( x264_slicetype_decide, h );
- +
- +#ifdef _DEBUG
- + if ( h->lookahead->next.list[0] ) {
- + x264_log(h, X264_LOG_INFO, "[0]i_frame %d\n", h->lookahead->next.list[0]->i_frame);
- + }
- + if ( h->lookahead->next.list[1] ) {
- + x264_log(h, X264_LOG_INFO, "[1]i_frame %d\n", h->lookahead->next.list[1]->i_frame);
- + }
- + if ( h->lookahead->next.list[2] ) {
- + x264_log(h, X264_LOG_INFO, "[2]i_frame %d\n", h->lookahead->next.list[2]->i_frame);
- + }
- +
- + if ( h->lookahead->next_dependent.list[0] ) {
- + x264_log(h, X264_LOG_INFO, "dep[0]i_frame %d\n", h->lookahead->next_dependent.list[0]->i_frame);
- + }
- + if ( h->lookahead->next_dependent.list[1] ) {
- + x264_log(h, X264_LOG_INFO, "dep[1]i_frame %d\n", h->lookahead->next_dependent.list[1]->i_frame);
- + }
- + if ( h->lookahead->next_dependent.list[2] ) {
- + x264_log(h, X264_LOG_INFO, "dep[2]i_frame %d\n", h->lookahead->next_dependent.list[2]->i_frame);
- + }
- +#endif
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[update last_nonb 2]: frame %d\n", h->lookahead->next.list[0]->i_frame);
- +#endif
- + x264_lookahead_update_last_nonb( h, h->lookahead->next.list[0] );
- + x264_lookahead_update_last_nonb_dep( h, h->lookahead->next_dependent.list[0] );
- + }
- + }
- +
- + int shift = h->lookahead->next.list[0]->i_bframes + 1;
- +
- + if (!h->param.b_mvc) {
- + x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, shift );
- + } else { // for MVC
- + // if (!(frameNum & 0x1)) { // if even frame, next buf data is moved to the ofbuf
- + if (b_frame_pair_exists) {
- +
- + // make cost and slice_type for dependent view
- + for (int i = 0; i < shift; i++) {
- + int base_i_type = h->lookahead->next.list[0]->i_type;
- + for (int j = 0; j < X264_BFRAME_MAX + 2; j++) {
- + for (int k = 0; k < X264_BFRAME_MAX + 2; k++) {
- + h->lookahead->next_dependent.list[0]->i_cost_est[j][k] = h->lookahead->next.list[0]->i_cost_est[j][k];
- + h->lookahead->next_dependent.list[0]->i_cost_est_aq[j][k] = h->lookahead->next.list[0]->i_cost_est_aq[j][k];
- +
- + h->lookahead->next_dependent.list[0]->i_cpb_duration = h->lookahead->next.list[0]->i_cpb_duration;
- +
- +#ifdef __DEBUG
- + if ( h->lookahead->next.list[0]->i_cost_est[j][k] >= 0) {
- + x264_log(h, X264_LOG_INFO, "i_cost_est[%d][%d] = %d\n", j, k, h->lookahead->next.list[0]->i_cost_est[j][k]);
- + }
- +#endif
- + }
- + }
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "base_i_type %d\n", base_i_type);
- +#endif
- +
- + int dep_i_type;
- + int b_anchor = 0;
- + switch(base_i_type) {
- + case X264_TYPE_I :
- + case X264_TYPE_IDR :
- + case X264_TYPE_KEYFRAME :
- + dep_i_type = X264_TYPE_ANCHOR;
- + b_anchor = 1;
- + break;
- + case X264_TYPE_P :
- + dep_i_type = X264_TYPE_P;
- + break;
- + case X264_TYPE_B :
- + dep_i_type = X264_TYPE_B;
- + break;
- + case X264_TYPE_BREF :
- + dep_i_type = X264_TYPE_BREF;
- + break;
- + default :
- + dep_i_type = X264_TYPE_P;
- + break;
- + }
- + h->lookahead->next_dependent.list[0]->i_type = dep_i_type;
- + //h->lookahead->next_dependent.list[0]->b_anchor = b_anchor;
- +
- +
- + x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next, 1 );
- + x264_lookahead_shift( &h->lookahead->ofbuf, &h->lookahead->next_dependent, 1 );
- +
- +#ifdef _DEBUG
- + x264_log(h, X264_LOG_INFO, "lookahead_shift [next] i_frame %d\n", h->lookahead->next.i_size);
- + x264_log(h, X264_LOG_INFO, "lookahead_shift [next_dep] i_frame %d\n", h->lookahead->next_dependent.i_size);
- + x264_log(h, X264_LOG_INFO, "ofbuf_suze %d\n", h->lookahead->ofbuf.i_size);
- +#endif
- + }
- + }
- + } // end of MVC case
- +
- /* For MB-tree and VBV lookahead, we have to perform propagation analysis on I-frames too. */
- - if( h->lookahead->b_analyse_keyframe && IS_X264_TYPE_I( h->lookahead->last_nonb->i_type ) )
- +
- + if (!h->param.b_mvc) {
- + if( h->lookahead->b_analyse_keyframe && IS_X264_TYPE_I( h->lookahead->last_nonb->i_type ) )
- x264_stack_align( x264_slicetype_analyse, h, 1 );
- - x264_lookahead_encoder_shift( h );
- + x264_lookahead_encoder_shift( h );
- + } else {
- + // if (!(frameNum & 0x1)) {
- + if (b_frame_pair_exists) {
- + if( h->lookahead->b_analyse_keyframe && IS_X264_TYPE_I( h->lookahead->last_nonb->i_type ) )
- + x264_stack_align( x264_slicetype_analyse, h, 1 );
- +
- + x264_lookahead_encoder_shift( h );
- + }
- + }
- +
- + frameNum++;
- }
- }
- diff --git encoder/ratecontrol.c encoder/ratecontrol.c
- index 3abd198..de3e602 100644
- --- encoder/ratecontrol.c
- +++ encoder/ratecontrol.c
- @@ -7,7 +7,7 @@
- * Michael Niedermayer <michaelni@gmx.at>
- * Gabriel Bouvigne <gabriel.bouvigne@joost.com>
- * Jason Garrett-Glaser <darkshikari@gmail.com>
- - * M蚣s Rullg蚌d <mru@mru.ath.cx>
- + * M・スns Rullg・スrd <mru@mru.ath.cx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- @@ -30,6 +30,10 @@
- #define _ISOC99_SOURCE
- #undef NDEBUG // always check asserts, the speed effect is far too small to disable them
- +//#define _DEBUG
- +//#define __DEBUG
- +//#define __RC_DEBUG
- +
- #include "common/common.h"
- #include "ratecontrol.h"
- #include "me.h"
- @@ -37,6 +41,7 @@
- typedef struct
- {
- int pict_type;
- + int b_anchor;
- int frame_type;
- int kept_as_ref;
- double qscale;
- @@ -246,6 +251,18 @@ static NOINLINE uint32_t x264_ac_energy_mb( x264_t *h, int mb_x, int mb_y, x264_
- return var;
- }
- +static ALWAYS_INLINE int get_view_num( x264_t *h )
- +{
- + return h->param.b_mvc ? 2 : 1;
- + //return 1;
- +}
- +
- +static ALWAYS_INLINE int get_view_id( x264_t *h )
- +{
- + return h->param.b_mvc ? (h->fenc ? h->fenc->i_frame & 1 : 0) : 0;
- + //return 0;
- +}
- +
- void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame, float *quant_offsets )
- {
- /* constants chosen to result in approximately the same overall bitrate as without AQ.
- @@ -353,7 +370,7 @@ void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame, float *quant_off
- int x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame, float *quant_offsets )
- {
- - x264_ratecontrol_t *rc = h->rc;
- + x264_ratecontrol_t *rc = h->rc_mvc[get_view_id(h)];
- uint8_t i_type_actual = rc->entry[frame->i_frame].pict_type;
- if( rc->entry[frame->i_frame].kept_as_ref )
- @@ -396,11 +413,14 @@ fail:
- int x264_reference_build_list_optimal( x264_t *h )
- {
- - ratecontrol_entry_t *rce = h->rc->rce;
- + ratecontrol_entry_t *rce = h->rc_mvc[get_view_id(h)]->rce;
- x264_frame_t *frames[16];
- x264_weight_t weights[16][3];
- int refcount[16];
- + static int called = 0;
- + x264_log( h, X264_LOG_INFO, "x264_reference_build_list_optimal() has called %d time(s).\n", ++called);
- +
- if( rce->refs != h->i_ref[0] )
- return -1;
- @@ -431,6 +451,114 @@ int x264_reference_build_list_optimal( x264_t *h )
- return 0;
- }
- +static int compare_p_frame(const void *a, const void *b)
- +{
- + return (*(x264_frame_t **)b)->i_frame - (*(x264_frame_t **)a)->i_frame;
- +}
- +
- +static int compare_b_frame_l0(const void *a, const void *b)
- +{
- + return (*(x264_frame_t **)b)->i_poc - (*(x264_frame_t **)a)->i_poc;
- +}
- +
- +static int compare_b_frame_l1(const void *a, const void *b)
- +{
- + return (*(x264_frame_t **)a)->i_poc - (*(x264_frame_t **)b)->i_poc;
- +}
- +
- +static void x264_reference_build_list_b( x264_t *h, int l, int (*compare)(const void *, const void *))
- +{
- + qsort( h->fref[l], h->i_ref[l], sizeof(x264_frame_t *), compare );
- + for( int i = 0; i < h->i_ref[l]; i++ )
- + {
- + if( (*compare)(&h->fref[l][i], &h->fenc) < 0 )
- + {
- + x264_frame_t *tmp = h->fref[l][i];
- + for( int j = i + 1; j < h->i_ref[l] - i; j++)
- + h->fref[l][j - 1] = h->fref[l][j];
- + h->fref[l][h->i_ref[l] - i] = tmp;
- + }
- + else
- + break;
- + }
- +}
- +
- +int x264_reference_build_list_mvc( x264_t *h )
- +{
- + for (int i = 0; i < h->i_ref[0]; ++i) {
- + //x264_log( NULL, X264_LOG_INFO, "x264_reference_build_list_mvc(): %d.\n", h->fref[0][0]->i_frame );
- + }
- +
- + if (h->fenc->i_type == X264_TYPE_P || h->fenc->i_type == X264_TYPE_ANCHOR)
- + {
- + qsort( h->fref[0], h->i_ref[0], sizeof(x264_frame_t *),
- + &compare_p_frame );
- +
- + if ( h->i_ref[0] >= 2 )
- + {
- + /* swap */
- + h->fref[0][0] = (uintptr_t)h->fref[0][0] ^ (uintptr_t)h->fref[0][1];
- + h->fref[0][1] = (uintptr_t)h->fref[0][0] ^ (uintptr_t)h->fref[0][1];
- + h->fref[0][0] = (uintptr_t)h->fref[0][0] ^ (uintptr_t)h->fref[0][1];
- + }
- + }
- + else if( h->fenc->i_type == X264_TYPE_B )
- + {
- + x264_frame_t *inter_view[2] = { 0 };
- + for( int i = 0; i < 2; i++ )
- + for( int j = 0; j < h->i_ref[i]; j++ )
- + if ( h->fref[i][j]->i_frame_num == h->i_frame_num / 2 )
- + {
- + inter_view[i] = h->fref[i][j];
- + h->fref[i][j] = h->fref[i][h->i_ref[i] - 1];
- + h->i_ref[i]--;
- + break;
- + }
- +
- + x264_reference_build_list_b( h, 0, &compare_b_frame_l0 );
- + x264_reference_build_list_b( h, 1, &compare_b_frame_l1 );
- +
- + if( inter_view[0] )
- + {
- + int i;
- + for( i = h->i_ref[0]; i > 1; i-- )
- + {
- + h->fref[0][i] = h->fref[0][i - 1];
- + }
- + h->fref[0][i] = inter_view[0];
- + h->i_ref[0]++;
- + }
- +
- + if( inter_view[1] )
- + {
- + /* Please test here when starting using these code. */
- + int insert_point = 1;
- + for( int i = 0; h->fref[1][i]->i_poc < h->fenc->i_poc; i++ )
- + {
- + insert_point = i + 2;
- + }
- + if( insert_point >= h->i_ref[1])
- + insert_point = h->i_ref[1] - 1;
- + for( int i = h->i_ref[1]; i > insert_point; i-- )
- + h->fref[1][i] = h->fref[1][i - 1];
- + h->fref[1][insert_point] = inter_view[1];
- + h->i_ref[1]++;
- + }
- + }
- +
- +#ifdef __DEBUG
- + for (int j = 0; j < 2; j++) {
- + for (int i = 0; i < h->i_ref[j]; ++i) {
- + x264_log(h, X264_LOG_INFO, "ref%d[%2d] : no = %4d, poc = %2d\n",
- + j, i,
- + h->fref[j][i] ? h->fref[j][i]->i_frame : 9999,
- + h->fref[j][i] ? h->fref[j][i]->i_poc : -1);
- + }
- + }
- +#endif
- + return 0;
- +}
- +
- static char *x264_strcat_filename( char *input, char *suffix )
- {
- char *output = x264_malloc( strlen( input ) + strlen( suffix ) + 1 );
- @@ -443,224 +571,256 @@ static char *x264_strcat_filename( char *input, char *suffix )
- void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
- {
- - x264_ratecontrol_t *rc = h->rc;
- - if( !b_init && rc->b_2pass )
- - return;
- + int rc_num = get_view_num(h);
- - if( h->param.rc.i_rc_method == X264_RC_CRF )
- - {
- - /* Arbitrary rescaling to make CRF somewhat similar to QP.
- - * Try to compensate for MB-tree's effects as well. */
- - double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
- - double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;
- - rc->rate_factor_constant = pow( base_cplx, 1 - rc->qcompress )
- - / qp2qscale( h->param.rc.f_rf_constant + mbtree_offset + QP_BD_OFFSET );
- - }
- + for (int view = 0; view < rc_num; view ++) {
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- + if( !b_init && rc->b_2pass )
- + return;
- - if( h->param.rc.i_vbv_max_bitrate > 0 && h->param.rc.i_vbv_buffer_size > 0 )
- - {
- - if( h->param.rc.i_vbv_buffer_size < (int)(h->param.rc.i_vbv_max_bitrate / rc->fps) )
- + x264_sps_t * sps = view == 0 ? h->sps : h->subset_sps;
- +
- + if( h->param.rc.i_rc_method == X264_RC_CRF )
- {
- - h->param.rc.i_vbv_buffer_size = h->param.rc.i_vbv_max_bitrate / rc->fps;
- - x264_log( h, X264_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",
- - h->param.rc.i_vbv_buffer_size );
- + /* Arbitrary rescaling to make CRF somewhat similar to QP.
- + * Try to compensate for MB-tree's effects as well. */
- + double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
- + double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;
- + rc->rate_factor_constant = pow( base_cplx, 1 - rc->qcompress )
- + / qp2qscale( h->param.rc.f_rf_constant + mbtree_offset + QP_BD_OFFSET );
- }
- - /* We don't support changing the ABR bitrate right now,
- - so if the stream starts as CBR, keep it CBR. */
- - if( rc->b_vbv_min_rate )
- - h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
- + int vbv_max_rate = view == 0 ? h->param.rc.i_vbv_max_bitrate : h->param.rc.i_vbv_max_bitrate_dep[view-1];
- + float max_rate_ratio = view == 0 ? 1.0f : (float)h->param.rc.i_vbv_max_bitrate_dep[view-1] / (float)h->param.rc.i_vbv_max_bitrate;
- + if( vbv_max_rate > 0 && h->param.rc.i_vbv_buffer_size > 0 )
- + {
- + if( h->param.rc.i_vbv_buffer_size < (int)(vbv_max_rate / rc->fps) )
- + {
- + h->param.rc.i_vbv_buffer_size = vbv_max_rate / rc->fps;
- + x264_log( h, X264_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",
- + h->param.rc.i_vbv_buffer_size );
- + }
- - int vbv_buffer_size = h->param.rc.i_vbv_buffer_size * 1000;
- - int vbv_max_bitrate = h->param.rc.i_vbv_max_bitrate * 1000;
- + /* We don't support changing the ABR bitrate right now,
- + so if the stream starts as CBR, keep it CBR. */
- + if( rc->b_vbv_min_rate ) {
- + if (view == 0) {
- + h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
- + vbv_max_rate = h->param.rc.i_bitrate;
- + } else {
- + h->param.rc.i_vbv_max_bitrate_dep[view-1] = h->param.rc.i_bitrate_dep[view-1];
- + vbv_max_rate = h->param.rc.i_bitrate_dep[view-1];
- + }
- + }
- - /* Init HRD */
- - h->sps->vui.hrd.i_bit_rate_unscaled = vbv_max_bitrate;
- - h->sps->vui.hrd.i_cpb_size_unscaled = vbv_buffer_size;
- - if( h->param.i_nal_hrd && b_init )
- - {
- - h->sps->vui.hrd.i_cpb_cnt = 1;
- - h->sps->vui.hrd.b_cbr_hrd = h->param.i_nal_hrd == X264_NAL_HRD_CBR;
- - h->sps->vui.hrd.i_time_offset_length = 0;
- + int vbv_buffer_size = h->param.rc.i_vbv_buffer_size * 1000;
- + int vbv_max_bitrate = vbv_max_rate * 1000;
- - #define BR_SHIFT 6
- - #define CPB_SHIFT 4
- + /* Init HRD */
- + sps->vui.hrd.i_bit_rate_unscaled = vbv_max_bitrate;
- + sps->vui.hrd.i_cpb_size_unscaled = vbv_buffer_size;
- + if( h->param.i_nal_hrd && b_init )
- + {
- + sps->vui.hrd.i_cpb_cnt = 1;
- + sps->vui.hrd.b_cbr_hrd = h->param.i_nal_hrd == X264_NAL_HRD_CBR;
- + // h->sps->vui.hrd.i_time_offset_length = 0;
- + sps->vui.hrd.i_time_offset_length = 24;
- - int bitrate = 1000*h->param.rc.i_vbv_max_bitrate;
- - int bufsize = 1000*h->param.rc.i_vbv_buffer_size;
- + #define BR_SHIFT 6
- + #define CPB_SHIFT 4
- - // normalize HRD size and rate to the value / scale notation
- - h->sps->vui.hrd.i_bit_rate_scale = x264_clip3( x264_ctz( bitrate ) - BR_SHIFT, 0, 15 );
- - h->sps->vui.hrd.i_bit_rate_value = bitrate >> ( h->sps->vui.hrd.i_bit_rate_scale + BR_SHIFT );
- - h->sps->vui.hrd.i_bit_rate_unscaled = h->sps->vui.hrd.i_bit_rate_value << ( h->sps->vui.hrd.i_bit_rate_scale + BR_SHIFT );
- - h->sps->vui.hrd.i_cpb_size_scale = x264_clip3( x264_ctz( bufsize ) - CPB_SHIFT, 0, 15 );
- - h->sps->vui.hrd.i_cpb_size_value = bufsize >> ( h->sps->vui.hrd.i_cpb_size_scale + CPB_SHIFT );
- - h->sps->vui.hrd.i_cpb_size_unscaled = h->sps->vui.hrd.i_cpb_size_value << ( h->sps->vui.hrd.i_cpb_size_scale + CPB_SHIFT );
- + int bitrate = 1000*vbv_max_rate;
- + int bufsize = 1000*h->param.rc.i_vbv_buffer_size;
- - #undef CPB_SHIFT
- - #undef BR_SHIFT
- + // normalize HRD size and rate to the value / scale notation
- + sps->vui.hrd.i_bit_rate_scale = x264_clip3( x264_ctz( bitrate ) - BR_SHIFT, 0, 15 );
- + sps->vui.hrd.i_bit_rate_value = bitrate >> ( sps->vui.hrd.i_bit_rate_scale + BR_SHIFT );
- + sps->vui.hrd.i_bit_rate_unscaled = sps->vui.hrd.i_bit_rate_value << ( sps->vui.hrd.i_bit_rate_scale + BR_SHIFT );
- + sps->vui.hrd.i_cpb_size_scale = x264_clip3( x264_ctz( bufsize ) - CPB_SHIFT, 0, 15 );
- + sps->vui.hrd.i_cpb_size_value = bufsize >> ( sps->vui.hrd.i_cpb_size_scale + CPB_SHIFT );
- + sps->vui.hrd.i_cpb_size_unscaled = sps->vui.hrd.i_cpb_size_value << ( sps->vui.hrd.i_cpb_size_scale + CPB_SHIFT );
- - // arbitrary
- - #define MAX_DURATION 0.5
- + //sps->vui.hrd.i_cpb_size_unscaled = (float)sps->vui.hrd.i_cpb_size_unscaled * max_rate_ratio;
- + #undef CPB_SHIFT
- + #undef BR_SHIFT
- - int max_cpb_output_delay = X264_MIN( h->param.i_keyint_max * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick, INT_MAX );
- - int max_dpb_output_delay = h->sps->vui.i_max_dec_frame_buffering * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick;
- - int max_delay = (int)(90000.0 * (double)h->sps->vui.hrd.i_cpb_size_unscaled / h->sps->vui.hrd.i_bit_rate_unscaled + 0.5);
- + // arbitrary
- + #define MAX_DURATION 0.5
- - h->sps->vui.hrd.i_initial_cpb_removal_delay_length = 2 + x264_clip3( 32 - x264_clz( max_delay ), 4, 22 );
- - h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 31 );
- - h->sps->vui.hrd.i_dpb_output_delay_length = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 31 );
- + int max_cpb_output_delay = X264_MIN( h->param.i_keyint_max * MAX_DURATION * sps->vui.i_time_scale / sps->vui.i_num_units_in_tick, INT_MAX );
- + int max_dpb_output_delay = sps->vui.i_max_dec_frame_buffering * MAX_DURATION * sps->vui.i_time_scale / sps->vui.i_num_units_in_tick;
- + int max_delay = (int)(90000.0 * (double)sps->vui.hrd.i_cpb_size_unscaled / sps->vui.hrd.i_bit_rate_unscaled + 0.5);
- - #undef MAX_DURATION
- + sps->vui.hrd.i_initial_cpb_removal_delay_length = 2 + x264_clip3( 32 - x264_clz( max_delay ), 4, 22 );
- + sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 31 );
- + sps->vui.hrd.i_dpb_output_delay_length = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 31 );
- - vbv_buffer_size = h->sps->vui.hrd.i_cpb_size_unscaled;
- - vbv_max_bitrate = h->sps->vui.hrd.i_bit_rate_unscaled;
- - }
- - else if( h->param.i_nal_hrd && !b_init )
- - {
- - x264_log( h, X264_LOG_WARNING, "VBV parameters cannot be changed when NAL HRD is in use\n" );
- - return;
- - }
- + #undef MAX_DURATION
- - rc->buffer_rate = vbv_max_bitrate / rc->fps;
- - rc->vbv_max_rate = vbv_max_bitrate;
- - rc->buffer_size = vbv_buffer_size;
- - rc->single_frame_vbv = rc->buffer_rate * 1.1 > rc->buffer_size;
- - rc->cbr_decay = 1.0 - rc->buffer_rate / rc->buffer_size
- - * 0.5 * X264_MAX(0, 1.5 - rc->buffer_rate * rc->fps / rc->bitrate);
- - if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.f_rf_constant_max )
- - {
- - rc->rate_factor_max_increment = h->param.rc.f_rf_constant_max - h->param.rc.f_rf_constant;
- - if( rc->rate_factor_max_increment <= 0 )
- + vbv_buffer_size = sps->vui.hrd.i_cpb_size_unscaled;
- + vbv_max_bitrate = sps->vui.hrd.i_bit_rate_unscaled;
- + }
- + else if( h->param.i_nal_hrd && !b_init )
- {
- - x264_log( h, X264_LOG_WARNING, "CRF max must be greater than CRF\n" );
- - rc->rate_factor_max_increment = 0;
- + x264_log( h, X264_LOG_WARNING, "VBV parameters cannot be changed when NAL HRD is in use\n" );
- + return;
- + }
- +
- + rc->buffer_rate = vbv_max_bitrate / rc->fps;
- + rc->vbv_max_rate = vbv_max_bitrate;
- + rc->buffer_size = vbv_buffer_size;
- + rc->single_frame_vbv = rc->buffer_rate * 1.1 > rc->buffer_size;
- + rc->cbr_decay = 1.0 - rc->buffer_rate / rc->buffer_size
- + * 0.5 * X264_MAX(0, 1.5 - rc->buffer_rate * rc->fps / rc->bitrate);
- + if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.f_rf_constant_max )
- + {
- + rc->rate_factor_max_increment = h->param.rc.f_rf_constant_max - h->param.rc.f_rf_constant;
- + if( rc->rate_factor_max_increment <= 0 )
- + {
- + x264_log( h, X264_LOG_WARNING, "CRF max must be greater than CRF\n" );
- + rc->rate_factor_max_increment = 0;
- + }
- + }
- + if( b_init )
- + {
- + if( h->param.rc.f_vbv_buffer_init > 1. )
- + h->param.rc.f_vbv_buffer_init = x264_clip3f( h->param.rc.f_vbv_buffer_init / h->param.rc.i_vbv_buffer_size, 0, 1 );
- + h->param.rc.f_vbv_buffer_init = x264_clip3f( X264_MAX( h->param.rc.f_vbv_buffer_init, rc->buffer_rate / rc->buffer_size ), 0, 1);
- + rc->buffer_fill_final = rc->buffer_size * h->param.rc.f_vbv_buffer_init * sps->vui.i_time_scale;
- + rc->b_vbv = 1;
- + rc->b_vbv_min_rate = !rc->b_2pass
- + && h->param.rc.i_rc_method == X264_RC_ABR
- + && vbv_max_rate <= (view==0 ? h->param.rc.i_bitrate : h->param.rc.i_bitrate_dep[view-1]);
- }
- - }
- - if( b_init )
- - {
- - if( h->param.rc.f_vbv_buffer_init > 1. )
- - h->param.rc.f_vbv_buffer_init = x264_clip3f( h->param.rc.f_vbv_buffer_init / h->param.rc.i_vbv_buffer_size, 0, 1 );
- - h->param.rc.f_vbv_buffer_init = x264_clip3f( X264_MAX( h->param.rc.f_vbv_buffer_init, rc->buffer_rate / rc->buffer_size ), 0, 1);
- - rc->buffer_fill_final = rc->buffer_size * h->param.rc.f_vbv_buffer_init * h->sps->vui.i_time_scale;
- - rc->b_vbv = 1;
- - rc->b_vbv_min_rate = !rc->b_2pass
- - && h->param.rc.i_rc_method == X264_RC_ABR
- - && h->param.rc.i_vbv_max_bitrate <= h->param.rc.i_bitrate;
- }
- }
- }
- int x264_ratecontrol_new( x264_t *h )
- {
- + int i, j;
- x264_ratecontrol_t *rc;
- x264_emms();
- - CHECKED_MALLOCZERO( h->rc, h->param.i_threads * sizeof(x264_ratecontrol_t) );
- - rc = h->rc;
- -
- - rc->b_abr = h->param.rc.i_rc_method != X264_RC_CQP && !h->param.rc.b_stat_read;
- - rc->b_2pass = h->param.rc.i_rc_method == X264_RC_ABR && h->param.rc.b_stat_read;
- -
- - /* FIXME: use integers */
- - if( h->param.i_fps_num > 0 && h->param.i_fps_den > 0 )
- - rc->fps = (float) h->param.i_fps_num / h->param.i_fps_den;
- - else
- - rc->fps = 25.0;
- + int rc_num = get_view_num(h);
- + for (int view=0; view<rc_num; view++) {
- + CHECKED_MALLOCZERO( h->rc_mvc[view], h->param.i_threads * sizeof(x264_ratecontrol_t));
- - if( h->param.rc.b_mb_tree )
- - {
- - h->param.rc.f_pb_factor = 1;
- - rc->qcompress = 1;
- - }
- - else
- - rc->qcompress = h->param.rc.f_qcompress;
- + rc = h->rc_mvc[view];
- + //if (view == 0) h->rc = h->rc_mvc[0];
- - rc->bitrate = h->param.rc.i_bitrate * 1000.;
- - rc->rate_tolerance = h->param.rc.f_rate_tolerance;
- - rc->nmb = h->mb.i_mb_count;
- - rc->last_non_b_pict_type = -1;
- - rc->cbr_decay = 1.0;
- + rc->b_abr = h->param.rc.i_rc_method != X264_RC_CQP && !h->param.rc.b_stat_read;
- + rc->b_2pass = h->param.rc.i_rc_method == X264_RC_ABR && h->param.rc.b_stat_read;
- - if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read )
- - {
- - x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n");
- - return -1;
- - }
- + /* FIXME: use integers */
- + if( h->param.i_fps_num > 0 && h->param.i_fps_den > 0 )
- + rc->fps = (float) h->param.i_fps_num / h->param.i_fps_den;
- + else
- + rc->fps = 25.0;
- - x264_ratecontrol_init_reconfigurable( h, 1 );
- + if( h->param.rc.b_mb_tree )
- + {
- + h->param.rc.f_pb_factor = 1;
- + rc->qcompress = 1;
- + }
- + else
- + rc->qcompress = h->param.rc.f_qcompress;
- - if( h->param.i_nal_hrd )
- - {
- - uint64_t denom = (uint64_t)h->sps->vui.hrd.i_bit_rate_unscaled * h->sps->vui.i_time_scale;
- - uint64_t num = 180000;
- - x264_reduce_fraction64( &num, &denom );
- - rc->hrd_multiply_denom = 180000 / num;
- + if (view == 0) {
- + rc->bitrate = h->param.rc.i_bitrate * 1000.;
- + } else {
- + rc->bitrate = h->param.rc.i_bitrate_dep[view-1] * 1000.;
- + }
- + rc->rate_tolerance = h->param.rc.f_rate_tolerance;
- + rc->nmb = h->mb.i_mb_count;
- + rc->last_non_b_pict_type = -1;
- + rc->cbr_decay = 1.0;
- - double bits_required = log2( 180000 / rc->hrd_multiply_denom )
- - + log2( h->sps->vui.i_time_scale )
- - + log2( h->sps->vui.hrd.i_cpb_size_unscaled );
- - if( bits_required >= 63 )
- + if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read )
- {
- - x264_log( h, X264_LOG_ERROR, "HRD with very large timescale and bufsize not supported\n" );
- + x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n");
- return -1;
- }
- }
- - if( rc->rate_tolerance < 0.01 )
- - {
- - x264_log(h, X264_LOG_WARNING, "bitrate tolerance too small, using .01\n");
- - rc->rate_tolerance = 0.01;
- - }
- + x264_ratecontrol_init_reconfigurable( h, 1 );
- - h->mb.b_variable_qp = rc->b_vbv || h->param.rc.i_aq_mode;
- + for (int view=0; view<rc_num; view++) {
- + x264_sps_t * sps = view == 0 ? h->sps : h->subset_sps;
- + rc = h->rc_mvc[view];
- - if( rc->b_abr )
- - {
- - /* FIXME ABR_INIT_QP is actually used only in CRF */
- -#define ABR_INIT_QP (( h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24 ) + QP_BD_OFFSET)
- - rc->accum_p_norm = .01;
- - rc->accum_p_qp = ABR_INIT_QP * rc->accum_p_norm;
- - /* estimated ratio that produces a reasonable QP for the first I-frame */
- - rc->cplxr_sum = .01 * pow( 7.0e5, rc->qcompress ) * pow( h->mb.i_mb_count, 0.5 );
- - rc->wanted_bits_window = 1.0 * rc->bitrate / rc->fps;
- - rc->last_non_b_pict_type = SLICE_TYPE_I;
- - }
- -
- - rc->ip_offset = 6.0 * log2f( h->param.rc.f_ip_factor );
- - rc->pb_offset = 6.0 * log2f( h->param.rc.f_pb_factor );
- - rc->qp_constant[SLICE_TYPE_P] = h->param.rc.i_qp_constant;
- - rc->qp_constant[SLICE_TYPE_I] = x264_clip3( h->param.rc.i_qp_constant - rc->ip_offset + 0.5, 0, QP_MAX );
- - rc->qp_constant[SLICE_TYPE_B] = x264_clip3( h->param.rc.i_qp_constant + rc->pb_offset + 0.5, 0, QP_MAX );
- - h->mb.ip_offset = rc->ip_offset + 0.5;
- -
- - rc->lstep = pow( 2, h->param.rc.i_qp_step / 6.0 );
- - rc->last_qscale = qp2qscale( 26 );
- - int num_preds = h->param.b_sliced_threads * h->param.i_threads + 1;
- - CHECKED_MALLOC( rc->pred, 5 * sizeof(predictor_t) * num_preds );
- - CHECKED_MALLOC( rc->pred_b_from_p, sizeof(predictor_t) );
- - for( int i = 0; i < 3; i++ )
- - {
- - rc->last_qscale_for[i] = qp2qscale( ABR_INIT_QP );
- - rc->lmin[i] = qp2qscale( h->param.rc.i_qp_min );
- - rc->lmax[i] = qp2qscale( h->param.rc.i_qp_max );
- - for( int j = 0; j < num_preds; j++ )
- + if( h->param.i_nal_hrd )
- + {
- + uint64_t denom = (uint64_t)sps->vui.hrd.i_bit_rate_unscaled * sps->vui.i_time_scale;
- + uint64_t num = 180000;
- + x264_reduce_fraction64( &num, &denom );
- + rc->hrd_multiply_denom = 180000 / num;
- +
- + double bits_required = log2( 180000 / rc->hrd_multiply_denom )
- + + log2( sps->vui.i_time_scale )
- + + log2( sps->vui.hrd.i_cpb_size_unscaled );
- + if( bits_required >= 63 )
- + {
- + x264_log( h, X264_LOG_ERROR, "HRD with very large timescale and bufsize not supported\n" );
- + return -1;
- + }
- + }
- +
- + if( rc->rate_tolerance < 0.01 )
- {
- - rc->pred[i+j*5].coeff= 2.0;
- - rc->pred[i+j*5].count= 1.0;
- - rc->pred[i+j*5].decay= 0.5;
- - rc->pred[i+j*5].offset= 0.0;
- + x264_log(h, X264_LOG_WARNING, "bitrate tolerance too small, using .01\n");
- + rc->rate_tolerance = 0.01;
- }
- - for( int j = 0; j < 2; j++ )
- +
- + h->mb.b_variable_qp = rc->b_vbv || h->param.rc.i_aq_mode;
- +
- + if( rc->b_abr )
- {
- - rc->row_preds[i][j].coeff= .25;
- - rc->row_preds[i][j].count= 1.0;
- - rc->row_preds[i][j].decay= 0.5;
- - rc->row_preds[i][j].offset= 0.0;
- + /* FIXME ABR_INIT_QP is actually used only in CRF */
- +#define ABR_INIT_QP (( h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24 ) + QP_BD_OFFSET)
- + rc->accum_p_norm = .01;
- + rc->accum_p_qp = ABR_INIT_QP * rc->accum_p_norm;
- + /* estimated ratio that produces a reasonable QP for the first I-frame */
- + rc->cplxr_sum = .01 * pow( 7.0e5, rc->qcompress ) * pow( h->mb.i_mb_count, 0.5 );
- + rc->wanted_bits_window = 1.0 * rc->bitrate / rc->fps;
- + rc->last_non_b_pict_type = SLICE_TYPE_I;
- + }
- +
- + rc->ip_offset = 6.0 * log2f( h->param.rc.f_ip_factor );
- + rc->pb_offset = 6.0 * log2f( h->param.rc.f_pb_factor );
- + rc->qp_constant[SLICE_TYPE_P] = h->param.rc.i_qp_constant;
- + rc->qp_constant[SLICE_TYPE_I] = x264_clip3( h->param.rc.i_qp_constant - rc->ip_offset + 0.5, 0, QP_MAX );
- + rc->qp_constant[SLICE_TYPE_B] = x264_clip3( h->param.rc.i_qp_constant + rc->pb_offset + 0.5, 0, QP_MAX );
- + h->mb.ip_offset = rc->ip_offset + 0.5;
- +
- + rc->lstep = pow( 2, h->param.rc.i_qp_step / 6.0 );
- + rc->last_qscale = qp2qscale( 26 );
- + int num_preds = h->param.b_sliced_threads * h->param.i_threads + 1;
- + CHECKED_MALLOC( rc->pred, 5 * sizeof(predictor_t) * num_preds );
- + CHECKED_MALLOC( rc->pred_b_from_p, sizeof(predictor_t) );
- + for( i = 0; i < 3; i++ )
- + {
- + rc->last_qscale_for[i] = qp2qscale( ABR_INIT_QP );
- + rc->lmin[i] = qp2qscale( h->param.rc.i_qp_min );
- + rc->lmax[i] = qp2qscale( h->param.rc.i_qp_max );
- + for( j = 0; j < num_preds; j++ )
- + {
- + rc->pred[i+j*5].coeff= 2.0;
- + rc->pred[i+j*5].count= 1.0;
- + rc->pred[i+j*5].decay= 0.5;
- + rc->pred[i+j*5].offset= 0.0;
- + }
- + for( j = 0; j < 2; j++ )
- + {
- + rc->row_preds[i][j].coeff= .25;
- + rc->row_preds[i][j].count= 1.0;
- + rc->row_preds[i][j].decay= 0.5;
- + rc->row_preds[i][j].offset= 0.0;
- + }
- }
- + *rc->pred_b_from_p = rc->pred[0];
- }
- - *rc->pred_b_from_p = rc->pred[0];
- if( parse_zones( h ) < 0 )
- {
- @@ -668,209 +828,220 @@ int x264_ratecontrol_new( x264_t *h )
- return -1;
- }
- - /* Load stat file and init 2pass algo */
- - if( h->param.rc.b_stat_read )
- - {
- - char *p, *stats_in, *stats_buf;
- -
- - /* read 1st pass stats */
- - assert( h->param.rc.psz_stat_in );
- - stats_buf = stats_in = x264_slurp_file( h->param.rc.psz_stat_in );
- - if( !stats_buf )
- - {
- - x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
- - return -1;
- - }
- - if( h->param.rc.b_mb_tree )
- + for (int view=0; view<rc_num; view++) {
- + rc = h->rc_mvc[view];
- + /* Load stat file and init 2pass algo */
- + if( h->param.rc.b_stat_read )
- {
- - char *mbtree_stats_in = x264_strcat_filename( h->param.rc.psz_stat_in, ".mbtree" );
- - if( !mbtree_stats_in )
- - return -1;
- - rc->p_mbtree_stat_file_in = fopen( mbtree_stats_in, "rb" );
- - x264_free( mbtree_stats_in );
- - if( !rc->p_mbtree_stat_file_in )
- - {
- - x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n");
- - return -1;
- - }
- - }
- + char *p, *stats_in, *stats_buf;
- - /* check whether 1st pass options were compatible with current options */
- - if( !strncmp( stats_buf, "#options:", 9 ) )
- - {
- - int i, j;
- - uint32_t k, l;
- - char *opts = stats_buf;
- - stats_in = strchr( stats_buf, '\n' );
- - if( !stats_in )
- - return -1;
- - *stats_in = '\0';
- - stats_in++;
- - if( sscanf( opts, "#options: %dx%d", &i, &j ) != 2 )
- + /* read 1st pass stats */
- + assert( h->param.rc.psz_stat_in );
- + stats_buf = stats_in = x264_slurp_file( h->param.rc.psz_stat_in );
- + if( !stats_buf )
- {
- - x264_log( h, X264_LOG_ERROR, "resolution specified in stats file not valid\n" );
- + x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
- return -1;
- }
- - else if( h->param.rc.b_mb_tree && (i != h->param.i_width || j != h->param.i_height) )
- + if( h->param.rc.b_mb_tree )
- {
- - x264_log( h, X264_LOG_ERROR, "MB-tree doesn't support different resolution than 1st pass (%dx%d vs %dx%d)\n",
- - h->param.i_width, h->param.i_height, i, j );
- - return -1;
- - }
- -
- - if( ( p = strstr( opts, "timebase=" ) ) && sscanf( p, "timebase=%u/%u", &k, &l ) != 2 )
- - {
- - x264_log( h, X264_LOG_ERROR, "timebase specified in stats file not valid\n" );
- - return -1;
- - }
- - if( k != h->param.i_timebase_num || l != h->param.i_timebase_den )
- - {
- - x264_log( h, X264_LOG_ERROR, "timebase mismatch with 1st pass (%u/%u vs %u/%u)\n",
- - h->param.i_timebase_num, h->param.i_timebase_den, k, l );
- - return -1;
- - }
- -
- - CMP_OPT_FIRST_PASS( "bitdepth", BIT_DEPTH );
- - CMP_OPT_FIRST_PASS( "weightp", X264_MAX( 0, h->param.analyse.i_weighted_pred ) );
- - CMP_OPT_FIRST_PASS( "bframes", h->param.i_bframe );
- - CMP_OPT_FIRST_PASS( "b_pyramid", h->param.i_bframe_pyramid );
- - CMP_OPT_FIRST_PASS( "intra_refresh", h->param.b_intra_refresh );
- - CMP_OPT_FIRST_PASS( "open_gop", h->param.i_open_gop );
- + char *mbtree_stats_in;
- + if (view == 0) {
- + mbtree_stats_in = x264_strcat_filename( h->param.rc.psz_stat_in, ".mbtree" );
- + } else {
- + char buf[12];
- + sprintf(buf, ".mbtree_%d", view+1);
- + mbtree_stats_in = x264_strcat_filename( h->param.rc.psz_stat_in, buf );
- + }
- - if( (p = strstr( opts, "keyint=" )) )
- - {
- - p += 7;
- - char buf[13] = "infinite ";
- - if( h->param.i_keyint_max != X264_KEYINT_MAX_INFINITE )
- - sprintf( buf, "%d ", h->param.i_keyint_max );
- - if( strncmp( p, buf, strlen(buf) ) )
- + if( !mbtree_stats_in )
- + return -1;
- + rc->p_mbtree_stat_file_in = fopen( mbtree_stats_in, "rb" );
- + x264_free( mbtree_stats_in );
- + if( !rc->p_mbtree_stat_file_in )
- {
- - x264_log( h, X264_LOG_ERROR, "different keyint setting than first pass (%.*s vs %.*s)\n",
- - strlen(buf)-1, buf, strcspn(p, " "), p );
- + x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n");
- return -1;
- }
- }
- - if( strstr( opts, "qp=0" ) && h->param.rc.i_rc_method == X264_RC_ABR )
- - x264_log( h, X264_LOG_WARNING, "1st pass was lossless, bitrate prediction will be inaccurate\n" );
- -
- - if( !strstr( opts, "direct=3" ) && h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO )
- + /* check whether 1st pass options were compatible with current options */
- + if( !strncmp( stats_buf, "#options:", 9 ) )
- {
- - x264_log( h, X264_LOG_WARNING, "direct=auto not used on the first pass\n" );
- - h->mb.b_direct_auto_write = 1;
- - }
- -
- - if( ( p = strstr( opts, "b_adapt=" ) ) && sscanf( p, "b_adapt=%d", &i ) && i >= X264_B_ADAPT_NONE && i <= X264_B_ADAPT_TRELLIS )
- - h->param.i_bframe_adaptive = i;
- - else if( h->param.i_bframe )
- - {
- - x264_log( h, X264_LOG_ERROR, "b_adapt method specified in stats file not valid\n" );
- - return -1;
- - }
- + uint32_t k, l;
- + char *opts = stats_buf;
- + stats_in = strchr( stats_buf, '\n' );
- + if( !stats_in )
- + return -1;
- + *stats_in = '\0';
- + stats_in++;
- + if( sscanf( opts, "#options: %dx%d", &i, &j ) != 2 )
- + {
- + x264_log( h, X264_LOG_ERROR, "resolution specified in stats file not valid\n" );
- + return -1;
- + }
- + else if( h->param.rc.b_mb_tree && (i != h->param.i_width || j != h->param.i_height) )
- + {
- + x264_log( h, X264_LOG_ERROR, "MB-tree doesn't support different resolution than 1st pass (%dx%d vs %dx%d)\n",
- + h->param.i_width, h->param.i_height, i, j );
- + return -1;
- + }
- - if( (h->param.rc.b_mb_tree || h->param.rc.i_vbv_buffer_size) && ( p = strstr( opts, "rc_lookahead=" ) ) && sscanf( p, "rc_lookahead=%d", &i ) )
- - h->param.rc.i_lookahead = i;
- - }
- + if( ( p = strstr( opts, "timebase=" ) ) && sscanf( p, "timebase=%u/%u", &k, &l ) != 2 )
- + {
- + x264_log( h, X264_LOG_ERROR, "timebase specified in stats file not valid\n" );
- + return -1;
- + }
- + if( k != h->param.i_timebase_num || l != h->param.i_timebase_den )
- + {
- + x264_log( h, X264_LOG_ERROR, "timebase mismatch with 1st pass (%u/%u vs %u/%u)\n",
- + h->param.i_timebase_num, h->param.i_timebase_den, k, l );
- + return -1;
- + }
- - /* find number of pics */
- - p = stats_in;
- - int num_entries;
- - for( num_entries = -1; p; num_entries++ )
- - p = strchr( p + 1, ';' );
- - if( !num_entries )
- - {
- - x264_log(h, X264_LOG_ERROR, "empty stats file\n");
- - return -1;
- - }
- - rc->num_entries = num_entries;
- + CMP_OPT_FIRST_PASS( "bitdepth", BIT_DEPTH );
- + CMP_OPT_FIRST_PASS( "weightp", X264_MAX( 0, h->param.analyse.i_weighted_pred ) );
- + CMP_OPT_FIRST_PASS( "bframes", h->param.i_bframe );
- + CMP_OPT_FIRST_PASS( "b_pyramid", h->param.i_bframe_pyramid );
- + CMP_OPT_FIRST_PASS( "intra_refresh", h->param.b_intra_refresh );
- + CMP_OPT_FIRST_PASS( "open_gop", h->param.i_open_gop );
- - if( h->param.i_frame_total < rc->num_entries && h->param.i_frame_total > 0 )
- - {
- - x264_log( h, X264_LOG_WARNING, "2nd pass has fewer frames than 1st pass (%d vs %d)\n",
- - h->param.i_frame_total, rc->num_entries );
- - }
- - if( h->param.i_frame_total > rc->num_entries )
- - {
- - x264_log( h, X264_LOG_ERROR, "2nd pass has more frames than 1st pass (%d vs %d)\n",
- - h->param.i_frame_total, rc->num_entries );
- - return -1;
- - }
- + if( (p = strstr( opts, "keyint=" )) )
- + {
- + p += 7;
- + char buf[13] = "infinite ";
- + if( h->param.i_keyint_max != X264_KEYINT_MAX_INFINITE )
- + sprintf( buf, "%d ", h->param.i_keyint_max );
- + if( strncmp( p, buf, strlen(buf) ) )
- + {
- + x264_log( h, X264_LOG_ERROR, "different keyint setting than first pass (%.*s vs %.*s)\n",
- + strlen(buf)-1, buf, strcspn(p, " "), p );
- + return -1;
- + }
- + }
- - CHECKED_MALLOCZERO( rc->entry, rc->num_entries * sizeof(ratecontrol_entry_t) );
- + if( strstr( opts, "qp=0" ) && h->param.rc.i_rc_method == X264_RC_ABR )
- + x264_log( h, X264_LOG_WARNING, "1st pass was lossless, bitrate prediction will be inaccurate\n" );
- - /* init all to skipped p frames */
- - for( int i = 0; i < rc->num_entries; i++ )
- - {
- - ratecontrol_entry_t *rce = &rc->entry[i];
- - rce->pict_type = SLICE_TYPE_P;
- - rce->qscale = rce->new_qscale = qp2qscale( 20 );
- - rce->misc_bits = rc->nmb + 10;
- - rce->new_qp = 0;
- - }
- + if( !strstr( opts, "direct=3" ) && h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO )
- + {
- + x264_log( h, X264_LOG_WARNING, "direct=auto not used on the first pass\n" );
- + h->mb.b_direct_auto_write = 1;
- + }
- - /* read stats */
- - p = stats_in;
- - for( int i = 0; i < rc->num_entries; i++ )
- - {
- - ratecontrol_entry_t *rce;
- - int frame_number;
- - char pict_type;
- - int e;
- - char *next;
- - float qp;
- - int ref;
- + if( ( p = strstr( opts, "b_adapt=" ) ) && sscanf( p, "b_adapt=%d", &i ) && i >= X264_B_ADAPT_NONE && i <= X264_B_ADAPT_TRELLIS )
- + h->param.i_bframe_adaptive = i;
- + else if( h->param.i_bframe )
- + {
- + x264_log( h, X264_LOG_ERROR, "b_adapt method specified in stats file not valid\n" );
- + return -1;
- + }
- - next= strchr(p, ';');
- - if( next )
- - *next++ = 0; //sscanf is unbelievably slow on long strings
- - e = sscanf( p, " in:%d ", &frame_number );
- + if( (h->param.rc.b_mb_tree || h->param.rc.i_vbv_buffer_size) && ( p = strstr( opts, "rc_lookahead=" ) ) && sscanf( p, "rc_lookahead=%d", &i ) )
- + h->param.rc.i_lookahead = i;
- + }
- - if( frame_number < 0 || frame_number >= rc->num_entries )
- + /* find number of pics */
- + p = stats_in;
- + int num_entries;
- + for( num_entries = -1; p; num_entries++ )
- + p = strchr( p + 1, ';' );
- + x264_log( h, X264_LOG_INFO, "num_entries: %d\n", num_entries ); // tmplog
- + if( !num_entries )
- {
- - x264_log( h, X264_LOG_ERROR, "bad frame number (%d) at stats line %d\n", frame_number, i );
- + x264_log(h, X264_LOG_ERROR, "empty stats file\n");
- return -1;
- }
- - rce = &rc->entry[frame_number];
- - rce->direct_mode = 0;
- -
- - e += sscanf( p, " in:%*d out:%*d type:%c dur:%"SCNd64" cpbdur:%"SCNd64" q:%f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c",
- - &pict_type, &rce->i_duration, &rce->i_cpb_duration, &qp, &rce->tex_bits,
- - &rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count,
- - &rce->s_count, &rce->direct_mode );
- -
- - p = strstr( p, "ref:" );
- - if( !p )
- - goto parse_error;
- - p += 4;
- - for( ref = 0; ref < 16; ref++ )
- + rc->num_entries = num_entries;
- +
- + if( h->param.i_frame_total < rc->num_entries && h->param.i_frame_total > 0 )
- {
- - if( sscanf( p, " %d", &rce->refcount[ref] ) != 1 )
- - break;
- - p = strchr( p+1, ' ' );
- - if( !p )
- - goto parse_error;
- + x264_log( h, X264_LOG_WARNING, "2nd pass has fewer frames than 1st pass (%d vs %d)\n",
- + h->param.i_frame_total, rc->num_entries );
- + }
- + if( h->param.i_frame_total > rc->num_entries )
- + {
- + x264_log( h, X264_LOG_ERROR, "2nd pass has more frames than 1st pass (%d vs %d)\n",
- + h->param.i_frame_total, rc->num_entries );
- + return -1;
- }
- - rce->refs = ref;
- - /* find weights */
- - rce->i_weight_denom[0] = rce->i_weight_denom[1] = -1;
- - char *w = strchr( p, 'w' );
- - if( w )
- + CHECKED_MALLOCZERO( rc->entry, rc->num_entries * sizeof(ratecontrol_entry_t) );
- +
- + /* init all to skipped p frames */
- + for( i = 0; i < rc->num_entries; i++ )
- {
- - int count = sscanf( w, "w:%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",
- - &rce->i_weight_denom[0], &rce->weight[0][0], &rce->weight[0][1],
- - &rce->i_weight_denom[1], &rce->weight[1][0], &rce->weight[1][1],
- - &rce->weight[2][0], &rce->weight[2][1] );
- - if( count == 3 )
- - rce->i_weight_denom[1] = -1;
- - else if ( count != 8 )
- - rce->i_weight_denom[0] = rce->i_weight_denom[1] = -1;
- + ratecontrol_entry_t *rce = &rc->entry[i];
- + rce->pict_type = SLICE_TYPE_P;
- + rce->b_anchor = 0;
- + rce->qscale = rce->new_qscale = qp2qscale( 20 );
- + rce->misc_bits = rc->nmb + 10;
- + rce->new_qp = 0;
- }
- - if( pict_type != 'b' )
- - rce->kept_as_ref = 1;
- - switch( pict_type )
- + /* read stats */
- + p = stats_in;
- + for( i = 0; i < rc->num_entries; i++ )
- {
- + ratecontrol_entry_t *rce;
- + int frame_number;
- + char pict_type;
- + int e;
- + char *next;
- + float qp;
- + int ref;
- +
- + next= strchr(p, ';');
- + if( next )
- + *next++ = 0; //sscanf is unbelievably slow on long strings
- + e = sscanf( p, " in:%d ", &frame_number );
- +
- + if( frame_number < 0 || frame_number >= rc->num_entries )
- + {
- + x264_log( h, X264_LOG_ERROR, "bad frame number (%d) at stats line %d\n", frame_number, i );
- + return -1;
- + }
- + rce = &rc->entry[frame_number];
- + rce->direct_mode = 0;
- +
- + e += sscanf( p, " in:%*d out:%*d type:%c dur:%"SCNd64" cpbdur:%"SCNd64" q:%f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c",
- + &pict_type, &rce->i_duration, &rce->i_cpb_duration, &qp, &rce->tex_bits,
- + &rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count,
- + &rce->s_count, &rce->direct_mode );
- +
- + p = strstr( p, "ref:" );
- + if( !p )
- + goto parse_error;
- + p += 4;
- + for( ref = 0; ref < 16; ref++ )
- + {
- + if( sscanf( p, " %d", &rce->refcount[ref] ) != 1 )
- + break;
- + p = strchr( p+1, ' ' );
- + if( !p )
- + goto parse_error;
- + }
- + rce->refs = ref;
- +
- + /* find weights */
- + rce->i_weight_denom[0] = rce->i_weight_denom[1] = -1;
- + char *w = strchr( p, 'w' );
- + if( w )
- + {
- + int count = sscanf( w, "w:%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",
- + &rce->i_weight_denom[0], &rce->weight[0][0], &rce->weight[0][1],
- + &rce->i_weight_denom[1], &rce->weight[1][0], &rce->weight[1][1],
- + &rce->weight[2][0], &rce->weight[2][1] );
- + if( count == 3 )
- + rce->i_weight_denom[1] = -1;
- + else if ( count != 8 )
- + rce->i_weight_denom[0] = rce->i_weight_denom[1] = -1;
- + }
- +
- + if( pict_type != 'b' )
- + rce->kept_as_ref = 1;
- + switch( pict_type )
- + {
- case 'I':
- rce->frame_type = X264_TYPE_IDR;
- rce->pict_type = SLICE_TYPE_I;
- @@ -892,83 +1063,100 @@ int x264_ratecontrol_new( x264_t *h )
- rce->pict_type = SLICE_TYPE_B;
- break;
- default: e = -1; break;
- - }
- - if( e < 12 )
- - {
- + }
- + if( e < 12 )
- + {
- parse_error:
- - x264_log( h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e );
- - return -1;
- + x264_log( h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e );
- + return -1;
- + }
- + rce->qscale = qp2qscale( qp );
- + p = next;
- }
- - rce->qscale = qp2qscale( qp );
- - p = next;
- - }
- - x264_free( stats_buf );
- -
- - if( h->param.rc.i_rc_method == X264_RC_ABR )
- - {
- - if( init_pass2( h ) < 0 )
- - return -1;
- - } /* else we're using constant quant, so no need to run the bitrate allocation */
- + x264_free( stats_buf );
- + }
- }
- -
- - /* Open output file */
- - /* If input and output files are the same, output to a temp file
- - * and move it to the real name only when it's complete */
- - if( h->param.rc.b_stat_write )
- + if( h->param.rc.i_rc_method == X264_RC_ABR )
- {
- - char *p;
- - rc->psz_stat_file_tmpname = x264_strcat_filename( h->param.rc.psz_stat_out, ".temp" );
- - if( !rc->psz_stat_file_tmpname )
- - return -1;
- -
- - rc->p_stat_file_out = fopen( rc->psz_stat_file_tmpname, "wb" );
- - if( rc->p_stat_file_out == NULL )
- - {
- - x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
- + if( init_pass2( h ) < 0 )
- return -1;
- - }
- -
- - p = x264_param2string( &h->param, 1 );
- - if( p )
- - fprintf( rc->p_stat_file_out, "#options: %s\n", p );
- - x264_free( p );
- - if( h->param.rc.b_mb_tree && !h->param.rc.b_stat_read )
- - {
- - rc->psz_mbtree_stat_file_tmpname = x264_strcat_filename( h->param.rc.psz_stat_out, ".mbtree.temp" );
- - rc->psz_mbtree_stat_file_name = x264_strcat_filename( h->param.rc.psz_stat_out, ".mbtree" );
- - if( !rc->psz_mbtree_stat_file_tmpname || !rc->psz_mbtree_stat_file_name )
- + } /* else we're using constant quant, so no need to run the bitrate allocation */
- +
- + for (int view=0; view<rc_num; view++) {
- + rc = h->rc_mvc[view];
- + /* Open output file */
- + /* If input and output files are the same, output to a temp file
- + * and move it to the real name only when it's complete */
- + if( h->param.rc.b_stat_write )
- + {
- + char *p;
- + if (view == 0) {
- + rc->psz_stat_file_tmpname = x264_strcat_filename( h->param.rc.psz_stat_out, ".temp" );
- + } else {
- + char buf[10];
- + sprintf(buf, ".temp_%d", view+1);
- + rc->psz_stat_file_tmpname = x264_strcat_filename( h->param.rc.psz_stat_out, buf );
- + }
- + if( !rc->psz_stat_file_tmpname )
- return -1;
- - rc->p_mbtree_stat_file_out = fopen( rc->psz_mbtree_stat_file_tmpname, "wb" );
- - if( rc->p_mbtree_stat_file_out == NULL )
- + rc->p_stat_file_out = fopen( rc->psz_stat_file_tmpname, "wb" );
- + if( rc->p_stat_file_out == NULL )
- {
- - x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n");
- + x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open stats file\n");
- return -1;
- }
- +
- + p = x264_param2string( &h->param, 1, view);
- + if( p )
- + fprintf( rc->p_stat_file_out, "#options: %s\n", p );
- + x264_free( p );
- + if( h->param.rc.b_mb_tree && !h->param.rc.b_stat_read )
- + {
- + rc->psz_mbtree_stat_file_tmpname = x264_strcat_filename( h->param.rc.psz_stat_out, ".mbtree.temp" );
- + rc->psz_mbtree_stat_file_name = x264_strcat_filename( h->param.rc.psz_stat_out, ".mbtree" );
- + if( !rc->psz_mbtree_stat_file_tmpname || !rc->psz_mbtree_stat_file_name )
- + return -1;
- +
- + rc->p_mbtree_stat_file_out = fopen( rc->psz_mbtree_stat_file_tmpname, "wb" );
- + if( rc->p_mbtree_stat_file_out == NULL )
- + {
- + x264_log(h, X264_LOG_ERROR, "ratecontrol_init: can't open mbtree stats file\n");
- + return -1;
- + }
- + }
- }
- - }
- - if( h->param.rc.b_mb_tree && (h->param.rc.b_stat_read || h->param.rc.b_stat_write) )
- - {
- - CHECKED_MALLOC( rc->qp_buffer[0], h->mb.i_mb_count * sizeof(uint16_t) );
- - if( h->param.i_bframe_pyramid && h->param.rc.b_stat_read )
- - CHECKED_MALLOC( rc->qp_buffer[1], h->mb.i_mb_count * sizeof(uint16_t) );
- - rc->qpbuf_pos = -1;
- + if( h->param.rc.b_mb_tree && (h->param.rc.b_stat_read || h->param.rc.b_stat_write) )
- + {
- + CHECKED_MALLOC( rc->qp_buffer[0], h->mb.i_mb_count * sizeof(uint16_t) );
- + if( h->param.i_bframe_pyramid && h->param.rc.b_stat_read )
- + CHECKED_MALLOC( rc->qp_buffer[1], h->mb.i_mb_count * sizeof(uint16_t) );
- + rc->qpbuf_pos = -1;
- + }
- }
- - for( int i = 0; i<h->param.i_threads; i++ )
- + for( i = 0; i<h->param.i_threads; i++ )
- {
- - h->thread[i]->rc = rc+i;
- - if( i )
- - {
- - rc[i] = rc[0];
- - h->thread[i]->param = h->param;
- - h->thread[i]->mb.b_variable_qp = h->mb.b_variable_qp;
- - h->thread[i]->mb.ip_offset = h->mb.ip_offset;
- + for (int view=rc_num-1; view>=0; view--) {
- + rc = h->rc_mvc[view];
- + h->thread[i]->rc_mvc[view] = rc+i;
- + if( i )
- + {
- + rc[i] = rc[0];
- + }
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "thread[%d]->rc_mvc[%d] = %p\n",
- + i, view, h->thread[i]->rc_mvc[view]);
- +#endif
- }
- + //h->thread[i]->rc = rc+i;
- + h->thread[i]->param = h->param;
- + h->thread[i]->mb.b_variable_qp = h->mb.b_variable_qp;
- + h->thread[i]->mb.ip_offset = h->mb.ip_offset;
- }
- -
- +
- return 0;
- fail:
- return -1;
- @@ -1019,8 +1207,12 @@ fail:
- static int parse_zones( x264_t *h )
- {
- - x264_ratecontrol_t *rc = h->rc;
- - if( h->param.rc.psz_zones && !h->param.rc.i_zones )
- + int rc_num = get_view_num(h);
- + if (rc_num > 1) return 0;
- + int view = 0;
- +
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- + if( h->param.rc.psz_zones && !h->param.rc.i_zones)
- {
- char *psz_zones, *p;
- CHECKED_MALLOC( psz_zones, strlen( h->param.rc.psz_zones )+1 );
- @@ -1085,9 +1277,11 @@ fail:
- static x264_zone_t *get_zone( x264_t *h, int frame_num )
- {
- - for( int i = h->rc->i_zones - 1; i >= 0; i-- )
- + x264_ratecontrol_t * rc = h->rc_mvc[get_view_id(h)];
- +
- + for( int i = rc->i_zones - 1; i >= 0; i-- )
- {
- - x264_zone_t *z = &h->rc->zones[i];
- + x264_zone_t *z = &rc->zones[i];
- if( frame_num >= z->i_start && frame_num <= z->i_end )
- return z;
- }
- @@ -1096,72 +1290,83 @@ static x264_zone_t *get_zone( x264_t *h, int frame_num )
- void x264_ratecontrol_summary( x264_t *h )
- {
- - x264_ratecontrol_t *rc = h->rc;
- - if( rc->b_abr && h->param.rc.i_rc_method == X264_RC_ABR && rc->cbr_decay > .9999 )
- - {
- - double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
- - double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;
- - x264_log( h, X264_LOG_INFO, "final ratefactor: %.2f\n",
- - qscale2qp( pow( base_cplx, 1 - rc->qcompress )
- - * rc->cplxr_sum / rc->wanted_bits_window ) - mbtree_offset - QP_BD_OFFSET );
- + int rc_num = get_view_num(h);
- +
- + for (int view = 0; view < rc_num; view++) {
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- + if( rc->b_abr && h->param.rc.i_rc_method == X264_RC_ABR && rc->cbr_decay > .9999 )
- + {
- + char dep_string[15];
- + if (view > 0) sprintf(dep_string, " (view %d)", view);
- + double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
- + double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;
- + x264_log( h, X264_LOG_INFO, "final ratefactor%s: %.2f\n",
- + view == 0 ? "" : dep_string,
- + qscale2qp( pow( base_cplx, 1 - rc->qcompress )
- + * rc->cplxr_sum / rc->wanted_bits_window ) - mbtree_offset - QP_BD_OFFSET );
- + }
- }
- }
- void x264_ratecontrol_delete( x264_t *h )
- {
- - x264_ratecontrol_t *rc = h->rc;
- - int b_regular_file;
- + int rc_num = get_view_num(h);
- - if( rc->p_stat_file_out )
- - {
- - b_regular_file = x264_is_regular_file( rc->p_stat_file_out );
- - fclose( rc->p_stat_file_out );
- - if( h->i_frame >= rc->num_entries && b_regular_file )
- - if( rename( rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out ) != 0 )
- - {
- - x264_log( h, X264_LOG_ERROR, "failed to rename \"%s\" to \"%s\"\n",
- - rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out );
- - }
- - x264_free( rc->psz_stat_file_tmpname );
- - }
- - if( rc->p_mbtree_stat_file_out )
- - {
- - b_regular_file = x264_is_regular_file( rc->p_mbtree_stat_file_out );
- - fclose( rc->p_mbtree_stat_file_out );
- - if( h->i_frame >= rc->num_entries && b_regular_file )
- - if( rename( rc->psz_mbtree_stat_file_tmpname, rc->psz_mbtree_stat_file_name ) != 0 )
- - {
- - x264_log( h, X264_LOG_ERROR, "failed to rename \"%s\" to \"%s\"\n",
- - rc->psz_mbtree_stat_file_tmpname, rc->psz_mbtree_stat_file_name );
- - }
- - x264_free( rc->psz_mbtree_stat_file_tmpname );
- - x264_free( rc->psz_mbtree_stat_file_name );
- - }
- - if( rc->p_mbtree_stat_file_in )
- - fclose( rc->p_mbtree_stat_file_in );
- - x264_free( rc->pred );
- - x264_free( rc->pred_b_from_p );
- - x264_free( rc->entry );
- - x264_free( rc->qp_buffer[0] );
- - x264_free( rc->qp_buffer[1] );
- - if( rc->zones )
- - {
- - x264_free( rc->zones[0].param );
- - for( int i = 1; i < rc->i_zones; i++ )
- - if( rc->zones[i].param != rc->zones[0].param && rc->zones[i].param->param_free )
- - rc->zones[i].param->param_free( rc->zones[i].param );
- - x264_free( rc->zones );
- + for (int view = 0; view < rc_num; view++) {
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- + int b_regular_file;
- +
- + if( rc->p_stat_file_out )
- + {
- + b_regular_file = x264_is_regular_file( rc->p_stat_file_out );
- + fclose( rc->p_stat_file_out );
- + if( h->i_frame >= rc->num_entries && b_regular_file )
- + if( rename( rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out ) != 0 )
- + {
- + x264_log( h, X264_LOG_ERROR, "failed to rename \"%s\" to \"%s\"\n",
- + rc->psz_stat_file_tmpname, h->param.rc.psz_stat_out );
- + }
- + x264_free( rc->psz_stat_file_tmpname );
- + }
- + if( rc->p_mbtree_stat_file_out )
- + {
- + b_regular_file = x264_is_regular_file( rc->p_mbtree_stat_file_out );
- + fclose( rc->p_mbtree_stat_file_out );
- + if( h->i_frame >= rc->num_entries && b_regular_file )
- + if( rename( rc->psz_mbtree_stat_file_tmpname, rc->psz_mbtree_stat_file_name ) != 0 )
- + {
- + x264_log( h, X264_LOG_ERROR, "failed to rename \"%s\" to \"%s\"\n",
- + rc->psz_mbtree_stat_file_tmpname, rc->psz_mbtree_stat_file_name );
- + }
- + x264_free( rc->psz_mbtree_stat_file_tmpname );
- + x264_free( rc->psz_mbtree_stat_file_name );
- + }
- + if( rc->p_mbtree_stat_file_in )
- + fclose( rc->p_mbtree_stat_file_in );
- + x264_free( rc->pred );
- + x264_free( rc->pred_b_from_p );
- + x264_free( rc->entry );
- + x264_free( rc->qp_buffer[0] );
- + x264_free( rc->qp_buffer[1] );
- + if( rc->zones )
- + {
- + x264_free( rc->zones[0].param );
- + for( int i = 1; i < rc->i_zones; i++ )
- + if( rc->zones[i].param != rc->zones[0].param && rc->zones[i].param->param_free )
- + rc->zones[i].param->param_free( rc->zones[i].param );
- + x264_free( rc->zones );
- + }
- + x264_free( rc );
- }
- - x264_free( rc );
- }
- static void accum_p_qp_update( x264_t *h, float qp )
- {
- - x264_ratecontrol_t *rc = h->rc;
- + x264_ratecontrol_t *rc = h->rc_mvc[get_view_id(h)];
- rc->accum_p_qp *= .95;
- rc->accum_p_norm *= .95;
- rc->accum_p_norm += 1;
- - if( h->sh.i_type == SLICE_TYPE_I )
- + if( IS_SLICE_TYPE_I(h->sh.i_type)/* || h->sh.b_anchor*/)
- rc->accum_p_qp += qp + rc->ip_offset;
- else
- rc->accum_p_qp += qp;
- @@ -1170,7 +1375,9 @@ static void accum_p_qp_update( x264_t *h, float qp )
- /* Before encoding a frame, choose a QP for it */
- void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
- {
- - x264_ratecontrol_t *rc = h->rc;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- + x264_sps_t * sps = get_view_id(h)==0 ? h->sps : h->subset_sps;
- ratecontrol_entry_t *rce = NULL;
- x264_zone_t *zone = get_zone( h, h->fenc->i_frame );
- float q;
- @@ -1185,9 +1392,9 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
- {
- int frame = h->fenc->i_frame;
- assert( frame >= 0 && frame < rc->num_entries );
- - rce = h->rc->rce = &h->rc->entry[frame];
- + rce = rc->rce = &rc->entry[frame];
- - if( h->sh.i_type == SLICE_TYPE_B
- + if( IS_SLICE_TYPE_B(h->sh.i_type)
- && h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO )
- {
- h->sh.b_direct_spatial_mv_pred = ( rce->direct_mode == 's' );
- @@ -1198,8 +1405,8 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
- if( rc->b_vbv )
- {
- memset( h->fdec->i_row_bits, 0, h->mb.i_mb_height * sizeof(int) );
- - rc->row_pred = &rc->row_preds[h->sh.i_type];
- - rc->buffer_rate = h->fenc->i_cpb_duration * rc->vbv_max_rate * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
- + rc->row_pred = &rc->row_preds[/*h->sh.b_anchor ? SLICE_TYPE_I :*/ h->sh.i_type];
- + rc->buffer_rate = h->fenc->i_cpb_duration * rc->vbv_max_rate * sps->vui.i_num_units_in_tick / sps->vui.i_time_scale;
- update_vbv_plan( h, overhead );
- const x264_level_t *l = x264_levels;
- @@ -1213,12 +1420,12 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
- mincr = 4;
- /* High 10 doesn't require minCR, so just set the maximum to a large value. */
- - if( h->sps->i_profile_idc == PROFILE_HIGH10 )
- + if( sps->i_profile_idc == PROFILE_HIGH10 )
- rc->frame_size_maximum = 1e9;
- else
- {
- /* The spec has a bizarre special case for the first frame. */
- - if( h->i_frame == 0 )
- + if( h->i_frame == 0 || (h->i_frame == 1 && h->param.b_mvc))
- {
- //384 * ( Max( PicSizeInMbs, fR * MaxMBPS ) + MaxMBPS * ( tr( 0 ) - tr,n( 0 ) ) ) / MinCR
- double fr = 1. / 172;
- @@ -1228,14 +1435,21 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
- else
- {
- //384 * MaxMBPS * ( tr( n ) - tr( n - 1 ) ) / MinCR
- - rc->frame_size_maximum = 384 * BIT_DEPTH * ((double)h->fenc->i_cpb_duration * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale) * l->mbps / mincr;
- + rc->frame_size_maximum = 384 * BIT_DEPTH * ((double)h->fenc->i_cpb_duration * sps->vui.i_num_units_in_tick / sps->vui.i_time_scale) * l->mbps / mincr;
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "cpb_duration = %d, num_units_in_tick = %d, time_scale = %d\n",
- + h->fenc->i_cpb_duration, sps->vui.i_num_units_in_tick, sps->vui.i_time_scale);
- +#endif
- }
- }
- }
- - if( h->sh.i_type != SLICE_TYPE_B )
- + if( !IS_SLICE_TYPE_B(h->sh.i_type) ) {
- rc->bframes = h->fenc->i_bframes;
- -
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[%4d]: rc->bframes = %d (%s)[%p]\n", h->fenc->i_frame, h->fenc->i_bframes, h->b_dependent ? "d" : "m", rc);
- +#endif
- + }
- if( i_force_qp != X264_QP_AUTO )
- {
- q = i_force_qp - 1;
- @@ -1251,7 +1465,7 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
- }
- else /* CQP */
- {
- - if( h->sh.i_type == SLICE_TYPE_B && h->fdec->b_kept_as_ref )
- + if( IS_SLICE_TYPE_B(h->sh.i_type) && h->fdec->b_kept_as_ref )
- q = ( rc->qp_constant[ SLICE_TYPE_B ] + rc->qp_constant[ SLICE_TYPE_P ] ) / 2;
- else
- q = rc->qp_constant[ h->sh.i_type ];
- @@ -1278,20 +1492,21 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
- accum_p_qp_update( h, rc->qpm );
- - if( h->sh.i_type != SLICE_TYPE_B )
- - rc->last_non_b_pict_type = h->sh.i_type;
- + if( !IS_SLICE_TYPE_B(h->sh.i_type) ) {
- + rc->last_non_b_pict_type = h->sh.b_anchor ? SLICE_TYPE_I : h->sh.i_type;
- + }
- }
- static double predict_row_size( x264_t *h, int y, double qp )
- {
- /* average between two predictors:
- * absolute SATD, and scaled bit cost of the colocated row in the previous frame */
- - x264_ratecontrol_t *rc = h->rc;
- + x264_ratecontrol_t *rc = h->rc_mvc[get_view_id(h)];
- double pred_s = predict_size( rc->row_pred[0], qp2qscale( qp ), h->fdec->i_row_satd[y] );
- double pred_t = 0;
- - if( h->sh.i_type == SLICE_TYPE_I || qp >= h->fref[0][0]->f_row_qp[y] )
- + if( h->sh.i_type == SLICE_TYPE_I || h->sh.b_anchor || qp >= h->fref[0][0]->f_row_qp[y] )
- {
- - if( h->sh.i_type == SLICE_TYPE_P
- + if( IS_SLICE_TYPE_P(h->sh.i_type) && !h->sh.b_anchor
- && h->fref[0][0]->i_type == h->fdec->i_type
- && h->fref[0][0]->i_row_satd[y] > 0
- && (abs(h->fref[0][0]->i_row_satd[y] - h->fdec->i_row_satd[y]) < h->fdec->i_row_satd[y]/2))
- @@ -1331,8 +1546,9 @@ static double predict_row_size_sum( x264_t *h, int y, double qp )
- void x264_ratecontrol_mb( x264_t *h, int bits )
- {
- - x264_ratecontrol_t *rc = h->rc;
- + x264_ratecontrol_t *rc = h->rc_mvc[get_view_id(h)];
- const int y = h->mb.i_mb_y;
- + int b_anchor = h->sh.b_anchor;
- x264_emms();
- @@ -1346,7 +1562,7 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
- h->fdec->f_row_qp[y] = rc->qpm;
- update_predictor( rc->row_pred[0], qp2qscale( rc->qpm ), h->fdec->i_row_satd[y], h->fdec->i_row_bits[y] );
- - if( h->sh.i_type == SLICE_TYPE_P && rc->qpm < h->fref[0][0]->f_row_qp[y] )
- + if( IS_SLICE_TYPE_P(h->sh.i_type) && !b_anchor && rc->qpm < h->fref[0][0]->f_row_qp[y] )
- update_predictor( rc->row_pred[1], qp2qscale( rc->qpm ), h->fdec->i_row_satds[0][0][y], h->fdec->i_row_bits[y] );
- /* tweak quality based on difference from predicted size */
- @@ -1361,7 +1577,7 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
- float step_size = 0.5;
- /* B-frames shouldn't use lower QP than their reference frames. */
- - if( h->sh.i_type == SLICE_TYPE_B )
- + if( IS_SLICE_TYPE_B(h->sh.i_type) )
- {
- qp_min = X264_MAX( qp_min, X264_MAX( h->fref[0][0]->f_row_qp[y+1], h->fref[1][0]->f_row_qp[y+1] ) );
- rc->qpm = X264_MAX( rc->qpm, qp_min );
- @@ -1393,7 +1609,7 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
- if( row_bits_so_far( h, y ) < 0.05 * slice_size_planned )
- return;
- - if( h->sh.i_type != SLICE_TYPE_I )
- + if( !IS_SLICE_TYPE_I(h->sh.i_type) && !h->sh.b_anchor)
- rc_tol /= 2;
- if( !rc->b_vbv_min_rate )
- @@ -1426,20 +1642,20 @@ void x264_ratecontrol_mb( x264_t *h, int bits )
- b1 = predict_row_size_sum( h, y, rc->qpm ) + size_of_other_slices;
- }
- - h->rc->frame_size_estimated = predict_row_size_sum( h, y, rc->qpm );
- + rc->frame_size_estimated = predict_row_size_sum( h, y, rc->qpm );
- }
- }
- int x264_ratecontrol_qp( x264_t *h )
- {
- x264_emms();
- - return x264_clip3( h->rc->qpm + .5, h->param.rc.i_qp_min, h->param.rc.i_qp_max );
- + return x264_clip3( h->rc_mvc[get_view_id(h)]->qpm + .5, h->param.rc.i_qp_min, h->param.rc.i_qp_max );
- }
- int x264_ratecontrol_mb_qp( x264_t *h )
- {
- x264_emms();
- - float qp = h->rc->qpm;
- + float qp = h->rc_mvc[get_view_id(h)]->qpm;
- if( h->param.rc.i_aq_mode )
- {
- /* MB-tree currently doesn't adjust quantizers in unreferenced frames. */
- @@ -1455,7 +1671,8 @@ int x264_ratecontrol_mb_qp( x264_t *h )
- /* In 2pass, force the same frame types as in the 1st pass */
- int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
- {
- - x264_ratecontrol_t *rc = h->rc;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- if( h->param.rc.b_stat_read )
- {
- if( frame_num >= rc->num_entries )
- @@ -1463,8 +1680,8 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
- /* We could try to initialize everything required for ABR and
- * adaptive B-frames, but that would be complicated.
- * So just calculate the average QP used so far. */
- - h->param.rc.i_qp_constant = (h->stat.i_frame_count[SLICE_TYPE_P] == 0) ? 24 + QP_BD_OFFSET
- - : 1 + h->stat.f_frame_qp[SLICE_TYPE_P] / h->stat.i_frame_count[SLICE_TYPE_P];
- + h->param.rc.i_qp_constant = (view ? h->stat.i_frame_dep_count[SLICE_TYPE_P] : h->stat.i_frame_count[SLICE_TYPE_P]) == 0 ? 24 + QP_BD_OFFSET
- + : 1 + (view ? h->stat.f_frame_dep_qp[SLICE_TYPE_P] / h->stat.i_frame_dep_count[SLICE_TYPE_P] : h->stat.f_frame_qp[SLICE_TYPE_P] / h->stat.i_frame_count[SLICE_TYPE_P]);
- rc->qp_constant[SLICE_TYPE_P] = x264_clip3( h->param.rc.i_qp_constant, 0, QP_MAX );
- rc->qp_constant[SLICE_TYPE_I] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) / fabs( h->param.rc.f_ip_factor )) + 0.5 ), 0, QP_MAX );
- rc->qp_constant[SLICE_TYPE_B] = x264_clip3( (int)( qscale2qp( qp2qscale( h->param.rc.i_qp_constant ) * fabs( h->param.rc.f_pb_factor )) + 0.5 ), 0, QP_MAX );
- @@ -1496,7 +1713,7 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
- void x264_ratecontrol_set_weights( x264_t *h, x264_frame_t *frm )
- {
- - ratecontrol_entry_t *rce = &h->rc->entry[frm->i_frame];
- + ratecontrol_entry_t *rce = &h->rc_mvc[get_view_id(h)]->entry[frm->i_frame];
- if( h->param.analyse.i_weighted_pred <= 0 )
- return;
- @@ -1513,7 +1730,9 @@ void x264_ratecontrol_set_weights( x264_t *h, x264_frame_t *frm )
- /* After encoding one frame, save stats and update ratecontrol state */
- int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
- {
- - x264_ratecontrol_t *rc = h->rc;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- + x264_sps_t * sps = get_view_id(h)==0 ? h->sps : h->subset_sps;
- const int *mbs = h->stat.frame.i_mb_count;
- x264_emms();
- @@ -1529,8 +1748,8 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
- if( h->param.rc.b_stat_write )
- {
- - char c_type = h->sh.i_type==SLICE_TYPE_I ? (h->fenc->i_poc==0 ? 'I' : 'i')
- - : h->sh.i_type==SLICE_TYPE_P ? 'P'
- + char c_type = IS_SLICE_TYPE_I(h->sh.i_type) ? (h->fenc->i_poc==0 ? 'I' : 'i')
- + : IS_SLICE_TYPE_P(h->sh.i_type) ? 'P'
- : h->fenc->b_kept_as_ref ? 'B' : 'b';
- int dir_frame = h->stat.frame.i_direct_score[1] - h->stat.frame.i_direct_score[0];
- int dir_avg = h->stat.i_direct_score[1] - h->stat.i_direct_score[0];
- @@ -1599,7 +1818,7 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
- if( rc->b_abr )
- {
- - if( h->sh.i_type != SLICE_TYPE_B )
- + if( !IS_SLICE_TYPE_B(h->sh.i_type) )
- rc->cplxr_sum += bits * qp2qscale( rc->qpa_rc ) / rc->last_rceq;
- else
- {
- @@ -1617,11 +1836,14 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
- if( h->mb.b_variable_qp )
- {
- - if( h->sh.i_type == SLICE_TYPE_B )
- + if( IS_SLICE_TYPE_B(h->sh.i_type) )
- {
- rc->bframe_bits += bits;
- if( h->fenc->b_last_minigop_bframe )
- {
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[%4d]: rc_end: rc->bframes = %d, (%s)[%p]\n", h->fenc->i_frame, rc->bframes, h->b_dependent ? "d" : "m", rc);
- +#endif
- update_predictor( rc->pred_b_from_p, qp2qscale( rc->qpa_rc ),
- h->fref[1][h->i_ref[1]-1]->i_satd, rc->bframe_bits / rc->bframes );
- rc->bframe_bits = 0;
- @@ -1632,20 +1854,20 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
- *filler = update_vbv( h, bits );
- rc->filler_bits_sum += *filler * 8;
- - if( h->sps->vui.b_nal_hrd_parameters_present )
- + if( sps->vui.b_nal_hrd_parameters_present )
- {
- if( h->fenc->i_frame == 0 )
- {
- // access unit initialises the HRD
- h->fenc->hrd_timing.cpb_initial_arrival_time = 0;
- - rc->initial_cpb_removal_delay = h->initial_cpb_removal_delay;
- - rc->initial_cpb_removal_delay_offset = h->initial_cpb_removal_delay_offset;
- + rc->initial_cpb_removal_delay = view ? h->initial_cpb_removal_delay_dep : h->initial_cpb_removal_delay;
- + rc->initial_cpb_removal_delay_offset = view ? h->initial_cpb_removal_delay_offset_dep : h->initial_cpb_removal_delay_offset;
- h->fenc->hrd_timing.cpb_removal_time = rc->nrt_first_access_unit = (double)rc->initial_cpb_removal_delay / 90000;
- }
- else
- {
- h->fenc->hrd_timing.cpb_removal_time = rc->nrt_first_access_unit + (double)(h->fenc->i_cpb_delay - h->i_cpb_delay_pir_offset) *
- - h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
- + sps->vui.i_num_units_in_tick / sps->vui.i_time_scale;
- double cpb_earliest_arrival_time = h->fenc->hrd_timing.cpb_removal_time - (double)rc->initial_cpb_removal_delay / 90000;
- if( h->fenc->b_keyframe )
- @@ -1657,7 +1879,7 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
- else
- cpb_earliest_arrival_time -= (double)rc->initial_cpb_removal_delay_offset / 90000;
- - if( h->sps->vui.hrd.b_cbr_hrd )
- + if( sps->vui.hrd.b_cbr_hrd )
- h->fenc->hrd_timing.cpb_initial_arrival_time = rc->previous_cpb_final_arrival_time;
- else
- h->fenc->hrd_timing.cpb_initial_arrival_time = X264_MAX( rc->previous_cpb_final_arrival_time, cpb_earliest_arrival_time );
- @@ -1665,9 +1887,9 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
- int filler_bits = *filler ? X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), *filler )*8 : 0;
- // Equation C-6
- h->fenc->hrd_timing.cpb_final_arrival_time = rc->previous_cpb_final_arrival_time = h->fenc->hrd_timing.cpb_initial_arrival_time +
- - (double)(bits + filler_bits) / h->sps->vui.hrd.i_bit_rate_unscaled;
- + (double)(bits + filler_bits) / sps->vui.hrd.i_bit_rate_unscaled;
- - h->fenc->hrd_timing.dpb_output_time = (double)h->fenc->i_dpb_output_delay * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale +
- + h->fenc->hrd_timing.dpb_output_time = (double)h->fenc->i_dpb_output_delay * sps->vui.i_num_units_in_tick / sps->vui.i_time_scale +
- h->fenc->hrd_timing.cpb_removal_time;
- }
- @@ -1686,7 +1908,9 @@ fail:
- */
- static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor, int frame_num)
- {
- - x264_ratecontrol_t *rcc= h->rc;
- + if (h->param.b_mvc) frame_num /= 2;
- +
- + x264_ratecontrol_t *rcc= h->rc_mvc[get_view_id(h)];
- x264_zone_t *zone = get_zone( h, frame_num );
- double q = pow( rce->blurred_complexity, 1 - rcc->qcompress );
- @@ -1713,13 +1937,14 @@ static double get_qscale(x264_t *h, ratecontrol_entry_t *rce, double rate_factor
- static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
- {
- - x264_ratecontrol_t *rcc = h->rc;
- + x264_ratecontrol_t *rcc = h->rc_mvc[get_view_id(h)];
- const int pict_type = rce->pict_type;
- + int b_anchor = rce->b_anchor;
- // force I/B quants as a function of P quants
- const double last_p_q = rcc->last_qscale_for[SLICE_TYPE_P];
- const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type];
- - if( pict_type == SLICE_TYPE_I )
- + if( IS_SLICE_TYPE_I(pict_type) || b_anchor)
- {
- double iq = q;
- double pq = qp2qscale( rcc->accum_p_qp / rcc->accum_p_norm );
- @@ -1734,15 +1959,15 @@ static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
- else
- q = rcc->accum_p_norm * pq / ip_factor + (1 - rcc->accum_p_norm) * iq;
- }
- - else if( pict_type == SLICE_TYPE_B )
- + else if( IS_SLICE_TYPE_B(pict_type) )
- {
- if( h->param.rc.f_pb_factor > 0 )
- q = last_non_b_q;
- if( !rce->kept_as_ref )
- q *= fabs( h->param.rc.f_pb_factor );
- }
- - else if( pict_type == SLICE_TYPE_P
- - && rcc->last_non_b_pict_type == SLICE_TYPE_P
- + else if( IS_SLICE_TYPE_P(pict_type)
- + && IS_SLICE_TYPE_P(rcc->last_non_b_pict_type)
- && rce->tex_bits == 0 )
- {
- q = last_p_q;
- @@ -1750,7 +1975,7 @@ static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
- /* last qscale / qdiff stuff */
- if( rcc->last_non_b_pict_type == pict_type &&
- - (pict_type!=SLICE_TYPE_I || rcc->last_accum_p_norm < 1) )
- + (!IS_SLICE_TYPE_I(pict_type) || rcc->last_accum_p_norm < 1) )
- {
- double last_q = rcc->last_qscale_for[pict_type];
- double max_qscale = last_q * rcc->lstep;
- @@ -1761,15 +1986,15 @@ static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
- }
- rcc->last_qscale_for[pict_type] = q;
- - if( pict_type != SLICE_TYPE_B )
- + if( !IS_SLICE_TYPE_B(pict_type) )
- rcc->last_non_b_pict_type = pict_type;
- - if( pict_type == SLICE_TYPE_I )
- + if( IS_SLICE_TYPE_I(pict_type) )
- {
- rcc->last_accum_p_norm = rcc->accum_p_norm;
- rcc->accum_p_norm = 0;
- rcc->accum_p_qp = 0;
- }
- - if( pict_type == SLICE_TYPE_P )
- + if( IS_SLICE_TYPE_P(pict_type) )
- {
- float mask = 1 - pow( (float)rce->i_count / rcc->nmb, 2 );
- rcc->accum_p_qp = mask * (qscale2qp( q ) + rcc->accum_p_qp);
- @@ -1780,7 +2005,7 @@ static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
- static double predict_size( predictor_t *p, double q, double var )
- {
- - return (p->coeff*var + p->offset) / (q*p->count);
- + return (p->coeff*var + p->offset) / (q*p->count);
- }
- static void update_predictor( predictor_t *p, double q, double var, double bits )
- @@ -1808,29 +2033,31 @@ static void update_predictor( predictor_t *p, double q, double var, double bits
- static int update_vbv( x264_t *h, int bits )
- {
- int filler = 0;
- - int bitrate = h->sps->vui.hrd.i_bit_rate_unscaled;
- - x264_ratecontrol_t *rcc = h->rc;
- - x264_ratecontrol_t *rct = h->thread[0]->rc;
- - uint64_t buffer_size = (uint64_t)h->sps->vui.hrd.i_cpb_size_unscaled * h->sps->vui.i_time_scale;
- + int view = get_view_id(h);
- + x264_sps_t * sps = view == 0 ? h->sps : h->subset_sps;
- + x264_ratecontrol_t *rcc = h->rc_mvc[view];
- + x264_ratecontrol_t *rct = h->thread[0]->rc_mvc[view];
- + uint64_t buffer_size = (uint64_t)sps->vui.hrd.i_cpb_size_unscaled * sps->vui.i_time_scale;
- + int bitrate = sps->vui.hrd.i_bit_rate_unscaled;
- if( rcc->last_satd >= h->mb.i_mb_count )
- - update_predictor( &rct->pred[h->sh.i_type], qp2qscale( rcc->qpa_rc ), rcc->last_satd, bits );
- + update_predictor( &rct->pred[h->sh.b_anchor ? SLICE_TYPE_I : h->sh.i_type], qp2qscale( rcc->qpa_rc ), rcc->last_satd, bits );
- if( !rcc->b_vbv )
- return filler;
- - rct->buffer_fill_final -= (uint64_t)bits * h->sps->vui.i_time_scale;
- + rct->buffer_fill_final -= (uint64_t)bits * sps->vui.i_time_scale;
- if( rct->buffer_fill_final < 0 )
- - x264_log( h, X264_LOG_WARNING, "VBV underflow (frame %d, %.0f bits)\n", h->i_frame, (double)rct->buffer_fill_final / h->sps->vui.i_time_scale );
- + x264_log( h, X264_LOG_WARNING, "VBV underflow (frame %d, %.0f bits)\n", h->i_frame, (double)rct->buffer_fill_final / sps->vui.i_time_scale );
- rct->buffer_fill_final = X264_MAX( rct->buffer_fill_final, 0 );
- - rct->buffer_fill_final += (uint64_t)bitrate * h->sps->vui.i_num_units_in_tick * h->fenc->i_cpb_duration;
- + rct->buffer_fill_final += (uint64_t)bitrate * sps->vui.i_num_units_in_tick * h->fenc->i_cpb_duration;
- - if( h->sps->vui.hrd.b_cbr_hrd && rct->buffer_fill_final > buffer_size )
- + if( sps->vui.hrd.b_cbr_hrd && rct->buffer_fill_final > buffer_size )
- {
- - filler = ceil( (rct->buffer_fill_final - buffer_size) / (8. * h->sps->vui.i_time_scale) );
- + filler = ceil( (rct->buffer_fill_final - buffer_size) / (8. * sps->vui.i_time_scale) );
- bits = X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), filler ) * 8;
- - rct->buffer_fill_final -= (uint64_t)bits * h->sps->vui.i_time_scale;
- + rct->buffer_fill_final -= (uint64_t)bits * sps->vui.i_time_scale;
- }
- else
- rct->buffer_fill_final = X264_MIN( rct->buffer_fill_final, buffer_size );
- @@ -1840,10 +2067,12 @@ static int update_vbv( x264_t *h, int bits )
- void x264_hrd_fullness( x264_t *h )
- {
- - x264_ratecontrol_t *rct = h->thread[0]->rc;
- - uint64_t denom = (uint64_t)h->sps->vui.hrd.i_bit_rate_unscaled * h->sps->vui.i_time_scale / rct->hrd_multiply_denom;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rct = h->thread[0]->rc_mvc[view];
- + x264_sps_t * sps = view==0 ? h->sps : h->subset_sps;
- + uint64_t denom = (uint64_t)sps->vui.hrd.i_bit_rate_unscaled * sps->vui.i_time_scale / rct->hrd_multiply_denom;
- uint64_t cpb_state = rct->buffer_fill_final;
- - uint64_t cpb_size = (uint64_t)h->sps->vui.hrd.i_cpb_size_unscaled * h->sps->vui.i_time_scale;
- + uint64_t cpb_size = (uint64_t)sps->vui.hrd.i_cpb_size_unscaled * sps->vui.i_time_scale;
- uint64_t multiply_factor = 180000 / rct->hrd_multiply_denom;
- if( rct->buffer_fill_final < 0 || rct->buffer_fill_final > cpb_size )
- @@ -1852,28 +2081,42 @@ void x264_hrd_fullness( x264_t *h )
- rct->buffer_fill_final < 0 ? "underflow" : "overflow", (float)rct->buffer_fill_final/denom, (float)cpb_size/denom );
- }
- - h->initial_cpb_removal_delay = (multiply_factor * cpb_state + denom) / (2*denom);
- - h->initial_cpb_removal_delay_offset = (multiply_factor * cpb_size + denom) / (2*denom) - h->initial_cpb_removal_delay;
- + if (!h->b_dependent) {
- + h->initial_cpb_removal_delay = (multiply_factor * cpb_state + denom) / (2*denom);
- + h->initial_cpb_removal_delay_offset = (multiply_factor * cpb_size + denom) / (2*denom) - h->initial_cpb_removal_delay;
- + } else {
- + h->initial_cpb_removal_delay_dep = (multiply_factor * cpb_state + denom) / (2*denom);
- + h->initial_cpb_removal_delay_offset_dep = (multiply_factor * cpb_size + denom) / (2*denom) - h->initial_cpb_removal_delay_dep;
- + }
- +}
- +
- +void x264_hrd_copy_to_dependent(x264_t *h, x264_t *thread_next)
- +{
- + /* cannot be equal thease values with base ones, so copy base values to them. */
- + thread_next->initial_cpb_removal_delay = h->initial_cpb_removal_delay;
- + thread_next->initial_cpb_removal_delay_offset = h->initial_cpb_removal_delay_offset;
- }
- // provisionally update VBV according to the planned size of all frames currently in progress
- static void update_vbv_plan( x264_t *h, int overhead )
- {
- - x264_ratecontrol_t *rcc = h->rc;
- - rcc->buffer_fill = h->thread[0]->rc->buffer_fill_final / h->sps->vui.i_time_scale;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rcc = h->rc_mvc[view];
- + x264_sps_t *sps = view == 0 ? h->sps : h->subset_sps;
- + rcc->buffer_fill = h->thread[0]->rc_mvc[view]->buffer_fill_final / sps->vui.i_time_scale;
- if( h->i_thread_frames > 1 )
- {
- - int j = h->rc - h->thread[0]->rc;
- + int j = h->rc_mvc[view] - h->thread[0]->rc_mvc[view];
- for( int i = 1; i < h->i_thread_frames; i++ )
- {
- x264_t *t = h->thread[ (j+i)%h->i_thread_frames ];
- - double bits = t->rc->frame_size_planned;
- + double bits = t->rc_mvc[view]->frame_size_planned;
- if( !t->b_thread_active )
- continue;
- - bits = X264_MAX(bits, t->rc->frame_size_estimated);
- + bits = X264_MAX(bits, t->rc_mvc[view]->frame_size_estimated);
- rcc->buffer_fill -= bits;
- rcc->buffer_fill = X264_MAX( rcc->buffer_fill, 0 );
- - rcc->buffer_fill += t->rc->buffer_rate;
- + rcc->buffer_fill += t->rc_mvc[view]->buffer_rate;
- rcc->buffer_fill = X264_MIN( rcc->buffer_fill, rcc->buffer_size );
- }
- }
- @@ -1884,7 +2127,8 @@ static void update_vbv_plan( x264_t *h, int overhead )
- // apply VBV constraints and clip qscale to between lmin and lmax
- static double clip_qscale( x264_t *h, int pict_type, double q )
- {
- - x264_ratecontrol_t *rcc = h->rc;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rcc = h->rc_mvc[view];
- double lmin = rcc->lmin[pict_type];
- double lmax = rcc->lmax[pict_type];
- if( rcc->rate_factor_max_increment )
- @@ -1907,15 +2151,18 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
- for( int iterations = 0; iterations < 1000 && terminate != 3; iterations++ )
- {
- double frame_q[3];
- - double cur_bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
- + double cur_bits = predict_size( &rcc->pred[h->sh.b_anchor ? SLICE_TYPE_I : h->sh.i_type], q, rcc->last_satd );
- double buffer_fill_cur = rcc->buffer_fill - cur_bits;
- double target_fill;
- double total_duration = 0;
- - frame_q[0] = h->sh.i_type == SLICE_TYPE_I ? q * h->param.rc.f_ip_factor : q;
- + frame_q[0] = IS_SLICE_TYPE_I(h->sh.i_type) || h->sh.b_anchor ? q * h->param.rc.f_ip_factor : q;
- frame_q[1] = frame_q[0] * h->param.rc.f_pb_factor;
- frame_q[2] = frame_q[0] / h->param.rc.f_ip_factor;
- /* Loop over the planned future frames. */
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "buffer_fill_cur = %f, buffer_size = %f\n", buffer_fill_cur, rcc->buffer_size);
- +#endif
- for( int j = 0; buffer_fill_cur >= 0 && buffer_fill_cur <= rcc->buffer_size; j++ )
- {
- total_duration += h->fenc->f_planned_cpb_duration[j];
- @@ -1930,10 +2177,17 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
- }
- /* Try to get to get the buffer at least 50% filled, but don't set an impossible goal. */
- target_fill = X264_MIN( rcc->buffer_fill + total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.5 );
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "buffer_fill = %7.4f, total_duration = %7.4f, vbv_max_rate = %7.4f, buffer_size = %7.4f\n",
- + rcc->buffer_fill, total_duration, rcc->vbv_max_rate, rcc->buffer_size);
- +#endif
- if( buffer_fill_cur < target_fill )
- {
- q *= 1.01;
- terminate |= 1;
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "target_fill(a) = %7.4f, q = %7.4f\n", target_fill, q);
- +#endif
- continue;
- }
- /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */
- @@ -1942,16 +2196,22 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
- {
- q /= 1.01;
- terminate |= 2;
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "target_fill(b) = %7.4f, q = %7.4f\n", target_fill, q);
- +#endif
- continue;
- }
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "target_fill(c) = %7.4f, q = %7.4f\n", target_fill, q);
- +#endif
- break;
- }
- }
- /* Fallback to old purely-reactive algorithm: no lookahead. */
- else
- {
- - if( ( pict_type == SLICE_TYPE_P ||
- - ( pict_type == SLICE_TYPE_I && rcc->last_non_b_pict_type == SLICE_TYPE_I ) ) &&
- + if( ( IS_SLICE_TYPE_P(pict_type) ||
- + ( IS_SLICE_TYPE_I(pict_type) && IS_SLICE_TYPE_I(rcc->last_non_b_pict_type) ) ) &&
- rcc->buffer_fill/rcc->buffer_size < 0.5 )
- {
- q /= x264_clip3f( 2.0*rcc->buffer_fill/rcc->buffer_size, 0.5, 1.0 );
- @@ -1959,10 +2219,12 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
- /* Now a hard threshold to make sure the frame fits in VBV.
- * This one is mostly for I-frames. */
- - double bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
- + double bits = predict_size( &rcc->pred[h->sh.b_anchor ? SLICE_TYPE_I : h->sh.i_type], q, rcc->last_satd );
- double qf = 1.0;
- /* For small VBVs, allow the frame to use up the entire VBV. */
- - double max_fill_factor = h->param.rc.i_vbv_buffer_size >= 5*h->param.rc.i_vbv_max_bitrate / rcc->fps ? 2 : 1;
- +
- + int vbv_max_rate = view == 0 ? h->param.rc.i_vbv_max_bitrate : h->param.rc.i_vbv_max_bitrate_dep[view-1];
- + double max_fill_factor = h->param.rc.i_vbv_buffer_size >= 5*vbv_max_rate / rcc->fps ? 2 : 1;
- /* For single-frame VBVs, request that the frame use up the entire VBV. */
- double min_fill_factor = rcc->single_frame_vbv ? 1 : 2;
- @@ -1976,14 +2238,17 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
- }
- /* Apply MinCR restrictions */
- - double bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
- + double bits = predict_size( &rcc->pred[h->sh.b_anchor ? SLICE_TYPE_I : h->sh.i_type], q, rcc->last_satd );
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "bits = %7.4f, predictor.coeff = %7.4f, predictor.offset = %7.4f, bitsMax=%7.4f\n", bits, rcc->pred[h->sh.i_type].coeff, rcc->pred[h->sh.i_type].offset, rcc->frame_size_maximum);
- +#endif
- if( bits > rcc->frame_size_maximum )
- q *= bits / rcc->frame_size_maximum;
- - bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
- + bits = predict_size( &rcc->pred[h->sh.b_anchor ? SLICE_TYPE_I : h->sh.i_type], q, rcc->last_satd );
- /* Check B-frame complexity, and use up any bits that would
- * overflow before the next P-frame. */
- - if( h->sh.i_type == SLICE_TYPE_P && !rcc->single_frame_vbv )
- + if( IS_SLICE_TYPE_P(h->sh.i_type) && !h->sh.b_anchor && !rcc->single_frame_vbv )
- {
- int nb = rcc->bframes;
- double pbbits = bits;
- @@ -2030,13 +2295,24 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
- static float rate_estimate_qscale( x264_t *h )
- {
- float q;
- - x264_ratecontrol_t *rcc = h->rc;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rcc = h->rc_mvc[view];
- ratecontrol_entry_t UNINIT(rce);
- - int pict_type = h->sh.i_type;
- - int64_t total_bits = 8*(h->stat.i_frame_size[SLICE_TYPE_I]
- - + h->stat.i_frame_size[SLICE_TYPE_P]
- - + h->stat.i_frame_size[SLICE_TYPE_B])
- - - rcc->filler_bits_sum;
- + int pict_type = h->sh.b_anchor ? SLICE_TYPE_I : h->sh.i_type;
- + int b_anchor = h->sh.b_anchor;
- + int64_t total_bits =
- + (view
- + ? 8*(h->stat.i_frame_dep_size[SLICE_TYPE_I]
- + + h->stat.i_frame_dep_size[SLICE_TYPE_P]
- + + h->stat.i_frame_dep_size[SLICE_TYPE_B])
- + : 8*(h->stat.i_frame_size[SLICE_TYPE_I]
- + + h->stat.i_frame_size[SLICE_TYPE_P]
- + + h->stat.i_frame_size[SLICE_TYPE_B]))
- + - rcc->filler_bits_sum;
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[rate_estimate_qscale] pict_type %d \n", pict_type);
- +#endif
- if( rcc->b_2pass )
- {
- @@ -2048,7 +2324,7 @@ static float rate_estimate_qscale( x264_t *h )
- }
- }
- - if( pict_type == SLICE_TYPE_B )
- + if( IS_SLICE_TYPE_B(pict_type ) )
- {
- /* B-frames don't have independent ratecontrol, but rather get the
- * average QP of the two adjacent P-frames + an offset */
- @@ -2083,7 +2359,7 @@ static float rate_estimate_qscale( x264_t *h )
- rcc->frame_size_planned = qscale2bits( &rce, qp2qscale( q ) );
- else
- rcc->frame_size_planned = predict_size( rcc->pred_b_from_p, qp2qscale( q ), h->fref[1][h->i_ref[1]-1]->i_satd );
- - h->rc->frame_size_estimated = rcc->frame_size_planned;
- + h->rc_mvc[view]->frame_size_estimated = rcc->frame_size_planned;
- /* For row SATDs */
- if( rcc->b_vbv )
- @@ -2106,14 +2382,14 @@ static float rate_estimate_qscale( x264_t *h )
- {
- if( h->i_thread_frames > 1 )
- {
- - int j = h->rc - h->thread[0]->rc;
- + int j = h->rc_mvc[view] - h->thread[0]->rc_mvc[view];
- for( int i = 1; i < h->i_thread_frames; i++ )
- {
- x264_t *t = h->thread[ (j+i)%h->i_thread_frames ];
- - double bits = t->rc->frame_size_planned;
- + double bits = t->rc_mvc[view]->frame_size_planned;
- if( !t->b_thread_active )
- continue;
- - bits = X264_MAX(bits, t->rc->frame_size_estimated);
- + bits = X264_MAX(bits, t->rc_mvc[view]->frame_size_estimated);
- predicted_bits += (int64_t)bits;
- }
- }
- @@ -2185,6 +2461,9 @@ static float rate_estimate_qscale( x264_t *h )
- double wanted_bits, overflow = 1;
- rcc->last_satd = x264_rc_analyse_slice( h );
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "(%s): last_satd[%d] = %d\n", h->b_dependent ? "d" : "m", h->i_frame, rcc->last_satd);
- +#endif
- rcc->short_term_cplxsum *= 0.5;
- rcc->short_term_cplxcount *= 0.5;
- rcc->short_term_cplxsum += rcc->last_satd / (CLIP_DURATION(h->fenc->f_duration) / BASE_FRAME_DURATION);
- @@ -2198,6 +2477,7 @@ static float rate_estimate_qscale( x264_t *h )
- rce.s_count = 0;
- rce.qscale = 1;
- rce.pict_type = pict_type;
- + rce.b_anchor = b_anchor;
- if( h->param.rc.i_rc_method == X264_RC_CRF )
- {
- @@ -2206,14 +2486,16 @@ static float rate_estimate_qscale( x264_t *h )
- else
- {
- q = get_qscale( h, &rce, rcc->wanted_bits_window / rcc->cplxr_sum, h->fenc->i_frame );
- -
- +#ifdef __RC_DEBUG
- + x264_log(h, X264_LOG_INFO, "(%s): qscale = %7.4f\n", h->b_dependent ? "d" : "m", q);
- +#endif
- /* ABR code can potentially be counterproductive in CBR, so just don't bother.
- * Don't run it if the frame complexity is zero either. */
- if( !rcc->b_vbv_min_rate && rcc->last_satd )
- {
- // FIXME is it simpler to keep track of wanted_bits in ratecontrol_end?
- int i_frame_done = h->i_frame + 1 - h->i_thread_frames;
- - double time_done = i_frame_done / rcc->fps;
- + double time_done = i_frame_done / ((h->param.b_mvc ? 2 : 1) * rcc->fps);
- if( h->param.b_vfr_input && i_frame_done > 0 )
- time_done = ((double)(h->fenc->i_reordered_pts - h->i_reordered_pts_delay)) * h->param.i_timebase_num / h->param.i_timebase_den;
- wanted_bits = time_done * rcc->bitrate;
- @@ -2226,14 +2508,14 @@ static float rate_estimate_qscale( x264_t *h )
- }
- }
- - if( pict_type == SLICE_TYPE_I && h->param.i_keyint_max > 1
- + if( (IS_SLICE_TYPE_I(pict_type) || b_anchor) && h->param.i_keyint_max > 1
- /* should test _next_ pict type, but that isn't decided yet */
- - && rcc->last_non_b_pict_type != SLICE_TYPE_I )
- + && !IS_SLICE_TYPE_I(rcc->last_non_b_pict_type) )
- {
- q = qp2qscale( rcc->accum_p_qp / rcc->accum_p_norm );
- q /= fabs( h->param.rc.f_ip_factor );
- }
- - else if( h->i_frame > 0 )
- + else if( (!h->param.b_mvc && h->i_frame > 0) || h->i_frame > 1)
- {
- if( h->param.rc.i_rc_method != X264_RC_CRF )
- {
- @@ -2255,8 +2537,14 @@ static float rate_estimate_qscale( x264_t *h )
- }
- rcc->qp_novbv = qscale2qp( q );
- +#ifdef __RC_DEBUG
- + x264_log(h, X264_LOG_INFO, "(%s): qscale2 = %7.4f\n", h->b_dependent ? "d" : "m", q);
- +#endif
- //FIXME use get_diff_limited_q() ?
- q = clip_qscale( h, pict_type, q );
- +#ifdef __RC_DEBUG
- + x264_log(h, X264_LOG_INFO, "(%s): qscale3 = %7.4f\n", h->b_dependent ? "d" : "m", q);
- +#endif
- }
- rcc->last_qscale_for[pict_type] =
- @@ -2273,49 +2561,54 @@ static float rate_estimate_qscale( x264_t *h )
- /* Always use up the whole VBV in this case. */
- if( rcc->single_frame_vbv )
- rcc->frame_size_planned = rcc->buffer_rate;
- - h->rc->frame_size_estimated = rcc->frame_size_planned;
- + h->rc_mvc[view]->frame_size_estimated = rcc->frame_size_planned;
- +#ifdef __RC_DEBUG
- + x264_log(h, X264_LOG_INFO, "(%s): qscalef = %7.4f\n", h->b_dependent ? "d" : "m", q);
- +#endif
- return q;
- }
- }
- void x264_threads_normalize_predictors( x264_t *h )
- {
- + int view = get_view_id(h);
- double totalsize = 0;
- for( int i = 0; i < h->param.i_threads; i++ )
- - totalsize += h->thread[i]->rc->slice_size_planned;
- - double factor = h->rc->frame_size_planned / totalsize;
- + totalsize += h->thread[i]->rc_mvc[view]->slice_size_planned;
- + double factor = h->rc_mvc[view]->frame_size_planned / totalsize;
- for( int i = 0; i < h->param.i_threads; i++ )
- - h->thread[i]->rc->slice_size_planned *= factor;
- + h->thread[i]->rc_mvc[view]->slice_size_planned *= factor;
- }
- void x264_threads_distribute_ratecontrol( x264_t *h )
- {
- int row;
- - x264_ratecontrol_t *rc = h->rc;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- /* Initialize row predictors */
- - if( h->i_frame == 0 )
- + if(h->i_frame == view)
- for( int i = 0; i < h->param.i_threads; i++ )
- {
- - x264_ratecontrol_t *t = h->thread[i]->rc;
- + x264_ratecontrol_t *t = h->thread[i]->rc_mvc[view];
- memcpy( t->row_preds, rc->row_preds, sizeof(rc->row_preds) );
- }
- for( int i = 0; i < h->param.i_threads; i++ )
- {
- x264_t *t = h->thread[i];
- - memcpy( t->rc, rc, offsetof(x264_ratecontrol_t, row_pred) );
- - t->rc->row_pred = &t->rc->row_preds[h->sh.i_type];
- + memcpy( t->rc_mvc[view], rc, offsetof(x264_ratecontrol_t, row_pred) );
- + t->rc_mvc[view]->row_pred = &t->rc_mvc[view]->row_preds[h->sh.i_type];
- /* Calculate the planned slice size. */
- if( rc->b_vbv && rc->frame_size_planned )
- {
- int size = 0;
- for( row = t->i_threadslice_start; row < t->i_threadslice_end; row++ )
- size += h->fdec->i_row_satd[row];
- - t->rc->slice_size_planned = predict_size( &rc->pred[h->sh.i_type + (i+1)*5], rc->qpm, size );
- + t->rc_mvc[view]->slice_size_planned = predict_size( &rc->pred[h->sh.i_type + (i+1)*5], rc->qpm, size );
- }
- else
- - t->rc->slice_size_planned = 0;
- + t->rc_mvc[view]->slice_size_planned = 0;
- }
- if( rc->b_vbv && rc->frame_size_planned )
- {
- @@ -2328,25 +2621,26 @@ void x264_threads_distribute_ratecontrol( x264_t *h )
- {
- x264_t *t = h->thread[i];
- float max_frame_error = X264_MAX( 0.05, 1.0 / (t->i_threadslice_end - t->i_threadslice_start) );
- - t->rc->slice_size_planned += 2 * max_frame_error * rc->frame_size_planned;
- + t->rc_mvc[view]->slice_size_planned += 2 * max_frame_error * rc->frame_size_planned;
- }
- x264_threads_normalize_predictors( h );
- }
- for( int i = 0; i < h->param.i_threads; i++ )
- - h->thread[i]->rc->frame_size_estimated = h->thread[i]->rc->slice_size_planned;
- + h->thread[i]->rc_mvc[view]->frame_size_estimated = h->thread[i]->rc_mvc[view]->slice_size_planned;
- }
- }
- void x264_threads_merge_ratecontrol( x264_t *h )
- {
- - x264_ratecontrol_t *rc = h->rc;
- + int view = get_view_id(h);
- + x264_ratecontrol_t *rc = h->rc_mvc[view];
- x264_emms();
- for( int i = 0; i < h->param.i_threads; i++ )
- {
- x264_t *t = h->thread[i];
- - x264_ratecontrol_t *rct = h->thread[i]->rc;
- + x264_ratecontrol_t *rct = h->thread[i]->rc_mvc[view];
- if( h->param.rc.i_vbv_buffer_size )
- {
- int size = 0;
- @@ -2367,7 +2661,8 @@ void x264_thread_sync_ratecontrol( x264_t *cur, x264_t *prev, x264_t *next )
- {
- if( cur != prev )
- {
- -#define COPY(var) memcpy(&cur->rc->var, &prev->rc->var, sizeof(cur->rc->var))
- + for (int view = 0; view < get_view_num(cur); view++) {
- +#define COPY(var) memcpy(&cur->rc_mvc[view]->var, &prev->rc_mvc[view]->var, sizeof(cur->rc_mvc[view]->var))
- /* these vars are updated in x264_ratecontrol_start()
- * so copy them from the context that most recently started (prev)
- * to the context that's about to start (cur). */
- @@ -2391,10 +2686,12 @@ void x264_thread_sync_ratecontrol( x264_t *cur, x264_t *prev, x264_t *next )
- COPY(rate_factor_constant);
- COPY(bitrate);
- #undef COPY
- + }
- }
- if( cur != next )
- {
- -#define COPY(var) next->rc->var = cur->rc->var
- + for (int view = 0; view < get_view_num(cur); view++) {
- +#define COPY(var) next->rc_mvc[view]->var = cur->rc_mvc[view]->var
- /* these vars are updated in x264_ratecontrol_end()
- * so copy them from the context that most recently ended (cur)
- * to the context that's about to end (next) */
- @@ -2408,6 +2705,7 @@ void x264_thread_sync_ratecontrol( x264_t *cur, x264_t *prev, x264_t *next )
- COPY(nrt_first_access_unit);
- COPY(previous_cpb_final_arrival_time);
- #undef COPY
- + }
- }
- //FIXME row_preds[] (not strictly necessary, but would improve prediction)
- /* the rest of the variables are either constant or thread-local */
- @@ -2418,7 +2716,8 @@ static int find_underflow( x264_t *h, double *fills, int *t0, int *t1, int over
- /* find an interval ending on an overflow or underflow (depending on whether
- * we're adding or removing bits), and starting on the earliest frame that
- * can influence the buffer fill of that end frame. */
- - x264_ratecontrol_t *rcc = h->rc;
- + x264_ratecontrol_t *rcc = h->rc_mvc[get_view_id(h)];
- + x264_sps_t * sps = get_view_id(h)==0 ? h->sps : h->subset_sps;
- const double buffer_min = (over ? .1 : .1) * rcc->buffer_size;
- const double buffer_max = .9 * rcc->buffer_size;
- double fill = fills[*t0-1];
- @@ -2426,7 +2725,7 @@ static int find_underflow( x264_t *h, double *fills, int *t0, int *t1, int over
- int start = -1, end = -1;
- for( int i = *t0; i < rcc->num_entries; i++ )
- {
- - fill += (rcc->entry[i].i_cpb_duration * rcc->vbv_max_rate * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale -
- + fill += (rcc->entry[i].i_cpb_duration * rcc->vbv_max_rate * sps->vui.i_num_units_in_tick / sps->vui.i_time_scale -
- qscale2bits( &rcc->entry[i], rcc->entry[i].new_qscale )) * parity;
- fill = x264_clip3f(fill, 0, rcc->buffer_size);
- fills[i] = fill;
- @@ -2446,7 +2745,7 @@ static int find_underflow( x264_t *h, double *fills, int *t0, int *t1, int over
- static int fix_underflow( x264_t *h, int t0, int t1, double adjustment, double qscale_min, double qscale_max)
- {
- - x264_ratecontrol_t *rcc = h->rc;
- + x264_ratecontrol_t *rcc = h->rc_mvc[get_view_id(h)];
- double qscale_orig, qscale_new;
- int adjusted = 0;
- if( t0 > 0 )
- @@ -2465,7 +2764,7 @@ static int fix_underflow( x264_t *h, int t0, int t1, double adjustment, double q
- static double count_expected_bits( x264_t *h )
- {
- - x264_ratecontrol_t *rcc = h->rc;
- + x264_ratecontrol_t *rcc = h->rc_mvc[get_view_id(h)];
- double expected_bits = 0;
- for( int i = 0; i < rcc->num_entries; i++ )
- {
- @@ -2483,7 +2782,7 @@ static int vbv_pass2( x264_t *h, double all_available_bits )
- * last frame in the interval no longer underflows. Recompute intervals and repeat.
- * Then do the converse to put bits back into overflow areas until target size is met */
- - x264_ratecontrol_t *rcc = h->rc;
- + x264_ratecontrol_t *rcc = h->rc_mvc[get_view_id(h)];
- double *fills;
- double expected_bits = 0;
- double adjustment;
- @@ -2542,7 +2841,12 @@ fail:
- static int init_pass2( x264_t *h )
- {
- - x264_ratecontrol_t *rcc = h->rc;
- + int rc_num = get_view_num(h);
- +
- + // unsupported 2pass encode at mvc;
- + if (rc_num > 1) return 0;
- +
- + x264_ratecontrol_t *rcc = h->rc_mvc[0];
- uint64_t all_const_bits = 0;
- double timescale = (double)h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
- double duration = 0;
- diff --git encoder/ratecontrol.h encoder/ratecontrol.h
- index f5aa9a8..eb3e16a 100644
- --- encoder/ratecontrol.h
- +++ encoder/ratecontrol.h
- @@ -47,6 +47,7 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init );
- void x264_adaptive_quant_frame( x264_t *h, x264_frame_t *frame, float *quant_offsets );
- int x264_macroblock_tree_read( x264_t *h, x264_frame_t *frame, float *quant_offsets );
- int x264_reference_build_list_optimal( x264_t *h );
- +int x264_reference_build_list_mvc( x264_t *h );
- void x264_thread_sync_ratecontrol( x264_t *cur, x264_t *prev, x264_t *next );
- void x264_ratecontrol_start( x264_t *, int i_force_qp, int overhead );
- int x264_ratecontrol_slice_type( x264_t *, int i_frame );
- @@ -63,5 +64,6 @@ int x264_weighted_reference_duplicate( x264_t *h, int i_ref, const x264_weight_t
- void x264_threads_distribute_ratecontrol( x264_t *h );
- void x264_threads_merge_ratecontrol( x264_t *h );
- void x264_hrd_fullness( x264_t *h );
- +void x264_hrd_copy_to_dependent( x264_t *h, x264_t *thread_next );
- #endif
- diff --git encoder/set.c encoder/set.c
- index 78f1b56..ffeef3c 100644
- --- encoder/set.c
- +++ encoder/set.c
- @@ -74,6 +74,39 @@ static void scaling_list_write( bs_t *s, x264_pps_t *pps, int idx )
- }
- }
- +static void calculate_timecode_from_frame(int64_t frame, int num, int denom, struct timecode *time)
- +{
- + if (denom == 0) {
- + time->hour = 0;
- + time->minute = 0;
- + time->second = 0;
- + time->frame = 0;
- + return;
- + }
- +
- + if (denom == 1001 && time->b_drop) {
- + int32_t minute10_frame_count = 10 * 60 * num / 1000 - 18;
- + int32_t minute_frame_count = 60 * num / 1000 - 2;
- + int32_t ten_min_count = frame / minute10_frame_count;
- + int32_t remain = frame - (int64_t)minute10_frame_count * ten_min_count;
- + int32_t one_min_count = 0;
- + if (remain > 2) {
- + one_min_count = (remain - 2) / minute_frame_count;
- + }
- + frame += ten_min_count * 18 + one_min_count * 2;
- + }
- + if (denom == 1001) denom = 1000;
- +
- + int32_t fps = num/denom;
- + time->frame = frame % fps;
- + frame /= fps;
- + time->second = frame % 60;
- + frame /= 60;
- + time->minute = frame % 60;
- + frame /= 60;
- + time->hour = frame % 24;
- +}
- +
- void x264_sei_write( bs_t *s, uint8_t *payload, int payload_size, int payload_type )
- {
- int i;
- @@ -106,6 +139,8 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- sps->i_profile_idc = PROFILE_HIGH444_PREDICTIVE;
- else if( BIT_DEPTH > 8 )
- sps->i_profile_idc = PROFILE_HIGH10;
- + else if (( param->b_mvc ) && (i_id != 0))
- + sps->i_profile_idc = PROFILE_STEREO_HIGH;
- else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT )
- sps->i_profile_idc = PROFILE_HIGH;
- else if( param->b_cabac || param->i_bframe > 0 || param->b_interlaced || param->b_fake_interlaced || param->analyse.i_weighted_pred > 0 )
- @@ -146,14 +181,18 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- /* number of refs + current frame */
- int max_frame_num = sps->vui.i_max_dec_frame_buffering * (!!param->i_bframe_pyramid+1) + 1;
- +
- /* Intra refresh cannot write a recovery time greater than max frame num-1 */
- if( param->b_intra_refresh )
- {
- int time_to_recovery = X264_MIN( sps->i_mb_width - 1, param->i_keyint_max ) + param->i_bframe - 1;
- max_frame_num = X264_MAX( max_frame_num, time_to_recovery+1 );
- }
- + if (param->b_mvc) max_frame_num *= 2;
- +
- + // for MVC
- + sps->i_log2_max_frame_num = param->b_mvc ? 8 : 4;
- - sps->i_log2_max_frame_num = 4;
- while( (1 << sps->i_log2_max_frame_num) <= max_frame_num )
- sps->i_log2_max_frame_num++;
- @@ -161,7 +200,9 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- if( sps->i_poc_type == 0 )
- {
- int max_delta_poc = (param->i_bframe + 2) * (!!param->i_bframe_pyramid + 1) * 2;
- - sps->i_log2_max_poc_lsb = 4;
- +
- + sps->i_log2_max_poc_lsb = param->b_mvc ? 8 : 4;
- +
- while( (1 << sps->i_log2_max_poc_lsb) <= max_delta_poc * 2 )
- sps->i_log2_max_poc_lsb++;
- }
- @@ -254,7 +295,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable
- - sps->vui.b_bitstream_restriction = 1;
- + sps->vui.b_bitstream_restriction = 0;
- if( sps->vui.b_bitstream_restriction )
- {
- sps->vui.b_motion_vectors_over_pic_boundaries = 1;
- @@ -428,6 +469,250 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps )
- bs_flush( s );
- }
- +void x264_subset_sps_write( bs_t *s, x264_sps_t *sps )
- +{
- + bs_realign( s );
- + bs_write( s, 8, sps->i_profile_idc );
- + bs_write1( s, sps->b_constraint_set0 );
- + bs_write1( s, sps->b_constraint_set1 );
- + bs_write1( s, sps->b_constraint_set2 );
- + bs_write1( s, sps->b_constraint_set3 );
- +
- + bs_write( s, 4, 0 ); /* reserved */
- +
- + bs_write( s, 8, sps->i_level_idc );
- +
- + bs_write_ue( s, sps->i_id );
- +
- + if( sps->i_profile_idc >= PROFILE_HIGH )
- + {
- + bs_write_ue( s, 1 ); // chroma_format_idc = 4:2:0
- + bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_luma_minus8
- + bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_chroma_minus8
- + bs_write1( s, sps->b_qpprime_y_zero_transform_bypass );
- + bs_write1( s, 0 ); // seq_scaling_matrix_present_flag
- + }
- +
- + bs_write_ue( s, sps->i_log2_max_frame_num - 4 );
- + bs_write_ue( s, sps->i_poc_type );
- + if( sps->i_poc_type == 0 )
- + {
- + bs_write_ue( s, sps->i_log2_max_poc_lsb - 4 );
- + }
- + else if( sps->i_poc_type == 1 )
- + {
- + bs_write1( s, sps->b_delta_pic_order_always_zero );
- + bs_write_se( s, sps->i_offset_for_non_ref_pic );
- + bs_write_se( s, sps->i_offset_for_top_to_bottom_field );
- + bs_write_ue( s, sps->i_num_ref_frames_in_poc_cycle );
- +
- + for( int i = 0; i < sps->i_num_ref_frames_in_poc_cycle; i++ )
- + bs_write_se( s, sps->i_offset_for_ref_frame[i] );
- + }
- + bs_write_ue( s, sps->i_num_ref_frames );
- + bs_write1( s, sps->b_gaps_in_frame_num_value_allowed );
- + bs_write_ue( s, sps->i_mb_width - 1 );
- + bs_write_ue( s, (sps->i_mb_height >> !sps->b_frame_mbs_only) - 1);
- + bs_write1( s, sps->b_frame_mbs_only );
- + if( !sps->b_frame_mbs_only )
- + bs_write1( s, sps->b_mb_adaptive_frame_field );
- + bs_write1( s, sps->b_direct8x8_inference );
- +
- + bs_write1( s, sps->b_crop );
- + if( sps->b_crop )
- + {
- + bs_write_ue( s, sps->crop.i_left / 2 );
- + bs_write_ue( s, sps->crop.i_right / 2 );
- + bs_write_ue( s, sps->crop.i_top / 2 );
- + bs_write_ue( s, sps->crop.i_bottom / 2 );
- + }
- +
- + bs_write1( s, sps->b_vui );
- + if( sps->b_vui )
- + {
- + bs_write1( s, sps->vui.b_aspect_ratio_info_present );
- + if( sps->vui.b_aspect_ratio_info_present )
- + {
- + int i;
- + static const struct { uint8_t w, h, sar; } sar[] =
- + {
- + // aspect_ratio_idc = 0 -> unspecified
- + { 1, 1, 1 }, { 12, 11, 2 }, { 10, 11, 3 }, { 16, 11, 4 },
- + { 40, 33, 5 }, { 24, 11, 6 }, { 20, 11, 7 }, { 32, 11, 8 },
- + { 80, 33, 9 }, { 18, 11, 10}, { 15, 11, 11}, { 64, 33, 12},
- + {160, 99, 13}, { 4, 3, 14}, { 3, 2, 15}, { 2, 1, 16},
- + // aspect_ratio_idc = [17..254] -> reserved
- + { 0, 0, 255 }
- + };
- + for( i = 0; sar[i].sar != 255; i++ )
- + {
- + if( sar[i].w == sps->vui.i_sar_width &&
- + sar[i].h == sps->vui.i_sar_height )
- + break;
- + }
- + bs_write( s, 8, sar[i].sar );
- + if( sar[i].sar == 255 ) /* aspect_ratio_idc (extended) */
- + {
- + bs_write( s, 16, sps->vui.i_sar_width );
- + bs_write( s, 16, sps->vui.i_sar_height );
- + }
- + }
- +
- + bs_write1( s, sps->vui.b_overscan_info_present );
- + if( sps->vui.b_overscan_info_present )
- + bs_write1( s, sps->vui.b_overscan_info );
- +
- + bs_write1( s, sps->vui.b_signal_type_present );
- + if( sps->vui.b_signal_type_present )
- + {
- + bs_write( s, 3, sps->vui.i_vidformat );
- + bs_write1( s, sps->vui.b_fullrange );
- + bs_write1( s, sps->vui.b_color_description_present );
- + if( sps->vui.b_color_description_present )
- + {
- + bs_write( s, 8, sps->vui.i_colorprim );
- + bs_write( s, 8, sps->vui.i_transfer );
- + bs_write( s, 8, sps->vui.i_colmatrix );
- + }
- + }
- +
- + bs_write1( s, sps->vui.b_chroma_loc_info_present );
- + if( sps->vui.b_chroma_loc_info_present )
- + {
- + bs_write_ue( s, sps->vui.i_chroma_loc_top );
- + bs_write_ue( s, sps->vui.i_chroma_loc_bottom );
- + }
- +
- + bs_write1( s, sps->vui.b_timing_info_present );
- + if( sps->vui.b_timing_info_present )
- + {
- + bs_write32( s, sps->vui.i_num_units_in_tick );
- + bs_write32( s, sps->vui.i_time_scale );
- + bs_write1( s, sps->vui.b_fixed_frame_rate );
- + }
- +
- + bs_write1( s, sps->vui.b_nal_hrd_parameters_present );
- + if( sps->vui.b_nal_hrd_parameters_present )
- + {
- + // bs_write_ue( s, sps->vui.hrd.i_cpb_cnt - 1 );
- + bs_write_ue( s, 0 );
- + bs_write( s, 4, sps->vui.hrd.i_bit_rate_scale );
- + bs_write( s, 4, sps->vui.hrd.i_cpb_size_scale );
- +
- + bs_write_ue( s, sps->vui.hrd.i_bit_rate_value - 1 );
- + bs_write_ue( s, sps->vui.hrd.i_cpb_size_value - 1 );
- +
- + bs_write1( s, sps->vui.hrd.b_cbr_hrd );
- +
- + bs_write( s, 5, sps->vui.hrd.i_initial_cpb_removal_delay_length - 1 );
- + bs_write( s, 5, sps->vui.hrd.i_cpb_removal_delay_length - 1 );
- + bs_write( s, 5, sps->vui.hrd.i_dpb_output_delay_length - 1 );
- + bs_write( s, 5, sps->vui.hrd.i_time_offset_length );
- + }
- +
- + bs_write1( s, sps->vui.b_vcl_hrd_parameters_present );
- +
- + if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present )
- + bs_write1( s, 0 ); /* low_delay_hrd_flag */
- +
- + bs_write1( s, sps->vui.b_pic_struct_present );
- + bs_write1( s, sps->vui.b_bitstream_restriction );
- + if( sps->vui.b_bitstream_restriction )
- + {
- + bs_write1( s, sps->vui.b_motion_vectors_over_pic_boundaries );
- + bs_write_ue( s, sps->vui.i_max_bytes_per_pic_denom );
- + bs_write_ue( s, sps->vui.i_max_bits_per_mb_denom );
- + bs_write_ue( s, sps->vui.i_log2_max_mv_length_horizontal );
- + bs_write_ue( s, sps->vui.i_log2_max_mv_length_vertical );
- + bs_write_ue( s, sps->vui.i_num_reorder_frames );
- + bs_write_ue( s, sps->vui.i_max_dec_frame_buffering );
- + }
- + }
- +
- + bs_write1( s, 1 ); /* bit_equal_to_one f(1) */
- +
- + // seq_parameter_set_mvc_extension()
- + int num_views_minus1 = 1;
- +
- + int num_anchor_refs_l0 = 1;
- + int num_anchor_refs_l1 = 0;
- + int anchor_ref_l0 = 0;
- +
- + int num_non_anchor_refs_l0 = 1;
- + int num_non_anchor_refs_l1 = 0;
- +
- + int non_anchor_ref_l0 = 0;
- +
- + bs_write_ue( s, num_views_minus1 );
- +
- + // view_id[i]
- + for (int i = 0; i <= num_views_minus1; i++) {
- + bs_write_ue( s, i );
- + }
- +
- + for (int i = 1; i <= num_views_minus1; i++) {
- + // num_anchor_refs_l0
- + bs_write_ue( s, num_anchor_refs_l0 );
- + for ( int j = 0; j < num_anchor_refs_l0; j++) {
- + // anchor_ref_l0
- + bs_write_ue( s, anchor_ref_l0 );
- + }
- +
- + // num_anchor_refs_l1
- + bs_write_ue( s, num_anchor_refs_l1 );
- +
- + // num_non_anchor_refs_l0
- + bs_write_ue( s, num_non_anchor_refs_l0 );
- +
- + for ( int j = 0; j < num_non_anchor_refs_l0; j++) {
- + // non_anchor_ref_l0
- + bs_write_ue( s, non_anchor_ref_l0 );
- + }
- +
- + bs_write_ue( s, num_non_anchor_refs_l1 );
- + }
- +
- + int num_level_values_signalled_minus1 = 0;
- + bs_write_ue( s, num_level_values_signalled_minus1 );
- +
- + int applicable_op_temporal_id[1][2] = {{0, 0}};
- + int applicable_op_num_target_views_minus1[1][2] = {{0, 1}};
- +
- +
- + for (int i = 0; i <= num_level_values_signalled_minus1; i++) {
- + bs_write( s, 8, sps->i_level_idc );
- + int num_applicable_ops_minus1 = 1;
- + bs_write_ue( s, num_applicable_ops_minus1 );
- +
- + for ( int j = 0; j <= num_applicable_ops_minus1; j++) {
- + bs_write( s, 3, applicable_op_temporal_id[i][j] );
- + bs_write_ue( s, applicable_op_num_target_views_minus1[i][j] );
- +
- + // for ( int k = 0; k <= applicable_op_num_target_views_minus1[i][j]; k++) {
- + if (applicable_op_num_target_views_minus1[i][j] == 0) {
- + bs_write_ue( s, 0 );
- + } else {
- + bs_write_ue( s, 0 );
- + bs_write_ue( s, 1 );
- + }
- + // }
- + // applicable_op_num_views_minus1
- + bs_write_ue( s, j );
- + }
- + }
- +
- + // mvc_vui_parameters_present_flag
- + bs_write1( s, 0 );
- +
- + // additional_extension2_flag
- + bs_write1( s, 0 );
- +
- + bs_rbsp_trailing( s );
- + bs_flush( s );
- +}
- +
- +
- +
- void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps )
- {
- pps->i_id = i_id;
- @@ -562,7 +847,7 @@ int x264_sei_version_write( x264_t *h, bs_t *s )
- 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7,
- 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee, 0xef
- };
- - char *opts = x264_param2string( &h->param, 0 );
- + char *opts = x264_param2string( &h->param, 0, 0);
- char *payload;
- int length;
- @@ -588,7 +873,7 @@ fail:
- void x264_sei_buffering_period_write( x264_t *h, bs_t *s )
- {
- - x264_sps_t *sps = h->sps;
- + x264_sps_t *sps = h->b_dependent ? h->subset_sps : h->sps;
- bs_t q;
- uint8_t tmp_buf[100];
- bs_init( &q, tmp_buf, 100 );
- @@ -596,6 +881,10 @@ void x264_sei_buffering_period_write( x264_t *h, bs_t *s )
- bs_realign( &q );
- bs_write_ue( &q, sps->i_id );
- +// printf("[%4d](%s): sps = %d, cpb_length = %d, cpb_delay = %d, cpb_offset = %d h=%p \n",
- +// h->fenc->i_frame, h->b_dependent ? "d" : "m", sps->i_id, sps->vui.hrd.i_initial_cpb_removal_delay_length,
- +// h->initial_cpb_removal_delay, h->initial_cpb_removal_delay_offset, h);
- +
- if( sps->vui.b_nal_hrd_parameters_present )
- {
- bs_write( &q, sps->vui.hrd.i_initial_cpb_removal_delay_length, h->initial_cpb_removal_delay );
- @@ -610,7 +899,12 @@ void x264_sei_buffering_period_write( x264_t *h, bs_t *s )
- void x264_sei_pic_timing_write( x264_t *h, bs_t *s )
- {
- - x264_sps_t *sps = h->sps;
- + x264_sps_t *sps = h->b_dependent ? h->subset_sps : h->sps;
- +
- + struct timecode time;
- + time.b_drop = h->param.timecode_offset.b_drop;
- + calculate_timecode_from_frame((h->i_frame >> (h->param.b_mvc ? 1 : 0)) + h->offset_frame, h->param.i_fps_num, h->param.i_fps_den, &time);
- +
- bs_t q;
- uint8_t tmp_buf[100];
- bs_init( &q, tmp_buf, 100 );
- @@ -619,18 +913,61 @@ void x264_sei_pic_timing_write( x264_t *h, bs_t *s )
- if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present )
- {
- - bs_write( &q, sps->vui.hrd.i_cpb_removal_delay_length, h->fenc->i_cpb_delay - h->i_cpb_delay_pir_offset );
- + bs_write( &q, sps->vui.hrd.i_cpb_removal_delay_length, h->fenc->i_cpb_delay - (h->b_dependent ? h->i_cpb_delay_pir_offset_dep : h->i_cpb_delay_pir_offset) );
- bs_write( &q, sps->vui.hrd.i_dpb_output_delay_length, h->fenc->i_dpb_output_delay );
- +
- +// printf("[%4d](%s): cpb=%4lld, dpb=%4lld\n",
- +// h->fenc->i_frame, h->b_dependent ? "d" : "m",
- +// h->fenc->i_cpb_delay - (h->b_dependent ? h->i_cpb_delay_pir_offset_dep : h->i_cpb_delay_pir_offset),
- +// h->fenc->i_dpb_output_delay);
- }
- if( sps->vui.b_pic_struct_present )
- {
- - bs_write( &q, 4, h->fenc->i_pic_struct-1 ); // We use index 0 for "Auto"
- + int i_pic_struct = h->fenc->i_pic_struct;
- + bs_write( &q, 4, i_pic_struct-1 ); // We use index 0 for "Auto"
- // These clock timestamps are not standardised so we don't set them
- // They could be time of origin, capture or alternative ideal display
- + /*
- for( int i = 0; i < num_clock_ts[h->fenc->i_pic_struct]; i++ )
- bs_write1( &q, 0 ); // clock_timestamp_flag
- + */
- +
- + int numClockTS = i_pic_struct < 4 ? 1 : i_pic_struct < 6 ? 2 : i_pic_struct < 8 ? 3 : i_pic_struct == 8 ? 2 : 3;
- +
- + for (int clocks=0; clocks<numClockTS; clocks++) {
- + // for MVC
- + bs_write1( &q, 1 ); // clock_timestamp_flag
- + // ct_type
- + bs_write(&q, 2, h->param.b_interlaced ? 1 : 0);
- + // nuit_field_based_flag
- + bs_write1(&q, 1);
- + // counting_type
- + bs_write(&q, 5, time.b_drop ? 4 : 1);
- + // full_timestamp_flag
- + bs_write1(&q, clocks == 0 ? 1 : 0);
- + // discontinuity_flag
- + bs_write1(&q, 0);
- + // cnt_dropped_flag
- + bs_write1(&q, time.b_drop ? 4 : 0);
- + // nframes
- + bs_write(&q, 8, time.frame);
- + if (clocks == 0) {
- + // seconds_value
- + bs_write(&q, 6, time.second);
- + // minutes_value
- + bs_write(&q, 6, time.minute);
- + // hours_value
- + bs_write(&q, 5, time.hour);
- + } else {
- + // seconds_flag = false
- + bs_write(&q, 1, 0);
- + }
- + // time_offset
- + // sps->vui.hrd.i_time_offset_length = 24
- + bs_write(&q, sps->vui.hrd.i_time_offset_length, 0);
- + }
- }
- bs_align_10( &q );
- @@ -669,7 +1006,7 @@ void x264_sei_frame_packing_write( x264_t *h, bs_t *s )
- bs_write( &q, 4, 0 ); // frame1_grid_position_y
- }
- bs_write( &q, 8, 0 ); // frame_packing_arrangement_reserved_byte
- - bs_write_ue( &q, 1 ); // frame_packing_arrangement_repetition_period
- + bs_write_ue( &q, 0 ); // frame_packing_arrangement_repetition_period
- bs_write1( &q, 0 ); // frame_packing_arrangement_extension_flag
- bs_align_10( &q );
- diff --git encoder/set.h encoder/set.h
- index 7fcca13..fc54c85 100644
- --- encoder/set.h
- +++ encoder/set.h
- @@ -29,6 +29,8 @@
- void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param );
- void x264_sps_write( bs_t *s, x264_sps_t *sps );
- +void x264_subset_sps_write( bs_t *s, x264_sps_t *sps );
- +
- void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps );
- void x264_pps_write( bs_t *s, x264_pps_t *pps );
- void x264_sei_recovery_point_write( x264_t *h, bs_t *s, int recovery_frame_cnt );
- diff --git encoder/slicetype.c encoder/slicetype.c
- index 1e0c80a..1c83e32 100644
- --- encoder/slicetype.c
- +++ encoder/slicetype.c
- @@ -25,6 +25,8 @@
- * For more information, contact us at licensing@x264.com.
- *****************************************************************************/
- +//#define __DEBUG
- +
- #include "common/common.h"
- #include "macroblock.h"
- #include "me.h"
- @@ -70,9 +72,19 @@ static void x264_weight_get_h264( int weight_nonh264, int offset, x264_weight_t
- static NOINLINE pixel *x264_weight_cost_init_luma( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, pixel *dest )
- {
- - int ref0_distance = fenc->i_frame - ref->i_frame - 1;
- + int ref0_distance;
- +
- + int b_mvc = h->param.b_mvc;
- +
- + ref0_distance = fenc->i_frame / (b_mvc ? 2 : 1) - ref->i_frame / (b_mvc ? 2 : 1) - 1;
- +
- /* Note: this will never run during lookahead as weights_analyse is only called if no
- * motion search has been done. */
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[weight_cost_init_luma] ref0_distance %d (enc=%d, ref=%d)\n", ref0_distance, fenc->i_frame, ref->i_frame);
- +#endif
- +
- if( fenc->lowres_mvs[0][ref0_distance][0][0] != 0x7FFF )
- {
- int i_stride = fenc->i_stride_lowres;
- @@ -92,6 +104,7 @@ static NOINLINE pixel *x264_weight_cost_init_luma( x264_t *h, x264_frame_t *fenc
- x264_emms();
- return dest;
- }
- +
- x264_emms();
- return ref->lowres[0];
- }
- @@ -105,7 +118,8 @@ static NOINLINE pixel *x264_weight_cost_init_luma( x264_t *h, x264_frame_t *fenc
- static NOINLINE void x264_weight_cost_init_chroma( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, pixel *dstu, pixel *dstv )
- {
- - int ref0_distance = fenc->i_frame - ref->i_frame - 1;
- + int b_mvc = h->param.b_mvc;
- + int ref0_distance = (fenc->i_frame / (b_mvc ? 2 : 1)) - (ref->i_frame / (b_mvc ? 2 : 1)) - 1;
- int i_stride = fenc->i_stride[1];
- int i_offset = i_stride / 2;
- int i_lines = fenc->i_lines[1];
- @@ -219,13 +233,20 @@ static NOINLINE unsigned int x264_weight_cost_chroma( x264_t *h, x264_frame_t *f
- void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int b_lookahead )
- {
- - int i_delta_index = fenc->i_frame - ref->i_frame - 1;
- + int b_mvc = h->param.b_mvc;
- + int i_delta_index = (fenc->i_frame / (b_mvc ? 2 : 1)) - (ref->i_frame / (b_mvc ? 2 : 1)) - 1;
- +
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[weights_analyse] i_delta_index fenc->i_frame %d ref->i_frame %d - 1\n", fenc->i_frame, ref->i_frame);
- +#endif
- +
- /* epsilon is chosen to require at least a numerator of 127 (with denominator = 128) */
- const float epsilon = 1.f/128.f;
- x264_weight_t *weights = fenc->weight[0];
- SET_WEIGHT( weights[0], 0, 1, 0, 0 );
- SET_WEIGHT( weights[1], 0, 1, 0, 0 );
- SET_WEIGHT( weights[2], 0, 1, 0, 0 );
- +
- /* Don't check chroma in lookahead, or if there wasn't a luma weight. */
- for( int plane = 0; plane <= 2 && !( plane && ( !weights[0].weightfn || b_lookahead ) ); plane++ )
- {
- @@ -271,10 +292,17 @@ void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int
- {
- x264_mb_analysis_t a;
- x264_lowres_context_init( h, &a );
- - x264_slicetype_frame_cost( h, &a, &fenc, 0, 0, 0, 0 );
- +#ifdef __DEBUG
- + x264_log(h, X264_LOG_INFO, "[weights_analyse] slicetype_frame_cost is called by weights analyse\n");
- +#endif
- + x264_slicetype_frame_cost( h, &a, &fenc, 0, 0, 0, 0 );
- }
- + // x264_log(h, X264_LOG_INFO, "weights analyse 0\n");
- +
- mcbuf = x264_weight_cost_init_luma( h, fenc, ref, h->mb.p_weight_buf[0] );
- + // x264_log(h, X264_LOG_INFO, "weights analyse 0\n");
- origscore = minscore = x264_weight_cost_luma( h, fenc, mcbuf, NULL );
- + // x264_log(h, X264_LOG_INFO, "weights analyse 0\n");
- }
- else
- {
- @@ -290,6 +318,9 @@ void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int
- if( !minscore )
- continue;
- + // x264_log(h, X264_LOG_INFO, "weights analyse 1\n");
- +
- +
- // This gives a slight improvement due to rounding errors but only tests one offset in lookahead.
- // Currently only searches within +/- 1 of the best offset found so far.
- // TODO: Try other offsets/multipliers/combinations thereof?
- @@ -312,6 +343,8 @@ void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int
- }
- x264_emms();
- + // x264_log(h, X264_LOG_INFO, "weights analyse 2\n");
- +
- /* FIXME: More analysis can be done here on SAD vs. SATD termination. */
- /* 0.2% termination derived experimentally to avoid weird weights in frames that are mostly intra. */
- if( !found || (minscale == 1 << mindenom && minoff == 0) || (float)minscore / origscore > 0.998f )
- @@ -326,6 +359,7 @@ void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int
- fenc->f_weighted_cost_delta[i_delta_index] = (float)minscore / origscore;
- }
- + // x264_log(h, X264_LOG_INFO, "weights analyse 3\n");
- //FIXME, what is the correct way to deal with this?
- if( weights[1].weightfn && weights[2].weightfn && weights[1].i_denom != weights[2].i_denom )
- {
- @@ -339,6 +373,7 @@ void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int
- }
- }
- + // x264_log(h, X264_LOG_INFO, "weights analyse 4\n");
- if( weights[0].weightfn && b_lookahead )
- {
- //scale lowres in lookahead for slicetype_frame_cost
- @@ -350,6 +385,11 @@ void x264_weights_analyse( x264_t *h, x264_frame_t *fenc, x264_frame_t *ref, int
- width, height, &weights[0] );
- fenc->weighted[0] = h->mb.p_weight_buf[0] + PADH + ref->i_stride_lowres * PADV;
- }
- +
- + // x264_log ( h, X264_LOG_INFO, "weight analyse done \n");
- +
- +
- +
- }
- static void x264_slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,
- @@ -638,10 +678,18 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
- * If we have tried this frame as P, then we have also tried
- * the preceding frames as B. (is this still true?) */
- /* Also check that we already calculated the row SATDs for the current frame. */
- - if( frames[b]->i_cost_est[b-p0][p1-b] >= 0 && (!h->param.rc.i_vbv_buffer_size || frames[b]->i_row_satds[b-p0][p1-b][0] != -1) )
- + if( frames[b]->i_cost_est[b-p0][p1-b] >= 0 && (!h->param.rc.i_vbv_buffer_size || frames[b]->i_row_satds[b-p0][p1-b][0] != -1) ) {
- i_score = frames[b]->i_cost_est[b-p0][p1-b];
- +
- +#ifdef __DEBUG
- + x264_log( h, X264_LOG_INFO, "if 1 p0 %d p1 %d b %d b_intra %d\n", p0, p1, b, b_intra_penalty);
- +#endif
- + }
- else
- {
- +#ifdef __DEBUG
- + x264_log( h, X264_LOG_INFO, "if 2 p0 %d p1 %d b %d b_intra %d\n", p0, p1, b, b_intra_penalty);
- +#endif
- int dist_scale_factor = 128;
- int *row_satd = frames[b]->i_row_satds[b-p0][p1-b];
- int *row_satd_intra = frames[b]->i_row_satds[0][0];
- @@ -654,6 +702,10 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
- if( h->param.analyse.i_weighted_pred && b == p1 )
- {
- x264_emms();
- +
- + // x264_log( h, X264_LOG_INFO, "param.analyse.i_weighted_pred %d\n", h->param.analyse.i_weighted_pred);
- +
- + //x264_log( h, X264_LOG_INFO, "[slicetype frame cost] frames[%d] i_frame = %d to weights_analyse\n", b, frames[b]->i_frame);
- x264_weights_analyse( h, frames[b], frames[p0], 1 );
- w = frames[b]->weight[0];
- }
- @@ -679,6 +731,7 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
- /* The edge mbs seem to reduce the predictive quality of the
- * whole frame's score, but are needed for a spatial distribution. */
- +
- if( h->param.rc.b_mb_tree || h->param.rc.i_vbv_buffer_size ||
- h->mb.i_mb_width <= 2 || h->mb.i_mb_height <= 2 )
- {
- @@ -714,6 +767,8 @@ static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
- int nmb = NUM_MBS;
- i_score += i_score * frames[b]->i_intra_mbs[b-p0] / (nmb * 8);
- }
- +
- + // x264_log( h, X264_LOG_INFO, "return i_score %d\n", i_score);
- return i_score;
- }
- @@ -878,8 +933,10 @@ static void x264_macroblock_tree( x264_t *h, x264_mb_analysis_t *a, x264_frame_t
- int i = num_frames;
- - if( b_intra )
- + if( b_intra ) {
- + // x264_log( h, X264_LOG_INFO, "called macroblock_tree\n");
- x264_slicetype_frame_cost( h, a, frames, 0, 0, 0, 0 );
- + }
- while( i > 0 && frames[i]->i_type == X264_TYPE_B )
- i--;
- @@ -913,12 +970,15 @@ static void x264_macroblock_tree( x264_t *h, x264_mb_analysis_t *a, x264_frame_t
- cur_nonb--;
- if( cur_nonb < idx )
- break;
- +
- + // x264_log( h, X264_LOG_INFO, "called macroblock_tree\n");
- x264_slicetype_frame_cost( h, a, frames, cur_nonb, last_nonb, last_nonb, 0 );
- memset( frames[cur_nonb]->i_propagate_cost, 0, h->mb.i_mb_count * sizeof(uint16_t) );
- bframes = last_nonb - cur_nonb - 1;
- if( h->param.i_bframe_pyramid && bframes > 1 )
- {
- int middle = (bframes + 1)/2 + cur_nonb;
- + // x264_log( h, X264_LOG_INFO, "called macroblock_tree\n");
- x264_slicetype_frame_cost( h, a, frames, cur_nonb, last_nonb, middle, 0 );
- memset( frames[middle]->i_propagate_cost, 0, h->mb.i_mb_count * sizeof(uint16_t) );
- while( i > cur_nonb )
- @@ -927,6 +987,7 @@ static void x264_macroblock_tree( x264_t *h, x264_mb_analysis_t *a, x264_frame_t
- int p1 = i < middle ? middle : last_nonb;
- if( i != middle )
- {
- + // x264_log( h, X264_LOG_INFO, "called macroblock_tree\n");
- x264_slicetype_frame_cost( h, a, frames, p0, p1, i, 0 );
- x264_macroblock_tree_propagate( h, frames, average_duration, p0, p1, i, 0 );
- }
- @@ -938,6 +999,7 @@ static void x264_macroblock_tree( x264_t *h, x264_mb_analysis_t *a, x264_frame_t
- {
- while( i > cur_nonb )
- {
- + // x264_log( h, X264_LOG_INFO, "called macroblock_tree\n");
- x264_slicetype_frame_cost( h, a, frames, cur_nonb, last_nonb, i, 0 );
- x264_macroblock_tree_propagate( h, frames, average_duration, cur_nonb, last_nonb, i, 0 );
- i--;
- @@ -960,13 +1022,16 @@ static void x264_macroblock_tree( x264_t *h, x264_mb_analysis_t *a, x264_frame_t
- static int x264_vbv_frame_cost( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, int p0, int p1, int b )
- {
- +
- + // x264_log( h, X264_LOG_INFO, "called vbv_frame_cost\n");
- int cost = x264_slicetype_frame_cost( h, a, frames, p0, p1, b, 0 );
- if( h->param.rc.i_aq_mode )
- {
- - if( h->param.rc.b_mb_tree )
- + if( h->param.rc.b_mb_tree ) {
- return x264_slicetype_frame_cost_recalculate( h, frames, p0, p1, b );
- - else
- + } else {
- return frames[b]->i_cost_est_aq[b-p0][p1-b];
- + }
- }
- return cost;
- }
- @@ -977,8 +1042,12 @@ static void x264_calculate_durations( x264_t *h, x264_frame_t *cur_frame, x264_f
- cur_frame->i_dpb_output_delay = cur_frame->i_field_cnt - *i_coded_fields;
- // add a correction term for frame reordering
- - cur_frame->i_dpb_output_delay += h->sps->vui.i_num_reorder_frames*2;
- + cur_frame->i_dpb_output_delay += cur_frame->i_frame & 1 ? h->subset_sps->vui.i_num_reorder_frames*2 : h->sps->vui.i_num_reorder_frames*2;
- +// printf("[%4d]: dpb_output_delay = %lld, field_cnt = %lld, coded_fields = %lld, num_reorder_frames*2 = %lld \n",
- +// cur_frame->i_frame, cur_frame->i_dpb_output_delay, cur_frame->i_field_cnt, *i_coded_fields,
- +// cur_frame->i_frame & 1 ? h->subset_sps->vui.i_num_reorder_frames*2 : h->sps->vui.i_num_reorder_frames*2);
- +
- // fix possible negative dpb_output_delay because of pulldown changes and reordering
- if( cur_frame->i_dpb_output_delay < 0 )
- {
- @@ -1073,6 +1142,8 @@ static int x264_slicetype_path_cost( x264_t *h, x264_mb_analysis_t *a, x264_fram
- next_p++;
- /* Add the cost of the P-frame found above */
- + // x264_log( h, X264_LOG_INFO, "called slicetype_path_cost\n");
- +
- cost += x264_slicetype_frame_cost( h, a, frames, cur_p, next_p, next_p, 0 );
- /* Early terminate if the cost we have found is larger than the best path cost so far */
- if( cost > threshold )
- @@ -1081,6 +1152,7 @@ static int x264_slicetype_path_cost( x264_t *h, x264_mb_analysis_t *a, x264_fram
- if( h->param.i_bframe_pyramid && next_p - cur_p > 2 )
- {
- int middle = cur_p + (next_p - cur_p)/2;
- + // x264_log( h, X264_LOG_INFO, "called slicetype_path_cost\n");
- cost += x264_slicetype_frame_cost( h, a, frames, cur_p, next_p, middle, 0 );
- for( int next_b = loc; next_b < middle && cost < threshold; next_b++ )
- cost += x264_slicetype_frame_cost( h, a, frames, cur_p, middle, next_b, 0 );
- @@ -1088,8 +1160,10 @@ static int x264_slicetype_path_cost( x264_t *h, x264_mb_analysis_t *a, x264_fram
- cost += x264_slicetype_frame_cost( h, a, frames, middle, next_p, next_b, 0 );
- }
- else
- - for( int next_b = loc; next_b < next_p && cost < threshold; next_b++ )
- + for( int next_b = loc; next_b < next_p && cost < threshold; next_b++ ) {
- + // x264_log( h, X264_LOG_INFO, "called slicetype_path_cost\n");
- cost += x264_slicetype_frame_cost( h, a, frames, cur_p, next_p, next_b, 0 );
- + }
- loc = next_p + 1;
- cur_p = next_p;
- @@ -1132,18 +1206,20 @@ static void x264_slicetype_path( x264_t *h, x264_mb_analysis_t *a, x264_frame_t
- static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, int p0, int p1, int real_scenecut )
- {
- + int b_mvc = h->param.b_mvc;
- x264_frame_t *frame = frames[p1];
- /* Don't do scenecuts on the right view of a frame-packed video. */
- - if( real_scenecut && h->param.i_frame_packing == 5 && (frame->i_frame&1) )
- + if( real_scenecut && h->param.i_frame_packing == 5 && (frame->i_frame &1) )
- return 0;
- + // x264_log( h, X264_LOG_INFO, "called scenecut_internal\n");
- x264_slicetype_frame_cost( h, a, frames, p0, p1, p1, 0 );
- int icost = frame->i_cost_est[0][0];
- int pcost = frame->i_cost_est[p1-p0][0];
- float f_bias;
- - int i_gop_size = frame->i_frame - h->lookahead->i_last_keyframe;
- + int i_gop_size = (frame->i_frame / (b_mvc ? 2 : 1)) - h->lookahead->i_last_keyframe;
- float f_thresh_max = h->param.i_scenecut_threshold / 100.0;
- /* magic numbers pulled out of thin air */
- float f_thresh_min = f_thresh_max * 0.25;
- @@ -1219,35 +1295,58 @@ static int scenecut( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, in
- void x264_slicetype_analyse( x264_t *h, int keyframe )
- {
- x264_mb_analysis_t a;
- + x264_mb_analysis_t a_dep;
- x264_frame_t *frames[X264_LOOKAHEAD_MAX+3] = { NULL, };
- + x264_frame_t *frames_dep[X264_LOOKAHEAD_MAX+3] = { NULL, };
- int num_frames, orig_num_frames, keyint_limit, framecnt;
- int i_mb_count = NUM_MBS;
- int cost1p0, cost2p0, cost1b1, cost2p1;
- int i_max_search = X264_MIN( h->lookahead->next.i_size, X264_LOOKAHEAD_MAX );
- int vbv_lookahead = h->param.rc.i_vbv_buffer_size && h->param.rc.i_lookahead;
- +
- + int b_mvc = h->param.b_mvc;
- + //x264_log( h, X264_LOG_INFO, "[slicetype_analyse] keyframe %d\n", keyframe);
- +
- if( h->param.b_deterministic )
- i_max_search = X264_MIN( i_max_search, h->lookahead->i_slicetype_length + !keyframe );
- assert( h->frames.b_have_lowres );
- + // x264_log( h, X264_LOG_INFO, "0\n");
- +
- if( !h->lookahead->last_nonb )
- return;
- frames[0] = h->lookahead->last_nonb;
- - for( framecnt = 0; framecnt < i_max_search && h->lookahead->next.list[framecnt]->i_type == X264_TYPE_AUTO; framecnt++ )
- + if (b_mvc) frames_dep[0] = h->lookahead->last_nonb_dependent;
- +
- +#ifdef __DEBUG
- + x264_log (h, X264_LOG_INFO, "[slicetype_analyse] last_nonb's frame number %d\n", h->lookahead->last_nonb->i_frame);
- +#endif
- +
- + for( framecnt = 0; framecnt < i_max_search && h->lookahead->next.list[framecnt]->i_type == X264_TYPE_AUTO; framecnt++ ) {
- frames[framecnt+1] = h->lookahead->next.list[framecnt];
- + if (b_mvc) frames_dep[framecnt+1] = h->lookahead->next_dependent.list[framecnt];
- + }
- x264_lowres_context_init( h, &a );
- + if (b_mvc) x264_lowres_context_init( h, &a_dep );
- if( !framecnt )
- {
- - if( h->param.rc.b_mb_tree )
- + if( h->param.rc.b_mb_tree ) {
- x264_macroblock_tree( h, &a, frames, 0, keyframe );
- + if (b_mvc) x264_macroblock_tree( h, &a_dep, frames_dep, 0, keyframe );
- + }
- return;
- }
- - keyint_limit = h->param.i_keyint_max - frames[0]->i_frame + h->lookahead->i_last_keyframe - 1;
- + keyint_limit = h->param.i_keyint_max - (frames[0]->i_frame / (b_mvc ? 2 : 1)) + h->lookahead->i_last_keyframe - 1;
- orig_num_frames = num_frames = h->param.b_intra_refresh ? framecnt : X264_MIN( framecnt, keyint_limit );
- +#ifdef __DEBUG
- + x264_log (h, X264_LOG_INFO, "[slicetype_analyse] num_frames %d valid frames in the nextbuf %d\n", num_frames, h->lookahead->next.i_size);
- +#endif
- +
- /* This is important psy-wise: if we have a non-scenecut keyframe,
- * there will be significant visual artifacts if the frames just before
- * go down in quality due to being referenced less, despite it being
- @@ -1269,6 +1368,9 @@ void x264_slicetype_analyse( x264_t *h, int keyframe )
- return;
- }
- +
- + // x264_log( h, X264_LOG_INFO, "2 %d\n", h->param.i_bframe_adaptive);
- +
- if( h->param.i_bframe )
- {
- if( h->param.i_bframe_adaptive == X264_B_ADAPT_TRELLIS )
- @@ -1279,25 +1381,46 @@ void x264_slicetype_analyse( x264_t *h, int keyframe )
- int best_path_index = (num_frames-1) % (X264_BFRAME_MAX+1);