diff options
Diffstat (limited to 'vp8/encoder/pickinter.c')
-rw-r--r-- | vp8/encoder/pickinter.c | 923 |
1 files changed, 923 insertions, 0 deletions
diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c new file mode 100644 index 000000000..d61e2ceda --- /dev/null +++ b/vp8/encoder/pickinter.c @@ -0,0 +1,923 @@ +/* + * Copyright (c) 2010 The VP8 project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license and patent + * grant that can be found in the LICENSE file in the root of the source + * tree. All contributing project authors may be found in the AUTHORS + * file in the root of the source tree. + */ + + +#include <limits.h> +#include "vpx_ports/config.h" +#include "onyx_int.h" +#include "modecosts.h" +#include "encodeintra.h" +#include "entropymode.h" +#include "pickinter.h" +#include "findnearmv.h" +#include "encodemb.h" +#include "reconinter.h" +#include "reconintra.h" +#include "reconintra4x4.h" +#include "g_common.h" +#include "variance.h" +#include "mcomp.h" + +#include "vpx_mem/vpx_mem.h" + +#if CONFIG_RUNTIME_CPU_DETECT +#define IF_RTCD(x) (x) +#else +#define IF_RTCD(x) NULL +#endif + +extern int VP8_UVSSE(MACROBLOCK *x, const vp8_variance_rtcd_vtable_t *rtcd); + +#ifdef SPEEDSTATS +extern unsigned int cnt_pm; +#endif + +extern const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES]; +extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES]; + + +extern unsigned int (*vp8_get16x16pred_error)(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride); +extern unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int source_stride, unsigned char *ref_ptr, int recon_stride); +extern int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *best_ref_mv, int best_rd, int *, int *, int *, int, int *mvcost[2], int, int fullpixel); +extern int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]); +extern void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, MV *mv); + + +int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2]) +{ + (void) b; + (void) d; + (void) ref_mv; + (void) error_per_bit; + (void) svf; + (void) vf; + (void) mvcost; + bestmv->row <<= 3; + bestmv->col <<= 3; + return 0; +} + + +static int get_inter_mbpred_error(MACROBLOCK *mb, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, unsigned int *sse) +{ + + BLOCK *b = &mb->block[0]; + BLOCKD *d = &mb->e_mbd.block[0]; + unsigned char *what = (*(b->base_src) + b->src); + int what_stride = b->src_stride; + unsigned char *in_what = *(d->base_pre) + d->pre ; + int in_what_stride = d->pre_stride; + int xoffset = d->bmi.mv.as_mv.col & 7; + int yoffset = d->bmi.mv.as_mv.row & 7; + + in_what += (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3); + + if (xoffset | yoffset) + { + return svf(in_what, in_what_stride, xoffset, yoffset, what, what_stride, sse); + } + else + { + return vf(what, what_stride, in_what, in_what_stride, sse); + } + +} + +unsigned int vp8_get16x16pred_error_c +( + unsigned char *src_ptr, + int src_stride, + unsigned char *ref_ptr, + int ref_stride, + int max_sad +) +{ + unsigned pred_error = 0; + int i, j; + int sum = 0; + + for (i = 0; i < 16; i++) + { + int diff; + + for (j = 0; j < 16; j++) + { + diff = src_ptr[j] - ref_ptr[j]; + sum += diff; + pred_error += diff * diff; + } + + src_ptr += src_stride; + ref_ptr += ref_stride; + } + + pred_error -= sum * sum / 256; + return pred_error; +} + + +unsigned int vp8_get4x4sse_cs_c +( + unsigned char *src_ptr, + int source_stride, + unsigned char *ref_ptr, + int recon_stride, + int max_sad +) +{ + int distortion = 0; + int r, c; + + for (r = 0; r < 4; r++) + { + for (c = 0; c < 4; c++) + { + int diff = src_ptr[c] - ref_ptr[c]; + distortion += diff * diff; + } + + src_ptr += source_stride; + ref_ptr += recon_stride; + } + + return distortion; +} + +static int get_prediction_error(BLOCK *be, BLOCKD *b, const vp8_variance_rtcd_vtable_t *rtcd) +{ + unsigned char *sptr; + unsigned char *dptr; + sptr = (*(be->base_src) + be->src); + dptr = b->predictor; + + return VARIANCE_INVOKE(rtcd, get4x4sse_cs)(sptr, be->src_stride, dptr, 16, 0x7fffffff); + +} + +static int pick_intra4x4block( + const VP8_ENCODER_RTCD *rtcd, + MACROBLOCK *x, + BLOCK *be, + BLOCKD *b, + B_PREDICTION_MODE *best_mode, + B_PREDICTION_MODE above, + B_PREDICTION_MODE left, + ENTROPY_CONTEXT *a, + ENTROPY_CONTEXT *l, + + int *bestrate, + int *bestdistortion) +{ + B_PREDICTION_MODE mode; + int best_rd = INT_MAX; // 1<<30 + int rate; + int distortion; + unsigned int *mode_costs; + (void) l; + (void) a; + + if (x->e_mbd.frame_type == KEY_FRAME) + { + mode_costs = x->bmode_costs[above][left]; + } + else + { + mode_costs = x->inter_bmode_costs; + } + + for (mode = B_DC_PRED; mode <= B_HE_PRED /*B_HU_PRED*/; mode++) + { + int this_rd; + + rate = mode_costs[mode]; + vp8_predict_intra4x4(b, mode, b->predictor); + distortion = get_prediction_error(be, b, &rtcd->variance); + this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate, distortion); + + if (this_rd < best_rd) + { + *bestrate = rate; + *bestdistortion = distortion; + best_rd = this_rd; + *best_mode = mode; + } + } + + b->bmi.mode = (B_PREDICTION_MODE)(*best_mode); + vp8_encode_intra4x4block(rtcd, x, be, b, b->bmi.mode); + return best_rd; +} + + +int vp8_pick_intra4x4mby_modes(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *mb, int *Rate, int *best_dist) +{ + MACROBLOCKD *const xd = &mb->e_mbd; + int i; + TEMP_CONTEXT t; + int cost = mb->mbmode_cost [xd->frame_type] [B_PRED]; + int error = RD_ESTIMATE(mb->rdmult, mb->rddiv, cost, 0); // Rd estimate for the cost of the block prediction mode + int distortion = 0; + + vp8_intra_prediction_down_copy(xd); + vp8_setup_temp_context(&t, xd->above_context[Y1CONTEXT], xd->left_context[Y1CONTEXT], 4); + + for (i = 0; i < 16; i++) + { + MODE_INFO *const mic = xd->mode_info_context; + const int mis = xd->mode_info_stride; + const B_PREDICTION_MODE A = vp8_above_bmi(mic, i, mis)->mode; + const B_PREDICTION_MODE L = vp8_left_bmi(mic, i)->mode; + B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode); + int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(d); + + error += pick_intra4x4block(rtcd, + mb, mb->block + i, xd->block + i, &best_mode, A, L, + t.a + vp8_block2above[i], + t.l + vp8_block2left[i], &r, &d); + + cost += r; + distortion += d; + + mic->bmi[i].mode = xd->block[i].bmi.mode = best_mode; + + // Break out case where we have already exceeded best so far value that was bassed in + if (distortion > *best_dist) + break; + } + + for (i = 0; i < 16; i++) + xd->block[i].bmi.mv.as_int = 0; + + *Rate = cost; + + if (i == 16) + *best_dist = distortion; + else + *best_dist = INT_MAX; + + + return error; +} + +int vp8_pick_intra_mbuv_mode(MACROBLOCK *mb) +{ + + MACROBLOCKD *x = &mb->e_mbd; + unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride; + unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride; + unsigned char *usrc_ptr = (mb->block[16].src + *mb->block[16].base_src); + unsigned char *vsrc_ptr = (mb->block[20].src + *mb->block[20].base_src); + int uvsrc_stride = mb->block[16].src_stride; + unsigned char uleft_col[8]; + unsigned char vleft_col[8]; + unsigned char utop_left = uabove_row[-1]; + unsigned char vtop_left = vabove_row[-1]; + int i, j; + int expected_udc; + int expected_vdc; + int shift; + int Uaverage = 0; + int Vaverage = 0; + int diff; + int pred_error[4] = {0, 0, 0, 0}, best_error = INT_MAX; + MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode); + + + for (i = 0; i < 8; i++) + { + uleft_col[i] = x->dst.u_buffer [i* x->dst.uv_stride -1]; + vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1]; + } + + if (!x->up_available && !x->left_available) + { + expected_udc = 128; + expected_vdc = 128; + } + else + { + shift = 2; + + if (x->up_available) + { + + for (i = 0; i < 8; i++) + { + Uaverage += uabove_row[i]; + Vaverage += vabove_row[i]; + } + + shift ++; + + } + + if (x->left_available) + { + for (i = 0; i < 8; i++) + { + Uaverage += uleft_col[i]; + Vaverage += vleft_col[i]; + } + + shift ++; + + } + + expected_udc = (Uaverage + (1 << (shift - 1))) >> shift; + expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift; + } + + + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + { + + int predu = uleft_col[i] + uabove_row[j] - utop_left; + int predv = vleft_col[i] + vabove_row[j] - vtop_left; + int u_p, v_p; + + u_p = usrc_ptr[j]; + v_p = vsrc_ptr[j]; + + if (predu < 0) + predu = 0; + + if (predu > 255) + predu = 255; + + if (predv < 0) + predv = 0; + + if (predv > 255) + predv = 255; + + + diff = u_p - expected_udc; + pred_error[DC_PRED] += diff * diff; + diff = v_p - expected_vdc; + pred_error[DC_PRED] += diff * diff; + + + diff = u_p - uabove_row[j]; + pred_error[V_PRED] += diff * diff; + diff = v_p - vabove_row[j]; + pred_error[V_PRED] += diff * diff; + + + diff = u_p - uleft_col[i]; + pred_error[H_PRED] += diff * diff; + diff = v_p - vleft_col[i]; + pred_error[H_PRED] += diff * diff; + + + diff = u_p - predu; + pred_error[TM_PRED] += diff * diff; + diff = v_p - predv; + pred_error[TM_PRED] += diff * diff; + + + } + + usrc_ptr += uvsrc_stride; + vsrc_ptr += uvsrc_stride; + + if (i == 3) + { + usrc_ptr = (mb->block[18].src + *mb->block[18].base_src); + vsrc_ptr = (mb->block[22].src + *mb->block[22].base_src); + } + + + + } + + + for (i = DC_PRED; i <= TM_PRED; i++) + { + if (best_error > pred_error[i]) + { + best_error = pred_error[i]; + best_mode = (MB_PREDICTION_MODE)i; + } + } + + + mb->e_mbd.mbmi.uv_mode = best_mode; + return best_error; + +} + + +int vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra) +{ + BLOCK *b = &x->block[0]; + BLOCKD *d = &x->e_mbd.block[0]; + MACROBLOCKD *xd = &x->e_mbd; + B_MODE_INFO best_bmodes[16]; + MB_MODE_INFO best_mbmode; + MV best_ref_mv1; + MV mode_mv[MB_MODE_COUNT]; + MB_PREDICTION_MODE this_mode; + int num00; + int i; + int mdcounts[4]; + int best_rd = INT_MAX; // 1 << 30; + int best_intra_rd = INT_MAX; + int mode_index; + int ref_frame_cost[MAX_REF_FRAMES]; + int rate; + int rate2; + int distortion2; + int bestsme; + //int all_rds[MAX_MODES]; // Experimental debug code. + int best_mode_index = 0; + int sse = INT_MAX; + + MV nearest_mv[4]; + MV near_mv[4]; + MV best_ref_mv[4]; + int MDCounts[4][4]; + unsigned char *y_buffer[4]; + unsigned char *u_buffer[4]; + unsigned char *v_buffer[4]; + + int skip_mode[4] = {0, 0, 0, 0}; + + vpx_memset(mode_mv, 0, sizeof(mode_mv)); + vpx_memset(nearest_mv, 0, sizeof(nearest_mv)); + vpx_memset(near_mv, 0, sizeof(near_mv)); + + + // set up all the refframe dependent pointers. + if (cpi->ref_frame_flags & VP8_LAST_FLAG) + { + vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[LAST_FRAME], &near_mv[LAST_FRAME], + &best_ref_mv[LAST_FRAME], MDCounts[LAST_FRAME], LAST_FRAME, cpi->common.ref_frame_sign_bias); + + y_buffer[LAST_FRAME] = cpi->common.last_frame.y_buffer + recon_yoffset; + u_buffer[LAST_FRAME] = cpi->common.last_frame.u_buffer + recon_uvoffset; + v_buffer[LAST_FRAME] = cpi->common.last_frame.v_buffer + recon_uvoffset; + } + else + skip_mode[LAST_FRAME] = 1; + + if (cpi->ref_frame_flags & VP8_GOLD_FLAG) + { + vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[GOLDEN_FRAME], &near_mv[GOLDEN_FRAME], + &best_ref_mv[GOLDEN_FRAME], MDCounts[GOLDEN_FRAME], GOLDEN_FRAME, cpi->common.ref_frame_sign_bias); + + y_buffer[GOLDEN_FRAME] = cpi->common.golden_frame.y_buffer + recon_yoffset; + u_buffer[GOLDEN_FRAME] = cpi->common.golden_frame.u_buffer + recon_uvoffset; + v_buffer[GOLDEN_FRAME] = cpi->common.golden_frame.v_buffer + recon_uvoffset; + } + else + skip_mode[GOLDEN_FRAME] = 1; + + if (cpi->ref_frame_flags & VP8_ALT_FLAG && cpi->source_alt_ref_active) + { + vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[ALTREF_FRAME], &near_mv[ALTREF_FRAME], + &best_ref_mv[ALTREF_FRAME], MDCounts[ALTREF_FRAME], ALTREF_FRAME, cpi->common.ref_frame_sign_bias); + + y_buffer[ALTREF_FRAME] = cpi->common.alt_ref_frame.y_buffer + recon_yoffset; + u_buffer[ALTREF_FRAME] = cpi->common.alt_ref_frame.u_buffer + recon_uvoffset; + v_buffer[ALTREF_FRAME] = cpi->common.alt_ref_frame.v_buffer + recon_uvoffset; + } + else + skip_mode[ALTREF_FRAME] = 1; + + cpi->mbs_tested_so_far++; // Count of the number of MBs tested so far this frame + + *returnintra = best_intra_rd; + x->skip = 0; + + ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(cpi->prob_intra_coded); + + // Special case treatment when GF and ARF are not sensible options for reference + if (cpi->ref_frame_flags == VP8_LAST_FLAG) + { + ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded) + + vp8_cost_zero(255); + ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded) + + vp8_cost_one(255) + + vp8_cost_zero(128); + ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded) + + vp8_cost_one(255) + + vp8_cost_one(128); + } + else + { + ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded) + + vp8_cost_zero(cpi->prob_last_coded); + ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded) + + vp8_cost_one(cpi->prob_last_coded) + + vp8_cost_zero(cpi->prob_gf_coded); + ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded) + + vp8_cost_one(cpi->prob_last_coded) + + vp8_cost_one(cpi->prob_gf_coded); + } + + + + best_rd = INT_MAX; + + x->e_mbd.mbmi.ref_frame = INTRA_FRAME; + + // if we encode a new mv this is important + // find the best new motion vector + for (mode_index = 0; mode_index < MAX_MODES; mode_index++) + { + int frame_cost; + int this_rd = INT_MAX; + + if (best_rd <= cpi->rd_threshes[mode_index]) + continue; + + x->e_mbd.mbmi.ref_frame = vp8_ref_frame_order[mode_index]; + + if (skip_mode[x->e_mbd.mbmi.ref_frame]) + continue; + + // Check to see if the testing frequency for this mode is at its max + // If so then prevent it from being tested and increase the threshold for its testing + if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1)) + { + //if ( (cpi->mbs_tested_so_far / cpi->mode_test_hit_counts[mode_index]) <= cpi->mode_check_freq[mode_index] ) + if (cpi->mbs_tested_so_far <= (cpi->mode_check_freq[mode_index] * cpi->mode_test_hit_counts[mode_index])) + { + // Increase the threshold for coding this mode to make it less likely to be chosen + 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]; + + continue; + } + } + + // We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested + cpi->mode_test_hit_counts[mode_index] ++; + + rate2 = 0; + distortion2 = 0; + + this_mode = vp8_mode_order[mode_index]; + + // Experimental debug code. + //all_rds[mode_index] = -1; + + x->e_mbd.mbmi.mode = this_mode; + x->e_mbd.mbmi.uv_mode = DC_PRED; + + // Work out the cost assosciated with selecting the reference frame + frame_cost = ref_frame_cost[x->e_mbd.mbmi.ref_frame]; + rate2 += frame_cost; + + // everything but intra + if (x->e_mbd.mbmi.ref_frame) + { + x->e_mbd.pre.y_buffer = y_buffer[x->e_mbd.mbmi.ref_frame]; + x->e_mbd.pre.u_buffer = u_buffer[x->e_mbd.mbmi.ref_frame]; + x->e_mbd.pre.v_buffer = v_buffer[x->e_mbd.mbmi.ref_frame]; + mode_mv[NEARESTMV] = nearest_mv[x->e_mbd.mbmi.ref_frame]; + mode_mv[NEARMV] = near_mv[x->e_mbd.mbmi.ref_frame]; + best_ref_mv1 = best_ref_mv[x->e_mbd.mbmi.ref_frame]; + memcpy(mdcounts, MDCounts[x->e_mbd.mbmi.ref_frame], sizeof(mdcounts)); + } + + //Only consider ZEROMV/ALTREF_FRAME for alt ref frame. + if (cpi->is_src_frame_alt_ref) + { + if (this_mode != ZEROMV || x->e_mbd.mbmi.ref_frame != ALTREF_FRAME) + continue; + } + + switch (this_mode) + { + case B_PRED: + distortion2 = *returndistortion; // Best so far passed in as breakout value to vp8_pick_intra4x4mby_modes + vp8_pick_intra4x4mby_modes(IF_RTCD(&cpi->rtcd), x, &rate, &distortion2); + rate2 += rate; + distortion2 = VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16prederror)(x->src.y_buffer, x->src.y_stride, x->e_mbd.predictor, 16, 0x7fffffff); + + if (distortion2 == INT_MAX) + { + this_rd = INT_MAX; + } + else + { + this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2); + + if (this_rd < best_intra_rd) + { + best_intra_rd = this_rd; + *returnintra = best_intra_rd ; + } + } + + break; + + case SPLITMV: + + // Split MV modes currently not supported when RD is nopt enabled. + break; + + case DC_PRED: + case V_PRED: + case H_PRED: + case TM_PRED: + vp8_build_intra_predictors_mby_ptr(&x->e_mbd); + distortion2 = VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16prederror)(x->src.y_buffer, x->src.y_stride, x->e_mbd.predictor, 16, 0x7fffffff); + rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mbmi.mode]; + this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2); + + if (this_rd < best_intra_rd) + { + best_intra_rd = this_rd; + *returnintra = best_intra_rd ; + } + + break; + + case NEWMV: + { + int thissme; + int step_param; + int further_steps; + int n = 0; + int sadpb = x->sadperbit16; + + // Further step/diamond searches as necessary + if (cpi->Speed < 8) + { + step_param = cpi->sf.first_step + ((cpi->Speed > 5) ? 1 : 0); + further_steps = (cpi->sf.max_step_search_steps - 1) - step_param; + } + else + { + step_param = cpi->sf.first_step + 2; + further_steps = 0; + } + +#if 0 + + // Initial step Search + bestsme = vp8_diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param, x->errorperbit, &num00, &cpi->fn_ptr, cpi->mb.mvsadcost, cpi->mb.mvcost); + mode_mv[NEWMV].row = d->bmi.mv.as_mv.row; + mode_mv[NEWMV].col = d->bmi.mv.as_mv.col; + + // Further step searches + while (n < further_steps) + { + n++; + + if (num00) + num00--; + else + { + thissme = vp8_diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param + n, x->errorperbit, &num00, &cpi->fn_ptr, cpi->mb.mvsadcost, x->mvcost); + + if (thissme < bestsme) + { + bestsme = thissme; + mode_mv[NEWMV].row = d->bmi.mv.as_mv.row; + mode_mv[NEWMV].col = d->bmi.mv.as_mv.col; + } + else + { + d->bmi.mv.as_mv.row = mode_mv[NEWMV].row; + d->bmi.mv.as_mv.col = mode_mv[NEWMV].col; + } + } + } + +#else + + if (cpi->sf.search_method == HEX) + { + bestsme = vp8_hex_search(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param, sadpb/*x->errorperbit*/, &num00, cpi->fn_ptr.vf, cpi->fn_ptr.sdf, x->mvsadcost, x->mvcost); + mode_mv[NEWMV].row = d->bmi.mv.as_mv.row; + mode_mv[NEWMV].col = d->bmi.mv.as_mv.col; + } + else + { + bestsme = cpi->diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param, sadpb / 2/*x->errorperbit*/, &num00, &cpi->fn_ptr, x->mvsadcost, x->mvcost); //sadpb < 9 + mode_mv[NEWMV].row = d->bmi.mv.as_mv.row; + mode_mv[NEWMV].col = d->bmi.mv.as_mv.col; + + // Further step/diamond searches as necessary + n = 0; + //further_steps = (cpi->sf.max_step_search_steps - 1) - step_param; + + n = num00; + num00 = 0; + + while (n < further_steps) + { + n++; + + if (num00) + num00--; + else + { + thissme = cpi->diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param + n, sadpb / 4/*x->errorperbit*/, &num00, &cpi->fn_ptr, x->mvsadcost, x->mvcost); //sadpb = 9 + + if (thissme < bestsme) + { + bestsme = thissme; + mode_mv[NEWMV].row = d->bmi.mv.as_mv.row; + mode_mv[NEWMV].col = d->bmi.mv.as_mv.col; + } + else + { + d->bmi.mv.as_mv.row = mode_mv[NEWMV].row; + d->bmi.mv.as_mv.col = mode_mv[NEWMV].col; + } + } + } + } + +#endif + } + + if (bestsme < INT_MAX) + cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv.as_mv, &best_ref_mv1, x->errorperbit, cpi->fn_ptr.svf, cpi->fn_ptr.vf, cpi->mb.mvcost); + + mode_mv[NEWMV].row = d->bmi.mv.as_mv.row; + mode_mv[NEWMV].col = d->bmi.mv.as_mv.col; + + // mv cost; + rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv1, cpi->mb.mvcost, 128); + + + case NEARESTMV: + case NEARMV: + + if (mode_mv[this_mode].row == 0 && mode_mv[this_mode].col == 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].row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].row >> 3) > x->mv_row_max) || + ((mode_mv[this_mode].col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].col >> 3) > x->mv_col_max)) + continue; + + rate2 += vp8_cost_mv_ref(this_mode, mdcounts); + x->e_mbd.mbmi.mode = this_mode; + x->e_mbd.mbmi.mv.as_mv = mode_mv[this_mode]; + x->e_mbd.block[0].bmi.mode = this_mode; + x->e_mbd.block[0].bmi.mv.as_int = x->e_mbd.mbmi.mv.as_int; + + distortion2 = get_inter_mbpred_error(x, cpi->fn_ptr.svf, cpi->fn_ptr.vf, (unsigned int *)(&sse)); + + this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2); + + if (cpi->active_map_enabled && x->active_ptr[0] == 0) + { + x->skip = 1; + } + else if (sse < x->encode_breakout) + { + // Check u and v to make sure skip is ok + int sse2 = 0; + + sse2 = VP8_UVSSE(x, IF_RTCD(&cpi->rtcd.variance)); + + if (sse2 * 2 < x->encode_breakout) + x->skip = 1; + else + x->skip = 0; + } + + break; + default: + break; + } + + // Experimental debug code. + //all_rds[mode_index] = this_rd; + + if (this_rd < best_rd || x->skip) + { + // Note index of best mode + best_mode_index = mode_index; + + *returnrate = rate2; + *returndistortion = distortion2; + best_rd = this_rd; + vpx_memcpy(&best_mbmode, &x->e_mbd.mbmi, sizeof(MB_MODE_INFO)); + + if (this_mode == B_PRED || this_mode == SPLITMV) + for (i = 0; i < 16; i++) + { + vpx_memcpy(&best_bmodes[i], &x->e_mbd.block[i].bmi, sizeof(B_MODE_INFO)); + } + else + { + best_bmodes[0].mv = x->e_mbd.block[0].bmi.mv; + } + + // 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]; + } + + // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around. + else + { + 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]; + } + + if (x->skip) + break; + } + + // 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] >> 3); + + 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]; + } + + // Keep a record of best mode index for use in next loop + cpi->last_best_mode_index = best_mode_index; + + if (best_mbmode.mode <= B_PRED) + { + x->e_mbd.mbmi.ref_frame = INTRA_FRAME; + vp8_pick_intra_mbuv_mode(x); + best_mbmode.uv_mode = x->e_mbd.mbmi.uv_mode; + } + + + { + int this_rdbin = (*returndistortion >> 7); + + if (this_rdbin >= 1024) + { + this_rdbin = 1023; + } + + cpi->error_bins[this_rdbin] ++; + } + + + if (cpi->is_src_frame_alt_ref && (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME)) + { + best_mbmode.mode = ZEROMV; + best_mbmode.ref_frame = ALTREF_FRAME; + best_mbmode.mv.as_int = 0; + best_mbmode.uv_mode = 0; + best_mbmode.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0; + best_mbmode.partitioning = 0; + best_mbmode.dc_diff = 0; + + vpx_memcpy(&x->e_mbd.mbmi, &best_mbmode, sizeof(MB_MODE_INFO)); + + for (i = 0; i < 16; i++) + { + vpx_memset(&x->e_mbd.block[i].bmi, 0, sizeof(B_MODE_INFO)); + } + + x->e_mbd.mbmi.mv.as_int = 0; + + return best_rd; + } + + + // macroblock modes + vpx_memcpy(&x->e_mbd.mbmi, &best_mbmode, sizeof(MB_MODE_INFO)); + + if (x->e_mbd.mbmi.mode == B_PRED || x->e_mbd.mbmi.mode == SPLITMV) + for (i = 0; i < 16; i++) + { + vpx_memcpy(&x->e_mbd.block[i].bmi, &best_bmodes[i], sizeof(B_MODE_INFO)); + + } + else + { + vp8_set_mbmode_and_mvs(x, x->e_mbd.mbmi.mode, &best_bmodes[0].mv.as_mv); + } + + x->e_mbd.mbmi.mv.as_mv = x->e_mbd.block[15].bmi.mv.as_mv; + + return best_rd; +} |