summaryrefslogtreecommitdiff
path: root/vp8/encoder/rdopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'vp8/encoder/rdopt.c')
-rw-r--r--vp8/encoder/rdopt.c1068
1 files changed, 1021 insertions, 47 deletions
diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
index ed5b5c96d..97b02f033 100644
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -718,7 +718,7 @@ static void macro_block_yrd(MACROBLOCK *mb,
*Rate = vp8_rdcost_mby(mb);
}
-static int vp8_rdcost_mby_8x8(MACROBLOCK *mb) {
+static int vp8_rdcost_mby_8x8(MACROBLOCK *mb, int backup) {
int cost = 0;
int b;
MACROBLOCKD *xd = &mb->e_mbd;
@@ -726,11 +726,16 @@ static int vp8_rdcost_mby_8x8(MACROBLOCK *mb) {
ENTROPY_CONTEXT *ta;
ENTROPY_CONTEXT *tl;
- vpx_memcpy(&t_above,xd->above_context, sizeof(ENTROPY_CONTEXT_PLANES));
- vpx_memcpy(&t_left, xd->left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ if (backup) {
+ vpx_memcpy(&t_above,xd->above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, xd->left_context, sizeof(ENTROPY_CONTEXT_PLANES));
- ta = (ENTROPY_CONTEXT *)&t_above;
- tl = (ENTROPY_CONTEXT *)&t_left;
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+ } else {
+ ta = (ENTROPY_CONTEXT *)mb->e_mbd.above_context;
+ tl = (ENTROPY_CONTEXT *)mb->e_mbd.left_context;
+ }
for (b = 0; b < 16; b += 4)
cost += cost_coeffs(mb, xd->block + b, PLANE_TYPE_Y_NO_DC,
@@ -775,7 +780,7 @@ static void macro_block_yrd_8x8(MACROBLOCK *mb,
*Distortion = (d >> 2);
// rate
- *Rate = vp8_rdcost_mby_8x8(mb);
+ *Rate = vp8_rdcost_mby_8x8(mb, 1);
}
#if CONFIG_TX16X16
@@ -823,6 +828,66 @@ static void copy_predictor(unsigned char *dst, const unsigned char *predictor) {
d[12] = p[12];
}
+#if CONFIG_SUPERBLOCKS
+static void super_block_yrd_8x8(MACROBLOCK *x,
+ int *rate,
+ int *distortion,
+ const VP8_ENCODER_RTCD *rtcd, int *skip)
+{
+ MACROBLOCKD *const xd = &x->e_mbd;
+ BLOCK *const by2 = x->block + 24;
+ BLOCKD *const bdy2 = xd->block + 24;
+ int d = 0, r = 0, n;
+ const uint8_t *src = x->src.y_buffer, *dst = xd->dst.y_buffer;
+ int src_y_stride = x->src.y_stride, dst_y_stride = xd->dst.y_stride;
+ ENTROPY_CONTEXT_PLANES *ta = xd->above_context;
+ ENTROPY_CONTEXT_PLANES *tl = xd->left_context;
+ ENTROPY_CONTEXT_PLANES t_above[2];
+ ENTROPY_CONTEXT_PLANES t_left[2];
+ int skippable = 1;
+
+ vpx_memcpy(t_above, xd->above_context, sizeof(t_above));
+ vpx_memcpy(t_left, xd->left_context, sizeof(t_left));
+
+ for (n = 0; n < 4; n++) {
+ int x_idx = n & 1, y_idx = n >> 1;
+
+ vp8_subtract_mby_s_c(x->src_diff,
+ src + x_idx * 16 + y_idx * 16 * src_y_stride,
+ src_y_stride,
+ dst + x_idx * 16 + y_idx * 16 * dst_y_stride,
+ dst_y_stride);
+ vp8_transform_mby_8x8(x);
+ vp8_quantize_mby_8x8(x);
+
+ /* remove 1st order dc to properly combine 1st/2nd order distortion */
+ x->coeff[ 0] = 0;
+ x->coeff[ 64] = 0;
+ x->coeff[128] = 0;
+ x->coeff[192] = 0;
+ xd->dqcoeff[ 0] = 0;
+ xd->dqcoeff[ 64] = 0;
+ xd->dqcoeff[128] = 0;
+ xd->dqcoeff[192] = 0;
+
+ d += ENCODEMB_INVOKE(&rtcd->encodemb, mberr)(x, 0);
+ d += ENCODEMB_INVOKE(&rtcd->encodemb, berr)(by2->coeff, bdy2->dqcoeff, 16);
+ xd->above_context = ta + x_idx;
+ xd->left_context = tl + y_idx;
+ r += vp8_rdcost_mby_8x8(x, 0);
+ skippable = skippable && mby_is_skippable_8x8(xd);
+ }
+
+ *distortion = (d >> 2);
+ *rate = r;
+ if (skip) *skip = skippable;
+ xd->above_context = ta;
+ xd->left_context = tl;
+ vpx_memcpy(xd->above_context, &t_above, sizeof(t_above));
+ vpx_memcpy(xd->left_context, &t_left, sizeof(t_left));
+}
+#endif
+
static void copy_predictor_8x8(unsigned char *dst, const unsigned char *predictor) {
const unsigned int *p = (const unsigned int *)predictor;
unsigned int *d = (unsigned int *)dst;
@@ -1062,6 +1127,45 @@ static int64_t rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rat
return RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
}
+#if CONFIG_SUPERBLOCKS
+static int64_t rd_pick_intra_sby_mode(VP8_COMP *cpi,
+ MACROBLOCK *x,
+ int *rate,
+ int *rate_tokenonly,
+ int *distortion) {
+ MB_PREDICTION_MODE mode;
+ MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+ int this_rate, this_rate_tokenonly;
+ int this_distortion;
+ int64_t best_rd = INT64_MAX, this_rd;
+
+ /* Y Search for 32x32 intra prediction mode */
+ for (mode = DC_PRED; mode <= TM_PRED; mode++) {
+ x->e_mbd.mode_info_context->mbmi.mode = mode;
+ RECON_INVOKE(&cpi->common.rtcd.recon,
+ build_intra_predictors_sby_s)(&x->e_mbd);
+
+ super_block_yrd_8x8(x, &this_rate_tokenonly,
+ &this_distortion, IF_RTCD(&cpi->rtcd), NULL);
+ this_rate = this_rate_tokenonly +
+ x->mbmode_cost[x->e_mbd.frame_type]
+ [x->e_mbd.mode_info_context->mbmi.mode];
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+
+ if (this_rd < best_rd) {
+ mode_selected = mode;
+ best_rd = this_rd;
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ }
+ }
+
+ x->e_mbd.mode_info_context->mbmi.mode = mode_selected;
+
+ return best_rd;
+}
+#endif
static int64_t rd_pick_intra16x16mby_mode(VP8_COMP *cpi,
MACROBLOCK *x,
@@ -1372,18 +1476,23 @@ static int64_t rd_inter16x16_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
}
-static int rd_cost_mbuv_8x8(MACROBLOCK *mb) {
+static int rd_cost_mbuv_8x8(MACROBLOCK *mb, int backup) {
int b;
int cost = 0;
MACROBLOCKD *xd = &mb->e_mbd;
ENTROPY_CONTEXT_PLANES t_above, t_left;
ENTROPY_CONTEXT *ta, *tl;
- vpx_memcpy(&t_above, xd->above_context, sizeof(ENTROPY_CONTEXT_PLANES));
- vpx_memcpy(&t_left, xd->left_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ if (backup) {
+ vpx_memcpy(&t_above, xd->above_context, sizeof(ENTROPY_CONTEXT_PLANES));
+ vpx_memcpy(&t_left, xd->left_context, sizeof(ENTROPY_CONTEXT_PLANES));
- ta = (ENTROPY_CONTEXT *)&t_above;
- tl = (ENTROPY_CONTEXT *)&t_left;
+ ta = (ENTROPY_CONTEXT *)&t_above;
+ tl = (ENTROPY_CONTEXT *)&t_left;
+ } else {
+ ta = (ENTROPY_CONTEXT *)mb->e_mbd.above_context;
+ tl = (ENTROPY_CONTEXT *)mb->e_mbd.left_context;
+ }
for (b = 16; b < 24; b += 4)
cost += cost_coeffs(mb, xd->block + b, PLANE_TYPE_UV,
@@ -1393,6 +1502,54 @@ static int rd_cost_mbuv_8x8(MACROBLOCK *mb) {
return cost;
}
+#if CONFIG_SUPERBLOCKS
+static int64_t rd_inter32x32_uv_8x8(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
+ int *distortion, int fullpixel, int *skip) {
+ MACROBLOCKD *xd = &x->e_mbd;
+ int n, r = 0, d = 0;
+ const uint8_t *usrc = x->src.u_buffer, *udst = xd->dst.u_buffer;
+ const uint8_t *vsrc = x->src.v_buffer, *vdst = xd->dst.v_buffer;
+ int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->dst.uv_stride;
+ int skippable = 1;
+ ENTROPY_CONTEXT_PLANES t_above[2], t_left[2];
+ ENTROPY_CONTEXT_PLANES *ta = xd->above_context;
+ ENTROPY_CONTEXT_PLANES *tl = xd->left_context;
+
+ memcpy(t_above, xd->above_context, sizeof(t_above));
+ memcpy(t_left, xd->left_context, sizeof(t_left));
+
+ for (n = 0; n < 4; n++) {
+ int x_idx = n & 1, y_idx = n >> 1;
+
+ vp8_subtract_mbuv_s_c(x->src_diff,
+ usrc + x_idx * 8 + y_idx * 8 * src_uv_stride,
+ vsrc + x_idx * 8 + y_idx * 8 * src_uv_stride,
+ src_uv_stride,
+ udst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
+ vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
+ dst_uv_stride);
+
+ vp8_transform_mbuv_8x8(x);
+ vp8_quantize_mbuv_8x8(x);
+
+ xd->above_context = ta + x_idx;
+ xd->left_context = tl + y_idx;
+ r += rd_cost_mbuv_8x8(x, 0);
+ d += ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
+ skippable = skippable && mbuv_is_skippable_8x8(xd);
+ }
+
+ *rate = r;
+ *distortion = d;
+ if (skip) *skip = skippable;
+ xd->left_context = tl;
+ xd->above_context = ta;
+ memcpy(xd->above_context, t_above, sizeof(t_above));
+ memcpy(xd->left_context, t_left, sizeof(t_left));
+
+ return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
+}
+#endif
static int64_t rd_inter16x16_uv_8x8(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
int *distortion, int fullpixel) {
@@ -1403,7 +1560,7 @@ static int64_t rd_inter16x16_uv_8x8(VP8_COMP *cpi, MACROBLOCK *x, int *rate,
vp8_quantize_mbuv_8x8(x);
- *rate = rd_cost_mbuv_8x8(x);
+ *rate = rd_cost_mbuv_8x8(x, 1);
*distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
@@ -1527,7 +1684,7 @@ static void rd_pick_intra_mbuv_mode_8x8(VP8_COMP *cpi,
vp8_quantize_mbuv_8x8(x);
- rate_to = rd_cost_mbuv_8x8(x);
+ rate_to = rd_cost_mbuv_8x8(x, 1);
rate = rate_to + x->intra_uv_mode_cost[x->e_mbd.frame_type][mbmi->uv_mode];
distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
@@ -1546,6 +1703,91 @@ static void rd_pick_intra_mbuv_mode_8x8(VP8_COMP *cpi,
mbmi->uv_mode = mode_selected;
}
+#if CONFIG_SUPERBLOCKS
+static void super_block_uvrd_8x8(MACROBLOCK *x,
+ int *rate,
+ int *distortion,
+ const VP8_ENCODER_RTCD *rtcd) {
+ MACROBLOCKD *const xd = &x->e_mbd;
+ int d = 0, r = 0, n;
+ const uint8_t *usrc = x->src.u_buffer, *udst = xd->dst.u_buffer;
+ const uint8_t *vsrc = x->src.v_buffer, *vdst = xd->dst.v_buffer;
+ int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->dst.uv_stride;
+ ENTROPY_CONTEXT_PLANES t_above[2], t_left[2];
+ ENTROPY_CONTEXT_PLANES *ta = xd->above_context;
+ ENTROPY_CONTEXT_PLANES *tl = xd->left_context;
+
+ memcpy(t_above, xd->above_context, sizeof(t_above));
+ memcpy(t_left, xd->left_context, sizeof(t_left));
+
+ for (n = 0; n < 4; n++) {
+ int x_idx = n & 1, y_idx = n >> 1;
+
+ vp8_subtract_mbuv_s_c(x->src_diff,
+ usrc + x_idx * 8 + y_idx * 8 * src_uv_stride,
+ vsrc + x_idx * 8 + y_idx * 8 * src_uv_stride,
+ src_uv_stride,
+ udst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
+ vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
+ dst_uv_stride);
+ vp8_transform_mbuv_8x8(x);
+ vp8_quantize_mbuv_8x8(x);
+
+ d += ENCODEMB_INVOKE(&rtcd->encodemb, mbuverr)(x) >> 2;
+ xd->above_context = ta + x_idx;
+ xd->left_context = tl + y_idx;
+ r += rd_cost_mbuv_8x8(x, 0);
+ }
+
+ xd->above_context = ta;
+ xd->left_context = tl;
+ *distortion = (d >> 2);
+ *rate = r;
+
+ xd->left_context = tl;
+ xd->above_context = ta;
+ memcpy(xd->above_context, t_above, sizeof(t_above));
+ memcpy(xd->left_context, t_left, sizeof(t_left));
+}
+
+static int64_t rd_pick_intra_sbuv_mode(VP8_COMP *cpi,
+ MACROBLOCK *x,
+ int *rate,
+ int *rate_tokenonly,
+ int *distortion) {
+ MB_PREDICTION_MODE mode;
+ MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+ int64_t best_rd = INT64_MAX, this_rd;
+ int this_rate_tokenonly, this_rate;
+ int this_distortion;
+
+ for (mode = DC_PRED; mode <= TM_PRED; mode++) {
+ x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
+ RECON_INVOKE(&cpi->rtcd.common->recon,
+ build_intra_predictors_sbuv_s)(&x->e_mbd);
+
+ super_block_uvrd_8x8(x, &this_rate_tokenonly,
+ &this_distortion, IF_RTCD(&cpi->rtcd));
+ this_rate = this_rate_tokenonly +
+ x->mbmode_cost[x->e_mbd.frame_type]
+ [x->e_mbd.mode_info_context->mbmi.mode];
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+
+ if (this_rd < best_rd) {
+ mode_selected = mode;
+ best_rd = this_rd;
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ }
+ }
+
+ x->e_mbd.mode_info_context->mbmi.uv_mode = mode_selected;
+
+ return best_rd;
+}
+#endif
+
int vp8_cost_mv_ref(VP8_COMP *cpi,
MB_PREDICTION_MODE m,
const int near_mv_ref_ct[4]) {
@@ -2568,25 +2810,33 @@ static void vp8_estimate_ref_frame_costs(VP8_COMP *cpi, int segment_id, unsigned
}
}
-static void store_coding_context(MACROBLOCK *x, int mb_index,
+static void store_coding_context(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx,
int mode_index,
PARTITION_INFO *partition,
int_mv *ref_mv,
- int_mv *second_ref_mv) {
+ int_mv *second_ref_mv,
+ int single_pred_diff,
+ int comp_pred_diff,
+ int hybrid_pred_diff) {
MACROBLOCKD *xd = &x->e_mbd;
// Take a snapshot of the coding context so it can be
// restored if we decide to encode this way
- x->mb_context[mb_index].best_mode_index = mode_index;
- vpx_memcpy(&x->mb_context[mb_index].mic, xd->mode_info_context,
+ ctx->best_mode_index = mode_index;
+ vpx_memcpy(&ctx->mic, xd->mode_info_context,
sizeof(MODE_INFO));
- vpx_memcpy(&x->mb_context[mb_index].partition_info, partition,
- sizeof(PARTITION_INFO));
- x->mb_context[mb_index].best_ref_mv.as_int = ref_mv->as_int;
- x->mb_context[mb_index].second_best_ref_mv.as_int = second_ref_mv->as_int;
-
- // x->mb_context[mb_index].rddiv = x->rddiv;
- // x->mb_context[mb_index].rdmult = x->rdmult;
+ if (partition)
+ vpx_memcpy(&ctx->partition_info, partition,
+ sizeof(PARTITION_INFO));
+ ctx->best_ref_mv.as_int = ref_mv->as_int;
+ ctx->second_best_ref_mv.as_int = second_ref_mv->as_int;
+
+ // ctx[mb_index].rddiv = x->rddiv;
+ // ctx[mb_index].rdmult = x->rdmult;
+
+ ctx->single_pred_diff = single_pred_diff;
+ ctx->comp_pred_diff = comp_pred_diff;
+ ctx->hybrid_pred_diff = hybrid_pred_diff;
}
static void inter_mode_cost(VP8_COMP *cpi, MACROBLOCK *x, int this_mode,
@@ -3464,7 +3714,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
}
#endif
- if (x->skip)
+ if (x->skip && !mode_excluded)
break;
}
@@ -3557,16 +3807,36 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
}
end:
- // TODO Save these to add in only if MB coding mode is selected?
- for (i = 0; i < NB_PREDICTION_TYPES; ++i)
- cpi->rd_comp_pred_diff[i] += best_pred_diff[i];
+ 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],
+ best_pred_diff[0], best_pred_diff[1], best_pred_diff[2]);
+}
- store_coding_context(x, xd->mb_index, best_mode_index, &best_partition,
- &frame_best_ref_mv[mbmi->ref_frame],
- &frame_best_ref_mv[mbmi->second_ref_frame]);
+#if CONFIG_SUPERBLOCKS
+void vp8_rd_pick_intra_mode_sb(VP8_COMP *cpi, MACROBLOCK *x,
+ int *returnrate,
+ int *returndist) {
+ int rate_y, rate_uv;
+ int rate_y_tokenonly, rate_uv_tokenonly;
+ int error_y, error_uv;
+ int dist_y, dist_uv;
+
+ x->e_mbd.mode_info_context->mbmi.txfm_size = TX_8X8;
+
+ error_uv = rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly,
+ &dist_uv);
+ error_y = rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly,
+ &dist_y);
+
+ // TODO(rbultje): add rate_uv
+ *returnrate = rate_y;
+ *returndist = dist_y + (dist_uv >> 2);
}
+#endif
-int vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x) {
+void vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x,
+ int *returnrate, int *returndist) {
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
int64_t error4x4, error16x16;
@@ -3585,6 +3855,8 @@ int vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x) {
int rate8x8, dist8x8;
int mode16x16;
int mode8x8[2][4];
+ int dist;
+ int rateuv8, rateuv_tokenonly8, distuv8;
mbmi->ref_frame = INTRA_FRAME;
rd_pick_intra_mbuv_mode(cpi, x, &rateuv, &rateuv_tokenonly, &distuv);
@@ -3646,9 +3918,11 @@ int vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x) {
rate += rate4x4;
#endif
mbmi->mode = B_PRED;
+ dist = dist4x4;
} else {
mbmi->mode = mode16x16;
rate += rate16x16;
+ dist = dist16x16;
}
} else {
if (error4x4 < error8x8) {
@@ -3663,17 +3937,727 @@ int vp8_rd_pick_intra_mode(VP8_COMP *cpi, MACROBLOCK *x) {
rate += rate4x4;
#endif
mbmi->mode = B_PRED;
+ dist = dist4x4;
} else {
mbmi->mode = I8X8_PRED;
set_i8x8_block_modes(x, mode8x8);
rate += rate8x8;
+ dist = dist8x8;
}
}
- return rate;
+
+ // TODO(rbultje): should add rateuv here also
+ *returnrate = rate - rateuv;
+ *returndist = dist + (distuv >> 2);
}
-int vp8cx_pick_mode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
- int recon_yoffset, int recon_uvoffset) {
+#if CONFIG_SUPERBLOCKS
+int64_t vp8_rd_pick_inter_mode_sb(VP8_COMP *cpi, MACROBLOCK *x,
+ int recon_yoffset, int recon_uvoffset,
+ int *returnrate, int *returndistortion) {
+ VP8_COMMON *cm = &cpi->common;
+ MACROBLOCKD *xd = &x->e_mbd;
+ BLOCK *b = &x->block[0];
+ BLOCKD *d = &xd->block[0];
+ MB_PREDICTION_MODE this_mode;
+ MV_REFERENCE_FRAME ref_frame;
+ int mis = xd->mode_info_stride;
+ unsigned char segment_id = xd->mode_info_context->mbmi.segment_id;
+ int comp_pred;
+ int_mv best_ref_mv, second_best_ref_mv;
+ int_mv mode_mv[MB_MODE_COUNT];
+ int_mv frame_nearest_mv[4];
+ int_mv frame_near_mv[4];
+ int_mv frame_best_ref_mv[4];
+ int_mv mc_search_result[4];
+ int frame_mdcounts[4][4];
+ unsigned char *y_buffer[4];
+ unsigned char *u_buffer[4];
+ unsigned char *v_buffer[4];
+ static const int flag_list[4] = { 0, VP8_LAST_FLAG, VP8_GOLD_FLAG, VP8_ALT_FLAG };
+ int idx_list[4] = { 0, cpi->common.lst_fb_idx, cpi->common.gld_fb_idx, cpi->common.alt_fb_idx };
+ int mdcounts[4];
+ int near_sadidx[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+ int saddone = 0;
+ int sr = 0; // search range got from mv_pred(). It uses step_param levels. (0-7)
+ int64_t best_rd = INT64_MAX;
+ int64_t best_comp_rd = INT64_MAX;
+ int64_t best_single_rd = INT64_MAX;
+ int64_t best_hybrid_rd = INT64_MAX;
+ int64_t best_yrd = INT64_MAX;
+ MB_MODE_INFO best_mbmode;
+ int mode_index = 0;
+#if 0
+ PARTITION_INFO best_partition;
+ union b_mode_info best_bmodes[16];
+#endif
+ unsigned int ref_costs[MAX_REF_FRAMES];
+
+ xd->mode_info_context->mbmi.segment_id = segment_id;
+ vp8_estimate_ref_frame_costs(cpi, segment_id, ref_costs);
+
+ for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
+ if (cpi->ref_frame_flags & flag_list[ref_frame]) {
+ YV12_BUFFER_CONFIG *ref_buf = &cpi->common.yv12_fb[idx_list[ref_frame]];
+
+ vp8_find_near_mvs(xd, xd->mode_info_context,
+ xd->prev_mode_info_context,
+ &frame_nearest_mv[ref_frame], &frame_near_mv[ref_frame],
+ &frame_best_ref_mv[ref_frame], frame_mdcounts[ref_frame],
+ ref_frame, cpi->common.ref_frame_sign_bias);
+
+ y_buffer[ref_frame] = ref_buf->y_buffer + recon_yoffset;
+ u_buffer[ref_frame] = ref_buf->u_buffer + recon_uvoffset;
+ v_buffer[ref_frame] = ref_buf->v_buffer + recon_uvoffset;
+ }
+ mc_search_result[ref_frame].as_int = INVALID_MV;
+ }
+
+ for (mode_index = 0; mode_index < MAX_MODES; mode_index++) {
+ int_mv mvp;
+ int mode_excluded;
+ int64_t this_rd = INT64_MAX;
+ int disable_skip = 0;
+ int other_cost = 0;
+ int compmode_cost = 0;
+ int rate2 = 0;
+ int distortion2 = 0;
+ int rate_y = 0;
+ int rate_uv = 0;
+ int distortion_uv;
+ int distortion;
+ int skippable_y, skippable_uv;
+
+ // Test best rd so far against threshold for trying this mode.
+ if (best_rd <= cpi->rd_threshes[mode_index]) {
+ continue;
+ }
+
+ this_mode = vp8_mode_order[mode_index].mode;
+ ref_frame = vp8_mode_order[mode_index].ref_frame;
+ xd->mode_info_context->mbmi.ref_frame = ref_frame;
+ comp_pred = vp8_mode_order[mode_index].second_ref_frame != INTRA_FRAME;
+ xd->mode_info_context->mbmi.mode = this_mode;
+ xd->mode_info_context->mbmi.uv_mode = DC_PRED;
+#if 0 && CONFIG_PRED_FILTER
+ xd->mode_info_context->mbmi.pred_filter_enabled = 0;
+#endif
+
+#if 0 && CONFIG_COMP_INTRA_PRED
+ xd->mode_info_context->mbmi.second_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
+ xd->mode_info_context->mbmi.second_uv_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
+#endif
+
+ if (!(cpi->ref_frame_flags & flag_list[ref_frame]))
+ continue;
+
+ // not yet supported or not superblocky
+ // TODO(rbultje): support intra coding
+ if (ref_frame == INTRA_FRAME || this_mode == SPLITMV)
+ continue;
+
+ if (comp_pred) {
+ int second_ref;
+
+ if (ref_frame == ALTREF_FRAME) {
+ second_ref = LAST_FRAME;
+ } else {
+ second_ref = ref_frame + 1;
+ }
+ if (!(cpi->ref_frame_flags & flag_list[second_ref]))
+ continue;
+ xd->mode_info_context->mbmi.second_ref_frame = second_ref;
+
+ xd->second_pre.y_buffer = y_buffer[second_ref];
+ xd->second_pre.u_buffer = u_buffer[second_ref];
+ xd->second_pre.v_buffer = v_buffer[second_ref];
+ second_best_ref_mv = frame_best_ref_mv[second_ref];
+ mode_excluded = cm->comp_pred_mode == SINGLE_PREDICTION_ONLY;
+ } else {
+ xd->mode_info_context->mbmi.second_ref_frame = INTRA_FRAME;
+ mode_excluded = cm->comp_pred_mode == COMP_PREDICTION_ONLY;
+ }
+
+ xd->pre.y_buffer = y_buffer[ref_frame];
+ xd->pre.u_buffer = u_buffer[ref_frame];
+ xd->pre.v_buffer = v_buffer[ref_frame];
+ mode_mv[ZEROMV].as_int = 0;
+ mode_mv[NEARESTMV] = frame_nearest_mv[ref_frame];
+ mode_mv[NEARMV] = frame_near_mv[ref_frame];
+ best_ref_mv = frame_best_ref_mv[ref_frame];
+ vpx_memcpy(mdcounts, frame_mdcounts[ref_frame], sizeof(mdcounts));
+
+ // If the segment reference frame feature is enabled....
+ // then do nothing if the current ref frame is not allowed..
+ if (segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) &&
+ !check_segref(xd, segment_id, ref_frame)) {
+ continue;
+ }
+ // If the segment mode feature is enabled....
+ // then do nothing if the current mode is not allowed..
+ else if (segfeature_active(xd, segment_id, SEG_LVL_MODE) &&
+ (this_mode != get_segdata(xd, segment_id, SEG_LVL_MODE))) {
+ continue;
+ }
+ // Disable this drop out case if either the mode or ref frame
+ // segment level feature is enabled for this segment. This is to
+ // prevent the possibility that we end up unable to pick any mode.
+ else if (!segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) &&
+ !segfeature_active(xd, segment_id, SEG_LVL_MODE)) {
+ // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
+ // unless ARNR filtering is enabled in which case we want
+ // an unfiltered alternative
+ if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
+ if (this_mode != ZEROMV || ref_frame != ALTREF_FRAME) {
+ continue;
+ }
+ }
+ }
+
+ if (!comp_pred) {
+ switch (this_mode) {
+ case NEWMV: {
+ int thissme;
+ int bestsme = INT_MAX;
+ int step_param = cpi->sf.first_step;
+ int further_steps;
+ int n;
+ int do_refine = 1; /* If last step (1-away) of n-step search doesn't pick the center point as the best match,
+ we will do a final 1-away diamond refining search */
+ int num00;
+
+ int sadpb = x->sadperbit16;
+ int_mv mvp_full;
+
+ int col_min = (best_ref_mv.as_mv.col >> 3) - MAX_FULL_PEL_VAL + ((best_ref_mv.as_mv.col & 7) ? 1 : 0);
+ int row_min = (best_ref_mv.as_mv.row >> 3) - MAX_FULL_PEL_VAL + ((best_ref_mv.as_mv.row & 7) ? 1 : 0);
+ int col_max = (best_ref_mv.as_mv.col >> 3) + MAX_FULL_PEL_VAL;
+ int row_max = (best_ref_mv.as_mv.row >> 3) + MAX_FULL_PEL_VAL;
+
+ int tmp_col_min = x->mv_col_min;
+ int tmp_col_max = x->mv_col_max;
+ int tmp_row_min = x->mv_row_min;
+ int tmp_row_max = x->mv_row_max;
+
+ if (!saddone) {
+ vp8_cal_sad(cpi, xd, x, recon_yoffset, &near_sadidx[0]);
+ saddone = 1;
+ }
+
+ vp8_mv_pred(cpi, xs, xd->mode_info_context, &mvp,
+ xd->mode_info_context->mbmi.ref_frame,
+ cpi->common.ref_frame_sign_bias, &sr, &near_sadidx[0]);
+
+ mvp_full.as_mv.col = mvp.as_mv.col >> 3;
+ mvp_full.as_mv.row = mvp.as_mv.row >> 3;
+
+ // Get intersection of UMV window and valid MV window to reduce # of checks in diamond search.
+ if (x->mv_col_min < col_min)
+ x->mv_col_min = col_min;
+ if (x->mv_col_max > col_max)
+ x->mv_col_max = col_max;
+ if (x->mv_row_min < row_min)
+ x->mv_row_min = row_min;
+ if (x->mv_row_max > row_max)
+ x->mv_row_max = row_max;
+
+ // adjust search range according to sr from mv prediction
+ if (sr > step_param)
+ step_param = sr;
+
+ // Initial step/diamond search
+ {
+ bestsme = cpi->diamond_search_sad(x, b, d, &mvp_full, &d->bmi.as_mv.first,
+ step_param, sadpb, &num00,
+ &cpi->fn_ptr[BLOCK_32X32],
+ XMVCOST, &best_ref_mv);
+ mode_mv[NEWMV].as_int = d->bmi.as_mv.first.as_int;
+
+ // Further step/diamond searches as necessary
+ n = 0;
+ further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
+
+ n = num00;
+ num00 = 0;
+
+ /* If there won't be more n-step search, check to see if refining search is needed. */
+ if (n > further_steps)
+ do_refine = 0;
+
+ while (n < further_steps) {
+ n++;
+
+ if (num00)
+ num00--;
+ else {
+ thissme = cpi->diamond_search_sad(x, b, d, &mvp_full,
+ &d->bmi.as_mv.first, step_param + n, sadpb, &num00,
+ &cpi->fn_ptr[BLOCK_32X32],
+ XMVCOST, &best_ref_mv);
+
+ /* check to see if refining search is needed. */
+ if (num00 > (further_steps - n))
+ do_refine = 0;
+
+ if (thissme < bestsme) {
+ bestsme = thissme;
+ mode_mv[NEWMV].as_int = d->bmi.as_mv.first.as_int;
+ } else {
+ d->bmi.as_mv.first.as_int = mode_mv[NEWMV].as_int;
+ }
+ }
+ }
+ }
+
+ /* final 1-away diamond refining search */
+ if (do_refine == 1) {
+ int search_range;
+
+ // It seems not a good way to set search_range. Need further investigation.
+ // search_range = MAXF(abs((mvp.row>>3) - d->bmi.mv.as_mv.row), abs((mvp.col>>3) - d->bmi.mv.as_mv.col));
+ search_range = 8;
+
+ thissme = cpi->refining_search_sad(x, b, d, &d->bmi.as_mv.first, sadpb,
+ search_range, &cpi->fn_ptr[BLOCK_32X32],
+ XMVCOST, &best_ref_mv);
+
+ if (thissme < bestsme) {
+ bestsme = thissme;
+ mode_mv[NEWMV].as_int = d->bmi.as_mv.first.as_int;
+ } else {
+ d->bmi.as_mv.first.as_int = mode_mv[NEWMV].as_int;
+ }
+ }
+
+ x->mv_col_min = tmp_col_min;
+ x->mv_col_max = tmp_col_max;
+ x->mv_row_min = tmp_row_min;
+ x->mv_row_max = tmp_row_max;
+
+ if (bestsme < INT_MAX) {
+ int dis; /* TODO: use dis in distortion calculation later. */
+ unsigned int sse;
+ cpi->find_fractional_mv_step(x, b, d, &d->bmi.as_mv.first, &best_ref_mv,
+ x->errorperbit,
+ &cpi->fn_ptr[BLOCK_32X32],
+ XMVCOST, &dis, &sse);
+ }
+ mc_search_result[xd->mode_info_context->mbmi.ref_frame].as_int =
+ d->bmi.as_mv.first.as_int;
+
+ mode_mv[NEWMV].as_int = d->bmi.as_mv.first.as_int;
+
+ // Add the new motion vector cost to our rolling cost variable
+ rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv,
+ XMVCOST, 96,
+ xd->allow_high_precision_mv);
+ }
+
+ case NEARESTMV:
+ case NEARMV:
+ // Clip "next_nearest" so that it does not extend to far out of image
+ vp8_clamp_mv2(&mode_mv[this_mode], xd);
+
+ // Do not bother proceeding if the vector (from newmv,nearest or near) is 0,0 as this should then be coded using the zeromv mode.
+ if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) && (mode_mv[this_mode].as_int == 0)) {
+ continue;
+ }
+
+ case ZEROMV:
+ // Trap vectors that reach beyond the UMV borders
+ // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
+ // because of the lack of break statements in the previous two cases.
+ if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
+ ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) {
+ continue;
+ }
+
+ vp8_set_mbmode_and_mvs(x, this_mode, &mode_mv[this_mode]);
+
+#if CONFIG_PRED_FILTER
+ // Filtered prediction:
+ xd->mode_info_context->mbmi.pred_filter_enabled =
+ vp8_mode_order[mode_index].pred_filter_flag;
+ rate2 += vp8_cost_bit(cpi->common.prob_pred_filter_off,
+ xd->mode_info_context->mbmi.pred_filter_enabled);
+#endif
+
+ vp8_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);
+
+ compmode_cost =
+ vp8_cost_bit(get_pred_prob(cm, xd, PRED_COMP), 0);
+
+ if (cpi->active_map_enabled && x->active_ptr[0] == 0) {
+ x->skip = 1;
+ } else if (x->encode_breakout) {
+ unsigned int sse;
+ unsigned int var;
+ int threshold = (xd->block[0].dequant[1] *
+ xd->block[0].dequant[1] >> 4);
+
+ if (threshold < x->encode_breakout)
+ threshold = x->encode_breakout;
+
+ var = VARIANCE_INVOKE(&cpi->rtcd.variance, var32x32)(*(b->base_src),
+ b->src_stride, xd->dst.y_buffer, xd->dst.y_stride, &sse);
+
+ if (sse < threshold) {
+ unsigned int q2dc = xd->block[24].dequant[0];
+ /* If there is no codeable 2nd order dc
+ or a very small uniform pixel change change */
+ if ((sse - var < q2dc *q2dc >> 4) ||
+ (sse / 2 > var && sse - var < 64)) {
+ // Check u and v to make sure skip is ok
+ int sse2, sse3;
+ int var2 = VARIANCE_INVOKE(&cpi->rtcd.variance, var16x16)
+ (x->src.u_buffer, x->src.uv_stride,
+ xd->dst.u_buffer, xd->dst.uv_stride, &sse2);
+ int var3 = VARIANCE_INVOKE(&cpi->rtcd.variance, var16x16)
+ (x->src.v_buffer, x->src.uv_stride,
+ xd->dst.v_buffer, xd->dst.uv_stride, &sse3);
+ sse2 += sse3;
+ if (sse2 * 2 < threshold) {
+ x->skip = 1;
+ distortion2 = sse + sse2;
+ rate2 = 500;
+
+ /* for best_yrd calculation */
+ rate_uv = 0;
+ distortion_uv = sse2;
+
+ disable_skip = 1;
+ this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+ break;
+ }
+ }
+ }
+ }
+
+ // Add in the Mv/mode cost
+ rate2 += vp8_cost_mv_ref(cpi, this_mode, mdcounts);
+
+ // Y cost and distortion - FIXME support other transform sizes
+ super_block_yrd_8x8(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd), &skippable_y);
+ rate2 += rate_y;
+ distortion2 += distortion;
+
+ rd_inter32x32_uv_8x8(cpi, x, &rate_uv, &distortion_uv,
+ cpi->common.full_pixel, &skippable_uv);
+
+ rate2 += rate_uv;
+ distortion2 += distortion_uv;
+ mode_excluded = cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY;
+ break;
+
+ default:
+ break;
+ }
+ } else { /* xd->mode_info_context->mbmi.second_ref_frame != 0 */
+ int ref1 = xd->mode_info_context->mbmi.ref_frame;
+ int ref2 = xd->mode_info_context->mbmi.second_ref_frame;
+
+ mode_excluded = cpi->common.comp_pred_mode == SINGLE_PREDICTION_ONLY;
+ switch (this_mode) {
+ case NEWMV:
+ if (mc_search_result[ref1].as_int == INVALID_MV ||
+ mc_search_result[ref2].as_int == INVALID_MV)
+ continue;
+ xd->mode_info_context->mbmi.mv[0].as_int = mc_search_result[ref1].as_int;
+ xd->mode_info_context->mbmi.mv[1].as_int = mc_search_result[ref2].as_int;
+ rate2 += vp8_mv_bit_cost(&mc_search_result[ref1],
+ &frame_best_ref_mv[ref1],
+ XMVCOST, 96,
+ xd->allow_high_precision_mv);
+ rate2 += vp8_mv_bit_cost(&mc_search_result[ref2],
+ &frame_best_ref_mv[ref2],
+ XMVCOST, 96,
+ xd->allow_high_precision_mv);
+ break;
+ case ZEROMV:
+ xd->mode_info_context->mbmi.mv[0].as_int = 0;
+ xd->mode_info_context->mbmi.mv[1].as_int = 0;
+ break;
+ case NEARMV:
+ if (frame_near_mv[ref1].as_int == 0 || frame_near_mv[ref2].as_int == 0) {
+ continue;
+ }
+ xd->mode_info_context->mbmi.mv[0].as_int = frame_near_mv[ref1].as_int;
+ xd->mode_info_context->mbmi.mv[1].as_int = frame_near_mv[ref2].as_int;
+ break;
+ case NEARESTMV:
+ if (frame_nearest_mv[ref1].as_int == 0 || frame_nearest_mv[ref2].as_int == 0) {
+ continue;
+ }
+ xd->mode_info_context->mbmi.mv[0].as_int = frame_nearest_mv[ref1].as_int;
+ xd->mode_info_context->mbmi.mv[1].as_int = frame_nearest_mv[ref2].as_int;
+ break;
+ default:
+ break;
+ }
+
+ /* Add in the Mv/mode cost */
+ rate2 += vp8_cost_mv_ref(cpi, this_mode, mdcounts);
+
+ vp8_clamp_mv2(&xd->mode_info_context->mbmi.mv[0], xd);
+ vp8_clamp_mv2(&xd->mode_info_context->mbmi.mv[1], xd);
+ if (((xd->mode_info_context->mbmi.mv[0].as_mv.row >> 3) < x->mv_row_min) ||
+ ((xd->mode_info_context->mbmi.mv[0].as_mv.row >> 3) > x->mv_row_max) ||
+ ((xd->mode_info_context->mbmi.mv[0].as_mv.col >> 3) < x->mv_col_min) ||
+ ((xd->mode_info_context->mbmi.mv[0].as_mv.col >> 3) > x->mv_col_max) ||
+ ((xd->mode_info_context->mbmi.mv[1].as_mv.row >> 3) < x->mv_row_min) ||
+ ((xd->mode_info_context->mbmi.mv[1].as_mv.row >> 3) > x->mv_row_max) ||
+ ((xd->mode_info_context->mbmi.mv[1].as_mv.col >> 3) < x->mv_col_min) ||
+ ((xd->mode_info_context->mbmi.mv[1].as_mv.col >> 3) > x->mv_col_max)) {
+ continue;
+ }
+
+ /* build first and second prediction */
+ vp8_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);
+
+ /* Y cost and distortion - TODO(rbultje) support other transform sizes */
+ super_block_yrd_8x8(x, &rate_y, &distortion,
+ IF_RTCD(&cpi->rtcd), &skippable_y);
+
+ rate2 += rate_y;
+ distortion2 += distortion;
+
+ /* UV cost and distortion */
+ rd_inter32x32_uv_8x8(cpi, x, &rate_uv, &distortion_uv,
+ cpi->common.full_pixel, &skippable_uv);
+
+ rate2 += rate_uv;
+ distortion2 += distortion_uv;
+
+ /* don't bother w/ skip, we would never have come here if skip were
+ * enabled */
+ xd->mode_info_context->mbmi.mode = this_mode;
+
+ /* We don't include the cost of the second reference here, because there
+ * are only three options: Last/Golden, ARF/Last or Golden/ARF, or in
+ * other words if you present them in that order, the second one is
+ * always known if the first is known */
+ compmode_cost = vp8_cost_bit(get_pred_prob(cm, xd, PRED_COMP), 1);
+ }
+
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
+ rate2 += compmode_cost;
+ }
+
+
+ // Estimate the reference frame signaling cost and add it
+ // to the rolling cost variable.
+ rate2 += ref_costs[xd->mode_info_context->mbmi.ref_frame];
+
+ if (!disable_skip) {
+ // Test for the condition where skip block will be activated
+ // because there are no non zero coefficients and make any
+ // necessary adjustment for rate. Ignore if skip is coded at
+ // segment level as the cost wont have been added in.
+ if (cpi->common.mb_no_coeff_skip) {
+ int mb_skippable = skippable_y && skippable_uv;
+ int mb_skip_allowed;
+
+ // Is Mb level skip allowed for this mb.
+ mb_skip_allowed =
+ !segfeature_active(xd, segment_id, SEG_LVL_EOB) ||
+ get_segdata(xd, segment_id, SEG_LVL_EOB);
+
+ if (mb_skippable) {
+ // Back out the coefficient coding costs
+ rate2 -= (rate_y + rate_uv);
+ // for best_yrd calculation
+ rate_uv = 0;
+
+ if (mb_skip_allowed) {
+ int prob_skip_cost;
+
+ // Cost the skip mb case
+ vp8_prob skip_prob =
+ get_pred_prob(cm, xd, PRED_MBSKIP);
+
+ if (skip_prob) {
+ prob_skip_cost = vp8_cost_bit(skip_prob, 1);
+ rate2 += prob_skip_cost;
+ other_cost += prob_skip_cost;
+ }
+ }
+ }
+ // Add in the cost of the no skip flag.
+ else if (mb_skip_allowed) {
+ int prob_skip_cost = vp8_cost_bit(get_pred_prob(cm, xd,
+ PRED_MBSKIP), 0);
+ rate2 += prob_skip_cost;
+ other_cost += prob_skip_cost;
+ }
+ }
+
+ // Calculate the final RD estimate for this mode.
+ this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
+ }
+
+#if 0
+ // Keep record of best intra distortion
+ if ((xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
+ (this_rd < best_intra_rd)) {
+ best_intra_rd = this_rd;
+ *returnintra = distortion2;
+ }
+#endif
+
+ if (!disable_skip && xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
+ if (this_rd < best_comp_rd)
+ best_comp_rd = this_rd;
+ if (this_rd < best_single_rd)
+ best_single_rd = this_rd;
+ if (this_rd < best_hybrid_rd)
+ best_hybrid_rd = this_rd;
+ }
+
+ // Did this mode help.. i.e. is it the new best mode
+ if (this_rd < best_rd || x->skip) {
+ if (!mode_excluded) {
+#if 0
+ // Note index of best mode so far
+ best_mode_index = mode_index;
+
+ if (this_mode <= B_PRED) {
+ xd->mode_info_context->mbmi.uv_mode = uv_intra_mode_8x8;
+ /* required for left and above block mv */
+ xd->mode_info_context->mbmi.mv.as_int = 0;
+ }
+#endif
+
+ other_cost += ref_costs[xd->mode_info_context->mbmi.ref_frame];
+
+ /* Calculate the final y RD estimate for this mode */
+ best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2 - rate_uv - other_cost),
+ (distortion2 - distortion_uv));
+
+ *returnrate = rate2;
+ *returndistortion = distortion2;
+ best_rd = this_rd;
+ vpx_memcpy(&best_mbmode, &xd->mode_info_context->mbmi, sizeof(MB_MODE_INFO));
+ }
+#if 0
+ // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
+ cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+ cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+#endif
+ }
+ // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around.
+ else {
+#if 0
+ cpi->rd_thresh_mult[mode_index] += 4;
+
+ if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+ cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+ cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+#endif
+ }
+
+ /* keep record of best compound/single-only prediction */
+ if (!disable_skip && xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME) {
+ int single_rd, hybrid_rd, single_rate, hybrid_rate;
+
+ if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
+ single_rate = rate2 - compmode_cost;
+ hybrid_rate = rate2;
+ } else {
+ single_rate = rate2;
+ hybrid_rate = rate2 + compmode_cost;
+ }
+
+ single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
+ hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
+
+ if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME &&
+ single_rd < best_single_rd) {
+ best_single_rd = single_rd;
+ } else if (xd->mode_info_context->mbmi.second_ref_frame != INTRA_FRAME &&
+ single_rd < best_comp_rd) {
+ best_comp_rd = single_rd;
+ }
+ if (hybrid_rd < best_hybrid_rd) {
+ best_hybrid_rd = hybrid_rd;
+ }
+ }
+
+ if (x->skip && !mode_excluded)
+ break;
+ }
+
+ // TODO(rbultje) integrate with RD thresholding
+#if 0
+ // Reduce the activation RD thresholds for the best choice mode
+ if ((cpi->rd_baseline_thresh[best_mode_index] > 0) &&
+ (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2))) {
+ int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 2);
+
+ cpi->rd_thresh_mult[best_mode_index] =
+ (cpi->rd_thresh_mult[best_mode_index] >= (MIN_THRESHMULT + best_adjustment)) ?
+ cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT;
+ cpi->rd_threshes[best_mode_index] =
+ (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index];
+ }
+#endif
+
+ // This code forces Altref,0,0 and skip for the frame that overlays a
+ // an alrtef unless Altref is filtered. However, this is unsafe if
+ // segment level coding of ref frame or mode is enabled for this
+ // segment.
+ if (!segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) &&
+ !segfeature_active(xd, segment_id, SEG_LVL_MODE) &&
+ cpi->is_src_frame_alt_ref &&
+ (cpi->oxcf.arnr_max_frames == 0) &&
+ (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME)) {
+ xd->mode_info_context->mbmi.mode = ZEROMV;
+ xd->mode_info_context->mbmi.ref_frame = ALTREF_FRAME;
+ xd->mode_info_context->mbmi.mv[0].as_int = 0;
+ xd->mode_info_context->mbmi.uv_mode = DC_PRED;
+ xd->mode_info_context->mbmi.mb_skip_coeff =
+ (cpi->common.mb_no_coeff_skip) ? 1 : 0;
+ xd->mode_info_context->mbmi.partitioning = 0;
+
+ xd->mode_info_context->mbmi.txfm_size = TX_8X8;
+
+ if (best_rd != INT64_MAX)
+ store_coding_context(x, &x->sb_context[0], mode_index, NULL,
+ &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, 0);
+ return best_rd;
+ }
+
+ // macroblock modes
+ vpx_memcpy(&xd->mode_info_context->mbmi, &best_mbmode,
+ sizeof(MB_MODE_INFO));
+ xd->mode_info_context->mbmi.txfm_size = TX_8X8;
+
+ if (best_rd != INT64_MAX)
+ store_coding_context(x, &x->sb_context[0], mode_index, NULL,
+ &frame_best_ref_mv[xd->mode_info_context->mbmi.ref_frame],
+ &frame_best_ref_mv[xd->mode_info_context->mbmi.second_ref_frame],
+ (best_single_rd == INT64_MAX) ? INT_MIN : (best_rd - best_single_rd),
+ (best_comp_rd == INT64_MAX) ? INT_MIN : (best_rd - best_comp_rd),
+ (best_hybrid_rd == INT64_MAX) ? INT_MIN : (best_rd - best_hybrid_rd));
+
+ return best_rd;
+}
+#endif
+
+void vp8cx_pick_mode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
+ int recon_yoffset,
+ int recon_uvoffset,
+ int *totalrate, int *totaldist) {
VP8_COMMON *cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
@@ -3694,17 +4678,6 @@ int vp8cx_pick_mode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
&distortion, &intra_error);
- if (mbmi->ref_frame) {
- unsigned char pred_context;
-
- pred_context = get_pred_context(cm, xd, PRED_COMP);
-
- if (mbmi->second_ref_frame == INTRA_FRAME)
- cpi->single_pred_count[pred_context]++;
- else
- cpi->comp_pred_count[pred_context]++;
- }
-
/* restore cpi->zbin_mode_boost_enabled */
cpi->zbin_mode_boost_enabled = zbin_mode_boost_enabled;
}
@@ -3717,5 +4690,6 @@ int vp8cx_pick_mode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
x->mb_context[xd->mb_index].distortion = distortion;
x->mb_context[xd->mb_index].intra_error = intra_error;
- return rate;
+ *totalrate = rate;
+ *totaldist = distortion;
}