X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=encoder%2Fencoder.c;h=fad8b3d9f5dc9abf5ce2b9b65874d6b93aed55c9;hb=ceb1484da34b7492f539b535a930652690372fe5;hp=2c7438ea2161d92e6c503559f1028852a9c544eb;hpb=807aeaaae7351e4c2c536463e69dacaac218bccb;p=x264 diff --git a/encoder/encoder.c b/encoder/encoder.c index 2c7438ea..fad8b3d9 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -467,7 +467,7 @@ static int x264_validate_parameters( x264_t *h, int b_open ) 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_V210 ) { x264_log( h, X264_LOG_ERROR, "not compiled with 4:2:2 support\n" ); return -1; @@ -609,7 +609,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 ) { @@ -618,7 +618,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; @@ -627,7 +636,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][7] = + } 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 }, @@ -652,31 +661,39 @@ static int x264_validate_parameters( x264_t *h, int b_open ) { 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; } @@ -765,8 +782,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 ); @@ -1070,10 +1088,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. */ @@ -1234,7 +1252,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 ); @@ -1894,10 +1911,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 ) @@ -2540,7 +2557,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; @@ -2550,7 +2567,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; @@ -2558,9 +2576,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 ); @@ -2613,11 +2632,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 ) @@ -2681,7 +2705,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; } } @@ -3443,7 +3467,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; @@ -3452,7 +3476,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; } @@ -3495,7 +3519,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 ); @@ -3551,7 +3575,7 @@ 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*/ x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE ); @@ -3723,7 +3747,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 );