X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=encoder%2Fencoder.c;h=2aae3f0c43896928c8c695e40e57d67e60952dca;hb=20821a26ec510979e49fcfd6becc6ad7e2d8b388;hp=90c8d78ec39af9af8171aecfa4af3878dddfdfb5;hpb=350b214c5abe7e82618ac46a14f23b7ab543045e;p=x264 diff --git a/encoder/encoder.c b/encoder/encoder.c index 90c8d78e..2aae3f0c 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -1,7 +1,7 @@ /***************************************************************************** * encoder.c: top-level encoder functions ***************************************************************************** - * Copyright (C) 2003-2013 x264 project + * Copyright (C) 2003-2016 x264 project * * Authors: Laurent Aimar * Loren Merritt @@ -32,9 +32,8 @@ #include "ratecontrol.h" #include "macroblock.h" #include "me.h" - -#if HAVE_VISUALIZE -#include "common/visualize.h" +#if HAVE_INTEL_DISPATCHER +#include "extras/intel_dispatcher.h" #endif //#define DEBUG_MB_TYPE @@ -92,20 +91,25 @@ 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) ); - 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 ); + 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 ) + { + 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 ); } @@ -416,6 +420,12 @@ static void x264_encoder_thread_init( x264_t *h ) static int x264_validate_parameters( x264_t *h, int b_open ) { + if( !h->param.pf_log ) + { + x264_log( NULL, X264_LOG_ERROR, "pf_log not set! did you forget to call x264_param_default?\n" ); + return -1; + } + #if HAVE_MMX if( b_open ) { @@ -466,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_NV16 ) + 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; @@ -484,36 +494,41 @@ 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; } - if( i_csp < X264_CSP_I444 && h->param.i_width % 2 ) + int w_mod = i_csp < X264_CSP_I444 ? 2 : 1; + int h_mod = (i_csp < X264_CSP_I422 ? 2 : 1) << PARAM_INTERLACED; + if( h->param.i_width % w_mod ) { - x264_log( h, X264_LOG_ERROR, "width not divisible by 2 (%dx%d)\n", - h->param.i_width, h->param.i_height ); + x264_log( h, X264_LOG_ERROR, "width not divisible by %d (%dx%d)\n", + w_mod, h->param.i_width, h->param.i_height ); return -1; } - - if( i_csp < X264_CSP_I422 && PARAM_INTERLACED && h->param.i_height % 4 ) + if( h->param.i_height % h_mod ) { - x264_log( h, X264_LOG_ERROR, "height not divisible by 4 (%dx%d)\n", - h->param.i_width, h->param.i_height ); + x264_log( h, X264_LOG_ERROR, "height not divisible by %d (%dx%d)\n", + h_mod, h->param.i_width, h->param.i_height ); return -1; } - if( (i_csp < X264_CSP_I422 || PARAM_INTERLACED) && h->param.i_height % 2 ) + if( h->param.crop_rect.i_left >= h->param.i_width || + h->param.crop_rect.i_right >= h->param.i_width || + h->param.crop_rect.i_top >= h->param.i_height || + h->param.crop_rect.i_bottom >= h->param.i_height || + h->param.crop_rect.i_left + h->param.crop_rect.i_right >= h->param.i_width || + h->param.crop_rect.i_top + h->param.crop_rect.i_bottom >= h->param.i_height ) { - x264_log( h, X264_LOG_ERROR, "height not divisible by 2 (%dx%d)\n", - h->param.i_width, h->param.i_height ); + x264_log( h, X264_LOG_ERROR, "invalid crop-rect %u,%u,%u,%u\n", h->param.crop_rect.i_left, + h->param.crop_rect.i_top, h->param.crop_rect.i_right, h->param.crop_rect.i_bottom ); return -1; } - - if( (h->param.crop_rect.i_left + h->param.crop_rect.i_right ) >= h->param.i_width || - (h->param.crop_rect.i_top + h->param.crop_rect.i_bottom) >= h->param.i_height ) + if( h->param.crop_rect.i_left % w_mod || h->param.crop_rect.i_right % w_mod || + h->param.crop_rect.i_top % h_mod || h->param.crop_rect.i_bottom % h_mod ) { - x264_log( h, X264_LOG_ERROR, "invalid crop-rect %u,%u,%u,%u\n", h->param.crop_rect.i_left, - h->param.crop_rect.i_top, h->param.crop_rect.i_right, h->param.crop_rect.i_bottom ); + x264_log( h, X264_LOG_ERROR, "crop-rect %u,%u,%u,%u not divisible by %dx%d\n", h->param.crop_rect.i_left, + h->param.crop_rect.i_top, h->param.crop_rect.i_right, h->param.crop_rect.i_bottom, w_mod, h_mod ); return -1; } @@ -524,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 ) { @@ -578,7 +599,20 @@ static int x264_validate_parameters( x264_t *h, int b_open ) h->param.i_dpb_size = 1; } - h->param.i_frame_packing = x264_clip3( h->param.i_frame_packing, -1, 5 ); + 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 ) @@ -613,7 +647,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) if( PARAM_INTERLACED ) h->param.b_pic_struct = 1; - if( h->param.b_avcintra_compat ) + if( h->param.i_avcintra_class ) { if( BIT_DEPTH != 10 ) { @@ -622,7 +656,16 @@ static int x264_validate_parameters( x264_t *h, int b_open ) return -1; } - /* [50/100][res][fps] */ + int type = h->param.i_avcintra_class == 200 ? 2 : + h->param.i_avcintra_class == 100 ? 1 : + h->param.i_avcintra_class == 50 ? 0 : -1; + if( type < 0 ) + { + x264_log( h, X264_LOG_ERROR, "Invalid AVC-Intra class\n" ); + return -1; + } + + /* [50/100/200][res][fps] */ static const struct { uint16_t fps_num; @@ -631,7 +674,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) uint16_t frame_size; const uint8_t *cqm_4ic; const uint8_t *cqm_8iy; - } avcintra_lut[2][2][5] = + } avcintra_lut[3][2][7] = { {{{ 60000, 1001, 0, 912, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, { 50, 1, 0, 1100, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, @@ -640,7 +683,9 @@ static int x264_validate_parameters( x264_t *h, int b_open ) { 24000, 1001, 0, 912, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }}, {{ 30000, 1001, 1, 1820, x264_cqm_avci50_4ic, x264_cqm_avci50_1080i_8iy }, { 25, 1, 1, 2196, x264_cqm_avci50_4ic, x264_cqm_avci50_1080i_8iy }, + { 60000, 1001, 0, 1820, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, { 30000, 1001, 0, 1820, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, + { 50, 1, 0, 2196, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, { 25, 1, 0, 2196, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }, { 24000, 1001, 0, 1820, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }}}, {{{ 60000, 1001, 0, 1848, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }, @@ -650,33 +695,43 @@ static int x264_validate_parameters( x264_t *h, int b_open ) { 24000, 1001, 0, 1848, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }}, {{ 30000, 1001, 1, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, { 25, 1, 1, 4444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, + { 60000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, { 30000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 50, 1, 0, 4444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, { 25, 1, 0, 4444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, - { 24000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}} + { 24000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}, + {{{ 60000, 1001, 0, 3724, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }, + { 50, 1, 0, 4472, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }}, + {{ 30000, 1001, 1, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, + { 25, 1, 1, 8940, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy }, + { 60000, 1001, 0, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 30000, 1001, 0, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 50, 1, 0, 8940, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 25, 1, 0, 8940, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }, + { 24000, 1001, 0, 7444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}} }; int res = -1; - int type = i_csp == X264_CSP_I422; - if( type ) - { - if( h->param.i_width == 1920 && h->param.i_height == 1080 ) res = 1; - else if( h->param.i_width == 1280 && h->param.i_height == 720 ) res = 0; - } - else if( i_csp == X264_CSP_I420 ) + if( i_csp >= X264_CSP_I420 && i_csp < X264_CSP_I422 && !type ) { if( h->param.i_width == 1440 && h->param.i_height == 1080 ) res = 1; else if( h->param.i_width == 960 && h->param.i_height == 720 ) res = 0; } + else if( i_csp >= X264_CSP_I422 && i_csp < X264_CSP_I444 && type ) + { + if( h->param.i_width == 1920 && h->param.i_height == 1080 ) res = 1; + else if( h->param.i_width == 1280 && h->param.i_height == 720 ) res = 0; + } else { - x264_log( h, X264_LOG_ERROR, "Invalid colorspace for AVC-Intra\n" ); + x264_log( h, X264_LOG_ERROR, "Invalid colorspace for AVC-Intra %d\n", h->param.i_avcintra_class ); return -1; } if( res < 0 ) { - x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid for AVC-Intra %s\n", - h->param.i_width, h->param.i_height, type ? "100" : "50" ); + x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid for AVC-Intra %d\n", + h->param.i_width, h->param.i_height, h->param.i_avcintra_class ); return -1; } @@ -695,7 +750,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) int i; uint32_t fps_num = h->param.i_fps_num, fps_den = h->param.i_fps_den; x264_reduce_fraction( &fps_num, &fps_den ); - for( i = 0; i < 5; i++ ) + for( i = 0; i < 7; i++ ) { if( avcintra_lut[type][res][i].fps_num == fps_num && avcintra_lut[type][res][i].fps_den == fps_den && @@ -704,7 +759,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) break; } } - if( i == 5 ) + if( i == 7 ) { x264_log( h, X264_LOG_ERROR, "FPS %d/%d%c not compatible with AVC-Intra\n", h->param.i_fps_num, h->param.i_fps_den, PARAM_INTERLACED ? 'i' : 'p' ); @@ -734,6 +789,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) h->param.rc.i_bitrate = h->param.rc.i_vbv_buffer_size * fps_num / fps_den; h->param.rc.i_rc_method = X264_RC_ABR; h->param.rc.f_vbv_buffer_init = 1.0; + h->param.rc.b_filler = 1; h->param.i_cqm_preset = X264_CQM_CUSTOM; memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof(h->param.cqm_4iy) ); memcpy( h->param.cqm_4ic, avcintra_lut[type][res][i].cqm_4ic, sizeof(h->param.cqm_4ic) ); @@ -764,8 +820,9 @@ static int x264_validate_parameters( x264_t *h, int b_open ) h->param.vui.i_sar_height = 3; } - /* Avid cannot handle negative QPs */ - h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET ); + /* Official encoder doesn't appear to go under 13 + * and Avid cannot handle negative QPs */ + h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET + 1 ); } h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, -QP_BD_OFFSET, 51 ); @@ -799,6 +856,8 @@ static int x264_validate_parameters( x264_t *h, int b_open ) /* 8x8dct is not useful without RD in CAVLC lossless */ if( !h->param.b_cabac && h->param.analyse.i_subpel_refine < 6 ) h->param.analyse.b_transform_8x8 = 0; + h->param.analyse.inter &= ~X264_ANALYSE_I8x8; + h->param.analyse.intra &= ~X264_ANALYSE_I8x8; } if( h->param.rc.i_rc_method == X264_RC_CQP ) { @@ -951,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 ); { @@ -1020,7 +1079,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) h->param.analyse.intra &= ~X264_ANALYSE_I8x8; } h->param.analyse.i_trellis = x264_clip3( h->param.analyse.i_trellis, 0, 2 ); - h->param.rc.i_aq_mode = x264_clip3( h->param.rc.i_aq_mode, 0, 2 ); + h->param.rc.i_aq_mode = x264_clip3( h->param.rc.i_aq_mode, 0, 3 ); h->param.rc.f_aq_strength = x264_clip3f( h->param.rc.f_aq_strength, 0, 3 ); if( h->param.rc.f_aq_strength == 0 ) h->param.rc.i_aq_mode = 0; @@ -1069,10 +1128,10 @@ static int x264_validate_parameters( x264_t *h, int b_open ) h->param.analyse.i_chroma_qp_offset += 6; /* Psy RDO increases overall quantizers to improve the quality of luma--this indirectly hurts chroma quality */ /* so we lower the chroma QP offset to compensate */ - if( b_open && h->mb.i_psy_rd && !h->param.b_avcintra_compat ) + if( b_open && h->mb.i_psy_rd && !h->param.i_avcintra_class ) h->param.analyse.i_chroma_qp_offset -= h->param.analyse.f_psy_rd < 0.25 ? 1 : 2; /* Psy trellis has a similar effect. */ - if( b_open && h->mb.i_psy_trellis && !h->param.b_avcintra_compat ) + if( b_open && h->mb.i_psy_trellis && !h->param.i_avcintra_class ) h->param.analyse.i_chroma_qp_offset -= h->param.analyse.f_psy_trellis < 0.25 ? 1 : 2; h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -12, 12); /* MB-tree requires AQ to be on, even if the strength is zero. */ @@ -1208,6 +1267,9 @@ static int x264_validate_parameters( x264_t *h, int b_open ) h->param.i_nal_hrd = X264_NAL_HRD_VBR; } + if( h->param.i_nal_hrd == X264_NAL_HRD_CBR ) + h->param.rc.b_filler = 1; + /* 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 ); @@ -1217,7 +1279,6 @@ static int x264_validate_parameters( x264_t *h, int b_open ) BOOLIFY( b_sliced_threads ); BOOLIFY( b_interlaced ); BOOLIFY( b_intra_refresh ); - BOOLIFY( b_visualize ); BOOLIFY( b_aud ); BOOLIFY( b_repeat_headers ); BOOLIFY( b_annexb ); @@ -1231,7 +1292,6 @@ static int x264_validate_parameters( x264_t *h, int b_open ) BOOLIFY( b_stitchable ); BOOLIFY( b_full_recon ); BOOLIFY( b_opencl ); - BOOLIFY( b_avcintra_compat ); BOOLIFY( analyse.b_transform_8x8 ); BOOLIFY( analyse.b_weighted_bipred ); BOOLIFY( analyse.b_chroma_me ); @@ -1244,6 +1304,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) BOOLIFY( rc.b_stat_write ); BOOLIFY( rc.b_stat_read ); BOOLIFY( rc.b_mb_tree ); + BOOLIFY( rc.b_filler ); #undef BOOLIFY return 0; @@ -1348,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) ); @@ -1358,6 +1419,10 @@ x264_t *x264_encoder_open( x264_param_t *param ) if( param->param_free ) param->param_free( param ); +#if HAVE_INTEL_DISPATCHER + x264_intel_dispatcher_override(); +#endif + if( x264_threading_init() ) { x264_log( h, X264_LOG_ERROR, "unable to initialize threading\n" ); @@ -1382,7 +1447,11 @@ x264_t *x264_encoder_open( x264_param_t *param ) /* Init x264_t */ h->i_frame = -1; h->i_frame_num = 0; - h->i_idr_pic_id = 0; + + if( h->param.i_avcintra_class ) + h->i_idr_pic_id = 5; + else + h->i_idr_pic_id = 0; if( (uint64_t)h->param.i_timebase_den * 2 > UINT32_MAX ) { @@ -1507,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. */ @@ -1640,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 ); @@ -1890,10 +1953,10 @@ static int x264_encoder_encapsulate_nals( x264_t *h, int start ) { int old_payload_len = h->out.nal[i].i_payload; h->out.nal[i].b_long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS || - h->param.b_avcintra_compat; + h->param.i_avcintra_class; x264_nal_encode( h, nal_buffer, &h->out.nal[i] ); nal_buffer += h->out.nal[i].i_payload; - if( h->param.b_avcintra_compat ) + if( h->param.i_avcintra_class ) { h->out.nal[i].i_padding -= h->out.nal[i].i_payload - (old_payload_len + NALU_OVERHEAD); if( h->out.nal[i].i_padding > 0 ) @@ -2133,6 +2196,31 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc ) h->fref[1][h->i_ref[1]++] = h->frames.reference[i]; } + if( h->sh.i_mmco_remove_from_end ) + { + /* Order ref0 for MMCO remove */ + do + { + b_ok = 1; + for( int i = 0; i < h->i_ref[0] - 1; i++ ) + { + if( h->fref[0][i]->i_frame < h->fref[0][i+1]->i_frame ) + { + XCHG( x264_frame_t*, h->fref[0][i], h->fref[0][i+1] ); + b_ok = 0; + break; + } + } + } while( !b_ok ); + + for( int i = h->i_ref[0]-1; i >= h->i_ref[0] - h->sh.i_mmco_remove_from_end; 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; + h->sh.mmco[h->sh.i_mmco_command_count++].i_difference_of_pic_nums = diff; + } + } + /* Order reference lists by distance from the current frame. */ for( int list = 0; list < 2; list++ ) { @@ -2155,14 +2243,6 @@ 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-- ) - { - 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; - h->sh.mmco[h->sh.i_mmco_command_count++].i_difference_of_pic_nums = diff; - } - x264_reference_check_reorder( h ); h->i_ref[1] = X264_MIN( h->i_ref[1], h->frames.i_max_ref1 ); @@ -2417,7 +2497,24 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp ) x264_slice_header_init( h, &h->sh, h->sps, h->pps, h->i_idr_pic_id, h->i_frame_num, i_global_qp ); /* alternate id */ - h->i_idr_pic_id ^= 1; + if( h->param.i_avcintra_class ) + { + switch( h->i_idr_pic_id ) + { + case 5: + h->i_idr_pic_id = 3; + break; + case 3: + h->i_idr_pic_id = 4; + break; + case 4: + default: + h->i_idr_pic_id = 5; + break; + } + } + else + h->i_idr_pic_id ^= 1; } else { @@ -2536,7 +2633,7 @@ static ALWAYS_INLINE void x264_bitstream_restore( x264_t *h, x264_bs_bak_t *bak, } } -static int x264_slice_write( x264_t *h ) +static intptr_t x264_slice_write( x264_t *h ) { int i_skip; int mb_xy, i_mb_x, i_mb_y; @@ -2546,7 +2643,8 @@ static int x264_slice_write( x264_t *h ) * other inaccuracies. */ int overhead_guess = (NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal)) + 1 + h->param.b_cabac + 5; int slice_max_size = h->param.i_slice_max_size > 0 ? (h->param.i_slice_max_size-overhead_guess)*8 : 0; - int back_up_bitstream = slice_max_size || (!h->param.b_cabac && h->sps->i_profile_idc < PROFILE_HIGH); + int back_up_bitstream_cavlc = !h->param.b_cabac && h->sps->i_profile_idc < PROFILE_HIGH; + int back_up_bitstream = slice_max_size || back_up_bitstream_cavlc; int starting_bits = bs_pos(&h->out.bs); int b_deblock = h->sh.i_disable_deblocking_filter_idc != 1; int b_hpel = h->fdec->b_kept_as_ref; @@ -2554,9 +2652,10 @@ static int x264_slice_write( x264_t *h ) int thread_last_mb = h->i_threadslice_end * h->mb.i_mb_width - 1; uint8_t *last_emu_check; #define BS_BAK_SLICE_MAX_SIZE 0 -#define BS_BAK_SLICE_MIN_MBS 1 -#define BS_BAK_ROW_VBV 2 - x264_bs_bak_t bs_bak[3]; +#define BS_BAK_CAVLC_OVERFLOW 1 +#define BS_BAK_SLICE_MIN_MBS 2 +#define BS_BAK_ROW_VBV 3 + x264_bs_bak_t bs_bak[4]; b_deblock &= b_hpel || h->param.b_full_recon || h->param.psz_dump_yuv; bs_realign( &h->out.bs ); @@ -2609,11 +2708,16 @@ static int x264_slice_write( x264_t *h ) x264_fdec_filter_row( h, i_mb_y, 0 ); } - if( !(i_mb_y & SLICE_MBAFF) && back_up_bitstream ) + if( back_up_bitstream ) { - x264_bitstream_backup( h, &bs_bak[BS_BAK_SLICE_MAX_SIZE], i_skip, 0 ); - if( slice_max_size && (thread_last_mb+1-mb_xy) == h->param.i_slice_min_mbs ) - x264_bitstream_backup( h, &bs_bak[BS_BAK_SLICE_MIN_MBS], i_skip, 0 ); + if( back_up_bitstream_cavlc ) + x264_bitstream_backup( h, &bs_bak[BS_BAK_CAVLC_OVERFLOW], i_skip, 0 ); + if( slice_max_size && !(i_mb_y & SLICE_MBAFF) ) + { + x264_bitstream_backup( h, &bs_bak[BS_BAK_SLICE_MAX_SIZE], i_skip, 0 ); + if( (thread_last_mb+1-mb_xy) == h->param.i_slice_min_mbs ) + x264_bitstream_backup( h, &bs_bak[BS_BAK_SLICE_MIN_MBS], i_skip, 0 ); + } } if( PARAM_INTERLACED ) @@ -2677,7 +2781,7 @@ reencode: h->mb.i_skip_intra = 0; h->mb.b_skip_mc = 0; h->mb.b_overflow = 0; - x264_bitstream_restore( h, &bs_bak[BS_BAK_SLICE_MAX_SIZE], &i_skip, 0 ); + x264_bitstream_restore( h, &bs_bak[BS_BAK_CAVLC_OVERFLOW], &i_skip, 0 ); goto reencode; } } @@ -2748,11 +2852,6 @@ reencode: cont: h->mb.b_reencode_mb = 0; -#if HAVE_VISUALIZE - if( h->param.b_visualize ) - x264_visualize_mb( h ); -#endif - /* save cache */ x264_macroblock_cache_save( h ); @@ -2937,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 ) @@ -2947,12 +3045,6 @@ static void *x264_slices_write( x264_t *h ) int i_slice_num = 0; int last_thread_mb = h->sh.i_last_mb; -#if HAVE_VISUALIZE - if( h->param.b_visualize ) - if( x264_visualize_init( h ) ) - goto fail; -#endif - /* init stats */ memset( &h->stat.frame, 0, sizeof(h->stat.frame) ); h->mb.b_reencode_mb = 0; @@ -2998,14 +3090,6 @@ static void *x264_slices_write( x264_t *h ) h->sh.i_first_mb -= h->mb.i_mb_stride; } -#if HAVE_VISUALIZE - if( h->param.b_visualize ) - { - x264_visualize_show( h ); - x264_visualize_close( h ); - } -#endif - return (void *)0; fail: @@ -3155,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 ) @@ -3249,7 +3339,7 @@ int x264_encoder_encode( x264_t *h, if( x264_threadpool_wait_all( h ) < 0 ) return -1; - if( h->i_frame == h->i_thread_frames - 1 ) + if( h->i_frame == 0 ) h->i_reordered_pts_delay = h->fenc->i_reordered_pts; if( h->reconfig ) { @@ -3458,7 +3548,7 @@ int x264_encoder_encode( x264_t *h, if( x264_nal_end( h ) ) return -1; /* Pad AUD/SPS to 256 bytes like Panasonic */ - if( h->param.b_avcintra_compat ) + if( h->param.i_avcintra_class ) h->out.nal[h->out.i_nal-1].i_padding = 256 - bs_pos( &h->out.bs ) / 8 - 2*NALU_OVERHEAD; overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + NALU_OVERHEAD; @@ -3467,7 +3557,7 @@ int x264_encoder_encode( x264_t *h, x264_pps_write( &h->out.bs, h->sps, h->pps ); if( x264_nal_end( h ) ) return -1; - if( h->param.b_avcintra_compat ) + if( h->param.i_avcintra_class ) h->out.nal[h->out.i_nal-1].i_padding = 256 - h->out.nal[h->out.i_nal-1].i_payload - NALU_OVERHEAD; overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + NALU_OVERHEAD; } @@ -3510,7 +3600,7 @@ int x264_encoder_encode( x264_t *h, if( h->fenc->b_keyframe ) { /* Avid's decoder strictly wants two SEIs for AVC-Intra so we can't insert the x264 SEI */ - if( h->param.b_repeat_headers && h->fenc->i_frame == 0 && !h->param.b_avcintra_compat ) + if( h->param.b_repeat_headers && h->fenc->i_frame == 0 && !h->param.i_avcintra_class ) { /* identify ourself */ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE ); @@ -3530,15 +3620,15 @@ int x264_encoder_encode( x264_t *h, return -1; overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD; } + } - 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 + SEI_OVERHEAD; - } + if( h->param.i_frame_packing >= 0 && (h->fenc->b_keyframe || h->param.i_frame_packing == 5) ) + { + 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 + SEI_OVERHEAD; } /* generate sei pic timing */ @@ -3566,28 +3656,24 @@ int x264_encoder_encode( x264_t *h, h->i_cpb_delay_pir_offset_next = h->fenc->i_cpb_delay; /* Filler space: 10 or 18 SEIs' worth of space, depending on resolution */ - if( h->param.b_avcintra_compat ) + if( h->param.i_avcintra_class ) { /* Write an empty filler NAL to mimic the AUD in the P2 format*/ - if( h->param.b_avcintra_compat ) - { - x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE ); - x264_filler_write( h, &h->out.bs, 0 ); - if( x264_nal_end( h ) ) - return -1; - overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD; - } + x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE ); + x264_filler_write( h, &h->out.bs, 0 ); + if( x264_nal_end( h ) ) + return -1; + overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD; /* All lengths are magic lengths that decoders expect to see */ /* "UMID" SEI */ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE ); - if( x264_sei_avcintra_write( h, &h->out.bs, 497, "UMID" ) < 0 ) + if( x264_sei_avcintra_umid_write( h, &h->out.bs ) < 0 ) return -1; if( x264_nal_end( h ) ) return -1; overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD; - int unpadded_len; int total_len; if( h->param.i_height == 1080 ) @@ -3602,7 +3688,7 @@ int x264_encoder_encode( x264_t *h, } /* "VANC" SEI */ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE ); - if( x264_sei_avcintra_write( h, &h->out.bs, unpadded_len, "VANC" ) < 0 ) + if( x264_sei_avcintra_vanc_write( h, &h->out.bs, unpadded_len ) < 0 ) return -1; if( x264_nal_end( h ) ) return -1; @@ -3742,7 +3828,7 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current, /* Filler in AVC-Intra mode is written as zero bytes to the last slice * We don't know the size of the last slice until encapsulation so we add filler to the encapsulated NAL */ - if( h->param.b_avcintra_compat ) + if( h->param.i_avcintra_class ) { x264_t *h0 = h->thread[0]; int ret = x264_check_encapsulated_buffer( h, h0, h->out.i_nal, frame_size, frame_size + filler ); @@ -3869,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, @@ -4033,14 +4119,14 @@ void x264_encoder_close ( x264_t *h ) if( h->stat.i_frame_count[SLICE_TYPE_I] > 0 ) { int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_I]; - double i_count = h->stat.i_frame_count[SLICE_TYPE_I] * h->mb.i_mb_count / 100.0; + double i_count = (double)h->stat.i_frame_count[SLICE_TYPE_I] * h->mb.i_mb_count / 100.0; x264_print_intra( i_mb_count, i_count, b_print_pcm, buf ); x264_log( h, X264_LOG_INFO, "mb I %s\n", buf ); } if( h->stat.i_frame_count[SLICE_TYPE_P] > 0 ) { int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_P]; - double i_count = h->stat.i_frame_count[SLICE_TYPE_P] * h->mb.i_mb_count / 100.0; + double i_count = (double)h->stat.i_frame_count[SLICE_TYPE_P] * h->mb.i_mb_count / 100.0; int64_t *i_mb_size = i_mb_count_size[SLICE_TYPE_P]; x264_print_intra( i_mb_count, i_count, b_print_pcm, buf ); x264_log( h, X264_LOG_INFO, @@ -4056,7 +4142,7 @@ void x264_encoder_close ( x264_t *h ) if( h->stat.i_frame_count[SLICE_TYPE_B] > 0 ) { int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_B]; - double i_count = h->stat.i_frame_count[SLICE_TYPE_B] * h->mb.i_mb_count / 100.0; + double i_count = (double)h->stat.i_frame_count[SLICE_TYPE_B] * h->mb.i_mb_count / 100.0; double i_mb_list_count; int64_t *i_mb_size = i_mb_count_size[SLICE_TYPE_B]; int64_t list_count[3] = {0}; /* 0 == L0, 1 == L1, 2 == BI */