/*****************************************************************************
* encoder.c: top-level encoder functions
*****************************************************************************
- * Copyright (C) 2003-2015 x264 project
+ * Copyright (C) 2003-2016 x264 project
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Loren Merritt <lorenm@u.washington.edu>
/* Write the frame in display order */
int frame_size = FRAME_SIZE( h->param.i_height * h->param.i_width * sizeof(pixel) );
- fseek( f, (uint64_t)h->fdec->i_frame * frame_size, SEEK_SET );
- for( int p = 0; p < (CHROMA444 ? 3 : 1); p++ )
- for( int y = 0; y < h->param.i_height; y++ )
- fwrite( &h->fdec->plane[p][y*h->fdec->i_stride[p]], sizeof(pixel), h->param.i_width, f );
- if( !CHROMA444 )
- {
- int cw = h->param.i_width>>1;
- int ch = h->param.i_height>>CHROMA_V_SHIFT;
- pixel *planeu = x264_malloc( (cw*ch*2+32)*sizeof(pixel) );
- if( planeu )
+ if( !fseek( f, (int64_t)h->fdec->i_frame * frame_size, SEEK_SET ) )
+ {
+ for( int p = 0; p < (CHROMA444 ? 3 : 1); p++ )
+ for( int y = 0; y < h->param.i_height; y++ )
+ fwrite( &h->fdec->plane[p][y*h->fdec->i_stride[p]], sizeof(pixel), h->param.i_width, f );
+ if( !CHROMA444 )
{
- pixel *planev = planeu + cw*ch + 16;
- h->mc.plane_copy_deinterleave( planeu, cw, planev, cw, h->fdec->plane[1], h->fdec->i_stride[1], cw, ch );
- fwrite( planeu, 1, cw*ch*sizeof(pixel), f );
- fwrite( planev, 1, cw*ch*sizeof(pixel), f );
- x264_free( planeu );
+ int cw = h->param.i_width>>1;
+ int ch = h->param.i_height>>CHROMA_V_SHIFT;
+ pixel *planeu = x264_malloc( (cw*ch*2+32)*sizeof(pixel) );
+ if( planeu )
+ {
+ pixel *planev = planeu + cw*ch + 16;
+ h->mc.plane_copy_deinterleave( planeu, cw, planev, cw, h->fdec->plane[1], h->fdec->i_stride[1], cw, ch );
+ fwrite( planeu, 1, cw*ch*sizeof(pixel), f );
+ fwrite( planev, 1, cw*ch*sizeof(pixel), f );
+ x264_free( planeu );
+ }
}
}
fclose( f );
int i_csp = h->param.i_csp & X264_CSP_MASK;
#if X264_CHROMA_FORMAT
- if( CHROMA_FORMAT != CHROMA_420 && i_csp >= X264_CSP_I420 && i_csp <= X264_CSP_NV12 )
+ if( CHROMA_FORMAT != CHROMA_420 && i_csp >= X264_CSP_I420 && i_csp < X264_CSP_I422 )
{
x264_log( h, X264_LOG_ERROR, "not compiled with 4:2:0 support\n" );
return -1;
}
- else if( CHROMA_FORMAT != CHROMA_422 && i_csp >= X264_CSP_I422 && i_csp <= X264_CSP_V210 )
+ else if( CHROMA_FORMAT != CHROMA_422 && i_csp >= X264_CSP_I422 && i_csp < X264_CSP_I444 )
{
x264_log( h, X264_LOG_ERROR, "not compiled with 4:2:2 support\n" );
return -1;
#endif
if( i_csp <= X264_CSP_NONE || i_csp >= X264_CSP_MAX )
{
- x264_log( h, X264_LOG_ERROR, "invalid CSP (only I420/YV12/NV12/I422/YV16/NV16/I444/YV24/BGR/BGRA/RGB supported)\n" );
+ x264_log( h, X264_LOG_ERROR, "invalid CSP (only I420/YV12/NV12/NV21/I422/YV16/NV16/I444/YV24/BGR/BGRA/RGB supported)\n" );
return -1;
}
}
if( h->param.i_threads == X264_THREADS_AUTO )
+ {
h->param.i_threads = x264_cpu_num_processors() * (h->param.b_sliced_threads?2:3)/2;
+ /* Avoid too many threads as they don't improve performance and
+ * complicate VBV. Capped at an arbitrary 2 rows per thread. */
+ int max_threads = X264_MAX( 1, (h->param.i_height+15)/16 / 2 );
+ h->param.i_threads = X264_MIN( h->param.i_threads, max_threads );
+ }
int max_sliced_threads = X264_MAX( 1, (h->param.i_height+15)/16 / 4 );
if( h->param.i_threads > 1 )
{
h->param.i_dpb_size = 1;
}
- if( h->param.i_frame_packing < -1 || h->param.i_frame_packing > 6 )
+ if( h->param.i_frame_packing < -1 || h->param.i_frame_packing > 7 )
{
x264_log( h, X264_LOG_WARNING, "ignoring unknown frame packing value\n" );
h->param.i_frame_packing = -1;
}
+ if( h->param.i_frame_packing == 7 &&
+ ((h->param.i_width - h->param.crop_rect.i_left - h->param.crop_rect.i_right) % 3 ||
+ (h->param.i_height - h->param.crop_rect.i_top - h->param.crop_rect.i_bottom) % 3) )
+ {
+ x264_log( h, X264_LOG_ERROR, "cropped resolution %dx%d not compatible with tile format frame packing\n",
+ h->param.i_width - h->param.crop_rect.i_left - h->param.crop_rect.i_right,
+ h->param.i_height - h->param.crop_rect.i_top - h->param.crop_rect.i_bottom );
+ return -1;
+ }
/* Detect default ffmpeg settings and terminate with an error. */
if( b_open )
h->param.i_fps_num = 25;
h->param.i_fps_den = 1;
}
- float fps = (float) h->param.i_fps_num / h->param.i_fps_den;
+ float fps = (float)h->param.i_fps_num / h->param.i_fps_den;
if( h->param.i_keyint_min == X264_KEYINT_MIN_AUTO )
- h->param.i_keyint_min = X264_MIN( h->param.i_keyint_max / 10, fps );
+ h->param.i_keyint_min = X264_MIN( h->param.i_keyint_max / 10, (int)fps );
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 );
{
{
x264_t *h;
char buf[1000], *p;
- int qp, i_slicetype_length;
+ int i_slicetype_length;
CHECKED_MALLOCZERO( h, sizeof(x264_t) );
p += sprintf( p, " none!" );
x264_log( h, X264_LOG_INFO, "%s\n", buf );
- float *logs = x264_analyse_prepare_costs( h );
- if( !logs )
+ if( x264_analyse_init_costs( h ) )
goto fail;
- for( qp = X264_MIN( h->param.rc.i_qp_min, QP_MAX_SPEC ); qp <= h->param.rc.i_qp_max; qp++ )
- if( x264_analyse_init_costs( h, logs, qp ) )
- goto fail;
- if( x264_analyse_init_costs( h, logs, X264_LOOKAHEAD_QP ) )
- goto fail;
- x264_free( logs );
static const uint16_t cost_mv_correct[7] = { 24, 47, 95, 189, 379, 757, 1515 };
/* Checks for known miscompilation issues. */
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 );
+ fclose( f );
goto fail;
}
fclose( f );
static void x264_thread_sync_stat( x264_t *dst, x264_t *src )
{
- if( dst == src )
- return;
- memcpy( &dst->stat.i_frame_count, &src->stat.i_frame_count, sizeof(dst->stat) - sizeof(dst->stat.frame) );
+ if( dst != src )
+ memcpy( &dst->stat, &src->stat, offsetof(x264_t, stat.frame) - offsetof(x264_t, stat) );
}
static void *x264_slices_write( x264_t *h )
/* ------------------- Setup new frame from picture -------------------- */
if( pic_in != NULL )
{
+ if( h->lookahead->b_exit_thread )
+ {
+ x264_log( h, X264_LOG_ERROR, "lookahead thread is already stopped\n" );
+ return -1;
+ }
+
/* 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 )
{
pic_out->prop.f_ssim = h->stat.frame.f_ssim / h->stat.frame.i_ssim_cnt;
h->stat.f_ssim_mean_y[h->sh.i_type] += pic_out->prop.f_ssim * dur;
- snprintf( psz_message + strlen(psz_message), 80 - strlen(psz_message),
- " SSIM Y:%.5f", pic_out->prop.f_ssim );
+ int msg_len = strlen(psz_message);
+ snprintf( psz_message + msg_len, 80 - msg_len, " SSIM Y:%.5f", pic_out->prop.f_ssim );
}
psz_message[79] = '\0';
x264_log( h, X264_LOG_DEBUG,
- "frame=%4d QP=%.2f NAL=%d Slice:%c Poc:%-3d I:%-4d P:%-4d SKIP:%-4d size=%d bytes%s\n",
+ "frame=%4d QP=%.2f NAL=%d Slice:%c Poc:%-3d I:%-4d P:%-4d SKIP:%-4d size=%d bytes%s\n",
h->i_frame,
h->fdec->f_qp_avg_aq,
h->i_nal_ref_idc,