X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=encoder%2Fencoder.c;h=a0b01fb943d4edf7ad588fe6869c9a48cc4ccac6;hb=d23d18655249944c1ca894b451e2c82c7a584c62;hp=b0a47a865f283421a81f1ce8301d1af436e7d591;hpb=f08b1c6b8e186ff5a931e9a80e8923e42efff0e4;p=x264 diff --git a/encoder/encoder.c b/encoder/encoder.c index b0a47a86..a0b01fb9 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -1,7 +1,7 @@ /***************************************************************************** * encoder.c: top-level encoder functions ***************************************************************************** - * Copyright (C) 2003-2015 x264 project + * Copyright (C) 2003-2016 x264 project * * Authors: Laurent Aimar * Loren Merritt @@ -91,22 +91,24 @@ static void x264_frame_dump( x264_t *h ) /* 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 ); @@ -474,12 +476,12 @@ static int x264_validate_parameters( x264_t *h, int b_open ) 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; @@ -492,7 +494,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) #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; } @@ -537,7 +539,13 @@ static int x264_validate_parameters( x264_t *h, int b_open ) } 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 ) { @@ -591,11 +599,20 @@ static int x264_validate_parameters( x264_t *h, int b_open ) 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 ) @@ -993,9 +1010,9 @@ static int x264_validate_parameters( x264_t *h, int 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 ); { @@ -1392,7 +1409,7 @@ x264_t *x264_encoder_open( x264_param_t *param ) { x264_t *h; char buf[1000], *p; - int qp, i_slicetype_length; + int i_slicetype_length; CHECKED_MALLOCZERO( h, sizeof(x264_t) ); @@ -1559,15 +1576,8 @@ x264_t *x264_encoder_open( x264_param_t *param ) 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. */ @@ -1692,6 +1702,7 @@ x264_t *x264_encoder_open( x264_param_t *param ) 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 ); @@ -3025,9 +3036,8 @@ static void x264_thread_sync_context( x264_t *dst, x264_t *src ) 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 ) @@ -3229,6 +3239,12 @@ int x264_encoder_encode( 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 ) @@ -3939,13 +3955,13 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current, { 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,