From 0c917fc9755108887901bc0ea44e1952de8a2c65 Mon Sep 17 00:00:00 2001 From: Deb Mukherjee Date: Wed, 7 Nov 2012 06:50:25 -0800 Subject: [PATCH] Compound inter-intra experiment A patch on compound inter-intra prediction. In compound inter-intra prediction, a new predictor for 16x16 inter coded MBs are obtained by combining a single inter predictor with a 16x16 intra predictor, in a manner that the weight varies with distance from the top/left boundary. The current search strategy is to combine the best inter mode with the best intra mode obtained independently. Results so far: derf +0.31% yt +0.32% std-hd +0.35% hd +0.42% It is conceivable that the results would improve somewhat with a more thorough search strategy where all intra modes are searched given the best mv, or even a joint search for the best mv and the best intra mode. Change-Id: I7951f1ed0d6eb31ca32ac24d120f1585bcd8d79b --- configure | 1 + vp9/common/blockd.h | 4 + vp9/common/entropymode.c | 29 +++ vp9/common/entropymode.h | 7 + vp9/common/findnearmv.h | 14 +- vp9/common/mvref_common.c | 10 +- vp9/common/onyxc_int.h | 8 + vp9/common/pred_common.c | 4 +- vp9/common/reconinter.c | 30 +-- vp9/common/reconintra.c | 302 +++++++++++++++++++++++++++++- vp9/common/reconintra.h | 15 ++ vp9/decoder/decodemv.c | 60 ++++-- vp9/decoder/decodframe.c | 50 +++-- vp9/encoder/bitstream.c | 65 ++++++- vp9/encoder/encodeframe.c | 24 ++- vp9/encoder/encodemv.c | 8 +- vp9/encoder/onyx_if.c | 104 +++++++++++ vp9/encoder/onyx_int.h | 50 ++++- vp9/encoder/ratectrl.c | 6 + vp9/encoder/rdopt.c | 378 ++++++++++++++++++++++++++------------ 20 files changed, 982 insertions(+), 187 deletions(-) diff --git a/configure b/configure index c1ee96dda..d1d25b3d5 100755 --- a/configure +++ b/configure @@ -246,6 +246,7 @@ EXPERIMENT_LIST=" new_mvref implicit_segmentation newbintramodes + comp_interintra_pred " CONFIG_LIST=" external_build diff --git a/vp9/common/blockd.h b/vp9/common/blockd.h index b3c8ff33c..412d2bc93 100644 --- a/vp9/common/blockd.h +++ b/vp9/common/blockd.h @@ -214,6 +214,7 @@ union b_mode_info { }; typedef enum { + NONE = -1, INTRA_FRAME = 0, LAST_FRAME = 1, GOLDEN_FRAME = 2, @@ -225,6 +226,9 @@ typedef struct { MB_PREDICTION_MODE mode, uv_mode; #if CONFIG_COMP_INTRA_PRED MB_PREDICTION_MODE second_mode, second_uv_mode; +#endif +#if CONFIG_COMP_INTERINTRA_PRED + MB_PREDICTION_MODE interintra_mode, interintra_uv_mode; #endif MV_REFERENCE_FRAME ref_frame, second_ref_frame; TX_SIZE txfm_size; diff --git a/vp9/common/entropymode.c b/vp9/common/entropymode.c index d0e83ecb2..83ba21c55 100644 --- a/vp9/common/entropymode.c +++ b/vp9/common/entropymode.c @@ -345,6 +345,9 @@ void vp9_init_mbmode_probs(VP9_COMMON *x) { vpx_memcpy(x->fc.mbsplit_prob, vp9_mbsplit_probs, sizeof(vp9_mbsplit_probs)); vpx_memcpy(x->fc.switchable_interp_prob, vp9_switchable_interp_prob, sizeof(vp9_switchable_interp_prob)); +#if CONFIG_COMP_INTERINTRA_PRED + x->fc.interintra_prob = VP9_DEF_INTERINTRA_PROB; +#endif } @@ -547,6 +550,9 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) { vp9_prob i8x8_mode_probs[VP9_I8X8_MODES - 1]; vp9_prob sub_mv_ref_probs[VP9_SUBMVREFS - 1]; vp9_prob mbsplit_probs[VP9_NUMMBSPLITS - 1]; +#if CONFIG_COMP_INTERINTRA_PRED + vp9_prob interintra_prob; +#endif #ifdef MODE_COUNT_TESTING printf("static const unsigned int\nymode_counts" "[VP9_YMODES] = {\n"); @@ -581,6 +587,12 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) { "[VP9_NUMMBSPLITS] = {\n"); for (t = 0; t < VP9_NUMMBSPLITS; ++t) printf("%d, ", cm->fc.mbsplit_counts[t]); printf("};\n"); +#if CONFIG_COMP_INTERINTRA_PRED + printf("static const unsigned int\ninterintra_counts" + "[2] = {\n"); + for (t = 0; t < 2; ++t) printf("%d, ", cm->fc.interintra_counts[t]); + printf("};\n"); +#endif #endif vp9_tree_probs_from_distribution( VP9_YMODES, vp9_ymode_encodings, vp9_ymode_tree, @@ -673,4 +685,21 @@ void vp9_adapt_mode_probs(VP9_COMMON *cm) { else if (prob > 255) cm->fc.mbsplit_prob[t] = 255; else cm->fc.mbsplit_prob[t] = prob; } +#if CONFIG_COMP_INTERINTRA_PRED + if (cm->use_interintra) { + int prob; + interintra_prob = vp9_bin_prob_from_distribution(cm->fc.interintra_counts); + count = cm->fc.interintra_counts[0] + cm->fc.interintra_counts[1]; + count = count > MODE_COUNT_SAT ? MODE_COUNT_SAT : count; + factor = (MODE_MAX_UPDATE_FACTOR * count / MODE_COUNT_SAT); + prob = ((int)cm->fc.pre_interintra_prob * (256 - factor) + + (int)interintra_prob * factor + 128) >> 8; + if (prob <= 0) + cm->fc.interintra_prob = 1; + else if (prob > 255) + cm->fc.interintra_prob = 255; + else + cm->fc.interintra_prob = prob; + } +#endif } diff --git a/vp9/common/entropymode.h b/vp9/common/entropymode.h index 34a2bea03..790f5597b 100644 --- a/vp9/common/entropymode.h +++ b/vp9/common/entropymode.h @@ -21,6 +21,13 @@ #define DEFAULT_COMP_INTRA_PROB 32 #endif +#if CONFIG_COMP_INTERINTRA_PRED +#define VP9_DEF_INTERINTRA_PROB 248 +#define VP9_UPD_INTERINTRA_PROB 192 +// whether to use a separate uv mode (1) or use the same as the y mode (0) +#define SEPARATE_INTERINTRA_UV 0 +#endif + typedef const int vp9_mbsplit[16]; extern vp9_mbsplit vp9_mbsplits[VP9_NUMMBSPLITS]; diff --git a/vp9/common/findnearmv.h b/vp9/common/findnearmv.h index 64233ec23..256745261 100644 --- a/vp9/common/findnearmv.h +++ b/vp9/common/findnearmv.h @@ -104,11 +104,14 @@ static int left_block_second_mv(const MODE_INFO *cur_mb, int b) { --cur_mb; if (cur_mb->mbmi.mode != SPLITMV) - return cur_mb->mbmi.second_ref_frame ? cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int; + return cur_mb->mbmi.second_ref_frame > 0 ? + cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int; b += 4; } - return cur_mb->mbmi.second_ref_frame ? (cur_mb->bmi + b - 1)->as_mv.second.as_int : (cur_mb->bmi + b - 1)->as_mv.first.as_int; + return cur_mb->mbmi.second_ref_frame > 0 ? + (cur_mb->bmi + b - 1)->as_mv.second.as_int : + (cur_mb->bmi + b - 1)->as_mv.first.as_int; } static int above_block_mv(const MODE_INFO *cur_mb, int b, int mi_stride) { @@ -130,11 +133,14 @@ static int above_block_second_mv(const MODE_INFO *cur_mb, int b, int mi_stride) cur_mb -= mi_stride; if (cur_mb->mbmi.mode != SPLITMV) - return cur_mb->mbmi.second_ref_frame ? cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int; + return cur_mb->mbmi.second_ref_frame > 0 ? + cur_mb->mbmi.mv[1].as_int : cur_mb->mbmi.mv[0].as_int; b += 16; } - return cur_mb->mbmi.second_ref_frame ? (cur_mb->bmi + b - 4)->as_mv.second.as_int : (cur_mb->bmi + b - 4)->as_mv.first.as_int; + return cur_mb->mbmi.second_ref_frame > 0 ? + (cur_mb->bmi + b - 4)->as_mv.second.as_int : + (cur_mb->bmi + b - 4)->as_mv.first.as_int; } static B_PREDICTION_MODE left_block_mode(const MODE_INFO *cur_mb, int b) { diff --git a/vp9/common/mvref_common.c b/vp9/common/mvref_common.c index a412a6c8a..0f5673697 100644 --- a/vp9/common/mvref_common.c +++ b/vp9/common/mvref_common.c @@ -54,7 +54,7 @@ static int get_candidate_mvref( ret_val = TRUE; // Is there a second non zero vector we can use. - if ((candidate_mi->mbmi.second_ref_frame != INTRA_FRAME) && + if ((candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) && (candidate_mi->mbmi.mv[1].as_int != 0) && (candidate_mi->mbmi.mv[1].as_int != c_mv->as_int)) { c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int; @@ -68,7 +68,7 @@ static int get_candidate_mvref( ret_val = TRUE; // Is there a second non zero vector we can use. - if ((candidate_mi->mbmi.ref_frame != INTRA_FRAME) && + if ((candidate_mi->mbmi.ref_frame > INTRA_FRAME) && (candidate_mi->mbmi.mv[0].as_int != 0) && (candidate_mi->mbmi.mv[0].as_int != c_mv->as_int)) { c2_mv->as_int = candidate_mi->mbmi.mv[0].as_int; @@ -76,13 +76,13 @@ static int get_candidate_mvref( } // No ref frame matches so use first ref mv as first choice - } else if (candidate_mi->mbmi.ref_frame != INTRA_FRAME) { + } else if (candidate_mi->mbmi.ref_frame > INTRA_FRAME) { c_mv->as_int = candidate_mi->mbmi.mv[0].as_int; *c_ref_frame = candidate_mi->mbmi.ref_frame; ret_val = TRUE; // Is there a second non zero vector we can use. - if ((candidate_mi->mbmi.second_ref_frame != INTRA_FRAME) && + if ((candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) && (candidate_mi->mbmi.mv[1].as_int != 0) && (candidate_mi->mbmi.mv[1].as_int != c_mv->as_int)) { c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int; @@ -91,7 +91,7 @@ static int get_candidate_mvref( // If only the second ref mv is valid:- (Should not trigger in current code // base given current possible compound prediction options). - } else if (candidate_mi->mbmi.second_ref_frame != INTRA_FRAME) { + } else if (candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) { c_mv->as_int = candidate_mi->mbmi.mv[1].as_int; *c_ref_frame = candidate_mi->mbmi.second_ref_frame; ret_val = TRUE; diff --git a/vp9/common/onyxc_int.h b/vp9/common/onyxc_int.h index 516bea3cc..f51cfd529 100644 --- a/vp9/common/onyxc_int.h +++ b/vp9/common/onyxc_int.h @@ -106,6 +106,11 @@ typedef struct frame_contexts { nmv_context_counts NMVcount; vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1] [VP9_SWITCHABLE_FILTERS - 1]; +#if CONFIG_COMP_INTERINTRA_PRED + unsigned int interintra_counts[2]; + vp9_prob interintra_prob; + vp9_prob pre_interintra_prob; +#endif int mode_context[INTER_MODE_CONTEXTS][4]; int mode_context_a[INTER_MODE_CONTEXTS][4]; @@ -311,6 +316,9 @@ typedef struct VP9Common { // 2=specified per MB (1=filtered, 0=non-filtered) vp9_prob prob_pred_filter_off; #endif +#if CONFIG_COMP_INTERINTRA_PRED + int use_interintra; +#endif } VP9_COMMON; diff --git a/vp9/common/pred_common.c b/vp9/common/pred_common.c index bac7a0962..d779c641d 100644 --- a/vp9/common/pred_common.c +++ b/vp9/common/pred_common.c @@ -40,8 +40,8 @@ unsigned char vp9_get_pred_context(const VP9_COMMON *const cm, case PRED_COMP: // Context based on use of comp pred flag by neighbours // pred_context = - // ((m - 1)->mbmi.second_ref_frame != INTRA_FRAME) + - // ((m - cm->mode_info_stride)->mbmi.second_ref_frame != INTRA_FRAME); + // ((m - 1)->mbmi.second_ref_frame > INTRA_FRAME) + + // ((m - cm->mode_info_stride)->mbmi.second_ref_frame > INTRA_FRAME); // Context based on mode and reference frame // if ( m->mbmi.ref_frame == LAST_FRAME ) diff --git a/vp9/common/reconinter.c b/vp9/common/reconinter.c index 8b81b28c7..b67cec798 100644 --- a/vp9/common/reconinter.c +++ b/vp9/common/reconinter.c @@ -14,6 +14,7 @@ #include "subpixel.h" #include "blockd.h" #include "reconinter.h" +#include "vp9/common/reconintra.h" #if CONFIG_RUNTIME_CPU_DETECT #include "onyxc_int.h" #endif @@ -511,7 +512,7 @@ void vp9_build_inter4x4_predictors_mbuv(MACROBLOCKD *xd) { blockd[voffset].bmi.as_mv.first.as_mv.col = blockd[uoffset].bmi.as_mv.first.as_mv.col; - if (xd->mode_info_context->mbmi.second_ref_frame) { + if (xd->mode_info_context->mbmi.second_ref_frame > 0) { temp = blockd[yoffset ].bmi.as_mv.second.as_mv.row + blockd[yoffset + 1].bmi.as_mv.second.as_mv.row + blockd[yoffset + 4].bmi.as_mv.second.as_mv.row @@ -559,7 +560,7 @@ void vp9_build_inter4x4_predictors_mbuv(MACROBLOCKD *xd) { vp9_build_inter_predictors_b(d1, 8, xd->subpixel_predict); } - if (xd->mode_info_context->mbmi.second_ref_frame) { + if (xd->mode_info_context->mbmi.second_ref_frame > 0) { vp9_build_2nd_inter_predictors_b(d0, 8, xd->subpixel_predict_avg); vp9_build_2nd_inter_predictors_b(d1, 8, xd->subpixel_predict_avg); } @@ -777,7 +778,7 @@ void vp9_build_inter32x32_predictors_sb(MACROBLOCKD *x, dst_u + y_idx * 8 * dst_uvstride + x_idx * 8, dst_v + y_idx * 8 * dst_uvstride + x_idx * 8, dst_ystride, dst_uvstride); - if (x->mode_info_context->mbmi.second_ref_frame) { + if (x->mode_info_context->mbmi.second_ref_frame > 0) { x->second_pre.y_buffer = y2 + y_idx * 16 * x->pre.y_stride + x_idx * 16; x->second_pre.u_buffer = u2 + y_idx * 8 * x->pre.uv_stride + x_idx * 8; x->second_pre.v_buffer = v2 + y_idx * 8 * x->pre.uv_stride + x_idx * 8; @@ -799,7 +800,7 @@ void vp9_build_inter32x32_predictors_sb(MACROBLOCKD *x, x->pre.u_buffer = u1; x->pre.v_buffer = v1; - if (x->mode_info_context->mbmi.second_ref_frame) { + if (x->mode_info_context->mbmi.second_ref_frame > 0) { x->second_pre.y_buffer = y2; x->second_pre.u_buffer = u2; x->second_pre.v_buffer = v2; @@ -979,7 +980,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *xd) { clamp_mv_to_umv_border(&blockd[ 2].bmi.as_mv.first.as_mv, xd); clamp_mv_to_umv_border(&blockd[ 8].bmi.as_mv.first.as_mv, xd); clamp_mv_to_umv_border(&blockd[10].bmi.as_mv.first.as_mv, xd); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { clamp_mv_to_umv_border(&blockd[ 0].bmi.as_mv.second.as_mv, xd); clamp_mv_to_umv_border(&blockd[ 2].bmi.as_mv.second.as_mv, xd); clamp_mv_to_umv_border(&blockd[ 8].bmi.as_mv.second.as_mv, xd); @@ -993,7 +994,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *xd) { vp9_build_inter_predictors4b(xd, &blockd[ 8], 16); vp9_build_inter_predictors4b(xd, &blockd[10], 16); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { vp9_build_2nd_inter_predictors4b(xd, &blockd[ 0], 16); vp9_build_2nd_inter_predictors4b(xd, &blockd[ 2], 16); vp9_build_2nd_inter_predictors4b(xd, &blockd[ 8], 16); @@ -1010,7 +1011,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *xd) { if (mbmi->need_to_clamp_mvs) { clamp_mv_to_umv_border(&blockd[i + 0].bmi.as_mv.first.as_mv, xd); clamp_mv_to_umv_border(&blockd[i + 1].bmi.as_mv.first.as_mv, xd); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { clamp_mv_to_umv_border(&blockd[i + 0].bmi.as_mv.second.as_mv, xd); clamp_mv_to_umv_border(&blockd[i + 1].bmi.as_mv.second.as_mv, xd); } @@ -1023,7 +1024,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *xd) { vp9_build_inter_predictors_b(d1, 16, xd->subpixel_predict); } - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { vp9_build_2nd_inter_predictors_b(d0, 16, xd->subpixel_predict_avg); vp9_build_2nd_inter_predictors_b(d1, 16, xd->subpixel_predict_avg); } @@ -1041,7 +1042,7 @@ static void build_inter4x4_predictors_mb(MACROBLOCKD *xd) { vp9_build_inter_predictors_b(d1, 8, xd->subpixel_predict); } - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { vp9_build_2nd_inter_predictors_b(d0, 8, xd->subpixel_predict_avg); vp9_build_2nd_inter_predictors_b(d1, 8, xd->subpixel_predict_avg); } @@ -1094,7 +1095,7 @@ void build_4x4uvmvs(MACROBLOCKD *xd) { blockd[voffset].bmi.as_mv.first.as_mv.col = blockd[uoffset].bmi.as_mv.first.as_mv.col; - if (xd->mode_info_context->mbmi.second_ref_frame) { + if (xd->mode_info_context->mbmi.second_ref_frame > 0) { temp = xd->mode_info_context->bmi[yoffset + 0].as_mv.second.as_mv.row + xd->mode_info_context->bmi[yoffset + 1].as_mv.second.as_mv.row + xd->mode_info_context->bmi[yoffset + 4].as_mv.second.as_mv.row @@ -1146,7 +1147,7 @@ void vp9_build_inter_predictors_mb(MACROBLOCKD *xd) { &xd->predictor[256], &xd->predictor[320], 16, 8); - if (xd->mode_info_context->mbmi.second_ref_frame) { + if (xd->mode_info_context->mbmi.second_ref_frame > 0) { /* 256 = offset of U plane in Y+U+V buffer; * 320 = offset of V plane in Y+U+V buffer. * (256=16x16, 320=16x16+8x8). */ @@ -1154,6 +1155,13 @@ void vp9_build_inter_predictors_mb(MACROBLOCKD *xd) { &xd->predictor[256], &xd->predictor[320], 16, 8); } +#if CONFIG_COMP_INTERINTRA_PRED + else if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) { + vp9_build_interintra_16x16_predictors_mb(xd, xd->predictor, + &xd->predictor[256], + &xd->predictor[320], 16, 8); + } +#endif } else { build_4x4uvmvs(xd); build_inter4x4_predictors_mb(xd); diff --git a/vp9/common/reconintra.c b/vp9/common/reconintra.c index c9b8bd052..2964ff462 100644 --- a/vp9/common/reconintra.c +++ b/vp9/common/reconintra.c @@ -372,6 +372,294 @@ void vp9_build_intra_predictors_internal(unsigned char *src, int src_stride, } } +#if CONFIG_COMP_INTERINTRA_PRED +static void combine_interintra(MB_PREDICTION_MODE mode, + unsigned char *interpred, + int interstride, + unsigned char *intrapred, + int intrastride, + int size) { + // TODO(debargha): Explore different ways of combining predictors + // or designing the tables below + static const int scale_bits = 8; + static const int scale_max = 1 << scale_bits; + static const int scale_round = (1 << scale_bits) - 1; + // This table is a function A + B*exp(-kx), where x is hor. index + static const int weights1d[32] = { + 128, 122, 116, 111, 107, 103, 99, 96, + 93, 90, 88, 85, 83, 81, 80, 78, + 77, 76, 75, 74, 73, 72, 71, 70, + 70, 69, 69, 68, 68, 68, 67, 67, + }; + // This table is a function A + B*exp(-k.sqrt(xy)), where x, y are + // hor. and vert. indices + static const int weights2d[1024] = { + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 122, 120, 118, 116, 115, 114, 113, + 112, 111, 111, 110, 109, 109, 108, 107, + 107, 106, 106, 105, 105, 104, 104, 104, + 103, 103, 102, 102, 102, 101, 101, 101, + 128, 120, 116, 114, 112, 111, 109, 108, + 107, 106, 105, 104, 103, 102, 102, 101, + 100, 100, 99, 99, 98, 97, 97, 96, + 96, 96, 95, 95, 94, 94, 93, 93, + 128, 118, 114, 111, 109, 107, 106, 104, + 103, 102, 101, 100, 99, 98, 97, 97, + 96, 95, 95, 94, 93, 93, 92, 92, + 91, 91, 90, 90, 90, 89, 89, 88, + 128, 116, 112, 109, 107, 105, 103, 102, + 100, 99, 98, 97, 96, 95, 94, 93, + 93, 92, 91, 91, 90, 90, 89, 89, + 88, 88, 87, 87, 86, 86, 85, 85, + 128, 115, 111, 107, 105, 103, 101, 99, + 98, 97, 96, 94, 93, 93, 92, 91, + 90, 89, 89, 88, 88, 87, 86, 86, + 85, 85, 84, 84, 84, 83, 83, 82, + 128, 114, 109, 106, 103, 101, 99, 97, + 96, 95, 93, 92, 91, 90, 90, 89, + 88, 87, 87, 86, 85, 85, 84, 84, + 83, 83, 82, 82, 82, 81, 81, 80, + 128, 113, 108, 104, 102, 99, 97, 96, + 94, 93, 92, 91, 90, 89, 88, 87, + 86, 85, 85, 84, 84, 83, 83, 82, + 82, 81, 81, 80, 80, 79, 79, 79, + 128, 112, 107, 103, 100, 98, 96, 94, + 93, 91, 90, 89, 88, 87, 86, 85, + 85, 84, 83, 83, 82, 82, 81, 80, + 80, 80, 79, 79, 78, 78, 78, 77, + 128, 111, 106, 102, 99, 97, 95, 93, + 91, 90, 89, 88, 87, 86, 85, 84, + 83, 83, 82, 81, 81, 80, 80, 79, + 79, 78, 78, 77, 77, 77, 76, 76, + 128, 111, 105, 101, 98, 96, 93, 92, + 90, 89, 88, 86, 85, 84, 84, 83, + 82, 81, 81, 80, 80, 79, 79, 78, + 78, 77, 77, 76, 76, 76, 75, 75, + 128, 110, 104, 100, 97, 94, 92, 91, + 89, 88, 86, 85, 84, 83, 83, 82, + 81, 80, 80, 79, 79, 78, 78, 77, + 77, 76, 76, 75, 75, 75, 74, 74, + 128, 109, 103, 99, 96, 93, 91, 90, + 88, 87, 85, 84, 83, 82, 82, 81, + 80, 79, 79, 78, 78, 77, 77, 76, + 76, 75, 75, 75, 74, 74, 74, 73, + 128, 109, 102, 98, 95, 93, 90, 89, + 87, 86, 84, 83, 82, 81, 81, 80, + 79, 78, 78, 77, 77, 76, 76, 75, + 75, 75, 74, 74, 73, 73, 73, 73, + 128, 108, 102, 97, 94, 92, 90, 88, + 86, 85, 84, 83, 82, 81, 80, 79, + 78, 78, 77, 77, 76, 76, 75, 75, + 74, 74, 73, 73, 73, 73, 72, 72, + 128, 107, 101, 97, 93, 91, 89, 87, + 85, 84, 83, 82, 81, 80, 79, 78, + 78, 77, 76, 76, 75, 75, 74, 74, + 74, 73, 73, 73, 72, 72, 72, 71, + 128, 107, 100, 96, 93, 90, 88, 86, + 85, 83, 82, 81, 80, 79, 78, 78, + 77, 76, 76, 75, 75, 74, 74, 73, + 73, 73, 72, 72, 72, 71, 71, 71, + 128, 106, 100, 95, 92, 89, 87, 85, + 84, 83, 81, 80, 79, 78, 78, 77, + 76, 76, 75, 75, 74, 74, 73, 73, + 72, 72, 72, 72, 71, 71, 71, 70, + 128, 106, 99, 95, 91, 89, 87, 85, + 83, 82, 81, 80, 79, 78, 77, 76, + 76, 75, 75, 74, 74, 73, 73, 72, + 72, 72, 71, 71, 71, 71, 70, 70, + 128, 105, 99, 94, 91, 88, 86, 84, + 83, 81, 80, 79, 78, 77, 77, 76, + 75, 75, 74, 74, 73, 73, 72, 72, + 72, 71, 71, 71, 70, 70, 70, 70, + 128, 105, 98, 93, 90, 88, 85, 84, + 82, 81, 80, 79, 78, 77, 76, 75, + 75, 74, 74, 73, 73, 72, 72, 71, + 71, 71, 71, 70, 70, 70, 70, 69, + 128, 104, 97, 93, 90, 87, 85, 83, + 82, 80, 79, 78, 77, 76, 76, 75, + 74, 74, 73, 73, 72, 72, 71, 71, + 71, 70, 70, 70, 70, 69, 69, 69, + 128, 104, 97, 92, 89, 86, 84, 83, + 81, 80, 79, 78, 77, 76, 75, 74, + 74, 73, 73, 72, 72, 71, 71, 71, + 70, 70, 70, 70, 69, 69, 69, 69, + 128, 104, 96, 92, 89, 86, 84, 82, + 80, 79, 78, 77, 76, 75, 75, 74, + 73, 73, 72, 72, 71, 71, 71, 70, + 70, 70, 70, 69, 69, 69, 69, 68, + 128, 103, 96, 91, 88, 85, 83, 82, + 80, 79, 78, 77, 76, 75, 74, 74, + 73, 72, 72, 72, 71, 71, 70, 70, + 70, 70, 69, 69, 69, 69, 68, 68, + 128, 103, 96, 91, 88, 85, 83, 81, + 80, 78, 77, 76, 75, 75, 74, 73, + 73, 72, 72, 71, 71, 70, 70, 70, + 70, 69, 69, 69, 69, 68, 68, 68, + 128, 102, 95, 90, 87, 84, 82, 81, + 79, 78, 77, 76, 75, 74, 73, 73, + 72, 72, 71, 71, 71, 70, 70, 70, + 69, 69, 69, 69, 68, 68, 68, 68, + 128, 102, 95, 90, 87, 84, 82, 80, + 79, 77, 76, 75, 75, 74, 73, 73, + 72, 72, 71, 71, 70, 70, 70, 69, + 69, 69, 69, 68, 68, 68, 68, 68, + 128, 102, 94, 90, 86, 84, 82, 80, + 78, 77, 76, 75, 74, 73, 73, 72, + 72, 71, 71, 70, 70, 70, 69, 69, + 69, 69, 68, 68, 68, 68, 68, 67, + 128, 101, 94, 89, 86, 83, 81, 79, + 78, 77, 76, 75, 74, 73, 73, 72, + 71, 71, 71, 70, 70, 69, 69, 69, + 69, 68, 68, 68, 68, 68, 67, 67, + 128, 101, 93, 89, 85, 83, 81, 79, + 78, 76, 75, 74, 74, 73, 72, 72, + 71, 71, 70, 70, 70, 69, 69, 69, + 68, 68, 68, 68, 68, 67, 67, 67, + 128, 101, 93, 88, 85, 82, 80, 79, + 77, 76, 75, 74, 73, 73, 72, 71, + 71, 70, 70, 70, 69, 69, 69, 68, + 68, 68, 68, 68, 67, 67, 67, 67, + }; + int size_scale = (size == 32 ? 1 : + size == 16 ? 2 : + size == 8 ? 4 : 8); + int i, j; + switch (mode) { + case V_PRED: + for (i = 0; i < size; ++i) { + for (j = 0; j < size; ++j) { + int k = i * interstride + j; + int scale = weights1d[i * size_scale]; + interpred[k] = + ((scale_max - scale) * interpred[k] + + scale * intrapred[i * intrastride + j] + scale_round) + >> scale_bits; + } + } + break; + + case H_PRED: + for (i = 0; i < size; ++i) { + for (j = 0; j < size; ++j) { + int k = i * interstride + j; + int scale = weights1d[j * size_scale]; + interpred[k] = + ((scale_max - scale) * interpred[k] + + scale * intrapred[i * intrastride + j] + scale_round) + >> scale_bits; + } + } + break; + + case D63_PRED: + case D117_PRED: + for (i = 0; i < size; ++i) { + for (j = 0; j < size; ++j) { + int k = i * interstride + j; + int scale = (weights2d[i * size_scale * 32 + j * size_scale] + + weights1d[i * size_scale]) >> 1; + interpred[k] = + ((scale_max - scale) * interpred[k] + + scale * intrapred[i * intrastride + j] + scale_round) + >> scale_bits; + } + } + break; + + case D27_PRED: + case D153_PRED: + for (i = 0; i < size; ++i) { + for (j = 0; j < size; ++j) { + int k = i * interstride + j; + int scale = (weights2d[i * size_scale * 32 + j * size_scale] + + weights1d[j * size_scale]) >> 1; + interpred[k] = + ((scale_max - scale) * interpred[k] + + scale * intrapred[i * intrastride + j] + scale_round) + >> scale_bits; + } + } + break; + + case D135_PRED: + for (i = 0; i < size; ++i) { + for (j = 0; j < size; ++j) { + int k = i * interstride + j; + int scale = weights2d[i * size_scale * 32 + j * size_scale]; + interpred[k] = + ((scale_max - scale) * interpred[k] + + scale * intrapred[i * intrastride + j] + scale_round) + >> scale_bits; + } + } + break; + + case D45_PRED: + case DC_PRED: + case TM_PRED: + default: + // simple average + for (i = 0; i < size; ++i) { + for (j = 0; j < size; ++j) { + int k = i * interstride + j; + interpred[k] = (interpred[k] + intrapred[i * intrastride + j]) >> 1; + } + } + break; + } +} + +void vp9_build_interintra_16x16_predictors_mb(MACROBLOCKD *xd, + unsigned char *ypred, + unsigned char *upred, + unsigned char *vpred, + int ystride, int uvstride) { + vp9_build_interintra_16x16_predictors_mby(xd, ypred, ystride); + vp9_build_interintra_16x16_predictors_mbuv(xd, upred, vpred, uvstride); +} + +void vp9_build_interintra_16x16_predictors_mby(MACROBLOCKD *xd, + unsigned char *ypred, + int ystride) { + static const int scale_bits = 6; + unsigned char intrapredictor[256]; + int i, j; + vp9_build_intra_predictors_internal( + xd->dst.y_buffer, xd->dst.y_stride, + intrapredictor, 16, + xd->mode_info_context->mbmi.interintra_mode, 16, + xd->up_available, xd->left_available); + combine_interintra(xd->mode_info_context->mbmi.interintra_mode, + ypred, ystride, intrapredictor, 16, 16); +} + +void vp9_build_interintra_16x16_predictors_mbuv(MACROBLOCKD *xd, + unsigned char *upred, + unsigned char *vpred, + int uvstride) { + int i, j; + unsigned char uintrapredictor[64]; + unsigned char vintrapredictor[64]; + vp9_build_intra_predictors_internal( + xd->dst.u_buffer, xd->dst.uv_stride, + uintrapredictor, 8, + xd->mode_info_context->mbmi.interintra_uv_mode, 8, + xd->up_available, xd->left_available); + vp9_build_intra_predictors_internal( + xd->dst.v_buffer, xd->dst.uv_stride, + vintrapredictor, 8, + xd->mode_info_context->mbmi.interintra_uv_mode, 8, + xd->up_available, xd->left_available); + combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode, + upred, uvstride, uintrapredictor, 8, 8); + combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode, + vpred, uvstride, vintrapredictor, 8, 8); +} +#endif + void vp9_build_intra_predictors_mby(MACROBLOCKD *xd) { vp9_build_intra_predictors_internal(xd->dst.y_buffer, xd->dst.y_stride, xd->predictor, 16, @@ -460,11 +748,11 @@ void vp9_build_comp_intra_predictors_mbuv(MACROBLOCKD *xd) { int i; vp9_build_intra_predictors_mbuv_internal( - xd, predictor[0][0], predictor[1][0], 8, - xd->mode_info_context->mbmi.uv_mode, 8); + xd, predictor[0][0], predictor[1][0], 8, + xd->mode_info_context->mbmi.uv_mode, 8); vp9_build_intra_predictors_mbuv_internal( - xd, predictor[0][1], predictor[1][1], 8, - xd->mode_info_context->mbmi.second_uv_mode, 8); + xd, predictor[0][1], predictor[1][1], 8, + xd->mode_info_context->mbmi.second_uv_mode, 8); for (i = 0; i < 64; i++) { xd->predictor[256 + i] = (predictor[0][0][i] + predictor[0][1][i] + 1) >> 1; xd->predictor[256 + 64 + i] = (predictor[1][0][i] + @@ -526,6 +814,6 @@ void vp9_comp_intra_uv4x4_predict(BLOCKD *xd, #endif /* TODO: try different ways of use Y-UV mode correlation - Current code assumes that a uv 4x4 block use same mode - as corresponding Y 8x8 area - */ + Current code assumes that a uv 4x4 block use same mode + as corresponding Y 8x8 area + */ diff --git a/vp9/common/reconintra.h b/vp9/common/reconintra.h index 35a839db3..c72e8e912 100644 --- a/vp9/common/reconintra.h +++ b/vp9/common/reconintra.h @@ -17,5 +17,20 @@ extern void vp9_recon_intra_mbuv(MACROBLOCKD *xd); extern B_PREDICTION_MODE vp9_find_dominant_direction(unsigned char *ptr, int stride, int n); extern B_PREDICTION_MODE vp9_find_bpred_context(BLOCKD *x); +#if CONFIG_COMP_INTERINTRA_PRED +extern void vp9_build_interintra_16x16_predictors_mb(MACROBLOCKD *xd, + unsigned char *ypred, + unsigned char *upred, + unsigned char *vpred, + int ystride, + int uvstride); +extern void vp9_build_interintra_16x16_predictors_mby(MACROBLOCKD *xd, + unsigned char *ypred, + int ystride); +extern void vp9_build_interintra_16x16_predictors_mbuv(MACROBLOCKD *xd, + unsigned char *upred, + unsigned char *vpred, + int uvstride); +#endif #endif // __INC_RECONINTRA_H diff --git a/vp9/decoder/decodemv.c b/vp9/decoder/decodemv.c index e7560765a..467a2958d 100644 --- a/vp9/decoder/decodemv.c +++ b/vp9/decoder/decodemv.c @@ -531,6 +531,12 @@ static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *bc) { #endif if (cm->mcomp_filter_type == SWITCHABLE) read_switchable_interp_probs(pbi, bc); +#if CONFIG_COMP_INTERINTRA_PRED + if (cm->use_interintra) { + if (vp9_read(bc, VP9_UPD_INTERINTRA_PROB)) + cm->fc.interintra_prob = (vp9_prob)vp9_read_literal(bc, 8); + } +#endif // Decode the baseline probabilities for decoding reference frame cm->prob_intra_coded = (vp9_prob)vp9_read_literal(bc, 8); cm->prob_last_coded = (vp9_prob)vp9_read_literal(bc, 8); @@ -671,7 +677,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN; mbmi->need_to_clamp_mvs = 0; mbmi->need_to_clamp_secondmv = 0; - mbmi->second_ref_frame = 0; + mbmi->second_ref_frame = NONE; /* Distance of Mb to the various image edges. * These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units */ @@ -819,7 +825,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mbmi->second_ref_frame = mbmi->ref_frame + 1; if (mbmi->second_ref_frame == 4) mbmi->second_ref_frame = 1; - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { int second_ref_fb_idx; /* Select the appropriate reference frame for this MB */ if (mbmi->second_ref_frame == LAST_FRAME) @@ -852,7 +858,33 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, } } else { - mbmi->second_ref_frame = 0; +#if CONFIG_COMP_INTERINTRA_PRED + if (pbi->common.use_interintra && + mbmi->mode >= NEARESTMV && mbmi->mode < SPLITMV && + mbmi->second_ref_frame == NONE) { + mbmi->second_ref_frame = (vp9_read(bc, pbi->common.fc.interintra_prob) ? + INTRA_FRAME : NONE); + // printf("-- %d (%d)\n", mbmi->second_ref_frame == INTRA_FRAME, + // pbi->common.fc.interintra_prob); + pbi->common.fc.interintra_counts[ + mbmi->second_ref_frame == INTRA_FRAME]++; + if (mbmi->second_ref_frame == INTRA_FRAME) { + mbmi->interintra_mode = (MB_PREDICTION_MODE)read_ymode( + bc, pbi->common.fc.ymode_prob); + pbi->common.fc.ymode_counts[mbmi->interintra_mode]++; +#if SEPARATE_INTERINTRA_UV + mbmi->interintra_uv_mode = (MB_PREDICTION_MODE)read_uv_mode( + bc, pbi->common.fc.uv_mode_prob[mbmi->interintra_mode]); + pbi->common.fc.uv_mode_counts[mbmi->interintra_mode] + [mbmi->interintra_uv_mode]++; +#else + mbmi->interintra_uv_mode = mbmi->interintra_mode; +#endif + // printf("** %d %d\n", + // mbmi->interintra_mode, mbmi->interintra_uv_mode); + } + } +#endif } mbmi->uv_mode = DC_PRED; @@ -876,7 +908,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, leftmv.as_int = left_block_mv(mi, k); abovemv.as_int = above_block_mv(mi, k, mis); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { second_leftmv.as_int = left_block_second_mv(mi, k); second_abovemv.as_int = above_block_second_mv(mi, k, mis); } @@ -894,7 +926,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, blockmv.as_mv.row += best_mv.as_mv.row; blockmv.as_mv.col += best_mv.as_mv.col; - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { read_nmv(bc, &secondmv.as_mv, &best_mv_second.as_mv, nmvc); read_nmv_fp(bc, &secondmv.as_mv, &best_mv_second.as_mv, nmvc, xd->allow_high_precision_mv); @@ -909,7 +941,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, break; case LEFT4X4: blockmv.as_int = leftmv.as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) secondmv.as_int = second_leftmv.as_int; #ifdef VPX_MODE_COUNT vp9_mv_cont_count[mv_contz][0]++; @@ -917,7 +949,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, break; case ABOVE4X4: blockmv.as_int = abovemv.as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) secondmv.as_int = second_abovemv.as_int; #ifdef VPX_MODE_COUNT vp9_mv_cont_count[mv_contz][1]++; @@ -925,7 +957,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, break; case ZERO4X4: blockmv.as_int = 0; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) secondmv.as_int = 0; #ifdef VPX_MODE_COUNT vp9_mv_cont_count[mv_contz][2]++; @@ -940,7 +972,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { mbmi->need_to_clamp_mvs |= check_mv_bounds(&secondmv, mb_to_left_edge, mb_to_right_edge, @@ -959,7 +991,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, do { mi->bmi[ *fill_offset].as_mv.first.as_int = blockmv.as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) mi->bmi[ *fill_offset].as_mv.second.as_int = secondmv.as_int; fill_offset++; } while (--fill_count); @@ -978,7 +1010,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, /* Clip "next_nearest" so that it does not extend to far out of image */ clamp_mv(mv, mb_to_left_edge, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { mbmi->mv[1].as_int = nearby_second.as_int; clamp_mv(&mbmi->mv[1], mb_to_left_edge, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge); @@ -990,7 +1022,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, /* Clip "next_nearest" so that it does not extend to far out of image */ clamp_mv(mv, mb_to_left_edge, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { mbmi->mv[1].as_int = nearest_second.as_int; clamp_mv(&mbmi->mv[1], mb_to_left_edge, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge); @@ -999,7 +1031,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, case ZEROMV: mv->as_int = 0; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) mbmi->mv[1].as_int = 0; break; @@ -1038,7 +1070,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mb_to_top_edge, mb_to_bottom_edge); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { #if CONFIG_NEW_MVREF { int best_index; diff --git a/vp9/decoder/decodframe.c b/vp9/decoder/decodframe.c index 5b56b158a..d9413b7ab 100644 --- a/vp9/decoder/decodframe.c +++ b/vp9/decoder/decodframe.c @@ -185,20 +185,39 @@ static void skip_recon_mb(VP9D_COMP *pbi, MACROBLOCKD *xd) { } else { #if CONFIG_SUPERBLOCKS if (xd->mode_info_context->mbmi.encoded_as_sb) { - vp9_build_inter32x32_predictors_sb(xd, xd->dst.y_buffer, - xd->dst.u_buffer, xd->dst.v_buffer, - xd->dst.y_stride, xd->dst.uv_stride); + vp9_build_inter32x32_predictors_sb(xd, + xd->dst.y_buffer, + xd->dst.u_buffer, + xd->dst.v_buffer, + xd->dst.y_stride, + xd->dst.uv_stride); } else { #endif - vp9_build_1st_inter16x16_predictors_mb(xd, xd->dst.y_buffer, - xd->dst.u_buffer, xd->dst.v_buffer, - xd->dst.y_stride, xd->dst.uv_stride); + vp9_build_1st_inter16x16_predictors_mb(xd, + xd->dst.y_buffer, + xd->dst.u_buffer, + xd->dst.v_buffer, + xd->dst.y_stride, + xd->dst.uv_stride); - if (xd->mode_info_context->mbmi.second_ref_frame) { - vp9_build_2nd_inter16x16_predictors_mb(xd, xd->dst.y_buffer, - xd->dst.u_buffer, xd->dst.v_buffer, - xd->dst.y_stride, xd->dst.uv_stride); + if (xd->mode_info_context->mbmi.second_ref_frame > 0) { + vp9_build_2nd_inter16x16_predictors_mb(xd, + xd->dst.y_buffer, + xd->dst.u_buffer, + xd->dst.v_buffer, + xd->dst.y_stride, + xd->dst.uv_stride); } +#if CONFIG_COMP_INTERINTRA_PRED + else if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) { + vp9_build_interintra_16x16_predictors_mb(xd, + xd->dst.y_buffer, + xd->dst.u_buffer, + xd->dst.v_buffer, + xd->dst.y_stride, + xd->dst.uv_stride); + } +#endif #if CONFIG_SUPERBLOCKS } #endif @@ -707,7 +726,7 @@ decode_sb_row(VP9D_COMP *pbi, VP9_COMMON *pc, int mbrow, MACROBLOCKD *xd, xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset; xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset; - if (xd->mode_info_context->mbmi.second_ref_frame) { + if (xd->mode_info_context->mbmi.second_ref_frame > 0) { int second_ref_fb_idx; /* Select the appropriate reference frame for this MB */ @@ -1281,6 +1300,9 @@ int vp9_decode_frame(VP9D_COMP *pbi) { } else { pc->mcomp_filter_type = vp9_read_literal(&header_bc, 2); } +#if CONFIG_COMP_INTERINTRA_PRED + pc->use_interintra = vp9_read_bit(&header_bc); +#endif /* To enable choice of different interploation filters */ vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc); } @@ -1323,6 +1345,9 @@ int vp9_decode_frame(VP9D_COMP *pbi) { vp9_copy(pbi->common.fc.pre_i8x8_mode_prob, pbi->common.fc.i8x8_mode_prob); vp9_copy(pbi->common.fc.pre_sub_mv_ref_prob, pbi->common.fc.sub_mv_ref_prob); vp9_copy(pbi->common.fc.pre_mbsplit_prob, pbi->common.fc.mbsplit_prob); +#if CONFIG_COMP_INTERINTRA_PRED + pbi->common.fc.pre_interintra_prob = pbi->common.fc.interintra_prob; +#endif pbi->common.fc.pre_nmvc = pbi->common.fc.nmvc; vp9_zero(pbi->common.fc.coef_counts); vp9_zero(pbi->common.fc.hybrid_coef_counts); @@ -1339,6 +1364,9 @@ int vp9_decode_frame(VP9D_COMP *pbi) { vp9_zero(pbi->common.fc.NMVcount); vp9_zero(pbi->common.fc.mv_ref_ct); vp9_zero(pbi->common.fc.mv_ref_ct_a); +#if CONFIG_COMP_INTERINTRA_PRED + vp9_zero(pbi->common.fc.interintra_counts); +#endif read_coef_probs(pbi, &header_bc); diff --git a/vp9/encoder/bitstream.c b/vp9/encoder/bitstream.c index 65614a176..a71472df3 100644 --- a/vp9/encoder/bitstream.c +++ b/vp9/encoder/bitstream.c @@ -338,6 +338,21 @@ static int prob_diff_update_savings_search(const unsigned int *ct, return bestsavings; } +static void vp9_cond_prob_update(vp9_writer *bc, vp9_prob *oldp, vp9_prob upd, + unsigned int *ct) { + vp9_prob newp; + int savings; + newp = get_binary_prob(ct[0], ct[1]); + savings = prob_update_savings(ct, *oldp, newp, upd); + if (savings > 0) { + vp9_write(bc, 1, upd); + vp9_write_literal(bc, newp, 8); + *oldp = newp; + } else { + vp9_write(bc, 0, upd); + } +} + static void pack_mb_tokens(vp9_writer* const bc, TOKENEXTRA **tp, const TOKENEXTRA *const stop) { @@ -975,7 +990,7 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) { } } - if (mi->second_ref_frame && + if (mi->second_ref_frame > 0 && (mode == NEWMV || mode == SPLITMV)) { int_mv n1, n2; @@ -986,9 +1001,30 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) { // does the feature use compound prediction or not // (if not specified at the frame/segment level) if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) { - vp9_write(bc, mi->second_ref_frame != INTRA_FRAME, + vp9_write(bc, mi->second_ref_frame > INTRA_FRAME, vp9_get_pred_prob(pc, xd, PRED_COMP)); } +#if CONFIG_COMP_INTERINTRA_PRED + if (cpi->common.use_interintra && + mode >= NEARESTMV && mode < SPLITMV && + mi->second_ref_frame <= INTRA_FRAME) { + vp9_write(bc, mi->second_ref_frame == INTRA_FRAME, + pc->fc.interintra_prob); + // if (!cpi->dummy_packing) + // printf("-- %d (%d)\n", mi->second_ref_frame == INTRA_FRAME, + // pc->fc.interintra_prob); + if (mi->second_ref_frame == INTRA_FRAME) { + // if (!cpi->dummy_packing) + // printf("** %d %d\n", mi->interintra_mode, + // mi->interintra_uv_mode); + write_ymode(bc, mi->interintra_mode, pc->fc.ymode_prob); +#if SEPARATE_INTERINTRA_UV + write_uv_mode(bc, mi->interintra_uv_mode, + pc->fc.uv_mode_prob[mi->interintra_mode]); +#endif + } + } +#endif { switch (mode) { /* new, split require MVs */ @@ -1024,7 +1060,7 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) { (const nmv_context*) nmvc, xd->allow_high_precision_mv); - if (mi->second_ref_frame) { + if (mi->second_ref_frame > 0) { #if CONFIG_NEW_MVREF unsigned int best_index; sec_ref_frame = mi->second_ref_frame; @@ -1095,7 +1131,7 @@ static void pack_inter_mode_mvs(VP9_COMP *const cpi, vp9_writer *const bc) { (const nmv_context*) nmvc, xd->allow_high_precision_mv); - if (mi->second_ref_frame) { + if (mi->second_ref_frame > 0) { write_nmv(bc, &cpi->mb.partition_info->bmi[j].second_mv.as_mv, &best_second_mv, @@ -2021,6 +2057,15 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, vp9_write_bit(&header_bc, (pc->mcomp_filter_type == SWITCHABLE)); if (pc->mcomp_filter_type != SWITCHABLE) vp9_write_literal(&header_bc, (pc->mcomp_filter_type), 2); +#if CONFIG_COMP_INTERINTRA_PRED + // printf("Counts: %d %d\n", cpi->interintra_count[0], + // cpi->interintra_count[1]); + if (!cpi->dummy_packing && pc->use_interintra) + pc->use_interintra = (cpi->interintra_count[1] > 0); + vp9_write_bit(&header_bc, pc->use_interintra); + if (!pc->use_interintra) + vp9_zero(cpi->interintra_count); +#endif } vp9_write_bit(&header_bc, pc->refresh_entropy_probs); @@ -2050,6 +2095,9 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, vp9_copy(cpi->common.fc.pre_mbsplit_prob, cpi->common.fc.mbsplit_prob); vp9_copy(cpi->common.fc.pre_i8x8_mode_prob, cpi->common.fc.i8x8_mode_prob); cpi->common.fc.pre_nmvc = cpi->common.fc.nmvc; +#if CONFIG_COMP_INTERINTRA_PRED + cpi->common.fc.pre_interintra_prob = cpi->common.fc.interintra_prob; +#endif vp9_zero(cpi->sub_mv_ref_count); vp9_zero(cpi->mbsplit_count); vp9_zero(cpi->common.fc.mv_ref_ct) @@ -2094,6 +2142,14 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, #endif if (pc->mcomp_filter_type == SWITCHABLE) update_switchable_interp_probs(cpi, &header_bc); +#if CONFIG_COMP_INTERINTRA_PRED + if (pc->use_interintra) { + vp9_cond_prob_update(&header_bc, + &pc->fc.interintra_prob, + VP9_UPD_INTERINTRA_PROB, + cpi->interintra_count); + } +#endif vp9_write_literal(&header_bc, pc->prob_intra_coded, 8); vp9_write_literal(&header_bc, pc->prob_last_coded, 8); @@ -2116,7 +2172,6 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, } } } - update_mbintra_mode_probs(cpi, &header_bc); vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc); diff --git a/vp9/encoder/encodeframe.c b/vp9/encoder/encodeframe.c index 98e03d6f7..b91cd04a2 100644 --- a/vp9/encoder/encodeframe.c +++ b/vp9/encoder/encodeframe.c @@ -578,6 +578,20 @@ static void update_state(VP9_COMP *cpi, MACROBLOCK *x, mbmi->best_second_mv.as_int = best_second_mv.as_int; vp9_update_nmv_count(cpi, x, &best_mv, &best_second_mv); } +#if CONFIG_COMP_INTERINTRA_PRED + if (mbmi->mode >= NEARESTMV && mbmi->mode < SPLITMV && + mbmi->second_ref_frame <= INTRA_FRAME) { + if (mbmi->second_ref_frame == INTRA_FRAME) { + ++cpi->interintra_count[1]; + ++cpi->ymode_count[mbmi->interintra_mode]; +#if SEPARATE_INTERINTRA_UV + ++cpi->y_uv_mode_count[mbmi->interintra_mode][mbmi->interintra_uv_mode]; +#endif + } else { + ++cpi->interintra_count[0]; + } + } +#endif cpi->prediction_error += ctx->distortion; cpi->intra_error += ctx->intra_error; @@ -1114,7 +1128,7 @@ static void encode_sb(VP9_COMP *cpi, pred_context = vp9_get_pred_context(cm, xd, PRED_COMP); - if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) + if (xd->mode_info_context->mbmi.second_ref_frame <= INTRA_FRAME) cpi->single_pred_count[pred_context]++; else cpi->comp_pred_count[pred_context]++; @@ -1393,6 +1407,10 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) { vp9_zero(cpi->sb_ymode_count) cpi->sb_count = 0; #endif +#if CONFIG_COMP_INTERINTRA_PRED + vp9_zero(cpi->interintra_count); + vp9_zero(cpi->interintra_select_count); +#endif vpx_memset(cm->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols); @@ -2219,7 +2237,7 @@ static void encode_inter_macroblock(VP9_COMP *cpi, MACROBLOCK *x, xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset; xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset; - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { int second_ref_fb_idx; if (mbmi->second_ref_frame == LAST_FRAME) @@ -2406,7 +2424,7 @@ static void encode_inter_superblock(VP9_COMP *cpi, MACROBLOCK *x, xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset; xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset; - if (xd->mode_info_context->mbmi.second_ref_frame) { + if (xd->mode_info_context->mbmi.second_ref_frame > 0) { int second_ref_fb_idx; if (xd->mode_info_context->mbmi.second_ref_frame == LAST_FRAME) diff --git a/vp9/encoder/encodemv.c b/vp9/encoder/encodemv.c index 04aa95d03..8b9c170a1 100644 --- a/vp9/encoder/encodemv.c +++ b/vp9/encoder/encodemv.c @@ -610,7 +610,7 @@ void vp9_update_nmv_count(VP9_COMP *cpi, MACROBLOCK *x, mv.col = (x->partition_info->bmi[i].mv.as_mv.col - best_ref_mv->as_mv.col); vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 1); - if (x->e_mbd.mode_info_context->mbmi.second_ref_frame) { + if (x->e_mbd.mode_info_context->mbmi.second_ref_frame > 0) { mv.row = (x->partition_info->bmi[i].second_mv.as_mv.row - second_best_ref_mv->as_mv.row); mv.col = (x->partition_info->bmi[i].second_mv.as_mv.col @@ -624,7 +624,7 @@ void vp9_update_nmv_count(VP9_COMP *cpi, MACROBLOCK *x, mv.col = (x->partition_info->bmi[i].mv.as_mv.col - best_ref_mv->as_mv.col); vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 0); - if (x->e_mbd.mode_info_context->mbmi.second_ref_frame) { + if (x->e_mbd.mode_info_context->mbmi.second_ref_frame > 0) { mv.row = (x->partition_info->bmi[i].second_mv.as_mv.row - second_best_ref_mv->as_mv.row); mv.col = (x->partition_info->bmi[i].second_mv.as_mv.col @@ -640,7 +640,7 @@ void vp9_update_nmv_count(VP9_COMP *cpi, MACROBLOCK *x, mv.row = (mbmi->mv[0].as_mv.row - best_ref_mv->as_mv.row); mv.col = (mbmi->mv[0].as_mv.col - best_ref_mv->as_mv.col); vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 1); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { mv.row = (mbmi->mv[1].as_mv.row - second_best_ref_mv->as_mv.row); mv.col = (mbmi->mv[1].as_mv.col - second_best_ref_mv->as_mv.col); vp9_increment_nmv(&mv, &second_best_ref_mv->as_mv, &cpi->NMVcount, 1); @@ -649,7 +649,7 @@ void vp9_update_nmv_count(VP9_COMP *cpi, MACROBLOCK *x, mv.row = (mbmi->mv[0].as_mv.row - best_ref_mv->as_mv.row); mv.col = (mbmi->mv[0].as_mv.col - best_ref_mv->as_mv.col); vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount, 0); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { mv.row = (mbmi->mv[1].as_mv.row - second_best_ref_mv->as_mv.row); mv.col = (mbmi->mv[1].as_mv.col - second_best_ref_mv->as_mv.col); vp9_increment_nmv(&mv, &second_best_ref_mv->as_mv, &cpi->NMVcount, 0); diff --git a/vp9/encoder/onyx_if.c b/vp9/encoder/onyx_if.c index 249572d04..215436134 100644 --- a/vp9/encoder/onyx_if.c +++ b/vp9/encoder/onyx_if.c @@ -224,6 +224,7 @@ static void init_minq_luts(void) { } } + static void set_mvcost(MACROBLOCK *mb) { if (mb->e_mbd.allow_high_precision_mv) { mb->mvcost = mb->nmvcost_hp; @@ -788,6 +789,21 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->thresh_mult[THR_COMP_SPLITGA ] = 5000; sf->thresh_mult[THR_COMP_SPLITLG ] = 5000; +#if CONFIG_COMP_INTERINTRA_PRED + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWA ] = 0; +#endif + sf->first_step = 0; sf->max_step_search_steps = MAX_MVSEARCH_STEPS; sf->search_best_filter = SEARCH_BEST_FILTER; @@ -912,6 +928,20 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->thresh_mult[THR_COMP_SPLITLA ] = 1700; sf->thresh_mult[THR_COMP_SPLITGA ] = 4500; sf->thresh_mult[THR_COMP_SPLITLG ] = 4500; +#if CONFIG_COMP_INTERINTRA_PRED + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWA ] = 0; +#endif if (Speed > 0) { /* Disable coefficient optimization above speed 0 */ @@ -1002,6 +1032,20 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->thresh_mult[THR_COMP_NEWLG ] = 2000; sf->thresh_mult[THR_COMP_NEWLA ] = 2000; sf->thresh_mult[THR_COMP_NEWGA ] = 2000; +#if CONFIG_COMP_INTERINTRA_PRED + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWA ] = 0; +#endif } if (Speed > 2) { @@ -1077,6 +1121,20 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->thresh_mult[THR_COMP_NEWLG ] = 2500; sf->thresh_mult[THR_COMP_NEWLA ] = 2500; sf->thresh_mult[THR_COMP_NEWGA ] = 2500; +#if CONFIG_COMP_INTERINTRA_PRED + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWL ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWG ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARA ] = 0; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWA ] = 0; +#endif sf->improved_dct = 0; @@ -1115,6 +1173,12 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->thresh_mult[THR_ZEROG_FILT ] = INT_MAX; sf->thresh_mult[THR_NEARG_FILT ] = INT_MAX; sf->thresh_mult[THR_NEWG_FILT ] = INT_MAX; +#endif +#if CONFIG_COMP_INTERINTRA_PRED + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROG ] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARG ] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWG ] = INT_MAX; #endif sf->thresh_mult[THR_SPLITG ] = INT_MAX; } @@ -1129,6 +1193,12 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->thresh_mult[THR_ZEROA_FILT ] = INT_MAX; sf->thresh_mult[THR_NEARA_FILT ] = INT_MAX; sf->thresh_mult[THR_NEWA_FILT ] = INT_MAX; +#endif +#if CONFIG_COMP_INTERINTRA_PRED + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROA ] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARA ] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWA ] = INT_MAX; #endif sf->thresh_mult[THR_SPLITA ] = INT_MAX; } @@ -1156,6 +1226,14 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->thresh_mult[THR_COMP_NEWGA ] = INT_MAX; sf->thresh_mult[THR_COMP_SPLITGA ] = INT_MAX; } +#if CONFIG_COMP_INTERINTRA_PRED + if ((cpi->ref_frame_flags & VP9_LAST_FLAG) != VP9_LAST_FLAG) { + sf->thresh_mult[THR_COMP_INTERINTRA_ZEROL ] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEARL ] = INT_MAX; + sf->thresh_mult[THR_COMP_INTERINTRA_NEWL ] = INT_MAX; + } +#endif // Slow quant, dct and trellis not worthwhile for first pass // so make sure they are always turned off. @@ -2850,6 +2928,19 @@ void update_pred_filt_prob(VP9_COMP *cpi) { */ } #endif +#if CONFIG_COMP_INTERINTRA_PRED +static void select_interintra_mode(VP9_COMP *cpi) { + static const double threshold = 0.01; + VP9_COMMON *cm = &cpi->common; + // FIXME(debargha): Make this RD based + int sum = cpi->interintra_select_count[1] + cpi->interintra_select_count[0]; + if (sum) { + double fraction = (double) cpi->interintra_select_count[1] / sum; + // printf("fraction: %f\n", fraction); + cm->use_interintra = (fraction > threshold); + } +} +#endif static void encode_frame_to_data_rate ( @@ -3144,6 +3235,12 @@ static void encode_frame_to_data_rate set_mvcost(&cpi->mb); } +#if CONFIG_COMP_INTERINTRA_PRED + if (cm->current_video_frame == 0) { + cm->use_interintra = 1; + } +#endif + #if CONFIG_POSTPROC if (cpi->oxcf.noise_sensitivity > 0) { @@ -3634,6 +3731,9 @@ static void encode_frame_to_data_rate vp9_copy(cpi->common.fc.i8x8_mode_counts, cpi->i8x8_mode_count); vp9_copy(cpi->common.fc.sub_mv_ref_counts, cpi->sub_mv_ref_count); vp9_copy(cpi->common.fc.mbsplit_counts, cpi->mbsplit_count); +#if CONFIG_COMP_INTERINTRA_PRED + vp9_copy(cpi->common.fc.interintra_counts, cpi->interintra_count); +#endif vp9_adapt_mode_probs(&cpi->common); cpi->common.fc.NMVcount = cpi->NMVcount; @@ -3644,6 +3744,10 @@ static void encode_frame_to_data_rate vp9_adapt_nmv_probs(&cpi->common, cpi->mb.e_mbd.allow_high_precision_mv); vp9_update_mode_context(&cpi->common); } +#if CONFIG_COMP_INTERINTRA_PRED + if (cm->frame_type != KEY_FRAME) + select_interintra_mode(cpi); +#endif /* Move storing frame_type out of the above loop since it is also * needed in motion search besides loopfilter */ diff --git a/vp9/encoder/onyx_int.h b/vp9/encoder/onyx_int.h index 2a9fd68b1..e1ddd45fb 100644 --- a/vp9/encoder/onyx_int.h +++ b/vp9/encoder/onyx_int.h @@ -43,9 +43,17 @@ #define ARF_DECAY_THRESH 12 #if CONFIG_PRED_FILTER +#if CONFIG_COMP_INTERINTRA_PRED +#define MAX_MODES 66 +#else #define MAX_MODES 54 +#endif #else // CONFIG_PRED_FILTER +#if CONFIG_COMP_INTERINTRA_PRED +#define MAX_MODES 54 +#else #define MAX_MODES 42 +#endif #endif // CONFIG_PRED_FILTER #define MIN_THRESHMULT 32 @@ -111,6 +119,9 @@ typedef struct { vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1] [VP9_SWITCHABLE_FILTERS - 1]; +#if CONFIG_COMP_INTERINTRA_PRED + vp9_prob interintra_prob; +#endif int mv_ref_ct[6][4][2]; int mode_context[6][4]; @@ -238,6 +249,22 @@ typedef enum { THR_COMP_SPLITLG, THR_COMP_SPLITLA, THR_COMP_SPLITGA, +#if CONFIG_COMP_INTERINTRA_PRED + THR_COMP_INTERINTRA_ZEROL, + THR_COMP_INTERINTRA_NEARESTL, + THR_COMP_INTERINTRA_NEARL, + THR_COMP_INTERINTRA_NEWL, + + THR_COMP_INTERINTRA_ZEROG, + THR_COMP_INTERINTRA_NEARESTG, + THR_COMP_INTERINTRA_NEARG, + THR_COMP_INTERINTRA_NEWG, + + THR_COMP_INTERINTRA_ZEROA, + THR_COMP_INTERINTRA_NEARESTA, + THR_COMP_INTERINTRA_NEARA, + THR_COMP_INTERINTRA_NEWA, +#endif } THR_MODES; #else @@ -296,7 +323,23 @@ typedef enum { THR_COMP_SPLITLG, THR_COMP_SPLITLA, - THR_COMP_SPLITGA + THR_COMP_SPLITGA, +#if CONFIG_COMP_INTERINTRA_PRED + THR_COMP_INTERINTRA_ZEROL, + THR_COMP_INTERINTRA_NEARESTL, + THR_COMP_INTERINTRA_NEARL, + THR_COMP_INTERINTRA_NEWL, + + THR_COMP_INTERINTRA_ZEROG, + THR_COMP_INTERINTRA_NEARESTG, + THR_COMP_INTERINTRA_NEARG, + THR_COMP_INTERINTRA_NEWG, + + THR_COMP_INTERINTRA_ZEROA, + THR_COMP_INTERINTRA_NEARESTA, + THR_COMP_INTERINTRA_NEARA, + THR_COMP_INTERINTRA_NEWA, +#endif } THR_MODES; #endif @@ -539,6 +582,10 @@ typedef struct VP9_COMP { int sub_mv_ref_count[SUBMVREF_COUNT][VP9_SUBMVREFS]; int mbsplit_count[VP9_NUMMBSPLITS]; int y_uv_mode_count[VP9_YMODES][VP9_UV_MODES]; +#if CONFIG_COMP_INTERINTRA_PRED + int interintra_count[2]; + int interintra_select_count[2]; +#endif nmv_context_counts NMVcount; @@ -751,7 +798,6 @@ typedef struct VP9_COMP { #endif unsigned int switchable_interp_count[VP9_SWITCHABLE_FILTERS + 1] [VP9_SWITCHABLE_FILTERS]; - #if CONFIG_NEW_MVREF unsigned int best_ref_index_counts[MAX_REF_FRAMES][MAX_MV_REFS]; #endif diff --git a/vp9/encoder/ratectrl.c b/vp9/encoder/ratectrl.c index b499f1df0..097a54d5a 100644 --- a/vp9/encoder/ratectrl.c +++ b/vp9/encoder/ratectrl.c @@ -175,6 +175,9 @@ void vp9_save_coding_context(VP9_COMP *cpi) { vp9_copy(cc->coef_probs_16x16, cm->fc.coef_probs_16x16); vp9_copy(cc->hybrid_coef_probs_16x16, cm->fc.hybrid_coef_probs_16x16); vp9_copy(cc->switchable_interp_prob, cm->fc.switchable_interp_prob); +#if CONFIG_COMP_INTERINTRA_PRED + cc->interintra_prob = cm->fc.interintra_prob; +#endif } void vp9_restore_coding_context(VP9_COMP *cpi) { @@ -231,6 +234,9 @@ void vp9_restore_coding_context(VP9_COMP *cpi) { vp9_copy(cm->fc.coef_probs_16x16, cc->coef_probs_16x16); vp9_copy(cm->fc.hybrid_coef_probs_16x16, cc->hybrid_coef_probs_16x16); vp9_copy(cm->fc.switchable_interp_prob, cc->switchable_interp_prob); +#if CONFIG_COMP_INTERINTRA_PRED + cm->fc.interintra_prob = cc->interintra_prob; +#endif } diff --git a/vp9/encoder/rdopt.c b/vp9/encoder/rdopt.c index 2a08ae8a1..1054e432f 100644 --- a/vp9/encoder/rdopt.c +++ b/vp9/encoder/rdopt.c @@ -78,54 +78,54 @@ static const int auto_speed_thresh[17] = { #if CONFIG_PRED_FILTER const MODE_DEFINITION vp9_mode_order[MAX_MODES] = { - {ZEROMV, LAST_FRAME, 0, 0}, - {ZEROMV, LAST_FRAME, 0, 1}, - {DC_PRED, INTRA_FRAME, 0, 0}, + {ZEROMV, LAST_FRAME, NONE, 0}, + {ZEROMV, LAST_FRAME, NONE, 1}, + {DC_PRED, INTRA_FRAME, NONE, 0}, - {NEARESTMV, LAST_FRAME, 0, 0}, - {NEARESTMV, LAST_FRAME, 0, 1}, - {NEARMV, LAST_FRAME, 0, 0}, - {NEARMV, LAST_FRAME, 0, 1}, + {NEARESTMV, LAST_FRAME, NONE, 0}, + {NEARESTMV, LAST_FRAME, NONE, 1}, + {NEARMV, LAST_FRAME, NONE, 0}, + {NEARMV, LAST_FRAME, NONE, 1}, - {ZEROMV, GOLDEN_FRAME, 0, 0}, - {ZEROMV, GOLDEN_FRAME, 0, 1}, - {NEARESTMV, GOLDEN_FRAME, 0, 0}, - {NEARESTMV, GOLDEN_FRAME, 0, 1}, + {ZEROMV, GOLDEN_FRAME, NONE, 0}, + {ZEROMV, GOLDEN_FRAME, NONE, 1}, + {NEARESTMV, GOLDEN_FRAME, NONE, 0}, + {NEARESTMV, GOLDEN_FRAME, NONE, 1}, - {ZEROMV, ALTREF_FRAME, 0, 0}, - {ZEROMV, ALTREF_FRAME, 0, 1}, - {NEARESTMV, ALTREF_FRAME, 0, 0}, - {NEARESTMV, ALTREF_FRAME, 0, 1}, + {ZEROMV, ALTREF_FRAME, NONE, 0}, + {ZEROMV, ALTREF_FRAME, NONE, 1}, + {NEARESTMV, ALTREF_FRAME, NONE, 0}, + {NEARESTMV, ALTREF_FRAME, NONE, 1}, - {NEARMV, GOLDEN_FRAME, 0, 0}, - {NEARMV, GOLDEN_FRAME, 0, 1}, - {NEARMV, ALTREF_FRAME, 0, 0}, - {NEARMV, ALTREF_FRAME, 0, 1}, + {NEARMV, GOLDEN_FRAME, NONE, 0}, + {NEARMV, GOLDEN_FRAME, NONE, 1}, + {NEARMV, ALTREF_FRAME, NONE, 0}, + {NEARMV, ALTREF_FRAME, NONE, 1}, - {V_PRED, INTRA_FRAME, 0, 0}, - {H_PRED, INTRA_FRAME, 0, 0}, - {D45_PRED, INTRA_FRAME, 0, 0}, - {D135_PRED, INTRA_FRAME, 0, 0}, - {D117_PRED, INTRA_FRAME, 0, 0}, - {D153_PRED, INTRA_FRAME, 0, 0}, - {D27_PRED, INTRA_FRAME, 0, 0}, - {D63_PRED, INTRA_FRAME, 0, 0}, + {V_PRED, INTRA_FRAME, NONE, 0}, + {H_PRED, INTRA_FRAME, NONE, 0}, + {D45_PRED, INTRA_FRAME, NONE, 0}, + {D135_PRED, INTRA_FRAME, NONE, 0}, + {D117_PRED, INTRA_FRAME, NONE, 0}, + {D153_PRED, INTRA_FRAME, NONE, 0}, + {D27_PRED, INTRA_FRAME, NONE, 0}, + {D63_PRED, INTRA_FRAME, NONE, 0}, - {TM_PRED, INTRA_FRAME, 0, 0}, + {TM_PRED, INTRA_FRAME, NONE, 0}, - {NEWMV, LAST_FRAME, 0, 0}, - {NEWMV, LAST_FRAME, 0, 1}, - {NEWMV, GOLDEN_FRAME, 0, 0}, - {NEWMV, GOLDEN_FRAME, 0, 1}, - {NEWMV, ALTREF_FRAME, 0, 0}, - {NEWMV, ALTREF_FRAME, 0, 1}, + {NEWMV, LAST_FRAME, NONE, 0}, + {NEWMV, LAST_FRAME, NONE, 1}, + {NEWMV, GOLDEN_FRAME, NONE, 0}, + {NEWMV, GOLDEN_FRAME, NONE, 1}, + {NEWMV, ALTREF_FRAME, NONE, 0}, + {NEWMV, ALTREF_FRAME, NONE, 1}, - {SPLITMV, LAST_FRAME, 0, 0}, - {SPLITMV, GOLDEN_FRAME, 0, 0}, - {SPLITMV, ALTREF_FRAME, 0, 0}, + {SPLITMV, LAST_FRAME, NONE, 0}, + {SPLITMV, GOLDEN_FRAME, NONE, 0}, + {SPLITMV, ALTREF_FRAME, NONE, 0}, - {B_PRED, INTRA_FRAME, 0, 0}, - {I8X8_PRED, INTRA_FRAME, 0, 0}, + {B_PRED, INTRA_FRAME, NONE, 0}, + {I8X8_PRED, INTRA_FRAME, NONE, 0}, /* compound prediction modes */ {ZEROMV, LAST_FRAME, GOLDEN_FRAME, 0}, @@ -146,46 +146,64 @@ const MODE_DEFINITION vp9_mode_order[MAX_MODES] = { {SPLITMV, LAST_FRAME, GOLDEN_FRAME, 0}, {SPLITMV, ALTREF_FRAME, LAST_FRAME, 0}, - {SPLITMV, GOLDEN_FRAME, ALTREF_FRAME, 0} + {SPLITMV, GOLDEN_FRAME, ALTREF_FRAME, 0}, + +#if CONFIG_COMP_INTERINTRA_PRED + /* compound inter-intra prediction */ + {ZEROMV, LAST_FRAME, INTRA_FRAME, 0}, + {NEARESTMV, LAST_FRAME, INTRA_FRAME, 0}, + {NEARMV, LAST_FRAME, INTRA_FRAME, 0}, + {NEWMV, LAST_FRAME, INTRA_FRAME, 0}, + + {ZEROMV, GOLDEN_FRAME, INTRA_FRAME, 0}, + {NEARESTMV, GOLDEN_FRAME, INTRA_FRAME, 0}, + {NEARMV, GOLDEN_FRAME, INTRA_FRAME, 0}, + {NEWMV, GOLDEN_FRAME, INTRA_FRAME, 0}, + + {ZEROMV, ALTREF_FRAME, INTRA_FRAME, 0}, + {NEARESTMV, ALTREF_FRAME, INTRA_FRAME, 0}, + {NEARMV, ALTREF_FRAME, INTRA_FRAME, 0}, + {NEWMV, ALTREF_FRAME, INTRA_FRAME, 0}, +#endif }; #else const MODE_DEFINITION vp9_mode_order[MAX_MODES] = { - {ZEROMV, LAST_FRAME, 0}, - {DC_PRED, INTRA_FRAME, 0}, + {ZEROMV, LAST_FRAME, NONE}, + {DC_PRED, INTRA_FRAME, NONE}, - {NEARESTMV, LAST_FRAME, 0}, - {NEARMV, LAST_FRAME, 0}, + {NEARESTMV, LAST_FRAME, NONE}, + {NEARMV, LAST_FRAME, NONE}, - {ZEROMV, GOLDEN_FRAME, 0}, - {NEARESTMV, GOLDEN_FRAME, 0}, + {ZEROMV, GOLDEN_FRAME, NONE}, + {NEARESTMV, GOLDEN_FRAME, NONE}, - {ZEROMV, ALTREF_FRAME, 0}, - {NEARESTMV, ALTREF_FRAME, 0}, + {ZEROMV, ALTREF_FRAME, NONE}, + {NEARESTMV, ALTREF_FRAME, NONE}, - {NEARMV, GOLDEN_FRAME, 0}, - {NEARMV, ALTREF_FRAME, 0}, + {NEARMV, GOLDEN_FRAME, NONE}, + {NEARMV, ALTREF_FRAME, NONE}, - {V_PRED, INTRA_FRAME, 0}, - {H_PRED, INTRA_FRAME, 0}, - {D45_PRED, INTRA_FRAME, 0}, - {D135_PRED, INTRA_FRAME, 0}, - {D117_PRED, INTRA_FRAME, 0}, - {D153_PRED, INTRA_FRAME, 0}, - {D27_PRED, INTRA_FRAME, 0}, - {D63_PRED, INTRA_FRAME, 0}, + {V_PRED, INTRA_FRAME, NONE}, + {H_PRED, INTRA_FRAME, NONE}, + {D45_PRED, INTRA_FRAME, NONE}, + {D135_PRED, INTRA_FRAME, NONE}, + {D117_PRED, INTRA_FRAME, NONE}, + {D153_PRED, INTRA_FRAME, NONE}, + {D27_PRED, INTRA_FRAME, NONE}, + {D63_PRED, INTRA_FRAME, NONE}, - {TM_PRED, INTRA_FRAME, 0}, + {TM_PRED, INTRA_FRAME, NONE}, - {NEWMV, LAST_FRAME, 0}, - {NEWMV, GOLDEN_FRAME, 0}, - {NEWMV, ALTREF_FRAME, 0}, + {NEWMV, LAST_FRAME, NONE}, + {NEWMV, GOLDEN_FRAME, NONE}, + {NEWMV, ALTREF_FRAME, NONE}, - {SPLITMV, LAST_FRAME, 0}, - {SPLITMV, GOLDEN_FRAME, 0}, - {SPLITMV, ALTREF_FRAME, 0}, + {SPLITMV, LAST_FRAME, NONE}, + {SPLITMV, GOLDEN_FRAME, NONE}, + {SPLITMV, ALTREF_FRAME, NONE}, - {B_PRED, INTRA_FRAME, 0}, - {I8X8_PRED, INTRA_FRAME, 0}, + {B_PRED, INTRA_FRAME, NONE}, + {I8X8_PRED, INTRA_FRAME, NONE}, /* compound prediction modes */ {ZEROMV, LAST_FRAME, GOLDEN_FRAME}, @@ -206,7 +224,25 @@ const MODE_DEFINITION vp9_mode_order[MAX_MODES] = { {SPLITMV, LAST_FRAME, GOLDEN_FRAME}, {SPLITMV, ALTREF_FRAME, LAST_FRAME }, - {SPLITMV, GOLDEN_FRAME, ALTREF_FRAME} + {SPLITMV, GOLDEN_FRAME, ALTREF_FRAME}, + +#if CONFIG_COMP_INTERINTRA_PRED + /* compound inter-intra prediction */ + {ZEROMV, LAST_FRAME, INTRA_FRAME}, + {NEARESTMV, LAST_FRAME, INTRA_FRAME}, + {NEARMV, LAST_FRAME, INTRA_FRAME}, + {NEWMV, LAST_FRAME, INTRA_FRAME}, + + {ZEROMV, GOLDEN_FRAME, INTRA_FRAME}, + {NEARESTMV, GOLDEN_FRAME, INTRA_FRAME}, + {NEARMV, GOLDEN_FRAME, INTRA_FRAME}, + {NEWMV, GOLDEN_FRAME, INTRA_FRAME}, + + {ZEROMV, ALTREF_FRAME, INTRA_FRAME}, + {NEARESTMV, ALTREF_FRAME, INTRA_FRAME}, + {NEARMV, ALTREF_FRAME, INTRA_FRAME}, + {NEWMV, ALTREF_FRAME, INTRA_FRAME}, +#endif }; #endif @@ -1960,7 +1996,7 @@ static int labels2mode( // is when we are on a new label (jbb May 08, 2007) switch (m = this_mode) { case NEW4X4 : - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { this_mv->as_int = seg_mvs[mbmi->ref_frame - 1].as_int; this_second_mv->as_int = seg_mvs[mbmi->second_ref_frame - 1].as_int; @@ -1968,7 +2004,7 @@ static int labels2mode( thismvcost = vp9_mv_bit_cost(this_mv, best_ref_mv, mvjcost, mvcost, 102, xd->allow_high_precision_mv); - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { thismvcost += vp9_mv_bit_cost(this_second_mv, second_best_ref_mv, mvjcost, mvcost, 102, xd->allow_high_precision_mv); @@ -1976,17 +2012,17 @@ static int labels2mode( break; case LEFT4X4: this_mv->as_int = col ? d[-1].bmi.as_mv.first.as_int : left_block_mv(mic, i); - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) this_second_mv->as_int = col ? d[-1].bmi.as_mv.second.as_int : left_block_second_mv(mic, i); break; case ABOVE4X4: this_mv->as_int = row ? d[-4].bmi.as_mv.first.as_int : above_block_mv(mic, i, mis); - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) this_second_mv->as_int = row ? d[-4].bmi.as_mv.second.as_int : above_block_second_mv(mic, i, mis); break; case ZERO4X4: this_mv->as_int = 0; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) this_second_mv->as_int = 0; break; default: @@ -1999,12 +2035,12 @@ static int labels2mode( left_second_mv.as_int = 0; left_mv.as_int = col ? d[-1].bmi.as_mv.first.as_int : left_block_mv(mic, i); - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) left_second_mv.as_int = col ? d[-1].bmi.as_mv.second.as_int : left_block_second_mv(mic, i); if (left_mv.as_int == this_mv->as_int && - (!mbmi->second_ref_frame || + (mbmi->second_ref_frame <= 0 || left_second_mv.as_int == this_second_mv->as_int)) m = LEFT4X4; } @@ -2018,12 +2054,12 @@ static int labels2mode( } d->bmi.as_mv.first.as_int = this_mv->as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) d->bmi.as_mv.second.as_int = this_second_mv->as_int; x->partition_info->bmi[i].mode = m; x->partition_info->bmi[i].mv.as_int = this_mv->as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) x->partition_info->bmi[i].second_mv.as_int = this_second_mv->as_int; } @@ -2051,7 +2087,7 @@ static int64_t encode_inter_mb_segment(MACROBLOCK *x, int thisdistortion; vp9_build_inter_predictors_b(bd, 16, xd->subpixel_predict); - if (xd->mode_info_context->mbmi.second_ref_frame) + if (xd->mode_info_context->mbmi.second_ref_frame > 0) vp9_build_2nd_inter_predictors_b(bd, 16, xd->subpixel_predict_avg); vp9_subtract_b(be, bd, 16); x->vp9_short_fdct4x4(be->src_diff, be->coeff, 32); @@ -2101,7 +2137,7 @@ static int64_t encode_inter_mb_segment_8x8(MACROBLOCK *x, int thisdistortion; vp9_build_inter_predictors4b(xd, bd, 16); - if (xd->mode_info_context->mbmi.second_ref_frame) + if (xd->mode_info_context->mbmi.second_ref_frame > 0) vp9_build_2nd_inter_predictors4b(xd, bd, 16); vp9_subtract_4b_c(be, bd, 16); @@ -2282,7 +2318,7 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, tl_s = (ENTROPY_CONTEXT *)&t_left_s; // motion search for newmv (single predictor case only) - if (!mbmi->second_ref_frame && this_mode == NEW4X4) { + if (mbmi->second_ref_frame <= 0 && this_mode == NEW4X4) { int sseshift, n; int step_param = 0; int further_steps; @@ -2368,8 +2404,8 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, // safe motion search result for use in compound prediction seg_mvs[i][mbmi->ref_frame - 1].as_int = mode_mv[NEW4X4].as_int; } - } /* NEW4X4 */ - else if (mbmi->second_ref_frame && this_mode == NEW4X4) { + } else if (mbmi->second_ref_frame > 0 && this_mode == NEW4X4) { + /* NEW4X4 */ /* motion search not completed? Then skip newmv for this block with * comppred */ if (seg_mvs[i][mbmi->second_ref_frame - 1].as_int == INVALID_MV || @@ -2390,7 +2426,7 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) { continue; } - if (mbmi->second_ref_frame && + if (mbmi->second_ref_frame > 0 && mv_check_bounds(x, &second_mode_mv[this_mode])) continue; @@ -2463,7 +2499,7 @@ static void rd_check_segment_txsize(VP9_COMP *cpi, MACROBLOCK *x, // store everything needed to come back to this!! for (i = 0; i < 16; i++) { bsi->mvs[i].as_mv = x->partition_info->bmi[i].mv.as_mv; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) bsi->second_mvs[i].as_mv = x->partition_info->bmi[i].second_mv.as_mv; bsi->modes[i] = x->partition_info->bmi[i].mode; bsi->eobs[i] = best_eobs[i]; @@ -2694,7 +2730,7 @@ static int rd_pick_best_mbsegmentation(VP9_COMP *cpi, MACROBLOCK *x, BLOCKD *bd = &x->e_mbd.block[i]; bd->bmi.as_mv.first.as_int = bsi.mvs[i].as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) bd->bmi.as_mv.second.as_int = bsi.second_mvs[i].as_int; bd->eob = bsi.eobs[i]; } @@ -2718,14 +2754,14 @@ static int rd_pick_best_mbsegmentation(VP9_COMP *cpi, MACROBLOCK *x, x->partition_info->bmi[i].mode = bsi.modes[j]; x->partition_info->bmi[i].mv.as_mv = bsi.mvs[j].as_mv; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) x->partition_info->bmi[i].second_mv.as_mv = bsi.second_mvs[j].as_mv; } /* * used to set mbmi->mv.as_int */ x->partition_info->bmi[15].mv.as_int = bsi.mvs[15].as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) x->partition_info->bmi[15].second_mv.as_int = bsi.second_mvs[15].as_int; return (int)(bsi.segment_rd); @@ -3165,7 +3201,7 @@ static void store_coding_context(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx, memcpy(ctx->txfm_rd_diff, txfm_size_diff, sizeof(ctx->txfm_rd_diff)); } -static void inter_mode_cost(VP9_COMP *cpi, MACROBLOCK *x, int this_mode, +static void inter_mode_cost(VP9_COMP *cpi, MACROBLOCK *x, int *rate2, int *distortion2, int *rate_y, int *distortion, int* rate_uv, int *distortion_uv, int *skippable, int64_t txfm_cache[NB_TXFM_MODES]) { @@ -3232,6 +3268,9 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, int mdcounts[4], int64_t txfm_cache[], int *rate2, int *distortion, int *skippable, int *compmode_cost, +#if CONFIG_COMP_INTERINTRA_PRED + int *compmode_interintra_cost, +#endif int *rate_y, int *distortion_y, int *rate_uv, int *distortion_uv, int *mode_excluded, int *disable_skip, @@ -3243,11 +3282,15 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi; BLOCK *b = &x->block[0]; BLOCKD *d = &xd->block[0]; - const int is_comp_pred = (mbmi->second_ref_frame != 0); + const int is_comp_pred = (mbmi->second_ref_frame > 0); +#if CONFIG_COMP_INTERINTRA_PRED + const int is_comp_interintra_pred = (mbmi->second_ref_frame == INTRA_FRAME); +#endif const int num_refs = is_comp_pred ? 2 : 1; const int this_mode = mbmi->mode; int i; - int refs[2] = { mbmi->ref_frame, mbmi->second_ref_frame }; + int refs[2] = { mbmi->ref_frame, + (mbmi->second_ref_frame < 0 ? 0 : mbmi->second_ref_frame) }; int_mv cur_mv[2]; int_mv mvp; int64_t this_rd = 0; @@ -3368,11 +3411,30 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, is_comp_pred); *rate2 += vp9_cost_mv_ref(cpi, this_mode, mbmi->mb_mode_context[mbmi->ref_frame]); +#if CONFIG_COMP_INTERINTRA_PRED + if (!is_comp_pred) { + *compmode_interintra_cost = vp9_cost_bit(cm->fc.interintra_prob, + is_comp_interintra_pred); + if (is_comp_interintra_pred) { + *compmode_interintra_cost += + x->mbmode_cost[xd->frame_type][mbmi->interintra_mode]; +#if SEPARATE_INTERINTRA_UV + *compmode_interintra_cost += + x->intra_uv_mode_cost[xd->frame_type][mbmi->interintra_uv_mode]; +#endif + } + } +#endif if (block_size == BLOCK_16X16) { vp9_build_1st_inter16x16_predictors_mby(xd, xd->predictor, 16, 0); if (is_comp_pred) vp9_build_2nd_inter16x16_predictors_mby(xd, xd->predictor, 16); +#if CONFIG_COMP_INTERINTRA_PRED + if (is_comp_interintra_pred) { + vp9_build_interintra_16x16_predictors_mby(xd, xd->predictor, 16); + } +#endif } else { #if CONFIG_SUPERBLOCKS vp9_build_inter32x32_predictors_sb(xd, @@ -3440,6 +3502,15 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, } } + if (is_comp_pred) { + *mode_excluded = (cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY); + } else { + *mode_excluded = (cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY); + } +#if CONFIG_COMP_INTERINTRA_PRED + if (is_comp_interintra_pred && !cm->use_interintra) *mode_excluded = 1; +#endif + if (!x->skip) { if (block_size == BLOCK_16X16) { vp9_build_1st_inter16x16_predictors_mbuv(xd, &xd->predictor[256], @@ -3447,7 +3518,13 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, if (is_comp_pred) vp9_build_2nd_inter16x16_predictors_mbuv(xd, &xd->predictor[256], &xd->predictor[320], 8); - inter_mode_cost(cpi, x, this_mode, rate2, distortion, +#if CONFIG_COMP_INTERINTRA_PRED + if (is_comp_interintra_pred) { + vp9_build_interintra_16x16_predictors_mbuv(xd, &xd->predictor[256], + &xd->predictor[320], 8); + } +#endif + inter_mode_cost(cpi, x, rate2, distortion, rate_y, distortion_y, rate_uv, distortion_uv, skippable, txfm_cache); } else { @@ -3469,12 +3546,6 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, #endif } } - if (is_comp_pred) { - *mode_excluded = (cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY); - } else { - *mode_excluded = (cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY); - } - return this_rd; // if 0, this will be re-calculated by caller } @@ -3503,9 +3574,12 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, int64_t best_pred_diff[NB_PREDICTION_TYPES]; int64_t best_pred_rd[NB_PREDICTION_TYPES]; int64_t best_rd = INT64_MAX, best_intra_rd = INT64_MAX; -#if CONFIG_PRED_FILTER - int64_t best_overall_rd = INT64_MAX; +#if CONFIG_COMP_INTERINTRA_PRED + int is_best_interintra = 0; + int64_t best_intra16_rd = INT64_MAX; + int best_intra16_mode = DC_PRED, best_intra16_uv_mode = DC_PRED; #endif + int64_t best_overall_rd = INT64_MAX; int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly; int uv_intra_skippable = 0; int uv_intra_rate_8x8 = 0, uv_intra_distortion_8x8 = 0, uv_intra_rate_tokenonly_8x8 = 0; @@ -3608,6 +3682,9 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, int disable_skip = 0, skippable = 0; int other_cost = 0; int compmode_cost = 0; +#if CONFIG_COMP_INTERINTRA_PRED + int compmode_interintra_cost = 0; +#endif int mode_excluded = 0; int64_t txfm_cache[NB_TXFM_MODES] = { 0 }; @@ -3645,6 +3722,10 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, mbmi->second_mode = (MB_PREDICTION_MODE)(DC_PRED - 1); mbmi->second_uv_mode = (MB_PREDICTION_MODE)(DC_PRED - 1); #endif +#if CONFIG_COMP_INTERINTRA_PRED + mbmi->interintra_mode = (MB_PREDICTION_MODE)(DC_PRED - 1); + mbmi->interintra_uv_mode = (MB_PREDICTION_MODE)(DC_PRED - 1); +#endif // If the segment reference frame feature is enabled.... // then do nothing if the current ref frame is not allowed.. @@ -3684,7 +3765,7 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, vpx_memcpy(mdcounts, frame_mdcounts[ref], sizeof(mdcounts)); } - if (mbmi->second_ref_frame) { + if (mbmi->second_ref_frame > 0) { int ref = mbmi->second_ref_frame; xd->second_pre.y_buffer = y_buffer[ref]; @@ -3872,7 +3953,7 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, // Split MV. The code is very different from the other inter modes so // special case it. else if (this_mode == SPLITMV) { - const int is_comp_pred = mbmi->second_ref_frame != 0; + const int is_comp_pred = mbmi->second_ref_frame > 0; int64_t tmp_rd, this_rd_thresh; int_mv *second_ref = is_comp_pred ? &second_best_ref_mv : NULL; @@ -3921,10 +4002,25 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, mbmi->mode = this_mode; } else { +#if CONFIG_COMP_INTERINTRA_PRED + if (mbmi->second_ref_frame == INTRA_FRAME) { + if (best_intra16_mode == DC_PRED - 1) continue; + mbmi->interintra_mode = best_intra16_mode; +#if SEPARATE_INTERINTRA_UV + mbmi->interintra_uv_mode = best_intra16_uv_mode; +#else + mbmi->interintra_uv_mode = best_intra16_mode; +#endif + } +#endif this_rd = handle_inter_mode(cpi, x, BLOCK_16X16, &saddone, near_sadidx, mdcounts, txfm_cache, &rate2, &distortion2, &skippable, - &compmode_cost, &rate_y, &distortion, + &compmode_cost, +#if CONFIG_COMP_INTERINTRA_PRED + &compmode_interintra_cost, +#endif + &rate_y, &distortion, &rate_uv, &distortion_uv, &mode_excluded, &disable_skip, recon_yoffset, mode_index, frame_mv, frame_best_ref_mv); @@ -3932,6 +4028,11 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, continue; } +#if CONFIG_COMP_INTERINTRA_PRED + if (cpi->common.use_interintra) + rate2 += compmode_interintra_cost; +#endif + if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) rate2 += compmode_cost; @@ -3996,18 +4097,33 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, best_intra_rd = this_rd; *returnintra = distortion2; } +#if CONFIG_COMP_INTERINTRA_PRED + if ((mbmi->ref_frame == INTRA_FRAME) && + (this_mode >= DC_PRED && this_mode <= TM_PRED) && + (this_rd < best_intra16_rd)) { + best_intra16_rd = this_rd; + best_intra16_mode = this_mode; + best_intra16_uv_mode = (mbmi->txfm_size != TX_4X4 ? + uv_intra_mode_8x8 : uv_intra_mode); + } +#endif + if (!disable_skip && mbmi->ref_frame == INTRA_FRAME) for (i = 0; i < NB_PREDICTION_TYPES; ++i) best_pred_rd[i] = MIN(best_pred_rd[i], this_rd); -#if CONFIG_PRED_FILTER - // Keep track of the best mode irrespective of prediction filter state if (this_rd < best_overall_rd) { best_overall_rd = this_rd; +#if CONFIG_PRED_FILTER best_filter_state = mbmi->pred_filter_enabled; +#endif +#if CONFIG_COMP_INTERINTRA_PRED + is_best_interintra = (mbmi->second_ref_frame == INTRA_FRAME); +#endif } +#if CONFIG_PRED_FILTER // Ignore modes where the prediction filter state doesn't // match the state signaled at the frame level if ((cm->pred_filter_mode == 2) || @@ -4017,6 +4133,11 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, // Did this mode help.. i.e. is it the new best mode if (this_rd < best_rd || x->skip) { if (!mode_excluded) { + /* + if (mbmi->second_ref_frame == INTRA_FRAME) { + printf("rd %d best %d bestintra16 %d\n", this_rd, best_rd, best_intra16_rd); + } + */ // Note index of best mode so far best_mode_index = mode_index; @@ -4087,10 +4208,10 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2); hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2); - if (mbmi->second_ref_frame == INTRA_FRAME && + if (mbmi->second_ref_frame <= INTRA_FRAME && single_rd < best_pred_rd[SINGLE_PREDICTION_ONLY]) { best_pred_rd[SINGLE_PREDICTION_ONLY] = single_rd; - } else if (mbmi->second_ref_frame != INTRA_FRAME && + } else if (mbmi->second_ref_frame > INTRA_FRAME && single_rd < best_pred_rd[COMP_PREDICTION_ONLY]) { best_pred_rd[COMP_PREDICTION_ONLY] = single_rd; } @@ -4127,6 +4248,9 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, ++cpi->pred_filter_on_count; else ++cpi->pred_filter_off_count; +#endif +#if CONFIG_COMP_INTERINTRA_PRED + ++cpi->interintra_select_count[is_best_interintra]; #endif if (cpi->common.mcomp_filter_type == SWITCHABLE && best_mbmode.mode >= NEARESTMV && @@ -4191,7 +4315,7 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, if (best_mbmode.mode == SPLITMV) { for (i = 0; i < 16; i++) xd->mode_info_context->bmi[i].as_mv.first.as_int = best_bmodes[i].as_mv.first.as_int; - if (mbmi->second_ref_frame) + if (mbmi->second_ref_frame > 0) for (i = 0; i < 16; i++) xd->mode_info_context->bmi[i].as_mv.second.as_int = best_bmodes[i].as_mv.second.as_int; @@ -4220,10 +4344,12 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, } end: - store_coding_context(x, &x->mb_context[xd->mb_index], best_mode_index, - &best_partition, &frame_best_ref_mv[mbmi->ref_frame], - &frame_best_ref_mv[mbmi->second_ref_frame], - best_pred_diff, best_txfm_diff); + store_coding_context( + x, &x->mb_context[xd->mb_index], best_mode_index, &best_partition, + &frame_best_ref_mv[xd->mode_info_context->mbmi.ref_frame], + &frame_best_ref_mv[xd->mode_info_context->mbmi.second_ref_frame < 0 ? + 0 : xd->mode_info_context->mbmi.second_ref_frame], + best_pred_diff, best_txfm_diff); } #if CONFIG_SUPERBLOCKS @@ -4448,6 +4574,11 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, MB_MODE_INFO best_mbmode; int mode_index, best_mode_index; unsigned int ref_costs[MAX_REF_FRAMES]; +#if CONFIG_COMP_INTERINTRA_PRED + int is_best_interintra = 0; + int64_t best_intra16_rd = INT64_MAX; + int best_intra16_mode = DC_PRED, best_intra16_uv_mode = DC_PRED; +#endif x->skip = 0; xd->mode_info_context->mbmi.segment_id = segment_id; @@ -4480,6 +4611,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, int distortion2 = 0, distortion_y = 0, distortion_uv = 0; int skippable; int64_t txfm_cache[NB_TXFM_MODES]; +#if CONFIG_COMP_INTERINTRA_PRED + int compmode_interintra_cost = 0; +#endif // Test best rd so far against threshold for trying this mode. if (best_rd <= cpi->rd_threshes[mode_index]) { @@ -4489,7 +4623,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, this_mode = vp9_mode_order[mode_index].mode; ref_frame = vp9_mode_order[mode_index].ref_frame; mbmi->ref_frame = ref_frame; - comp_pred = vp9_mode_order[mode_index].second_ref_frame != INTRA_FRAME; + comp_pred = vp9_mode_order[mode_index].second_ref_frame > INTRA_FRAME; mbmi->mode = this_mode; mbmi->uv_mode = DC_PRED; #if CONFIG_COMP_INTRA_PRED @@ -4502,7 +4636,8 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, // not yet supported or not superblocky // TODO(rbultje): support intra coding - if (ref_frame == INTRA_FRAME || this_mode == SPLITMV) + if (ref_frame == INTRA_FRAME || this_mode == SPLITMV || + vp9_mode_order[mode_index].second_ref_frame == INTRA_FRAME) continue; if (comp_pred) { @@ -4522,7 +4657,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, xd->second_pre.v_buffer = v_buffer[second_ref]; mode_excluded = cm->comp_pred_mode == SINGLE_PREDICTION_ONLY; } else { - mbmi->second_ref_frame = INTRA_FRAME; + mbmi->second_ref_frame = NONE; mode_excluded = cm->comp_pred_mode == COMP_PREDICTION_ONLY; } @@ -4559,7 +4694,11 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, this_rd = handle_inter_mode(cpi, x, BLOCK_32X32, &saddone, near_sadidx, mdcounts, txfm_cache, &rate2, &distortion2, &skippable, - &compmode_cost, &rate_y, &distortion_y, + &compmode_cost, +#if CONFIG_COMP_INTERINTRA_PRED + &compmode_interintra_cost, +#endif + &rate_y, &distortion_y, &rate_uv, &distortion_uv, &mode_excluded, &disable_skip, recon_yoffset, mode_index, frame_mv, frame_best_ref_mv); @@ -4691,10 +4830,10 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2); hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2); - if (mbmi->second_ref_frame == INTRA_FRAME && + if (mbmi->second_ref_frame <= INTRA_FRAME && single_rd < best_pred_rd[SINGLE_PREDICTION_ONLY]) { best_pred_rd[SINGLE_PREDICTION_ONLY] = single_rd; - } else if (mbmi->second_ref_frame != INTRA_FRAME && + } else if (mbmi->second_ref_frame > INTRA_FRAME && single_rd < best_pred_rd[COMP_PREDICTION_ONLY]) { best_pred_rd[COMP_PREDICTION_ONLY] = single_rd; } @@ -4746,7 +4885,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME)) { mbmi->mode = ZEROMV; mbmi->ref_frame = ALTREF_FRAME; - mbmi->second_ref_frame = 0; + mbmi->second_ref_frame = INTRA_FRAME; mbmi->mv[0].as_int = 0; mbmi->uv_mode = DC_PRED; mbmi->mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0; @@ -4783,7 +4922,8 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, end: store_coding_context(x, &x->sb_context[0], best_mode_index, NULL, &frame_best_ref_mv[mbmi->ref_frame], - &frame_best_ref_mv[mbmi->second_ref_frame], + &frame_best_ref_mv[mbmi->second_ref_frame < 0 ? + 0 : mbmi->second_ref_frame], best_pred_diff, best_txfm_diff); return best_rd;