X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=encoder%2Fanalyse.c;h=de3cf57234e3e21d0fdee267d77e115f59db7990;hb=bdfec13d6ac6e70f9a01b1a36b1398b800c58e0f;hp=95f111610454071b25a024a9e3de4ae131e2da12;hpb=c1f64a50b7563b737c8938ed796f46d3bad354a4;p=x264 diff --git a/encoder/analyse.c b/encoder/analyse.c index 95f11161..de3cf572 100644 --- a/encoder/analyse.c +++ b/encoder/analyse.c @@ -22,10 +22,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ -#include -#include #include #include +#ifndef _MSC_VER +#include +#endif #include "common/common.h" #include "macroblock.h" @@ -43,8 +44,8 @@ typedef struct /* 8x8 */ int i_cost8x8; - int mvc[16][5][2]; /* [ref][0] is 16x16 mv, - [ref][1..4] are 8x8 mv from partition [0..3] */ + /* [ref][0] is 16x16 mv, [ref][1..4] are 8x8 mv from partition [0..3] */ + DECLARE_ALIGNED_8( int mvc[32][5][2] ); x264_me_t me8x8[4]; /* Sub 4x4 */ @@ -57,7 +58,7 @@ typedef struct /* Sub 4x8 */ int i_cost4x8[4]; /* cost per 8x8 partition */ - x264_me_t me4x8[4][4]; + x264_me_t me4x8[4][2]; /* 16x8 */ int i_cost16x8; @@ -98,6 +99,7 @@ typedef struct /* Chroma part */ int i_satd_i8x8chroma; + int i_satd_i8x8chroma_dir[4]; int i_predict8x8chroma; /* II: Inter part P/B frame */ @@ -136,21 +138,19 @@ static const int i_qp0_cost_table[52] = { 40,45,51,57,64,72,81,91 /* 44-51 */ }; -/* pow(lambda,2) * .9 */ +/* lambda2 = pow(lambda,2) * .9 * 256 */ static const int i_qp0_cost2_table[52] = { - 1, 1, 1, 1, 1, 1, /* 0-5 */ - 1, 1, 1, 1, 1, 1, /* 6-11 */ - 1, 1, 1, 2, 2, 3, /* 12-17 */ - 4, 5, 6, 7, 9, 11, /* 18-23 */ - 14, 18, 23, 29, 36, 46, /* 24-29 */ - 58, 73, 91, 115, 145, 183, /* 30-35 */ - 230, 290, 366, 461, 581, 731, /* 36-41 */ - 922,1161,1463,1843,2322,2926, /* 42-47 */ -3686,4645,5852,7373 + 14, 18, 22, 28, 36, 45, 57, 72, /* 0 - 7 */ + 91, 115, 145, 182, 230, 290, 365, 460, /* 8 - 15 */ + 580, 731, 921, 1161, 1462, 1843, 2322, 2925, /* 16 - 23 */ + 3686, 4644, 5851, 7372, 9289, 11703, 14745, 18578, /* 24 - 31 */ + 23407, 29491, 37156, 46814, 58982, 74313, 93628, 117964, /* 32 - 39 */ +148626, 187257, 235929, 297252, 374514, 471859, 594505, 749029, /* 40 - 47 */ +943718, 1189010, 1498059, 1887436 /* 48 - 51 */ }; /* TODO: calculate CABAC costs */ -static const int i_mb_b_cost_table[19] = { +static const int i_mb_b_cost_table[X264_MBTYPE_MAX] = { 9, 9, 9, 9, 0, 0, 0, 1, 3, 7, 7, 7, 3, 7, 7, 7, 5, 9, 0 }; static const int i_mb_b16x8_cost_table[17] = { @@ -165,16 +165,18 @@ static const int i_sub_mb_p_cost_table[4] = { static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a ); +uint16_t *x264_cost_mv_fpel[52][4]; + /* initialize an array of lambda*nbits for all possible mvs */ static void x264_mb_analyse_load_costs( x264_t *h, x264_mb_analysis_t *a ) { static int16_t *p_cost_mv[52]; + int i, j; if( !p_cost_mv[a->i_qp] ) { /* could be faster, but isn't called many times */ /* factor of 4 from qpel, 2 from sign, and 2 because mv can be opposite from mvp */ - int i; p_cost_mv[a->i_qp] = x264_malloc( (4*4*2048 + 1) * sizeof(int16_t) ); p_cost_mv[a->i_qp] += 2*4*2048; for( i = 0; i <= 2*4*2048; i++ ) @@ -183,16 +185,26 @@ static void x264_mb_analyse_load_costs( x264_t *h, x264_mb_analysis_t *a ) p_cost_mv[a->i_qp][i] = a->i_lambda * bs_size_se( i ); } } - a->p_cost_mv = p_cost_mv[a->i_qp]; + + /* FIXME is this useful for all me methods? */ + if( h->param.analyse.i_me_method >= X264_ME_ESA && !x264_cost_mv_fpel[a->i_qp][0] ) + { + for( j=0; j<4; j++ ) + { + x264_cost_mv_fpel[a->i_qp][j] = x264_malloc( (4*2048 + 1) * sizeof(int16_t) ); + x264_cost_mv_fpel[a->i_qp][j] += 2*2048; + for( i = -2*2048; i < 2*2048; i++ ) + x264_cost_mv_fpel[a->i_qp][j][i] = p_cost_mv[a->i_qp][i*4+j]; + } + } } static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int i_qp ) { - memset( a, 0, sizeof( x264_mb_analysis_t ) ); - /* conduct the analysis using this lamda and QP */ a->i_qp = h->mb.i_qp = i_qp; + h->mb.i_chroma_qp = i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )]; a->i_lambda = i_qp0_cost_table[i_qp]; a->i_lambda2 = i_qp0_cost2_table[i_qp]; a->b_mbrd = h->param.analyse.i_subpel_refine >= 6 && @@ -213,29 +225,62 @@ static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int i_qp ) a->i_satd_i8x8chroma = COST_MAX; a->b_fast_intra = 0; + h->mb.i_skip_intra = + h->mb.b_lossless ? 0 : + a->b_mbrd ? 2 : + !h->param.analyse.i_trellis && !h->param.analyse.i_noise_reduction; /* II: Inter part P/B frame */ if( h->sh.i_type != SLICE_TYPE_I ) { - int i; - int i_fmv_range = h->param.analyse.i_mv_range - 16; + int i, j; + int i_fmv_range = 4 * h->param.analyse.i_mv_range; + // limit motion search to a slightly smaller range than the theoretical limit, + // since the search may go a few iterations past its given range + int i_fpel_border = 5; // umh unconditional radius + int i_spel_border = 8; // 1.5 for subpel_satd, 1.5 for subpel_rd, 2 for bime, round up /* Calculate max allowed MV range */ -#define CLIP_FMV(mv) x264_clip3( mv, -i_fmv_range, i_fmv_range ) +#define CLIP_FMV(mv) x264_clip3( mv, -i_fmv_range, i_fmv_range-1 ) h->mb.mv_min[0] = 4*( -16*h->mb.i_mb_x - 24 ); h->mb.mv_max[0] = 4*( 16*( h->sps->i_mb_width - h->mb.i_mb_x - 1 ) + 24 ); - h->mb.mv_min_fpel[0] = CLIP_FMV( -16*h->mb.i_mb_x - 8 ); - h->mb.mv_max_fpel[0] = CLIP_FMV( 16*( h->sps->i_mb_width - h->mb.i_mb_x - 1 ) + 8 ); - h->mb.mv_min_spel[0] = 4*( h->mb.mv_min_fpel[0] - 16 ); - h->mb.mv_max_spel[0] = 4*( h->mb.mv_max_fpel[0] + 16 ); + h->mb.mv_min_spel[0] = CLIP_FMV( h->mb.mv_min[0] ); + h->mb.mv_max_spel[0] = CLIP_FMV( h->mb.mv_max[0] ); + h->mb.mv_min_fpel[0] = (h->mb.mv_min_spel[0]>>2) + i_fpel_border; + h->mb.mv_max_fpel[0] = (h->mb.mv_max_spel[0]>>2) - i_fpel_border; if( h->mb.i_mb_x == 0) { - h->mb.mv_min[1] = 4*( -16*h->mb.i_mb_y - 24 ); - h->mb.mv_max[1] = 4*( 16*( h->sps->i_mb_height - h->mb.i_mb_y - 1 ) + 24 ); - h->mb.mv_min_fpel[1] = CLIP_FMV( -16*h->mb.i_mb_y - 8 ); - h->mb.mv_max_fpel[1] = CLIP_FMV( 16*( h->sps->i_mb_height - h->mb.i_mb_y - 1 ) + 8 ); - h->mb.mv_min_spel[1] = 4*( h->mb.mv_min_fpel[1] - 16 ); - h->mb.mv_max_spel[1] = 4*( h->mb.mv_max_fpel[1] + 16 ); + int mb_y = h->mb.i_mb_y >> h->sh.b_mbaff; + int mb_height = h->sps->i_mb_height >> h->sh.b_mbaff; + int thread_mvy_range = i_fmv_range; + + if( h->param.i_threads > 1 ) + { + int pix_y = (h->mb.i_mb_y | h->mb.b_interlaced) * 16; + int thresh = pix_y + h->param.analyse.i_mv_range_thread; + for( i = (h->sh.i_type == SLICE_TYPE_B); i >= 0; i-- ) + { + x264_frame_t **fref = i ? h->fref1 : h->fref0; + int i_ref = i ? h->i_ref1 : h->i_ref0; + for( j=0; ji_lines_completed - pix_y ); + } + } + if( h->param.b_deterministic ) + thread_mvy_range = h->param.analyse.i_mv_range_thread; + if( h->mb.b_interlaced ) + thread_mvy_range >>= 1; + } + + h->mb.mv_min[1] = 4*( -16*mb_y - 24 ); + h->mb.mv_max[1] = 4*( 16*( mb_height - mb_y - 1 ) + 24 ); + h->mb.mv_min_spel[1] = x264_clip3( h->mb.mv_min[1], X264_MAX(4*(-512+i_spel_border), -i_fmv_range), i_fmv_range ); + h->mb.mv_max_spel[1] = CLIP_FMV( h->mb.mv_max[1] ); + h->mb.mv_max_spel[1] = X264_MIN( h->mb.mv_max_spel[1], thread_mvy_range*4 ); + h->mb.mv_min_fpel[1] = (h->mb.mv_min_spel[1]>>2) + i_fpel_border; + h->mb.mv_max_fpel[1] = (h->mb.mv_max_spel[1]>>2) - i_fpel_border; } #undef CLIP_FMV @@ -308,7 +353,7 @@ static void predict_16x16_mode_available( unsigned int i_neighbour, int *mode, i { if( i_neighbour & MB_TOPLEFT ) { - /* top and left avaible */ + /* top and left available */ *mode++ = I_PRED_16x16_V; *mode++ = I_PRED_16x16_H; *mode++ = I_PRED_16x16_DC; @@ -331,7 +376,7 @@ static void predict_16x16_mode_available( unsigned int i_neighbour, int *mode, i } else { - /* none avaible */ + /* none available */ *mode = I_PRED_16x16_DC_128; *pi_count = 1; } @@ -342,7 +387,7 @@ static void predict_8x8chroma_mode_available( unsigned int i_neighbour, int *mod { if( i_neighbour & MB_TOPLEFT ) { - /* top and left avaible */ + /* top and left available */ *mode++ = I_PRED_CHROMA_V; *mode++ = I_PRED_CHROMA_H; *mode++ = I_PRED_CHROMA_DC; @@ -365,7 +410,7 @@ static void predict_8x8chroma_mode_available( unsigned int i_neighbour, int *mod } else { - /* none avaible */ + /* none available */ *mode = I_PRED_CHROMA_DC_128; *pi_count = 1; } @@ -422,7 +467,7 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a ) int i; int i_max; - int predict_mode[9]; + int predict_mode[4]; uint8_t *p_dstc[2], *p_srcc[2]; @@ -437,25 +482,49 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a ) predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max ); a->i_satd_i8x8chroma = COST_MAX; - for( i = 0; i < i_max; i++ ) - { - int i_satd; - int i_mode; + if( i_max == 4 && h->pixf.intra_satd_x3_8x8c && h->pixf.mbcmp[0] == h->pixf.satd[0] ) + { + int satdu[4], satdv[4]; + h->pixf.intra_satd_x3_8x8c( p_srcc[0], p_dstc[0], satdu ); + h->pixf.intra_satd_x3_8x8c( p_srcc[1], p_dstc[1], satdv ); + h->predict_8x8c[I_PRED_CHROMA_P]( p_dstc[0] ); + h->predict_8x8c[I_PRED_CHROMA_P]( p_dstc[1] ); + satdu[I_PRED_CHROMA_P] = + h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE, p_srcc[0], FENC_STRIDE ); + satdv[I_PRED_CHROMA_P] = + h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE, p_srcc[1], FENC_STRIDE ); + + for( i=0; ii_lambda * bs_size_ue(i_mode); - i_mode = predict_mode[i]; + a->i_satd_i8x8chroma_dir[i] = i_satd; + COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode ); + } + } + else + { + for( i=0; ipredict_8x8c[i_mode]( p_dstc[0] ); - h->predict_8x8c[i_mode]( p_dstc[1] ); + /* we do the prediction */ + h->predict_8x8c[i_mode]( p_dstc[0] ); + h->predict_8x8c[i_mode]( p_dstc[1] ); - /* we calculate the cost */ - i_satd = h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE, - p_srcc[0], FENC_STRIDE ) + - h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE, - p_srcc[1], FENC_STRIDE ) + - a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] ); + /* we calculate the cost */ + i_satd = h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE, + p_srcc[0], FENC_STRIDE ) + + h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE, + p_srcc[1], FENC_STRIDE ) + + a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] ); - COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode ); + a->i_satd_i8x8chroma_dir[i] = i_satd; + COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode ); + } } h->mb.i_chroma_pred_mode = a->i_predict8x8chroma; @@ -470,21 +539,38 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_ int i, idx; int i_max; int predict_mode[9]; + int b_merged_satd = h->pixf.intra_satd_x3_16x16 && h->pixf.mbcmp[0] == h->pixf.satd[0]; /*---------------- Try all mode and calculate their score ---------------*/ /* 16x16 prediction selection */ predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max ); - for( i = 0; i < i_max; i++ ) + + if( b_merged_satd && i_max == 4 ) { - int i_satd; - int i_mode = predict_mode[i]; - h->predict_16x16[i_mode]( p_dst ); + h->pixf.intra_satd_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir ); + h->predict_16x16[I_PRED_16x16_P]( p_dst ); + a->i_satd_i16x16_dir[I_PRED_16x16_P] = + h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ); + for( i=0; i<4; i++ ) + { + int cost = a->i_satd_i16x16_dir[i] += a->i_lambda * bs_size_ue(i); + COPY2_IF_LT( a->i_satd_i16x16, cost, a->i_predict16x16, i ); + } + } + else + { + for( i = 0; i < i_max; i++ ) + { + int i_satd; + int i_mode = predict_mode[i]; + h->predict_16x16[i_mode]( p_dst ); - i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) + - a->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] ); - COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode ); - a->i_satd_i16x16_dir[i_mode] = i_satd; + i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) + + a->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] ); + COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode ); + a->i_satd_i16x16_dir[i_mode] = i_satd; + } } if( h->sh.i_type == SLICE_TYPE_B ) @@ -496,9 +582,11 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_ /* 8x8 prediction selection */ if( flags & X264_ANALYSE_I8x8 ) { + DECLARE_ALIGNED_16( uint8_t edge[33] ); x264_pixel_cmp_t sa8d = (*h->pixf.mbcmp == *h->pixf.sad) ? h->pixf.sad[PIXEL_8x8] : h->pixf.sa8d[PIXEL_8x8]; int i_satd_thresh = a->b_mbrd ? COST_MAX : X264_MIN( i_satd_inter, a->i_satd_i16x16 ); int i_cost = 0; + b_merged_satd = h->pixf.intra_sa8d_x3_8x8 && h->pixf.mbcmp[0] == h->pixf.satd[0]; // FIXME some bias like in i4x4? if( h->sh.i_type == SLICE_TYPE_B ) @@ -514,12 +602,30 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_ int i_pred_mode = x264_mb_predict_intra4x4_mode( h, 4*idx ); predict_4x4_mode_available( h->mb.i_neighbour8[idx], predict_mode, &i_max ); - for( i = 0; i < i_max; i++ ) + x264_predict_8x8_filter( p_dst_by, edge, h->mb.i_neighbour8[idx], ALL_NEIGHBORS ); + + if( b_merged_satd && i_max == 9 ) + { + int satd[3]; + h->pixf.intra_sa8d_x3_8x8( p_src_by, edge, satd ); + if( i_pred_mode < 3 ) + satd[i_pred_mode] -= 3 * a->i_lambda; + for( i=2; i>=0; i-- ) + { + int cost = a->i_satd_i8x8_dir[i][idx] = satd[i] + 4 * a->i_lambda; + COPY2_IF_LT( i_best, cost, a->i_predict8x8[idx], i ); + } + i = 3; + } + else + i = 0; + + for( ; ipredict_8x8[i_mode]( p_dst_by, h->mb.i_neighbour8[idx] ); + h->predict_8x8[i_mode]( p_dst_by, edge ); i_satd = sa8d( p_dst_by, FDEC_STRIDE, p_src_by, FENC_STRIDE ) + a->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4); @@ -533,14 +639,22 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_ break; /* we need to encode this block now (for next ones) */ - h->predict_8x8[a->i_predict8x8[idx]]( p_dst_by, h->mb.i_neighbour8[idx] ); + h->predict_8x8[a->i_predict8x8[idx]]( p_dst_by, edge ); x264_mb_encode_i8x8( h, idx, a->i_qp ); x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[idx] ); } if( idx == 3 ) + { a->i_satd_i8x8 = i_cost; + if( h->mb.i_skip_intra ) + { + h->mc.copy[PIXEL_16x16]( h->mb.pic.i8x8_fdec_buf, 16, p_dst, FDEC_STRIDE, 16 ); + if( h->mb.i_skip_intra == 2 ) + h->mc.memcpy_aligned( h->mb.pic.i8x8_dct_buf, h->dct.luma8x8, sizeof(h->mb.pic.i8x8_dct_buf) ); + } + } else { a->i_satd_i8x8 = COST_MAX; @@ -555,6 +669,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_ { int i_cost; int i_satd_thresh = X264_MIN3( i_satd_inter, a->i_satd_i16x16, a->i_satd_i8x8 ); + b_merged_satd = h->pixf.intra_satd_x3_4x4 && h->pixf.mbcmp[0] == h->pixf.satd[0]; if( a->b_mbrd ) i_satd_thresh = i_satd_thresh * (10-a->b_fast_intra)/8; @@ -577,16 +692,29 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_ /* emulate missing topright samples */ *(uint32_t*) &p_dst_by[4 - FDEC_STRIDE] = p_dst_by[3 - FDEC_STRIDE] * 0x01010101U; - for( i = 0; i < i_max; i++ ) + if( b_merged_satd && i_max >= 6 ) + { + int satd[3]; + h->pixf.intra_satd_x3_4x4( p_src_by, p_dst_by, satd ); + if( i_pred_mode < 3 ) + satd[i_pred_mode] -= 3 * a->i_lambda; + for( i=2; i>=0; i-- ) + COPY2_IF_LT( i_best, satd[i] + 4 * a->i_lambda, + a->i_predict4x4[idx], i ); + i = 3; + } + else + i = 0; + + for( ; ipredict_4x4[i_mode]( p_dst_by ); i_satd = h->pixf.mbcmp[PIXEL_4x4]( p_dst_by, FDEC_STRIDE, - p_src_by, FENC_STRIDE ) + p_src_by, FENC_STRIDE ) + a->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4); COPY2_IF_LT( i_best, i_satd, a->i_predict4x4[idx], i_mode ); @@ -603,7 +731,15 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_ h->mb.cache.intra4x4_pred_mode[x264_scan8[idx]] = a->i_predict4x4[idx]; } if( idx == 15 ) + { a->i_satd_i4x4 = i_cost; + if( h->mb.i_skip_intra ) + { + h->mc.copy[PIXEL_16x16]( h->mb.pic.i4x4_fdec_buf, 16, p_dst, FDEC_STRIDE, 16 ); + if( h->mb.i_skip_intra == 2 ) + h->mc.memcpy_aligned( h->mb.pic.i4x4_dct_buf, h->dct.luma4x4, sizeof(h->mb.pic.i4x4_dct_buf) ); + } + } else a->i_satd_i4x4 = COST_MAX; } @@ -644,15 +780,16 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a ) uint8_t *p_src = h->mb.pic.p_fenc[0]; uint8_t *p_dst = h->mb.pic.p_fdec[0]; - int i, idx, x, y; - int i_max, i_satd, i_best, i_mode; + int i, j, idx, x, y; + int i_max, i_satd, i_best, i_mode, i_thresh; int i_pred_mode; int predict_mode[9]; + h->mb.i_skip_intra = 0; if( h->mb.i_type == I_16x16 ) { int old_pred_mode = a->i_predict16x16; - int i_thresh = a->i_satd_i16x16_dir[old_pred_mode] * 9/8; + i_thresh = a->i_satd_i16x16_dir[old_pred_mode] * 9/8; i_best = a->i_satd_i16x16; predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max ); for( i = 0; i < i_max; i++ ) @@ -716,6 +853,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a ) } else if( h->mb.i_type == I_8x8 ) { + DECLARE_ALIGNED_16( uint8_t edge[33] ); for( idx = 0; idx < 4; idx++ ) { uint64_t pels_h = 0; @@ -724,7 +862,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a ) uint8_t *p_src_by; uint8_t *p_dst_by; int j; - int i_thresh = a->i_satd_i8x8_dir[a->i_predict8x8[idx]][idx] * 11/8; + i_thresh = a->i_satd_i8x8_dir[a->i_predict8x8[idx]][idx] * 11/8; i_best = COST_MAX; i_pred_mode = x264_mb_predict_intra4x4_mode( h, 4*idx ); @@ -734,12 +872,14 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a ) p_src_by = p_src + 8*x + 8*y*FENC_STRIDE; p_dst_by = p_dst + 8*x + 8*y*FDEC_STRIDE; predict_4x4_mode_available( h->mb.i_neighbour8[idx], predict_mode, &i_max ); + x264_predict_8x8_filter( p_dst_by, edge, h->mb.i_neighbour8[idx], ALL_NEIGHBORS ); + for( i = 0; i < i_max; i++ ) { i_mode = predict_mode[i]; if( a->i_satd_i8x8_dir[i_mode][idx] > i_thresh ) continue; - h->predict_8x8[i_mode]( p_dst_by, h->mb.i_neighbour8[idx] ); + h->predict_8x8[i_mode]( p_dst_by, edge ); i_satd = x264_rd_cost_i8x8( h, a->i_lambda2, idx, i_mode ); if( i_best > i_satd ) @@ -766,6 +906,42 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a ) x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[idx] ); } } + + /* RD selection for chroma prediction */ + predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max ); + if( i_max > 1 ) + { + i_thresh = a->i_satd_i8x8chroma * 5/4; + + for( i = j = 0; i < i_max; i++ ) + if( a->i_satd_i8x8chroma_dir[i] < i_thresh && + predict_mode[i] != a->i_predict8x8chroma ) + { + predict_mode[j++] = predict_mode[i]; + } + i_max = j; + + if( i_max > 0 ) + { + int i_chroma_lambda = i_qp0_cost2_table[h->mb.i_chroma_qp]; + /* the previous thing encoded was x264_intra_rd(), so the pixels and + * coefs for the current chroma mode are still around, so we only + * have to recount the bits. */ + i_best = x264_rd_cost_i8x8_chroma( h, i_chroma_lambda, a->i_predict8x8chroma, 0 ); + for( i = 0; i < i_max; i++ ) + { + i_mode = predict_mode[i]; + h->predict_8x8c[i_mode]( h->mb.pic.p_fdec[1] ); + h->predict_8x8c[i_mode]( h->mb.pic.p_fdec[2] ); + /* if we've already found a mode that needs no residual, then + * probably any mode with a residual will be worse. + * so avoid dct on the remaining modes to improve speed. */ + i_satd = x264_rd_cost_i8x8_chroma( h, i_chroma_lambda, i_mode, h->mb.i_cbp_chroma != 0x00 ); + COPY2_IF_LT( i_best, i_satd, a->i_predict8x8chroma, i_mode ); + } + h->mb.i_chroma_pred_mode = a->i_predict8x8chroma; + } + } } #define LOAD_FENC( m, src, xoff, yoff) \ @@ -793,7 +969,7 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a ) int i_ref; int mvc[7][2], i_mvc; int i_halfpel_thresh = INT_MAX; - int *p_halfpel_thresh = h->i_ref0>1 ? &i_halfpel_thresh : NULL; + int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL; /* 16x16 Search on all ref frame */ m.i_pixel = PIXEL_16x16; @@ -801,7 +977,7 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a ) LOAD_FENC( &m, h->mb.pic.p_fenc, 0, 0 ); a->l0.me16x16.cost = INT_MAX; - for( i_ref = 0; i_ref < h->i_ref0; i_ref++ ) + for( i_ref = 0; i_ref < h->mb.pic.i_fref[0]; i_ref++ ) { const int i_ref_cost = REF_COST( 0, i_ref ); i_halfpel_thresh -= i_ref_cost; @@ -816,17 +992,17 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a ) /* early termination * SSD threshold would probably be better than SATD */ - if( i_ref == 0 && a->b_try_pskip && m.cost-m.cost_mv < 300*a->i_lambda ) + if( i_ref == 0 + && a->b_try_pskip + && m.cost-m.cost_mv < 300*a->i_lambda + && abs(m.mv[0]-h->mb.cache.pskip_mv[0]) + + abs(m.mv[1]-h->mb.cache.pskip_mv[1]) <= 1 + && x264_macroblock_probe_pskip( h ) ) { - int mvskip[2]; - x264_mb_predict_mv_pskip( h, mvskip ); - if( abs(m.mv[0]-mvskip[0]) + abs(m.mv[1]-mvskip[1]) <= 1 - && x264_macroblock_probe_pskip( h ) ) - { - h->mb.i_type = P_SKIP; - x264_analyse_update_cache( h, a ); - return; - } + h->mb.i_type = P_SKIP; + x264_analyse_update_cache( h, a ); + assert( h->mb.cache.pskip_mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 ); + return; } m.cost += i_ref_cost; @@ -843,18 +1019,16 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a ) } x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, a->l0.me16x16.i_ref ); + assert( a->l0.me16x16.mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 ); h->mb.i_type = P_L0; - if( a->b_mbrd && a->l0.i_ref == 0 ) + if( a->b_mbrd && a->l0.me16x16.i_ref == 0 + && a->l0.me16x16.mv[0] == h->mb.cache.pskip_mv[0] + && a->l0.me16x16.mv[1] == h->mb.cache.pskip_mv[1] ) { - int mvskip[2]; - x264_mb_predict_mv_pskip( h, mvskip ); - if( a->l0.me16x16.mv[0] == mvskip[0] && a->l0.me16x16.mv[1] == mvskip[1] ) - { - h->mb.i_partition = D_16x16; - x264_macroblock_cache_mv( h, 0, 0, 4, 4, 0, a->l0.me16x16.mv[0], a->l0.me16x16.mv[1] ); - a->l0.i_rd16x16 = x264_rd_cost_mb( h, a->i_lambda2 ); - } + h->mb.i_partition = D_16x16; + x264_macroblock_cache_mv( h, 0, 0, 4, 4, 0, a->l0.me16x16.mv[0], a->l0.me16x16.mv[1] ); + a->l0.i_rd16x16 = x264_rd_cost_mb( h, a->i_lambda2 ); } } @@ -864,9 +1038,9 @@ static void x264_mb_analyse_inter_p8x8_mixed_ref( x264_t *h, x264_mb_analysis_t int i_ref; uint8_t **p_fenc = h->mb.pic.p_fenc; int i_halfpel_thresh = INT_MAX; - int *p_halfpel_thresh = /*h->i_ref0>1 ? &i_halfpel_thresh : */NULL; + int *p_halfpel_thresh = /*h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : */NULL; int i; - int i_maxref = h->i_ref0-1; + int i_maxref = h->mb.pic.i_fref[0]-1; h->mb.i_partition = D_8x8; @@ -988,7 +1162,7 @@ static void x264_mb_analyse_inter_p16x8( x264_t *h, x264_mb_analysis_t *a ) { x264_me_t m; uint8_t **p_fenc = h->mb.pic.p_fenc; - int mvc[3][2]; + DECLARE_ALIGNED_8( int mvc[3][2] ); int i, j; /* XXX Needed for x264_mb_predict_mv */ @@ -1038,7 +1212,7 @@ static void x264_mb_analyse_inter_p8x16( x264_t *h, x264_mb_analysis_t *a ) { x264_me_t m; uint8_t **p_fenc = h->mb.pic.p_fenc; - int mvc[3][2]; + DECLARE_ALIGNED_8( int mvc[3][2] ); int i, j; /* XXX Needed for x264_mb_predict_mv */ @@ -1085,21 +1259,21 @@ static void x264_mb_analyse_inter_p8x16( x264_t *h, x264_mb_analysis_t *a ) static int x264_mb_analyse_inter_p4x4_chroma( x264_t *h, x264_mb_analysis_t *a, uint8_t **p_fref, int i8x8, int pixel ) { - DECLARE_ALIGNED( uint8_t, pix1[8*8], 8 ); - DECLARE_ALIGNED( uint8_t, pix2[8*8], 8 ); + DECLARE_ALIGNED_8( uint8_t pix1[16*8] ); + uint8_t *pix2 = pix1+8; const int i_stride = h->mb.pic.i_stride[1]; const int or = 4*(i8x8&1) + 2*(i8x8&2)*i_stride; const int oe = 4*(i8x8&1) + 2*(i8x8&2)*FENC_STRIDE; #define CHROMA4x4MC( width, height, me, x, y ) \ - h->mc.mc_chroma( &p_fref[4][or+x+y*i_stride], i_stride, &pix1[x+y*8], 8, (me).mv[0], (me).mv[1], width, height ); \ - h->mc.mc_chroma( &p_fref[5][or+x+y*i_stride], i_stride, &pix2[x+y*8], 8, (me).mv[0], (me).mv[1], width, height ); + h->mc.mc_chroma( &pix1[x+y*16], 16, &p_fref[4][or+x+y*i_stride], i_stride, (me).mv[0], (me).mv[1], width, height ); \ + h->mc.mc_chroma( &pix2[x+y*16], 16, &p_fref[5][or+x+y*i_stride], i_stride, (me).mv[0], (me).mv[1], width, height ); if( pixel == PIXEL_4x4 ) { CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][0], 0,0 ); - CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][1], 0,2 ); - CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][2], 2,0 ); + CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][1], 2,0 ); + CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][2], 0,2 ); CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][3], 2,2 ); } else if( pixel == PIXEL_8x4 ) @@ -1113,8 +1287,8 @@ static int x264_mb_analyse_inter_p4x4_chroma( x264_t *h, x264_mb_analysis_t *a, CHROMA4x4MC( 2,4, a->l0.me4x8[i8x8][1], 2,0 ); } - return h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[1][oe], FENC_STRIDE, pix1, 8 ) - + h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[2][oe], FENC_STRIDE, pix2, 8 ); + return h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[1][oe], FENC_STRIDE, pix1, 16 ) + + h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[2][oe], FENC_STRIDE, pix2, 16 ); } static void x264_mb_analyse_inter_p4x4( x264_t *h, x264_mb_analysis_t *a, int i8x8 ) @@ -1265,7 +1439,8 @@ static void x264_mb_analyse_inter_direct( x264_t *h, x264_mb_analysis_t *a ) static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) { - uint8_t pix1[16*16], pix2[16*16]; + DECLARE_ALIGNED_16( uint8_t pix1[16*16] ); + DECLARE_ALIGNED_16( uint8_t pix2[16*16] ); uint8_t *src2; int stride2 = 16; int weight; @@ -1274,7 +1449,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) int i_ref; int mvc[8][2], i_mvc; int i_halfpel_thresh = INT_MAX; - int *p_halfpel_thresh = h->i_ref0>1 ? &i_halfpel_thresh : NULL; + int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL; /* 16x16 Search on all ref frame */ m.i_pixel = PIXEL_16x16; @@ -1283,7 +1458,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) /* ME for List 0 */ a->l0.me16x16.cost = INT_MAX; - for( i_ref = 0; i_ref < h->i_ref0; i_ref++ ) + for( i_ref = 0; i_ref < h->mb.pic.i_fref[0]; i_ref++ ) { /* search with ref */ LOAD_HPELS( &m, h->mb.pic.p_fref[0][i_ref], 0, i_ref, 0, 0 ); @@ -1309,9 +1484,9 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) /* ME for list 1 */ i_halfpel_thresh = INT_MAX; - p_halfpel_thresh = h->i_ref1>1 ? &i_halfpel_thresh : NULL; + p_halfpel_thresh = h->mb.pic.i_fref[1]>1 ? &i_halfpel_thresh : NULL; a->l1.me16x16.cost = INT_MAX; - for( i_ref = 0; i_ref < h->i_ref1; i_ref++ ) + for( i_ref = 0; i_ref < h->mb.pic.i_fref[1]; i_ref++ ) { /* search with ref */ LOAD_HPELS( &m, h->mb.pic.p_fref[1][i_ref], 1, i_ref, 0, 0 ); @@ -1344,27 +1519,29 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) if ( ((a->l0.me16x16.mv[0] | a->l0.me16x16.mv[1]) & 1) == 0 ) { /* l0 reference is halfpel, so get_ref on it will make it faster */ - src2 = h->mc.get_ref( h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0], - pix2, &stride2, - a->l0.me16x16.mv[0], a->l0.me16x16.mv[1], - 16, 16 ); - h->mc.mc_luma( h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0], - pix1, 16, - a->l1.me16x16.mv[0], a->l1.me16x16.mv[1], - 16, 16 ); + src2 = + h->mc.get_ref( pix2, &stride2, + h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0], + a->l0.me16x16.mv[0], a->l0.me16x16.mv[1], + 16, 16 ); + h->mc.mc_luma( pix1, 16, + h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0], + a->l1.me16x16.mv[0], a->l1.me16x16.mv[1], + 16, 16 ); weight = 64 - weight; } else { /* if l0 was qpel, we'll use get_ref on l1 instead */ - h->mc.mc_luma( h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0], - pix1, 16, - a->l0.me16x16.mv[0], a->l0.me16x16.mv[1], - 16, 16 ); - src2 = h->mc.get_ref( h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0], - pix2, &stride2, - a->l1.me16x16.mv[0], a->l1.me16x16.mv[1], - 16, 16 ); + h->mc.mc_luma( pix1, 16, + h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0], + a->l0.me16x16.mv[0], a->l0.me16x16.mv[1], + 16, 16 ); + src2 = + h->mc.get_ref( pix2, &stride2, + h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0], + a->l1.me16x16.mv[0], a->l1.me16x16.mv[1], + 16, 16 ); } if( h->param.analyse.b_weighted_bipred ) @@ -1474,7 +1651,7 @@ static void x264_mb_analyse_inter_b8x8( x264_t *h, x264_mb_analysis_t *a ) uint8_t **p_fref[2] = { h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.p_fref[1][a->l1.i_ref] }; - uint8_t pix[2][8*8]; + DECLARE_ALIGNED_8( uint8_t pix[2][8*8] ); int i, l; /* XXX Needed for x264_mb_predict_mv */ @@ -1506,8 +1683,8 @@ static void x264_mb_analyse_inter_b8x8( x264_t *h, x264_mb_analysis_t *a ) x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, l, m->mv[0], m->mv[1] ); /* BI mode */ - h->mc.mc_luma( m->p_fref, m->i_stride[0], pix[l], 8, - m->mv[0], m->mv[1], 8, 8 ); + h->mc.mc_luma( pix[l], 8, m->p_fref, m->i_stride[0], + m->mv[0], m->mv[1], 8, 8 ); i_part_cost_bi += m->cost_mv; /* FIXME: ref cost */ } @@ -1538,8 +1715,8 @@ static void x264_mb_analyse_inter_b16x8( x264_t *h, x264_mb_analysis_t *a ) uint8_t **p_fref[2] = { h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.p_fref[1][a->l1.i_ref] }; - DECLARE_ALIGNED( uint8_t, pix[2][16*8], 16 ); - int mvc[2][2]; + DECLARE_ALIGNED_16( uint8_t pix[2][16*8] ); + DECLARE_ALIGNED_8( int mvc[2][2] ); int i, l; h->mb.i_partition = D_16x8; @@ -1562,17 +1739,15 @@ static void x264_mb_analyse_inter_b16x8( x264_t *h, x264_mb_analysis_t *a ) LOAD_FENC( m, h->mb.pic.p_fenc, 0, 8*i ); LOAD_HPELS( m, p_fref[l], l, lX->i_ref, 0, 8*i ); - mvc[0][0] = lX->me8x8[2*i].mv[0]; - mvc[0][1] = lX->me8x8[2*i].mv[1]; - mvc[1][0] = lX->me8x8[2*i+1].mv[0]; - mvc[1][1] = lX->me8x8[2*i+1].mv[1]; + *(uint64_t*)mvc[0] = *(uint64_t*)lX->me8x8[2*i].mv; + *(uint64_t*)mvc[1] = *(uint64_t*)lX->me8x8[2*i+1].mv; - x264_mb_predict_mv( h, 0, 8*i, 2, m->mvp ); + x264_mb_predict_mv( h, l, 8*i, 2, m->mvp ); x264_me_search( h, m, mvc, 2 ); /* BI mode */ - h->mc.mc_luma( m->p_fref, m->i_stride[0], pix[l], 16, - m->mv[0], m->mv[1], 16, 8 ); + h->mc.mc_luma( pix[l], 16, m->p_fref, m->i_stride[0], + m->mv[0], m->mv[1], 16, 8 ); /* FIXME: ref cost */ i_part_cost_bi += m->cost_mv; } @@ -1609,8 +1784,8 @@ static void x264_mb_analyse_inter_b8x16( x264_t *h, x264_mb_analysis_t *a ) uint8_t **p_fref[2] = { h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.p_fref[1][a->l1.i_ref] }; - uint8_t pix[2][8*16]; - int mvc[2][2]; + DECLARE_ALIGNED_8( uint8_t pix[2][8*16] ); + DECLARE_ALIGNED_8( int mvc[2][2] ); int i, l; h->mb.i_partition = D_8x16; @@ -1632,17 +1807,15 @@ static void x264_mb_analyse_inter_b8x16( x264_t *h, x264_mb_analysis_t *a ) LOAD_FENC( m, h->mb.pic.p_fenc, 8*i, 0 ); LOAD_HPELS( m, p_fref[l], l, lX->i_ref, 8*i, 0 ); - mvc[0][0] = lX->me8x8[i].mv[0]; - mvc[0][1] = lX->me8x8[i].mv[1]; - mvc[1][0] = lX->me8x8[i+2].mv[0]; - mvc[1][1] = lX->me8x8[i+2].mv[1]; + *(uint64_t*)mvc[0] = *(uint64_t*)lX->me8x8[i].mv; + *(uint64_t*)mvc[1] = *(uint64_t*)lX->me8x8[i+2].mv; - x264_mb_predict_mv( h, 0, 4*i, 2, m->mvp ); + x264_mb_predict_mv( h, l, 4*i, 2, m->mvp ); x264_me_search( h, m, mvc, 2 ); /* BI mode */ - h->mc.mc_luma( m->p_fref, m->i_stride[0], pix[l], 8, - m->mv[0], m->mv[1], 8, 16 ); + h->mc.mc_luma( pix[l], 8, m->p_fref, m->i_stride[0], + m->mv[0], m->mv[1], 8, 16 ); /* FIXME: ref cost */ i_part_cost_bi += m->cost_mv; } @@ -1838,11 +2011,7 @@ static void refine_bidir( x264_t *h, x264_mb_analysis_t *a ) static inline void x264_mb_analyse_transform( x264_t *h ) { - h->mb.cache.b_transform_8x8_allowed = - h->param.analyse.b_transform_8x8 - && !IS_INTRA( h->mb.i_type ) && x264_mb_transform_8x8_allowed( h ); - - if( h->mb.cache.b_transform_8x8_allowed ) + if( x264_mb_transform_8x8_allowed( h ) && h->param.analyse.b_transform_8x8 ) { int i_cost4, i_cost8; /* FIXME only luma mc is needed */ @@ -1859,10 +2028,7 @@ static inline void x264_mb_analyse_transform( x264_t *h ) static inline void x264_mb_analyse_transform_rd( x264_t *h, x264_mb_analysis_t *a, int *i_satd, int *i_rd ) { - h->mb.cache.b_transform_8x8_allowed = - h->param.analyse.b_transform_8x8 && x264_mb_transform_8x8_allowed( h ); - - if( h->mb.cache.b_transform_8x8_allowed ) + if( x264_mb_transform_8x8_allowed( h ) && h->param.analyse.b_transform_8x8 ) { int i_rd8; x264_analyse_update_cache( h, a ); @@ -1895,8 +2061,11 @@ void x264_macroblock_analyse( x264_t *h ) int i_cost = COST_MAX; int i; - /* init analysis */ - x264_mb_analyse_init( h, &analysis, x264_ratecontrol_qp( h ) ); + h->mb.i_qp = x264_ratecontrol_qp( h ); + if( h->param.rc.i_aq_mode ) + x264_adaptive_quant( h ); + + x264_mb_analyse_init( h, &analysis, h->mb.i_qp ); /*--------------------------- Do the analysis ---------------------------*/ if( h->sh.i_type == SLICE_TYPE_I ) @@ -1923,11 +2092,16 @@ void x264_macroblock_analyse( x264_t *h ) int b_skip = 0; int i_intra_cost, i_intra_type; + h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 0 ); + /* Fast P_SKIP detection */ analysis.b_try_pskip = 0; if( h->param.analyse.b_fast_pskip ) { - if( h->param.analyse.i_subpel_refine >= 3 ) + if( h->param.i_threads > 1 && h->mb.cache.pskip_mv[1] > h->mb.mv_max_spel[1] ) + // FIXME don't need to check this if the reference frame is done + {} + else if( h->param.analyse.i_subpel_refine >= 3 ) analysis.b_try_pskip = 1; else if( h->mb.i_mb_type_left == P_SKIP || h->mb.i_mb_type_top == P_SKIP || @@ -1936,10 +2110,13 @@ void x264_macroblock_analyse( x264_t *h ) b_skip = x264_macroblock_probe_pskip( h ); } + h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 1 ); + if( b_skip ) { h->mb.i_type = P_SKIP; h->mb.i_partition = D_16x16; + assert( h->mb.cache.pskip_mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 ); } else { @@ -2126,6 +2303,7 @@ void x264_macroblock_analyse( x264_t *h ) h->mb.i_type = i_type; h->stat.frame.i_intra_cost += i_intra_cost; h->stat.frame.i_inter_cost += i_cost; + h->stat.frame.i_mbs_analysed++; if( h->mb.i_subpel_refine >= 7 ) { @@ -2206,7 +2384,7 @@ void x264_macroblock_analyse( x264_t *h ) i_bskip_cost = ssd_mb( h ); /* 6 = minimum cavlc cost of a non-skipped MB */ - if( i_bskip_cost <= 6 * analysis.i_lambda2 ) + if( i_bskip_cost <= ((6 * analysis.i_lambda2 + 128) >> 8) ) { h->mb.i_type = B_SKIP; x264_analyse_update_cache( h, &analysis ); @@ -2398,7 +2576,9 @@ void x264_macroblock_analyse( x264_t *h ) h->mb.i_type = i_type; h->mb.i_partition = i_partition; - if( h->param.analyse.b_bidir_me ) + if( h->mb.i_subpel_refine >= 7 && IS_INTRA( i_type ) ) + x264_intra_rd_refine( h, &analysis ); + else if( h->param.analyse.b_bidir_me ) refine_bidir( h, &analysis ); } } @@ -2410,6 +2590,8 @@ void x264_macroblock_analyse( x264_t *h ) h->mb.b_trellis = h->param.analyse.i_trellis; h->mb.b_noise_reduction = h->param.analyse.i_noise_reduction; + if( h->mb.b_trellis == 1 || h->mb.b_noise_reduction ) + h->mb.i_skip_intra = 0; } /*-------------------- Update MB from the analysis ----------------------*/ @@ -2475,12 +2657,10 @@ static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a ) case P_SKIP: { - int mvp[2]; - x264_mb_predict_mv_pskip( h, mvp ); - /* */ h->mb.i_partition = D_16x16; x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, 0 ); - x264_macroblock_cache_mv ( h, 0, 0, 4, 4, 0, mvp[0], mvp[1] ); + x264_macroblock_cache_mv ( h, 0, 0, 4, 4, 0, h->mb.cache.pskip_mv[0], + h->mb.cache.pskip_mv[1] ); break; } @@ -2542,7 +2722,38 @@ static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a ) break; } } + +#ifndef NDEBUG + if( h->param.i_threads > 1 && !IS_INTRA(h->mb.i_type) ) + { + int l; + for( l=0; l <= (h->sh.i_type == SLICE_TYPE_B); l++ ) + { + int completed; + int ref = h->mb.cache.ref[l][x264_scan8[0]]; + if( ref < 0 ) + continue; + completed = (l ? h->fref1 : h->fref0)[ ref >> h->mb.b_interlaced ]->i_lines_completed; + if( (h->mb.cache.mv[l][x264_scan8[15]][1] >> (2 - h->mb.b_interlaced)) + h->mb.i_mb_y*16 > completed ) + { + x264_log( h, X264_LOG_WARNING, "internal error (MV out of thread range)\n"); + fprintf(stderr, "mb type: %d \n", h->mb.i_type); + fprintf(stderr, "mv: l%dr%d (%d,%d) \n", l, ref, + h->mb.cache.mv[l][x264_scan8[15]][0], + h->mb.cache.mv[l][x264_scan8[15]][1] ); + fprintf(stderr, "limit: %d \n", h->mb.mv_max_spel[1]); + fprintf(stderr, "mb_xy: %d,%d \n", h->mb.i_mb_x, h->mb.i_mb_y); + fprintf(stderr, "completed: %d \n", completed ); + x264_log( h, X264_LOG_WARNING, "recovering by using intra mode\n"); + x264_mb_analyse_intra( h, a, COST_MAX ); + h->mb.i_type = I_16x16; + h->mb.i_intra16x16_pred_mode = a->i_predict16x16; + x264_mb_analyse_intra_chroma( h, a ); + } + } + } +#endif } -#include "slicetype_decision.c" +#include "slicetype.c"