#include "macroblock.h"
#include "me.h"
-#if VISUALIZE
+#ifdef HAVE_VISUALIZE
#include "common/visualize.h"
#endif
x264_param_t *param = &h->param;
int i;
- /* First we fill all field */
+ /* First we fill all fields */
sh->sps = sps;
sh->pps = pps;
sh->i_redundant_pic_cnt = 0;
- if( !h->mb.b_direct_auto_read )
+ h->mb.b_direct_auto_write = h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO
+ && h->param.i_bframe
+ && ( h->param.rc.b_stat_write || !h->param.rc.b_stat_read );
+
+ if( !h->mb.b_direct_auto_read && sh->i_type == SLICE_TYPE_B )
{
- if( h->mb.b_direct_auto_write )
- sh->b_direct_spatial_mv_pred = ( h->stat.i_direct_score[1] > h->stat.i_direct_score[0] );
+ if( h->fref1[0]->i_poc_l0ref0 == h->fref0[0]->i_poc )
+ {
+ if( h->mb.b_direct_auto_write )
+ sh->b_direct_spatial_mv_pred = ( h->stat.i_direct_score[1] > h->stat.i_direct_score[0] );
+ else
+ sh->b_direct_spatial_mv_pred = ( param->analyse.i_direct_mv_pred == X264_DIRECT_PRED_SPATIAL );
+ }
else
- sh->b_direct_spatial_mv_pred = ( param->analyse.i_direct_mv_pred == X264_DIRECT_PRED_SPATIAL );
+ {
+ h->mb.b_direct_auto_write = 0;
+ sh->b_direct_spatial_mv_pred = 1;
+ }
}
/* else b_direct_spatial_mv_pred was read from the 2pass statsfile */
}
else
h->param.b_sliced_threads = 0;
+ h->i_thread_frames = h->param.b_sliced_threads ? 1 : h->param.i_threads;
if( h->param.b_interlaced )
{
x264_log( h, X264_LOG_WARNING, "interlace + me=esa is not implemented\n" );
h->param.analyse.i_me_method = X264_ME_UMH;
}
- if( h->param.analyse.i_direct_mv_pred > X264_DIRECT_PRED_SPATIAL )
- {
- x264_log( h, X264_LOG_WARNING, "interlace + direct=temporal is not implemented\n" );
- h->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
- }
if( h->param.analyse.i_weighted_pred > 0 )
{
x264_log( h, X264_LOG_WARNING, "interlace + weightp is not implemented\n" );
}
h->param.rc.i_qp_max = x264_clip3( h->param.rc.i_qp_max, 0, 51 );
h->param.rc.i_qp_min = x264_clip3( h->param.rc.i_qp_min, 0, h->param.rc.i_qp_max );
+ if( h->param.rc.i_vbv_buffer_size )
+ {
+ if( h->param.rc.i_rc_method == X264_RC_CQP )
+ {
+ x264_log( h, X264_LOG_WARNING, "VBV is incompatible with constant QP, ignored.\n" );
+ h->param.rc.i_vbv_max_bitrate = 0;
+ h->param.rc.i_vbv_buffer_size = 0;
+ }
+ else if( h->param.rc.i_vbv_max_bitrate == 0 )
+ {
+ if( h->param.rc.i_rc_method == X264_RC_ABR )
+ {
+ x264_log( h, X264_LOG_WARNING, "VBV maxrate unspecified, assuming CBR\n" );
+ h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
+ }
+ else
+ {
+ x264_log( h, X264_LOG_WARNING, "VBV bufsize set but maxrate unspecified, ignored\n" );
+ h->param.rc.i_vbv_buffer_size = 0;
+ }
+ }
+ 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" );
+ h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
+ }
+ }
+ else if( h->param.rc.i_vbv_max_bitrate )
+ {
+ x264_log( h, X264_LOG_WARNING, "VBV maxrate specified, but no bufsize, ignored\n" );
+ h->param.rc.i_vbv_max_bitrate = 0;
+ }
int max_slices = (h->param.i_height+((16<<h->param.b_interlaced)-1))/(16<<h->param.b_interlaced);
if( h->param.b_sliced_threads )
x264_log( h, X264_LOG_WARNING, "ref > 1 + intra-refresh is not supported\n" );
h->param.i_frame_reference = 1;
}
- if( h->param.b_intra_refresh )
- h->param.i_keyint_max = X264_MIN( h->param.i_keyint_max, (h->param.i_width+15)/16 - 1 );
h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 );
h->param.rc.i_lookahead = x264_clip3( h->param.rc.i_lookahead, 0, X264_LOOKAHEAD_MAX );
{
h->param.rc.i_lookahead = 0;
#ifdef HAVE_PTHREAD
if( h->param.i_sync_lookahead )
- h->param.i_sync_lookahead = x264_clip3( h->param.i_sync_lookahead, h->param.i_threads + h->param.i_bframe, X264_LOOKAHEAD_MAX );
- if( h->param.rc.b_stat_read || h->param.i_threads == 1 || h->param.b_sliced_threads )
+ h->param.i_sync_lookahead = x264_clip3( h->param.i_sync_lookahead, h->i_thread_frames + h->param.i_bframe, X264_LOOKAHEAD_MAX );
+ if( h->param.rc.b_stat_read || h->i_thread_frames == 1 )
h->param.i_sync_lookahead = 0;
#else
h->param.i_sync_lookahead = 0;
#endif
- h->mb.b_direct_auto_write = h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO
- && h->param.i_bframe
- && ( h->param.rc.b_stat_write || !h->param.rc.b_stat_read );
-
h->param.i_deblocking_filter_alphac0 = x264_clip3( h->param.i_deblocking_filter_alphac0, -6, 6 );
h->param.i_deblocking_filter_beta = x264_clip3( h->param.i_deblocking_filter_beta, -6, 6 );
h->param.analyse.i_luma_deadzone[0] = x264_clip3( h->param.analyse.i_luma_deadzone[0], 0, 32 );
/* Psy trellis has a similar effect. */
if( h->mb.i_psy_trellis )
h->param.analyse.i_chroma_qp_offset -= h->param.analyse.f_psy_trellis < 0.25 ? 1 : 2;
- else
- h->mb.i_psy_trellis = 0;
h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -12, 12);
h->param.rc.i_aq_mode = x264_clip3( h->param.rc.i_aq_mode, 0, 2 );
h->param.rc.f_aq_strength = x264_clip3f( h->param.rc.f_aq_strength, 0, 3 );
if( !h->param.analyse.i_weighted_pred && h->param.rc.b_mb_tree && h->param.analyse.b_psy && !h->param.b_interlaced )
h->param.analyse.i_weighted_pred = X264_WEIGHTP_FAKE;
- if( h->param.i_threads > 1 && !h->param.b_sliced_threads )
+ if( h->i_thread_frames > 1 )
{
int r = h->param.analyse.i_mv_range_thread;
int r2;
// the rest is allocated to whichever thread is far enough ahead to use it.
// reserving more space increases quality for some videos, but costs more time
// in thread synchronization.
- int max_range = (h->param.i_height + X264_THREAD_HEIGHT) / h->param.i_threads - X264_THREAD_HEIGHT;
+ int max_range = (h->param.i_height + X264_THREAD_HEIGHT) / h->i_thread_frames - X264_THREAD_HEIGHT;
r = max_range / 2;
}
r = X264_MAX( r, h->param.analyse.i_me_range );
if( h->param.rc.psz_stat_in )
h->param.rc.psz_stat_in = strdup( h->param.rc.psz_stat_in );
- x264_set_aspect_ratio( h, param, 1 );
+ x264_set_aspect_ratio( h, &h->param, 1 );
x264_reduce_fraction( &h->param.i_fps_num, &h->param.i_fps_den );
x264_reduce_fraction( &h->param.i_timebase_num, &h->param.i_timebase_den );
h->i_frame = -1;
h->i_frame_num = 0;
h->i_idr_pic_id = 0;
+ if( h->param.b_dts_compress )
+ {
+ /* h->i_dts_compress_multiplier == h->frames.i_bframe_delay + 1 */
+ h->i_dts_compress_multiplier = h->param.i_bframe ? (h->param.i_bframe_pyramid ? 3 : 2) : 1;
+ if( h->i_dts_compress_multiplier != 1 )
+ x264_log( h, X264_LOG_DEBUG, "DTS compresion changed timebase: %d/%d -> %d/%d\n",
+ h->param.i_timebase_num, h->param.i_timebase_den,
+ h->param.i_timebase_num, h->param.i_timebase_den * h->i_dts_compress_multiplier );
+ h->param.i_timebase_den *= h->i_dts_compress_multiplier;
+ }
+ else
+ h->i_dts_compress_multiplier = 1;
h->sps = &h->sps_array[0];
x264_sps_init( h->sps, h->param.i_sps_id, &h->param );
if( h->param.rc.b_mb_tree || h->param.rc.i_vbv_buffer_size )
h->frames.i_delay = X264_MAX( h->frames.i_delay, h->param.rc.i_lookahead );
i_slicetype_length = h->frames.i_delay;
- if( !h->param.b_sliced_threads )
- h->frames.i_delay += h->param.i_threads - 1;
+ h->frames.i_delay += h->i_thread_frames - 1;
h->frames.i_delay = X264_MIN( h->frames.i_delay, X264_LOOKAHEAD_MAX );
h->frames.i_delay += h->param.i_sync_lookahead;
h->frames.i_bframe_delay = h->param.i_bframe ? (h->param.i_bframe_pyramid ? 2 : 1) : 0;
CHECKED_MALLOCZERO( h->frames.unused[0], (h->frames.i_delay + 3) * sizeof(x264_frame_t *) );
/* Allocate room for max refs plus a few extra just in case. */
- CHECKED_MALLOCZERO( h->frames.unused[1], (h->param.i_threads + 20) * sizeof(x264_frame_t *) );
+ CHECKED_MALLOCZERO( h->frames.unused[1], (h->i_thread_frames + 20) * sizeof(x264_frame_t *) );
CHECKED_MALLOCZERO( h->frames.current, (h->param.i_sync_lookahead + h->param.i_bframe
- + h->param.i_threads + 3) * sizeof(x264_frame_t *) );
+ + h->i_thread_frames + 3) * sizeof(x264_frame_t *) );
if( h->param.analyse.i_weighted_pred > 0 )
- CHECKED_MALLOCZERO( h->frames.blank_unused, h->param.i_threads * 4 * sizeof(x264_frame_t *) );
+ CHECKED_MALLOCZERO( h->frames.blank_unused, h->i_thread_frames * 4 * sizeof(x264_frame_t *) );
h->i_ref0 = 0;
h->i_ref1 = 0;
for( i=0; x264_cpu_names[i].flags; i++ )
{
if( !strcmp(x264_cpu_names[i].name, "SSE2")
- && param->cpu & (X264_CPU_SSE2_IS_FAST|X264_CPU_SSE2_IS_SLOW) )
+ && h->param.cpu & (X264_CPU_SSE2_IS_FAST|X264_CPU_SSE2_IS_SLOW) )
continue;
if( !strcmp(x264_cpu_names[i].name, "SSE3")
- && (param->cpu & X264_CPU_SSSE3 || !(param->cpu & X264_CPU_CACHELINE_64)) )
+ && (h->param.cpu & X264_CPU_SSSE3 || !(h->param.cpu & X264_CPU_CACHELINE_64)) )
continue;
if( !strcmp(x264_cpu_names[i].name, "SSE4.1")
- && (param->cpu & X264_CPU_SSE42) )
+ && (h->param.cpu & X264_CPU_SSE42) )
continue;
- if( (param->cpu & x264_cpu_names[i].flags) == x264_cpu_names[i].flags
+ if( (h->param.cpu & x264_cpu_names[i].flags) == x264_cpu_names[i].flags
&& (!i || x264_cpu_names[i].flags != x264_cpu_names[i-1].flags) )
p += sprintf( p, " %s", x264_cpu_names[i].name );
}
- if( !param->cpu )
+ if( !h->param.cpu )
p += sprintf( p, " none!" );
x264_log( h, X264_LOG_INFO, "%s\n", buf );
h->nal_buffer_size = h->out.i_bitstream * 3/2 + 4;
h->thread[0] = h;
- h->i_thread_num = 0;
for( i = 1; i < h->param.i_threads + !!h->param.i_sync_lookahead; i++ )
CHECKED_MALLOC( h->thread[i], sizeof(x264_t) );
int buf_tesa = (h->param.analyse.i_me_method >= X264_ME_ESA) *
((me_range*2+18) * sizeof(int16_t) + (me_range+4) * (me_range+1) * 4 * sizeof(mvsad_t));
int buf_mbtree = h->param.rc.b_mb_tree * ((h->sps->i_mb_width+3)&~3) * sizeof(int);
- CHECKED_MALLOC( h->thread[i]->scratch_buffer, X264_MAX4( buf_hpel, buf_ssim, buf_tesa, buf_mbtree ) );
+ int buf_nnz = !h->param.b_cabac * h->pps->b_transform_8x8_mode * (h->sps->i_mb_width * 4 * 16 * sizeof(uint8_t));
+ int scratch_size = X264_MAX4( buf_hpel, buf_ssim, buf_tesa, X264_MAX( buf_mbtree, buf_nnz ) );
+ CHECKED_MALLOC( h->thread[i]->scratch_buffer, scratch_size );
}
if( x264_ratecontrol_new( h ) < 0 )
****************************************************************************/
int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
{
- h = h->thread[h->i_thread_phase];
+ h = h->thread[h->thread[0]->i_thread_phase];
x264_set_aspect_ratio( h, param, 0 );
#define COPY(var) h->param.var = param->var
COPY( i_frame_reference ); // but never uses more refs than initially specified
COPY( i_slice_max_size );
COPY( i_slice_max_mbs );
COPY( i_slice_count );
+ /* 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 )
+ {
+ COPY( rc.i_vbv_max_bitrate );
+ COPY( rc.i_vbv_buffer_size );
+ COPY( rc.i_bitrate );
+ }
+ COPY( rc.f_rf_constant );
#undef COPY
mbcmp_init( h );
- return x264_validate_parameters( h );
+ int ret = x264_validate_parameters( h );
+
+ /* Supported reconfiguration options (1-pass only):
+ * vbv-maxrate
+ * vbv-bufsize
+ * crf
+ * bitrate (CBR only) */
+ if( !ret )
+ x264_ratecontrol_init_reconfigurable( h, 0 );
+
+ return ret;
+}
+
+/****************************************************************************
+ * x264_encoder_parameters:
+ ****************************************************************************/
+void x264_encoder_parameters( x264_t *h, x264_param_t *param )
+{
+ memcpy( param, &h->thread[h->i_thread_phase]->param, sizeof(x264_param_t) );
}
/* internal usage */
x264_pps_write( &h->out.bs, h->pps );
if( x264_nal_end( h ) )
return -1;
- bs_flush( &h->out.bs );
frame_size = x264_encoder_encapsulate_nals( h );
}
}
- if( h->param.i_threads > 1 && h->fdec->b_kept_as_ref && !h->param.b_sliced_threads )
+ if( h->i_thread_frames > 1 && h->fdec->b_kept_as_ref )
x264_frame_cond_broadcast( h->fdec, mb_y*16 + (b_end ? 10000 : -(X264_THREAD_HEIGHT << h->sh.b_mbaff)) );
min_y = X264_MAX( min_y*16-8, 0 );
int i, j;
if( !h->fdec->b_kept_as_ref )
{
- if( h->param.i_threads > 1 && !h->param.b_sliced_threads )
+ if( h->i_thread_frames > 1 )
{
x264_frame_push_unused( h, h->fdec );
h->fdec = x264_frame_pop_unused( h, 1 );
/* Assume no more than 3 bytes of NALU escaping. */
int slice_max_size = h->param.i_slice_max_size > 0 ? (h->param.i_slice_max_size-3-NALU_OVERHEAD)*8 : INT_MAX;
int starting_bits = bs_pos(&h->out.bs);
+ bs_realign( &h->out.bs );
/* Slice */
x264_nal_start( h, h->i_nal_type, h->i_nal_ref_idc );
bs_write_ue( &h->out.bs, i_skip ); /* skip run */
i_skip = 0;
}
- x264_macroblock_write_cavlc( h, &h->out.bs );
+ x264_macroblock_write_cavlc( h );
}
}
else
h->mb.b_reencode_mb = 0;
-#if VISUALIZE
+#ifdef HAVE_VISUALIZE
if( h->param.b_visualize )
x264_visualize_mb( h );
#endif
x264_cpu_mask_misalign_sse();
#endif
-#if VISUALIZE
+#ifdef HAVE_VISUALIZE
if( h->param.b_visualize )
if( x264_visualize_init( h ) )
return (void *)-1;
h->sh.i_first_mb = h->sh.i_last_mb + 1;
}
-#if VISUALIZE
+#ifdef HAVE_VISUALIZE
if( h->param.b_visualize )
{
x264_visualize_show( h );
/* dispatch */
for( i = 0; i < h->param.i_threads; i++ )
+ {
if( x264_pthread_create( &h->thread[i]->thread_handle, NULL, (void*)x264_slices_write, (void*)h->thread[i] ) )
return -1;
+ h->thread[i]->b_thread_active = 1;
+ }
for( i = 0; i < h->param.i_threads; i++ )
{
x264_pthread_join( h->thread[i]->thread_handle, &ret );
+ h->thread[i]->b_thread_active = 0;
if( (intptr_t)ret )
return (intptr_t)ret;
}
for( i = 0; i <= h->sps->i_mb_height; i++ )
x264_fdec_filter_row( h, i );
+ x264_threads_merge_ratecontrol( h );
+
for( i = 1; i < h->param.i_threads; i++ )
{
x264_t *t = h->thread[i];
((int*)&h->stat.frame)[j] += ((int*)&t->stat.frame)[j];
}
- x264_threads_merge_ratecontrol( h );
-
return 0;
}
x264_t *thread_current, *thread_prev, *thread_oldest;
int i_nal_type, i_nal_ref_idc, i_global_qp, i;
- if( h->param.i_threads > 1 && !h->param.b_sliced_threads )
+ if( h->i_thread_frames > 1 )
{
thread_prev = h->thread[ h->i_thread_phase ];
- h->i_thread_phase = (h->i_thread_phase + 1) % h->param.i_threads;
+ 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->param.i_threads ];
+ thread_oldest = h->thread[ (h->i_thread_phase + 1) % 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;
/* 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 + (h->param.b_sliced_threads ? 0 : 1 - h->param.i_threads) )
+ 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;
if( h->param.b_intra_refresh && h->fenc->i_type == X264_TYPE_P )
{
int pocdiff = (h->fdec->i_poc - h->fref0[0]->i_poc)/2;
- float increment = ((float)h->sps->i_mb_width-1) / h->param.i_keyint_max;
+ float increment = X264_MAX( ((float)h->sps->i_mb_width-1) / h->param.i_keyint_max, 1 );
+ int max_position = (int)(increment * h->param.i_keyint_max);
if( IS_X264_TYPE_I( h->fref0[0]->i_type ) )
h->fdec->f_pir_position = 0;
else
{
- if( h->fref0[0]->i_pir_end_col == h->sps->i_mb_width - 1 )
+ h->fdec->f_pir_position = h->fref0[0]->f_pir_position;
+ if( h->fdec->f_pir_position+0.5 >= max_position )
{
h->fdec->f_pir_position = 0;
h->fenc->b_keyframe = 1;
}
- else
- h->fdec->f_pir_position = h->fref0[0]->f_pir_position;
}
h->fdec->i_pir_start_col = h->fdec->f_pir_position+0.5;
h->fdec->f_pir_position += increment * pocdiff;
- h->fdec->i_pir_end_col = X264_MIN( h->fdec->f_pir_position+0.5, h->sps->i_mb_width-1 );
+ h->fdec->i_pir_end_col = h->fdec->f_pir_position+0.5;
}
/* Write SPS and PPS */
if( h->fenc->i_type != X264_TYPE_IDR )
{
+ int time_to_recovery = X264_MIN( h->sps->i_mb_width - 1, h->param.i_keyint_max ) + h->param.i_bframe;
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- x264_sei_recovery_point_write( h, &h->out.bs, h->param.i_keyint_max );
+ x264_sei_recovery_point_write( h, &h->out.bs, time_to_recovery );
x264_nal_end( h );
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
}
x264_reference_check_reorder( h );
}
+ if( h->i_ref0 )
+ h->fdec->i_poc_l0ref0 = h->fref0[0]->i_poc;
+
if( h->sh.i_type == SLICE_TYPE_B )
x264_macroblock_bipred_init( h );
/* Write frame */
h->i_threadslice_start = 0;
h->i_threadslice_end = h->sps->i_mb_height;
- if( !h->param.b_sliced_threads && h->param.i_threads > 1 )
+ if( h->i_thread_frames > 1 )
{
if( x264_pthread_create( &h->thread_handle, NULL, (void*)x264_slices_write, h ) )
return -1;
{
void *ret = NULL;
x264_pthread_join( h->thread_handle, &ret );
+ h->b_thread_active = 0;
if( (intptr_t)ret )
return (intptr_t)ret;
- h->b_thread_active = 0;
}
if( !h->out.i_nal )
{
pic_out->i_type = X264_TYPE_B;
pic_out->b_keyframe = h->fenc->b_keyframe;
- pic_out->i_pts = h->fenc->i_pts;
- pic_out->i_dts = h->fenc->i_dts - h->frames.i_bframe_delay_time;
+
+ pic_out->i_pts = h->fenc->i_pts *= h->i_dts_compress_multiplier;
+ if( h->frames.i_bframe_delay )
+ {
+ int64_t *i_prev_dts = thread_current->frames.i_prev_dts;
+ if( h->i_frame <= h->frames.i_bframe_delay )
+ {
+ if( h->i_dts_compress_multiplier == 1 )
+ pic_out->i_dts = h->fenc->i_reordered_pts - h->frames.i_bframe_delay_time;
+ else
+ {
+ /* DTS compression */
+ if( h->i_frame == 1 )
+ thread_current->frames.i_init_delta = h->fenc->i_reordered_pts * h->i_dts_compress_multiplier;
+ pic_out->i_dts = h->i_frame * thread_current->frames.i_init_delta / h->i_dts_compress_multiplier;
+ }
+ }
+ else
+ pic_out->i_dts = i_prev_dts[ (h->i_frame - h->frames.i_bframe_delay) % h->frames.i_bframe_delay ];
+ i_prev_dts[ h->i_frame % h->frames.i_bframe_delay ] = h->fenc->i_reordered_pts * h->i_dts_compress_multiplier;
+ }
+ else
+ pic_out->i_dts = h->fenc->i_reordered_pts;
+ assert( pic_out->i_pts >= pic_out->i_dts );
+
pic_out->img.i_plane = h->fdec->i_plane;
for(i = 0; i < 3; i++)
{
x264_lookahead_delete( h );
- for( i = 0; i < h->param.i_threads; i++ )
+ if( h->param.i_threads > 1 )
{
// don't strictly have to wait for the other threads, but it's simpler than canceling them
- if( h->thread[i]->b_thread_active )
+ for( i = 0; i < h->param.i_threads; i++ )
+ if( h->thread[i]->b_thread_active )
+ x264_pthread_join( h->thread[i]->thread_handle, NULL );
+ if( h->i_thread_frames > 1 )
{
- x264_pthread_join( h->thread[i]->thread_handle, NULL );
- assert( h->thread[i]->fenc->i_reference_count == 1 );
- x264_frame_delete( h->thread[i]->fenc );
- }
- }
-
- if( h->param.i_threads > 1 && !h->param.b_sliced_threads )
- {
- x264_t *thread_prev;
+ for( i = 0; i < h->i_thread_frames; i++ )
+ {
+ if( h->thread[i]->b_thread_active )
+ {
+ assert( h->thread[i]->fenc->i_reference_count == 1 );
+ x264_frame_delete( h->thread[i]->fenc );
+ }
+ }
- thread_prev = h->thread[h->i_thread_phase];
- x264_thread_sync_ratecontrol( h, thread_prev, h );
- x264_thread_sync_ratecontrol( thread_prev, thread_prev, h );
- h->i_frame = thread_prev->i_frame + 1 - h->param.i_threads;
+ x264_t *thread_prev = h->thread[h->i_thread_phase];
+ x264_thread_sync_ratecontrol( h, thread_prev, h );
+ x264_thread_sync_ratecontrol( thread_prev, thread_prev, h );
+ h->i_frame = thread_prev->i_frame + 1 - h->i_thread_frames;
+ }
}
h->i_frame++;
x264_log( h, X264_LOG_INFO, "8x8 transform intra:%.1f%%%s\n", 100. * i_i8x8 / i_intra, buf );
}
- if( h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO
+ if( (h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO ||
+ (h->stat.i_direct_frames[0] && h->stat.i_direct_frames[1]))
&& h->stat.i_frame_count[SLICE_TYPE_B] )
{
x264_log( h, X264_LOG_INFO, "direct mvs spatial:%.1f%% temporal:%.1f%%\n",
x264_free( h->nal_buffer );
x264_analyse_free_costs( h );
- if( h->param.i_threads > 1)
+ if( h->i_thread_frames > 1)
h = h->thread[h->i_thread_phase];
/* frames */
{
int delayed_frames = 0;
int i;
- for( i=0; i<h->param.i_threads; i++ )
- delayed_frames += h->thread[i]->b_thread_active;
- h = h->thread[h->i_thread_phase];
+ if( h->i_thread_frames > 1 )
+ {
+ for( i=0; i<h->i_thread_frames; i++ )
+ delayed_frames += h->thread[i]->b_thread_active;
+ h = h->thread[h->i_thread_phase];
+ }
for( i=0; h->frames.current[i]; i++ )
delayed_frames++;
x264_pthread_mutex_lock( &h->lookahead->ofbuf.mutex );