1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <limits.h>
13*fb1b10abSAndroid Build Coastguard Worker #include "vpx_config.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "onyx_int.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "modecosts.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "encodeintra.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/common.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/entropymode.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "pickinter.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/findnearmv.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "encodemb.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/reconinter.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/reconintra.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/reconintra4x4.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/variance.h"
27*fb1b10abSAndroid Build Coastguard Worker #include "mcomp.h"
28*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/vp8_skin_detection.h"
29*fb1b10abSAndroid Build Coastguard Worker #include "rdopt.h"
30*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
31*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
32*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
33*fb1b10abSAndroid Build Coastguard Worker #include "denoising.h"
34*fb1b10abSAndroid Build Coastguard Worker #endif
35*fb1b10abSAndroid Build Coastguard Worker
36*fb1b10abSAndroid Build Coastguard Worker #ifdef SPEEDSTATS
37*fb1b10abSAndroid Build Coastguard Worker extern unsigned int cnt_pm;
38*fb1b10abSAndroid Build Coastguard Worker #endif
39*fb1b10abSAndroid Build Coastguard Worker
40*fb1b10abSAndroid Build Coastguard Worker extern const int vp8_ref_frame_order[MAX_MODES];
41*fb1b10abSAndroid Build Coastguard Worker extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
42*fb1b10abSAndroid Build Coastguard Worker
macroblock_corner_grad(unsigned char * signal,int stride,int offsetx,int offsety,int sgnx,int sgny)43*fb1b10abSAndroid Build Coastguard Worker static int macroblock_corner_grad(unsigned char *signal, int stride,
44*fb1b10abSAndroid Build Coastguard Worker int offsetx, int offsety, int sgnx,
45*fb1b10abSAndroid Build Coastguard Worker int sgny) {
46*fb1b10abSAndroid Build Coastguard Worker int y1 = signal[offsetx * stride + offsety];
47*fb1b10abSAndroid Build Coastguard Worker int y2 = signal[offsetx * stride + offsety + sgny];
48*fb1b10abSAndroid Build Coastguard Worker int y3 = signal[(offsetx + sgnx) * stride + offsety];
49*fb1b10abSAndroid Build Coastguard Worker int y4 = signal[(offsetx + sgnx) * stride + offsety + sgny];
50*fb1b10abSAndroid Build Coastguard Worker return VPXMAX(VPXMAX(abs(y1 - y2), abs(y1 - y3)), abs(y1 - y4));
51*fb1b10abSAndroid Build Coastguard Worker }
52*fb1b10abSAndroid Build Coastguard Worker
check_dot_artifact_candidate(VP8_COMP * cpi,MACROBLOCK * x,unsigned char * target_last,int stride,unsigned char * last_ref,int mb_row,int mb_col,int channel)53*fb1b10abSAndroid Build Coastguard Worker static int check_dot_artifact_candidate(VP8_COMP *cpi, MACROBLOCK *x,
54*fb1b10abSAndroid Build Coastguard Worker unsigned char *target_last, int stride,
55*fb1b10abSAndroid Build Coastguard Worker unsigned char *last_ref, int mb_row,
56*fb1b10abSAndroid Build Coastguard Worker int mb_col, int channel) {
57*fb1b10abSAndroid Build Coastguard Worker int threshold1 = 6;
58*fb1b10abSAndroid Build Coastguard Worker int threshold2 = 3;
59*fb1b10abSAndroid Build Coastguard Worker unsigned int max_num = (cpi->common.MBs) / 10;
60*fb1b10abSAndroid Build Coastguard Worker int grad_last = 0;
61*fb1b10abSAndroid Build Coastguard Worker int grad_source = 0;
62*fb1b10abSAndroid Build Coastguard Worker int index = mb_row * cpi->common.mb_cols + mb_col;
63*fb1b10abSAndroid Build Coastguard Worker // Threshold for #consecutive (base layer) frames using zero_last mode.
64*fb1b10abSAndroid Build Coastguard Worker int num_frames = 30;
65*fb1b10abSAndroid Build Coastguard Worker int shift = 15;
66*fb1b10abSAndroid Build Coastguard Worker if (channel > 0) {
67*fb1b10abSAndroid Build Coastguard Worker shift = 7;
68*fb1b10abSAndroid Build Coastguard Worker }
69*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.number_of_layers > 1) {
70*fb1b10abSAndroid Build Coastguard Worker num_frames = 20;
71*fb1b10abSAndroid Build Coastguard Worker }
72*fb1b10abSAndroid Build Coastguard Worker x->zero_last_dot_suppress = 0;
73*fb1b10abSAndroid Build Coastguard Worker // Blocks on base layer frames that have been using ZEROMV_LAST repeatedly
74*fb1b10abSAndroid Build Coastguard Worker // (i.e, at least |x| consecutive frames are candidates for increasing the
75*fb1b10abSAndroid Build Coastguard Worker // rd adjustment for zero_last mode.
76*fb1b10abSAndroid Build Coastguard Worker // Only allow this for at most |max_num| blocks per frame.
77*fb1b10abSAndroid Build Coastguard Worker // Don't allow this for screen content input.
78*fb1b10abSAndroid Build Coastguard Worker if (cpi->current_layer == 0 &&
79*fb1b10abSAndroid Build Coastguard Worker cpi->consec_zero_last_mvbias[index] > num_frames &&
80*fb1b10abSAndroid Build Coastguard Worker x->mbs_zero_last_dot_suppress < max_num &&
81*fb1b10abSAndroid Build Coastguard Worker !cpi->oxcf.screen_content_mode) {
82*fb1b10abSAndroid Build Coastguard Worker // If this block is checked here, label it so we don't check it again until
83*fb1b10abSAndroid Build Coastguard Worker // ~|x| framaes later.
84*fb1b10abSAndroid Build Coastguard Worker x->zero_last_dot_suppress = 1;
85*fb1b10abSAndroid Build Coastguard Worker // Dot artifact is noticeable as strong gradient at corners of macroblock,
86*fb1b10abSAndroid Build Coastguard Worker // for flat areas. As a simple detector for now, we look for a high
87*fb1b10abSAndroid Build Coastguard Worker // corner gradient on last ref, and a smaller gradient on source.
88*fb1b10abSAndroid Build Coastguard Worker // Check 4 corners, return if any satisfy condition.
89*fb1b10abSAndroid Build Coastguard Worker // Top-left:
90*fb1b10abSAndroid Build Coastguard Worker grad_last = macroblock_corner_grad(last_ref, stride, 0, 0, 1, 1);
91*fb1b10abSAndroid Build Coastguard Worker grad_source = macroblock_corner_grad(target_last, stride, 0, 0, 1, 1);
92*fb1b10abSAndroid Build Coastguard Worker if (grad_last >= threshold1 && grad_source <= threshold2) {
93*fb1b10abSAndroid Build Coastguard Worker x->mbs_zero_last_dot_suppress++;
94*fb1b10abSAndroid Build Coastguard Worker return 1;
95*fb1b10abSAndroid Build Coastguard Worker }
96*fb1b10abSAndroid Build Coastguard Worker // Top-right:
97*fb1b10abSAndroid Build Coastguard Worker grad_last = macroblock_corner_grad(last_ref, stride, 0, shift, 1, -1);
98*fb1b10abSAndroid Build Coastguard Worker grad_source = macroblock_corner_grad(target_last, stride, 0, shift, 1, -1);
99*fb1b10abSAndroid Build Coastguard Worker if (grad_last >= threshold1 && grad_source <= threshold2) {
100*fb1b10abSAndroid Build Coastguard Worker x->mbs_zero_last_dot_suppress++;
101*fb1b10abSAndroid Build Coastguard Worker return 1;
102*fb1b10abSAndroid Build Coastguard Worker }
103*fb1b10abSAndroid Build Coastguard Worker // Bottom-left:
104*fb1b10abSAndroid Build Coastguard Worker grad_last = macroblock_corner_grad(last_ref, stride, shift, 0, -1, 1);
105*fb1b10abSAndroid Build Coastguard Worker grad_source = macroblock_corner_grad(target_last, stride, shift, 0, -1, 1);
106*fb1b10abSAndroid Build Coastguard Worker if (grad_last >= threshold1 && grad_source <= threshold2) {
107*fb1b10abSAndroid Build Coastguard Worker x->mbs_zero_last_dot_suppress++;
108*fb1b10abSAndroid Build Coastguard Worker return 1;
109*fb1b10abSAndroid Build Coastguard Worker }
110*fb1b10abSAndroid Build Coastguard Worker // Bottom-right:
111*fb1b10abSAndroid Build Coastguard Worker grad_last = macroblock_corner_grad(last_ref, stride, shift, shift, -1, -1);
112*fb1b10abSAndroid Build Coastguard Worker grad_source =
113*fb1b10abSAndroid Build Coastguard Worker macroblock_corner_grad(target_last, stride, shift, shift, -1, -1);
114*fb1b10abSAndroid Build Coastguard Worker if (grad_last >= threshold1 && grad_source <= threshold2) {
115*fb1b10abSAndroid Build Coastguard Worker x->mbs_zero_last_dot_suppress++;
116*fb1b10abSAndroid Build Coastguard Worker return 1;
117*fb1b10abSAndroid Build Coastguard Worker }
118*fb1b10abSAndroid Build Coastguard Worker return 0;
119*fb1b10abSAndroid Build Coastguard Worker }
120*fb1b10abSAndroid Build Coastguard Worker return 0;
121*fb1b10abSAndroid Build Coastguard Worker }
122*fb1b10abSAndroid Build Coastguard Worker
vp8_skip_fractional_mv_step(MACROBLOCK * mb,BLOCK * b,BLOCKD * d,int_mv * bestmv,int_mv * ref_mv,int error_per_bit,const vp8_variance_fn_ptr_t * vfp,int * mvcost[2],int * distortion,unsigned int * sse)123*fb1b10abSAndroid Build Coastguard Worker int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d,
124*fb1b10abSAndroid Build Coastguard Worker int_mv *bestmv, int_mv *ref_mv,
125*fb1b10abSAndroid Build Coastguard Worker int error_per_bit,
126*fb1b10abSAndroid Build Coastguard Worker const vp8_variance_fn_ptr_t *vfp,
127*fb1b10abSAndroid Build Coastguard Worker int *mvcost[2], int *distortion,
128*fb1b10abSAndroid Build Coastguard Worker unsigned int *sse) {
129*fb1b10abSAndroid Build Coastguard Worker (void)b;
130*fb1b10abSAndroid Build Coastguard Worker (void)d;
131*fb1b10abSAndroid Build Coastguard Worker (void)ref_mv;
132*fb1b10abSAndroid Build Coastguard Worker (void)error_per_bit;
133*fb1b10abSAndroid Build Coastguard Worker (void)vfp;
134*fb1b10abSAndroid Build Coastguard Worker (void)mb;
135*fb1b10abSAndroid Build Coastguard Worker (void)mvcost;
136*fb1b10abSAndroid Build Coastguard Worker (void)distortion;
137*fb1b10abSAndroid Build Coastguard Worker (void)sse;
138*fb1b10abSAndroid Build Coastguard Worker bestmv->as_mv.row = clamp(bestmv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
139*fb1b10abSAndroid Build Coastguard Worker bestmv->as_mv.col = clamp(bestmv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
140*fb1b10abSAndroid Build Coastguard Worker return 0;
141*fb1b10abSAndroid Build Coastguard Worker }
142*fb1b10abSAndroid Build Coastguard Worker
vp8_get_inter_mbpred_error(MACROBLOCK * mb,const vp8_variance_fn_ptr_t * vfp,unsigned int * sse,int_mv this_mv)143*fb1b10abSAndroid Build Coastguard Worker int vp8_get_inter_mbpred_error(MACROBLOCK *mb, const vp8_variance_fn_ptr_t *vfp,
144*fb1b10abSAndroid Build Coastguard Worker unsigned int *sse, int_mv this_mv) {
145*fb1b10abSAndroid Build Coastguard Worker BLOCK *b = &mb->block[0];
146*fb1b10abSAndroid Build Coastguard Worker BLOCKD *d = &mb->e_mbd.block[0];
147*fb1b10abSAndroid Build Coastguard Worker unsigned char *what = (*(b->base_src) + b->src);
148*fb1b10abSAndroid Build Coastguard Worker int what_stride = b->src_stride;
149*fb1b10abSAndroid Build Coastguard Worker int pre_stride = mb->e_mbd.pre.y_stride;
150*fb1b10abSAndroid Build Coastguard Worker unsigned char *in_what = mb->e_mbd.pre.y_buffer + d->offset;
151*fb1b10abSAndroid Build Coastguard Worker int in_what_stride = pre_stride;
152*fb1b10abSAndroid Build Coastguard Worker int xoffset = this_mv.as_mv.col & 7;
153*fb1b10abSAndroid Build Coastguard Worker int yoffset = this_mv.as_mv.row & 7;
154*fb1b10abSAndroid Build Coastguard Worker
155*fb1b10abSAndroid Build Coastguard Worker in_what += (this_mv.as_mv.row >> 3) * pre_stride + (this_mv.as_mv.col >> 3);
156*fb1b10abSAndroid Build Coastguard Worker
157*fb1b10abSAndroid Build Coastguard Worker if (xoffset | yoffset) {
158*fb1b10abSAndroid Build Coastguard Worker return vfp->svf(in_what, in_what_stride, xoffset, yoffset, what,
159*fb1b10abSAndroid Build Coastguard Worker what_stride, sse);
160*fb1b10abSAndroid Build Coastguard Worker } else {
161*fb1b10abSAndroid Build Coastguard Worker return vfp->vf(what, what_stride, in_what, in_what_stride, sse);
162*fb1b10abSAndroid Build Coastguard Worker }
163*fb1b10abSAndroid Build Coastguard Worker }
164*fb1b10abSAndroid Build Coastguard Worker
get_prediction_error(BLOCK * be,BLOCKD * b)165*fb1b10abSAndroid Build Coastguard Worker static int get_prediction_error(BLOCK *be, BLOCKD *b) {
166*fb1b10abSAndroid Build Coastguard Worker unsigned char *sptr;
167*fb1b10abSAndroid Build Coastguard Worker unsigned char *dptr;
168*fb1b10abSAndroid Build Coastguard Worker sptr = (*(be->base_src) + be->src);
169*fb1b10abSAndroid Build Coastguard Worker dptr = b->predictor;
170*fb1b10abSAndroid Build Coastguard Worker
171*fb1b10abSAndroid Build Coastguard Worker return vpx_get4x4sse_cs(sptr, be->src_stride, dptr, 16);
172*fb1b10abSAndroid Build Coastguard Worker }
173*fb1b10abSAndroid Build Coastguard Worker
pick_intra4x4block(MACROBLOCK * x,int ib,B_PREDICTION_MODE * best_mode,const int * mode_costs,int * bestrate,int * bestdistortion)174*fb1b10abSAndroid Build Coastguard Worker static int pick_intra4x4block(MACROBLOCK *x, int ib,
175*fb1b10abSAndroid Build Coastguard Worker B_PREDICTION_MODE *best_mode,
176*fb1b10abSAndroid Build Coastguard Worker const int *mode_costs, int *bestrate,
177*fb1b10abSAndroid Build Coastguard Worker int *bestdistortion) {
178*fb1b10abSAndroid Build Coastguard Worker BLOCKD *b = &x->e_mbd.block[ib];
179*fb1b10abSAndroid Build Coastguard Worker BLOCK *be = &x->block[ib];
180*fb1b10abSAndroid Build Coastguard Worker int dst_stride = x->e_mbd.dst.y_stride;
181*fb1b10abSAndroid Build Coastguard Worker unsigned char *dst = x->e_mbd.dst.y_buffer + b->offset;
182*fb1b10abSAndroid Build Coastguard Worker B_PREDICTION_MODE mode;
183*fb1b10abSAndroid Build Coastguard Worker int best_rd = INT_MAX;
184*fb1b10abSAndroid Build Coastguard Worker int rate;
185*fb1b10abSAndroid Build Coastguard Worker int distortion;
186*fb1b10abSAndroid Build Coastguard Worker
187*fb1b10abSAndroid Build Coastguard Worker unsigned char *Above = dst - dst_stride;
188*fb1b10abSAndroid Build Coastguard Worker unsigned char *yleft = dst - 1;
189*fb1b10abSAndroid Build Coastguard Worker unsigned char top_left = Above[-1];
190*fb1b10abSAndroid Build Coastguard Worker
191*fb1b10abSAndroid Build Coastguard Worker for (mode = B_DC_PRED; mode <= B_HE_PRED; ++mode) {
192*fb1b10abSAndroid Build Coastguard Worker int this_rd;
193*fb1b10abSAndroid Build Coastguard Worker
194*fb1b10abSAndroid Build Coastguard Worker rate = mode_costs[mode];
195*fb1b10abSAndroid Build Coastguard Worker
196*fb1b10abSAndroid Build Coastguard Worker vp8_intra4x4_predict(Above, yleft, dst_stride, mode, b->predictor, 16,
197*fb1b10abSAndroid Build Coastguard Worker top_left);
198*fb1b10abSAndroid Build Coastguard Worker distortion = get_prediction_error(be, b);
199*fb1b10abSAndroid Build Coastguard Worker this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
200*fb1b10abSAndroid Build Coastguard Worker
201*fb1b10abSAndroid Build Coastguard Worker if (this_rd < best_rd) {
202*fb1b10abSAndroid Build Coastguard Worker *bestrate = rate;
203*fb1b10abSAndroid Build Coastguard Worker *bestdistortion = distortion;
204*fb1b10abSAndroid Build Coastguard Worker best_rd = this_rd;
205*fb1b10abSAndroid Build Coastguard Worker *best_mode = mode;
206*fb1b10abSAndroid Build Coastguard Worker }
207*fb1b10abSAndroid Build Coastguard Worker }
208*fb1b10abSAndroid Build Coastguard Worker
209*fb1b10abSAndroid Build Coastguard Worker b->bmi.as_mode = *best_mode;
210*fb1b10abSAndroid Build Coastguard Worker vp8_encode_intra4x4block(x, ib);
211*fb1b10abSAndroid Build Coastguard Worker return best_rd;
212*fb1b10abSAndroid Build Coastguard Worker }
213*fb1b10abSAndroid Build Coastguard Worker
pick_intra4x4mby_modes(MACROBLOCK * mb,int * Rate,int * best_dist)214*fb1b10abSAndroid Build Coastguard Worker static int pick_intra4x4mby_modes(MACROBLOCK *mb, int *Rate, int *best_dist) {
215*fb1b10abSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &mb->e_mbd;
216*fb1b10abSAndroid Build Coastguard Worker int i;
217*fb1b10abSAndroid Build Coastguard Worker int cost = mb->mbmode_cost[xd->frame_type][B_PRED];
218*fb1b10abSAndroid Build Coastguard Worker int error;
219*fb1b10abSAndroid Build Coastguard Worker int distortion = 0;
220*fb1b10abSAndroid Build Coastguard Worker const int *bmode_costs;
221*fb1b10abSAndroid Build Coastguard Worker
222*fb1b10abSAndroid Build Coastguard Worker intra_prediction_down_copy(xd, xd->dst.y_buffer - xd->dst.y_stride + 16);
223*fb1b10abSAndroid Build Coastguard Worker
224*fb1b10abSAndroid Build Coastguard Worker bmode_costs = mb->inter_bmode_costs;
225*fb1b10abSAndroid Build Coastguard Worker
226*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 16; ++i) {
227*fb1b10abSAndroid Build Coastguard Worker MODE_INFO *const mic = xd->mode_info_context;
228*fb1b10abSAndroid Build Coastguard Worker const int mis = xd->mode_info_stride;
229*fb1b10abSAndroid Build Coastguard Worker
230*fb1b10abSAndroid Build Coastguard Worker B_PREDICTION_MODE best_mode = B_MODE_COUNT;
231*fb1b10abSAndroid Build Coastguard Worker int r = 0, d = 0;
232*fb1b10abSAndroid Build Coastguard Worker
233*fb1b10abSAndroid Build Coastguard Worker if (mb->e_mbd.frame_type == KEY_FRAME) {
234*fb1b10abSAndroid Build Coastguard Worker const B_PREDICTION_MODE A = above_block_mode(mic, i, mis);
235*fb1b10abSAndroid Build Coastguard Worker const B_PREDICTION_MODE L = left_block_mode(mic, i);
236*fb1b10abSAndroid Build Coastguard Worker
237*fb1b10abSAndroid Build Coastguard Worker bmode_costs = mb->bmode_costs[A][L];
238*fb1b10abSAndroid Build Coastguard Worker }
239*fb1b10abSAndroid Build Coastguard Worker
240*fb1b10abSAndroid Build Coastguard Worker pick_intra4x4block(mb, i, &best_mode, bmode_costs, &r, &d);
241*fb1b10abSAndroid Build Coastguard Worker
242*fb1b10abSAndroid Build Coastguard Worker cost += r;
243*fb1b10abSAndroid Build Coastguard Worker distortion += d;
244*fb1b10abSAndroid Build Coastguard Worker assert(best_mode != B_MODE_COUNT);
245*fb1b10abSAndroid Build Coastguard Worker mic->bmi[i].as_mode = best_mode;
246*fb1b10abSAndroid Build Coastguard Worker
247*fb1b10abSAndroid Build Coastguard Worker /* Break out case where we have already exceeded best so far value
248*fb1b10abSAndroid Build Coastguard Worker * that was passed in
249*fb1b10abSAndroid Build Coastguard Worker */
250*fb1b10abSAndroid Build Coastguard Worker if (distortion > *best_dist) break;
251*fb1b10abSAndroid Build Coastguard Worker }
252*fb1b10abSAndroid Build Coastguard Worker
253*fb1b10abSAndroid Build Coastguard Worker *Rate = cost;
254*fb1b10abSAndroid Build Coastguard Worker
255*fb1b10abSAndroid Build Coastguard Worker if (i == 16) {
256*fb1b10abSAndroid Build Coastguard Worker *best_dist = distortion;
257*fb1b10abSAndroid Build Coastguard Worker error = RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
258*fb1b10abSAndroid Build Coastguard Worker } else {
259*fb1b10abSAndroid Build Coastguard Worker *best_dist = INT_MAX;
260*fb1b10abSAndroid Build Coastguard Worker error = INT_MAX;
261*fb1b10abSAndroid Build Coastguard Worker }
262*fb1b10abSAndroid Build Coastguard Worker
263*fb1b10abSAndroid Build Coastguard Worker return error;
264*fb1b10abSAndroid Build Coastguard Worker }
265*fb1b10abSAndroid Build Coastguard Worker
pick_intra_mbuv_mode(MACROBLOCK * mb)266*fb1b10abSAndroid Build Coastguard Worker static void pick_intra_mbuv_mode(MACROBLOCK *mb) {
267*fb1b10abSAndroid Build Coastguard Worker MACROBLOCKD *x = &mb->e_mbd;
268*fb1b10abSAndroid Build Coastguard Worker unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
269*fb1b10abSAndroid Build Coastguard Worker unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
270*fb1b10abSAndroid Build Coastguard Worker unsigned char *usrc_ptr = (mb->block[16].src + *mb->block[16].base_src);
271*fb1b10abSAndroid Build Coastguard Worker unsigned char *vsrc_ptr = (mb->block[20].src + *mb->block[20].base_src);
272*fb1b10abSAndroid Build Coastguard Worker int uvsrc_stride = mb->block[16].src_stride;
273*fb1b10abSAndroid Build Coastguard Worker unsigned char uleft_col[8];
274*fb1b10abSAndroid Build Coastguard Worker unsigned char vleft_col[8];
275*fb1b10abSAndroid Build Coastguard Worker unsigned char utop_left = uabove_row[-1];
276*fb1b10abSAndroid Build Coastguard Worker unsigned char vtop_left = vabove_row[-1];
277*fb1b10abSAndroid Build Coastguard Worker int i, j;
278*fb1b10abSAndroid Build Coastguard Worker int expected_udc;
279*fb1b10abSAndroid Build Coastguard Worker int expected_vdc;
280*fb1b10abSAndroid Build Coastguard Worker int shift;
281*fb1b10abSAndroid Build Coastguard Worker int Uaverage = 0;
282*fb1b10abSAndroid Build Coastguard Worker int Vaverage = 0;
283*fb1b10abSAndroid Build Coastguard Worker int diff;
284*fb1b10abSAndroid Build Coastguard Worker int pred_error[4] = { 0, 0, 0, 0 }, best_error = INT_MAX;
285*fb1b10abSAndroid Build Coastguard Worker MB_PREDICTION_MODE best_mode = MB_MODE_COUNT;
286*fb1b10abSAndroid Build Coastguard Worker
287*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; ++i) {
288*fb1b10abSAndroid Build Coastguard Worker uleft_col[i] = x->dst.u_buffer[i * x->dst.uv_stride - 1];
289*fb1b10abSAndroid Build Coastguard Worker vleft_col[i] = x->dst.v_buffer[i * x->dst.uv_stride - 1];
290*fb1b10abSAndroid Build Coastguard Worker }
291*fb1b10abSAndroid Build Coastguard Worker
292*fb1b10abSAndroid Build Coastguard Worker if (!x->up_available && !x->left_available) {
293*fb1b10abSAndroid Build Coastguard Worker expected_udc = 128;
294*fb1b10abSAndroid Build Coastguard Worker expected_vdc = 128;
295*fb1b10abSAndroid Build Coastguard Worker } else {
296*fb1b10abSAndroid Build Coastguard Worker shift = 2;
297*fb1b10abSAndroid Build Coastguard Worker
298*fb1b10abSAndroid Build Coastguard Worker if (x->up_available) {
299*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; ++i) {
300*fb1b10abSAndroid Build Coastguard Worker Uaverage += uabove_row[i];
301*fb1b10abSAndroid Build Coastguard Worker Vaverage += vabove_row[i];
302*fb1b10abSAndroid Build Coastguard Worker }
303*fb1b10abSAndroid Build Coastguard Worker
304*fb1b10abSAndroid Build Coastguard Worker shift++;
305*fb1b10abSAndroid Build Coastguard Worker }
306*fb1b10abSAndroid Build Coastguard Worker
307*fb1b10abSAndroid Build Coastguard Worker if (x->left_available) {
308*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; ++i) {
309*fb1b10abSAndroid Build Coastguard Worker Uaverage += uleft_col[i];
310*fb1b10abSAndroid Build Coastguard Worker Vaverage += vleft_col[i];
311*fb1b10abSAndroid Build Coastguard Worker }
312*fb1b10abSAndroid Build Coastguard Worker
313*fb1b10abSAndroid Build Coastguard Worker shift++;
314*fb1b10abSAndroid Build Coastguard Worker }
315*fb1b10abSAndroid Build Coastguard Worker
316*fb1b10abSAndroid Build Coastguard Worker expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
317*fb1b10abSAndroid Build Coastguard Worker expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
318*fb1b10abSAndroid Build Coastguard Worker }
319*fb1b10abSAndroid Build Coastguard Worker
320*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; ++i) {
321*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; ++j) {
322*fb1b10abSAndroid Build Coastguard Worker int predu = uleft_col[i] + uabove_row[j] - utop_left;
323*fb1b10abSAndroid Build Coastguard Worker int predv = vleft_col[i] + vabove_row[j] - vtop_left;
324*fb1b10abSAndroid Build Coastguard Worker int u_p, v_p;
325*fb1b10abSAndroid Build Coastguard Worker
326*fb1b10abSAndroid Build Coastguard Worker u_p = usrc_ptr[j];
327*fb1b10abSAndroid Build Coastguard Worker v_p = vsrc_ptr[j];
328*fb1b10abSAndroid Build Coastguard Worker
329*fb1b10abSAndroid Build Coastguard Worker if (predu < 0) predu = 0;
330*fb1b10abSAndroid Build Coastguard Worker
331*fb1b10abSAndroid Build Coastguard Worker if (predu > 255) predu = 255;
332*fb1b10abSAndroid Build Coastguard Worker
333*fb1b10abSAndroid Build Coastguard Worker if (predv < 0) predv = 0;
334*fb1b10abSAndroid Build Coastguard Worker
335*fb1b10abSAndroid Build Coastguard Worker if (predv > 255) predv = 255;
336*fb1b10abSAndroid Build Coastguard Worker
337*fb1b10abSAndroid Build Coastguard Worker diff = u_p - expected_udc;
338*fb1b10abSAndroid Build Coastguard Worker pred_error[DC_PRED] += diff * diff;
339*fb1b10abSAndroid Build Coastguard Worker diff = v_p - expected_vdc;
340*fb1b10abSAndroid Build Coastguard Worker pred_error[DC_PRED] += diff * diff;
341*fb1b10abSAndroid Build Coastguard Worker
342*fb1b10abSAndroid Build Coastguard Worker diff = u_p - uabove_row[j];
343*fb1b10abSAndroid Build Coastguard Worker pred_error[V_PRED] += diff * diff;
344*fb1b10abSAndroid Build Coastguard Worker diff = v_p - vabove_row[j];
345*fb1b10abSAndroid Build Coastguard Worker pred_error[V_PRED] += diff * diff;
346*fb1b10abSAndroid Build Coastguard Worker
347*fb1b10abSAndroid Build Coastguard Worker diff = u_p - uleft_col[i];
348*fb1b10abSAndroid Build Coastguard Worker pred_error[H_PRED] += diff * diff;
349*fb1b10abSAndroid Build Coastguard Worker diff = v_p - vleft_col[i];
350*fb1b10abSAndroid Build Coastguard Worker pred_error[H_PRED] += diff * diff;
351*fb1b10abSAndroid Build Coastguard Worker
352*fb1b10abSAndroid Build Coastguard Worker diff = u_p - predu;
353*fb1b10abSAndroid Build Coastguard Worker pred_error[TM_PRED] += diff * diff;
354*fb1b10abSAndroid Build Coastguard Worker diff = v_p - predv;
355*fb1b10abSAndroid Build Coastguard Worker pred_error[TM_PRED] += diff * diff;
356*fb1b10abSAndroid Build Coastguard Worker }
357*fb1b10abSAndroid Build Coastguard Worker
358*fb1b10abSAndroid Build Coastguard Worker usrc_ptr += uvsrc_stride;
359*fb1b10abSAndroid Build Coastguard Worker vsrc_ptr += uvsrc_stride;
360*fb1b10abSAndroid Build Coastguard Worker
361*fb1b10abSAndroid Build Coastguard Worker if (i == 3) {
362*fb1b10abSAndroid Build Coastguard Worker usrc_ptr = (mb->block[18].src + *mb->block[18].base_src);
363*fb1b10abSAndroid Build Coastguard Worker vsrc_ptr = (mb->block[22].src + *mb->block[22].base_src);
364*fb1b10abSAndroid Build Coastguard Worker }
365*fb1b10abSAndroid Build Coastguard Worker }
366*fb1b10abSAndroid Build Coastguard Worker
367*fb1b10abSAndroid Build Coastguard Worker for (i = DC_PRED; i <= TM_PRED; ++i) {
368*fb1b10abSAndroid Build Coastguard Worker if (best_error > pred_error[i]) {
369*fb1b10abSAndroid Build Coastguard Worker best_error = pred_error[i];
370*fb1b10abSAndroid Build Coastguard Worker best_mode = (MB_PREDICTION_MODE)i;
371*fb1b10abSAndroid Build Coastguard Worker }
372*fb1b10abSAndroid Build Coastguard Worker }
373*fb1b10abSAndroid Build Coastguard Worker
374*fb1b10abSAndroid Build Coastguard Worker assert(best_mode != MB_MODE_COUNT);
375*fb1b10abSAndroid Build Coastguard Worker mb->e_mbd.mode_info_context->mbmi.uv_mode = best_mode;
376*fb1b10abSAndroid Build Coastguard Worker }
377*fb1b10abSAndroid Build Coastguard Worker
update_mvcount(MACROBLOCK * x,int_mv * best_ref_mv)378*fb1b10abSAndroid Build Coastguard Worker static void update_mvcount(MACROBLOCK *x, int_mv *best_ref_mv) {
379*fb1b10abSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
380*fb1b10abSAndroid Build Coastguard Worker /* Split MV modes currently not supported when RD is nopt enabled,
381*fb1b10abSAndroid Build Coastguard Worker * therefore, only need to modify MVcount in NEWMV mode. */
382*fb1b10abSAndroid Build Coastguard Worker if (xd->mode_info_context->mbmi.mode == NEWMV) {
383*fb1b10abSAndroid Build Coastguard Worker const int row_val =
384*fb1b10abSAndroid Build Coastguard Worker ((xd->mode_info_context->mbmi.mv.as_mv.row - best_ref_mv->as_mv.row) >>
385*fb1b10abSAndroid Build Coastguard Worker 1);
386*fb1b10abSAndroid Build Coastguard Worker const int row_idx = mv_max + row_val;
387*fb1b10abSAndroid Build Coastguard Worker const int col_val =
388*fb1b10abSAndroid Build Coastguard Worker ((xd->mode_info_context->mbmi.mv.as_mv.col - best_ref_mv->as_mv.col) >>
389*fb1b10abSAndroid Build Coastguard Worker 1);
390*fb1b10abSAndroid Build Coastguard Worker const int col_idx = mv_max + col_val;
391*fb1b10abSAndroid Build Coastguard Worker if (row_idx >= 0 && row_idx < MVvals && col_idx >= 0 && col_idx < MVvals) {
392*fb1b10abSAndroid Build Coastguard Worker x->MVcount[0][row_idx]++;
393*fb1b10abSAndroid Build Coastguard Worker x->MVcount[1][col_idx]++;
394*fb1b10abSAndroid Build Coastguard Worker }
395*fb1b10abSAndroid Build Coastguard Worker }
396*fb1b10abSAndroid Build Coastguard Worker }
397*fb1b10abSAndroid Build Coastguard Worker
398*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
get_lower_res_motion_info(VP8_COMP * cpi,MACROBLOCKD * xd,int * dissim,int * parent_ref_frame,MB_PREDICTION_MODE * parent_mode,int_mv * parent_ref_mv,int mb_row,int mb_col)399*fb1b10abSAndroid Build Coastguard Worker static void get_lower_res_motion_info(VP8_COMP *cpi, MACROBLOCKD *xd,
400*fb1b10abSAndroid Build Coastguard Worker int *dissim, int *parent_ref_frame,
401*fb1b10abSAndroid Build Coastguard Worker MB_PREDICTION_MODE *parent_mode,
402*fb1b10abSAndroid Build Coastguard Worker int_mv *parent_ref_mv, int mb_row,
403*fb1b10abSAndroid Build Coastguard Worker int mb_col) {
404*fb1b10abSAndroid Build Coastguard Worker LOWER_RES_MB_INFO *store_mode_info =
405*fb1b10abSAndroid Build Coastguard Worker ((LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info)->mb_info;
406*fb1b10abSAndroid Build Coastguard Worker unsigned int parent_mb_index;
407*fb1b10abSAndroid Build Coastguard Worker
408*fb1b10abSAndroid Build Coastguard Worker /* Consider different down_sampling_factor. */
409*fb1b10abSAndroid Build Coastguard Worker {
410*fb1b10abSAndroid Build Coastguard Worker /* TODO: Removed the loop that supports special down_sampling_factor
411*fb1b10abSAndroid Build Coastguard Worker * such as 2, 4, 8. Will revisit it if needed.
412*fb1b10abSAndroid Build Coastguard Worker * Should also try using a look-up table to see if it helps
413*fb1b10abSAndroid Build Coastguard Worker * performance. */
414*fb1b10abSAndroid Build Coastguard Worker int parent_mb_row, parent_mb_col;
415*fb1b10abSAndroid Build Coastguard Worker
416*fb1b10abSAndroid Build Coastguard Worker parent_mb_row = mb_row * cpi->oxcf.mr_down_sampling_factor.den /
417*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_down_sampling_factor.num;
418*fb1b10abSAndroid Build Coastguard Worker parent_mb_col = mb_col * cpi->oxcf.mr_down_sampling_factor.den /
419*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_down_sampling_factor.num;
420*fb1b10abSAndroid Build Coastguard Worker parent_mb_index = parent_mb_row * cpi->mr_low_res_mb_cols + parent_mb_col;
421*fb1b10abSAndroid Build Coastguard Worker }
422*fb1b10abSAndroid Build Coastguard Worker
423*fb1b10abSAndroid Build Coastguard Worker /* Read lower-resolution mode & motion result from memory.*/
424*fb1b10abSAndroid Build Coastguard Worker *parent_ref_frame = store_mode_info[parent_mb_index].ref_frame;
425*fb1b10abSAndroid Build Coastguard Worker *parent_mode = store_mode_info[parent_mb_index].mode;
426*fb1b10abSAndroid Build Coastguard Worker *dissim = store_mode_info[parent_mb_index].dissim;
427*fb1b10abSAndroid Build Coastguard Worker
428*fb1b10abSAndroid Build Coastguard Worker /* For highest-resolution encoder, adjust dissim value. Lower its quality
429*fb1b10abSAndroid Build Coastguard Worker * for good performance. */
430*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.mr_encoder_id == (cpi->oxcf.mr_total_resolutions - 1))
431*fb1b10abSAndroid Build Coastguard Worker *dissim >>= 1;
432*fb1b10abSAndroid Build Coastguard Worker
433*fb1b10abSAndroid Build Coastguard Worker if (*parent_ref_frame != INTRA_FRAME) {
434*fb1b10abSAndroid Build Coastguard Worker /* Consider different down_sampling_factor.
435*fb1b10abSAndroid Build Coastguard Worker * The result can be rounded to be more precise, but it takes more time.
436*fb1b10abSAndroid Build Coastguard Worker */
437*fb1b10abSAndroid Build Coastguard Worker (*parent_ref_mv).as_mv.row = store_mode_info[parent_mb_index].mv.as_mv.row *
438*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_down_sampling_factor.num /
439*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_down_sampling_factor.den;
440*fb1b10abSAndroid Build Coastguard Worker (*parent_ref_mv).as_mv.col = store_mode_info[parent_mb_index].mv.as_mv.col *
441*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_down_sampling_factor.num /
442*fb1b10abSAndroid Build Coastguard Worker cpi->oxcf.mr_down_sampling_factor.den;
443*fb1b10abSAndroid Build Coastguard Worker
444*fb1b10abSAndroid Build Coastguard Worker vp8_clamp_mv2(parent_ref_mv, xd);
445*fb1b10abSAndroid Build Coastguard Worker }
446*fb1b10abSAndroid Build Coastguard Worker }
447*fb1b10abSAndroid Build Coastguard Worker #endif
448*fb1b10abSAndroid Build Coastguard Worker
check_for_encode_breakout(unsigned int sse,MACROBLOCK * x)449*fb1b10abSAndroid Build Coastguard Worker static void check_for_encode_breakout(unsigned int sse, MACROBLOCK *x) {
450*fb1b10abSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
451*fb1b10abSAndroid Build Coastguard Worker
452*fb1b10abSAndroid Build Coastguard Worker unsigned int threshold =
453*fb1b10abSAndroid Build Coastguard Worker (xd->block[0].dequant[1] * xd->block[0].dequant[1] >> 4);
454*fb1b10abSAndroid Build Coastguard Worker
455*fb1b10abSAndroid Build Coastguard Worker if (threshold < x->encode_breakout) threshold = x->encode_breakout;
456*fb1b10abSAndroid Build Coastguard Worker
457*fb1b10abSAndroid Build Coastguard Worker if (sse < threshold) {
458*fb1b10abSAndroid Build Coastguard Worker /* Check u and v to make sure skip is ok */
459*fb1b10abSAndroid Build Coastguard Worker unsigned int sse2 = 0;
460*fb1b10abSAndroid Build Coastguard Worker
461*fb1b10abSAndroid Build Coastguard Worker sse2 = VP8_UVSSE(x);
462*fb1b10abSAndroid Build Coastguard Worker
463*fb1b10abSAndroid Build Coastguard Worker if (sse2 * 2 < x->encode_breakout) {
464*fb1b10abSAndroid Build Coastguard Worker x->skip = 1;
465*fb1b10abSAndroid Build Coastguard Worker } else {
466*fb1b10abSAndroid Build Coastguard Worker x->skip = 0;
467*fb1b10abSAndroid Build Coastguard Worker }
468*fb1b10abSAndroid Build Coastguard Worker }
469*fb1b10abSAndroid Build Coastguard Worker }
470*fb1b10abSAndroid Build Coastguard Worker
evaluate_inter_mode(unsigned int * sse,int rate2,int * distortion2,VP8_COMP * cpi,MACROBLOCK * x,int rd_adj)471*fb1b10abSAndroid Build Coastguard Worker static int evaluate_inter_mode(unsigned int *sse, int rate2, int *distortion2,
472*fb1b10abSAndroid Build Coastguard Worker VP8_COMP *cpi, MACROBLOCK *x, int rd_adj) {
473*fb1b10abSAndroid Build Coastguard Worker MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
474*fb1b10abSAndroid Build Coastguard Worker int_mv mv = x->e_mbd.mode_info_context->mbmi.mv;
475*fb1b10abSAndroid Build Coastguard Worker int this_rd;
476*fb1b10abSAndroid Build Coastguard Worker int denoise_aggressive = 0;
477*fb1b10abSAndroid Build Coastguard Worker /* Exit early and don't compute the distortion if this macroblock
478*fb1b10abSAndroid Build Coastguard Worker * is marked inactive. */
479*fb1b10abSAndroid Build Coastguard Worker if (cpi->active_map_enabled && x->active_ptr[0] == 0) {
480*fb1b10abSAndroid Build Coastguard Worker *sse = 0;
481*fb1b10abSAndroid Build Coastguard Worker *distortion2 = 0;
482*fb1b10abSAndroid Build Coastguard Worker x->skip = 1;
483*fb1b10abSAndroid Build Coastguard Worker return INT_MAX;
484*fb1b10abSAndroid Build Coastguard Worker }
485*fb1b10abSAndroid Build Coastguard Worker
486*fb1b10abSAndroid Build Coastguard Worker if ((this_mode != NEWMV) || !(cpi->sf.half_pixel_search) ||
487*fb1b10abSAndroid Build Coastguard Worker cpi->common.full_pixel == 1) {
488*fb1b10abSAndroid Build Coastguard Worker *distortion2 =
489*fb1b10abSAndroid Build Coastguard Worker vp8_get_inter_mbpred_error(x, &cpi->fn_ptr[BLOCK_16X16], sse, mv);
490*fb1b10abSAndroid Build Coastguard Worker }
491*fb1b10abSAndroid Build Coastguard Worker
492*fb1b10abSAndroid Build Coastguard Worker this_rd = RDCOST(x->rdmult, x->rddiv, rate2, *distortion2);
493*fb1b10abSAndroid Build Coastguard Worker
494*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
495*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.noise_sensitivity > 0) {
496*fb1b10abSAndroid Build Coastguard Worker denoise_aggressive =
497*fb1b10abSAndroid Build Coastguard Worker (cpi->denoiser.denoiser_mode == kDenoiserOnYUVAggressive) ? 1 : 0;
498*fb1b10abSAndroid Build Coastguard Worker }
499*fb1b10abSAndroid Build Coastguard Worker #endif
500*fb1b10abSAndroid Build Coastguard Worker
501*fb1b10abSAndroid Build Coastguard Worker // Adjust rd for ZEROMV and LAST, if LAST is the closest reference frame.
502*fb1b10abSAndroid Build Coastguard Worker // TODO: We should also add condition on distance of closest to current.
503*fb1b10abSAndroid Build Coastguard Worker if (!cpi->oxcf.screen_content_mode && this_mode == ZEROMV &&
504*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME &&
505*fb1b10abSAndroid Build Coastguard Worker (denoise_aggressive || (cpi->closest_reference_frame == LAST_FRAME))) {
506*fb1b10abSAndroid Build Coastguard Worker // No adjustment if block is considered to be skin area.
507*fb1b10abSAndroid Build Coastguard Worker if (x->is_skin) rd_adj = 100;
508*fb1b10abSAndroid Build Coastguard Worker
509*fb1b10abSAndroid Build Coastguard Worker this_rd = (int)(((int64_t)this_rd) * rd_adj / 100);
510*fb1b10abSAndroid Build Coastguard Worker }
511*fb1b10abSAndroid Build Coastguard Worker
512*fb1b10abSAndroid Build Coastguard Worker check_for_encode_breakout(*sse, x);
513*fb1b10abSAndroid Build Coastguard Worker return this_rd;
514*fb1b10abSAndroid Build Coastguard Worker }
515*fb1b10abSAndroid Build Coastguard Worker
calculate_zeromv_rd_adjustment(VP8_COMP * cpi,MACROBLOCK * x,int * rd_adjustment)516*fb1b10abSAndroid Build Coastguard Worker static void calculate_zeromv_rd_adjustment(VP8_COMP *cpi, MACROBLOCK *x,
517*fb1b10abSAndroid Build Coastguard Worker int *rd_adjustment) {
518*fb1b10abSAndroid Build Coastguard Worker MODE_INFO *mic = x->e_mbd.mode_info_context;
519*fb1b10abSAndroid Build Coastguard Worker int_mv mv_l, mv_a, mv_al;
520*fb1b10abSAndroid Build Coastguard Worker int local_motion_check = 0;
521*fb1b10abSAndroid Build Coastguard Worker
522*fb1b10abSAndroid Build Coastguard Worker if (cpi->lf_zeromv_pct > 40) {
523*fb1b10abSAndroid Build Coastguard Worker /* left mb */
524*fb1b10abSAndroid Build Coastguard Worker mic -= 1;
525*fb1b10abSAndroid Build Coastguard Worker mv_l = mic->mbmi.mv;
526*fb1b10abSAndroid Build Coastguard Worker
527*fb1b10abSAndroid Build Coastguard Worker if (mic->mbmi.ref_frame != INTRA_FRAME) {
528*fb1b10abSAndroid Build Coastguard Worker if (abs(mv_l.as_mv.row) < 8 && abs(mv_l.as_mv.col) < 8) {
529*fb1b10abSAndroid Build Coastguard Worker local_motion_check++;
530*fb1b10abSAndroid Build Coastguard Worker }
531*fb1b10abSAndroid Build Coastguard Worker }
532*fb1b10abSAndroid Build Coastguard Worker
533*fb1b10abSAndroid Build Coastguard Worker /* above-left mb */
534*fb1b10abSAndroid Build Coastguard Worker mic -= x->e_mbd.mode_info_stride;
535*fb1b10abSAndroid Build Coastguard Worker mv_al = mic->mbmi.mv;
536*fb1b10abSAndroid Build Coastguard Worker
537*fb1b10abSAndroid Build Coastguard Worker if (mic->mbmi.ref_frame != INTRA_FRAME) {
538*fb1b10abSAndroid Build Coastguard Worker if (abs(mv_al.as_mv.row) < 8 && abs(mv_al.as_mv.col) < 8) {
539*fb1b10abSAndroid Build Coastguard Worker local_motion_check++;
540*fb1b10abSAndroid Build Coastguard Worker }
541*fb1b10abSAndroid Build Coastguard Worker }
542*fb1b10abSAndroid Build Coastguard Worker
543*fb1b10abSAndroid Build Coastguard Worker /* above mb */
544*fb1b10abSAndroid Build Coastguard Worker mic += 1;
545*fb1b10abSAndroid Build Coastguard Worker mv_a = mic->mbmi.mv;
546*fb1b10abSAndroid Build Coastguard Worker
547*fb1b10abSAndroid Build Coastguard Worker if (mic->mbmi.ref_frame != INTRA_FRAME) {
548*fb1b10abSAndroid Build Coastguard Worker if (abs(mv_a.as_mv.row) < 8 && abs(mv_a.as_mv.col) < 8) {
549*fb1b10abSAndroid Build Coastguard Worker local_motion_check++;
550*fb1b10abSAndroid Build Coastguard Worker }
551*fb1b10abSAndroid Build Coastguard Worker }
552*fb1b10abSAndroid Build Coastguard Worker
553*fb1b10abSAndroid Build Coastguard Worker if (((!x->e_mbd.mb_to_top_edge || !x->e_mbd.mb_to_left_edge) &&
554*fb1b10abSAndroid Build Coastguard Worker local_motion_check > 0) ||
555*fb1b10abSAndroid Build Coastguard Worker local_motion_check > 2) {
556*fb1b10abSAndroid Build Coastguard Worker *rd_adjustment = 80;
557*fb1b10abSAndroid Build Coastguard Worker } else if (local_motion_check > 0) {
558*fb1b10abSAndroid Build Coastguard Worker *rd_adjustment = 90;
559*fb1b10abSAndroid Build Coastguard Worker }
560*fb1b10abSAndroid Build Coastguard Worker }
561*fb1b10abSAndroid Build Coastguard Worker }
562*fb1b10abSAndroid Build Coastguard Worker
vp8_pick_inter_mode(VP8_COMP * cpi,MACROBLOCK * x,int recon_yoffset,int recon_uvoffset,int * returnrate,int * returndistortion,int * returnintra,int mb_row,int mb_col)563*fb1b10abSAndroid Build Coastguard Worker void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
564*fb1b10abSAndroid Build Coastguard Worker int recon_uvoffset, int *returnrate,
565*fb1b10abSAndroid Build Coastguard Worker int *returndistortion, int *returnintra, int mb_row,
566*fb1b10abSAndroid Build Coastguard Worker int mb_col) {
567*fb1b10abSAndroid Build Coastguard Worker BLOCK *b = &x->block[0];
568*fb1b10abSAndroid Build Coastguard Worker BLOCKD *d = &x->e_mbd.block[0];
569*fb1b10abSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
570*fb1b10abSAndroid Build Coastguard Worker MB_MODE_INFO best_mbmode;
571*fb1b10abSAndroid Build Coastguard Worker
572*fb1b10abSAndroid Build Coastguard Worker int_mv best_ref_mv_sb[2] = { { 0 }, { 0 } };
573*fb1b10abSAndroid Build Coastguard Worker int_mv mode_mv_sb[2][MB_MODE_COUNT];
574*fb1b10abSAndroid Build Coastguard Worker int_mv best_ref_mv;
575*fb1b10abSAndroid Build Coastguard Worker int_mv *mode_mv;
576*fb1b10abSAndroid Build Coastguard Worker MB_PREDICTION_MODE this_mode;
577*fb1b10abSAndroid Build Coastguard Worker int num00;
578*fb1b10abSAndroid Build Coastguard Worker int mdcounts[4];
579*fb1b10abSAndroid Build Coastguard Worker int best_rd = INT_MAX;
580*fb1b10abSAndroid Build Coastguard Worker int rd_adjustment = 100;
581*fb1b10abSAndroid Build Coastguard Worker int best_intra_rd = INT_MAX;
582*fb1b10abSAndroid Build Coastguard Worker int mode_index;
583*fb1b10abSAndroid Build Coastguard Worker int rate;
584*fb1b10abSAndroid Build Coastguard Worker int rate2;
585*fb1b10abSAndroid Build Coastguard Worker int distortion2;
586*fb1b10abSAndroid Build Coastguard Worker int bestsme = INT_MAX;
587*fb1b10abSAndroid Build Coastguard Worker int best_mode_index = 0;
588*fb1b10abSAndroid Build Coastguard Worker unsigned int sse = UINT_MAX, best_rd_sse = UINT_MAX;
589*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
590*fb1b10abSAndroid Build Coastguard Worker unsigned int zero_mv_sse = UINT_MAX, best_sse = UINT_MAX;
591*fb1b10abSAndroid Build Coastguard Worker #endif
592*fb1b10abSAndroid Build Coastguard Worker
593*fb1b10abSAndroid Build Coastguard Worker int sf_improved_mv_pred = cpi->sf.improved_mv_pred;
594*fb1b10abSAndroid Build Coastguard Worker
595*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
596*fb1b10abSAndroid Build Coastguard Worker int dissim = INT_MAX;
597*fb1b10abSAndroid Build Coastguard Worker int parent_ref_frame = 0;
598*fb1b10abSAndroid Build Coastguard Worker int_mv parent_ref_mv;
599*fb1b10abSAndroid Build Coastguard Worker MB_PREDICTION_MODE parent_mode = 0;
600*fb1b10abSAndroid Build Coastguard Worker int parent_ref_valid = 0;
601*fb1b10abSAndroid Build Coastguard Worker #endif
602*fb1b10abSAndroid Build Coastguard Worker
603*fb1b10abSAndroid Build Coastguard Worker int_mv mvp;
604*fb1b10abSAndroid Build Coastguard Worker
605*fb1b10abSAndroid Build Coastguard Worker int near_sadidx[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
606*fb1b10abSAndroid Build Coastguard Worker int saddone = 0;
607*fb1b10abSAndroid Build Coastguard Worker /* search range got from mv_pred(). It uses step_param levels. (0-7) */
608*fb1b10abSAndroid Build Coastguard Worker int sr = 0;
609*fb1b10abSAndroid Build Coastguard Worker
610*fb1b10abSAndroid Build Coastguard Worker unsigned char *plane[4][3] = { { 0, 0 } };
611*fb1b10abSAndroid Build Coastguard Worker int ref_frame_map[4];
612*fb1b10abSAndroid Build Coastguard Worker int sign_bias = 0;
613*fb1b10abSAndroid Build Coastguard Worker int dot_artifact_candidate = 0;
614*fb1b10abSAndroid Build Coastguard Worker get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset);
615*fb1b10abSAndroid Build Coastguard Worker
616*fb1b10abSAndroid Build Coastguard Worker // If the current frame is using LAST as a reference, check for
617*fb1b10abSAndroid Build Coastguard Worker // biasing the mode selection for dot artifacts.
618*fb1b10abSAndroid Build Coastguard Worker if (cpi->ref_frame_flags & VP8_LAST_FRAME) {
619*fb1b10abSAndroid Build Coastguard Worker unsigned char *target_y = x->src.y_buffer;
620*fb1b10abSAndroid Build Coastguard Worker unsigned char *target_u = x->block[16].src + *x->block[16].base_src;
621*fb1b10abSAndroid Build Coastguard Worker unsigned char *target_v = x->block[20].src + *x->block[20].base_src;
622*fb1b10abSAndroid Build Coastguard Worker int stride = x->src.y_stride;
623*fb1b10abSAndroid Build Coastguard Worker int stride_uv = x->block[16].src_stride;
624*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
625*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.noise_sensitivity) {
626*fb1b10abSAndroid Build Coastguard Worker const int uv_denoise = (cpi->oxcf.noise_sensitivity >= 2) ? 1 : 0;
627*fb1b10abSAndroid Build Coastguard Worker target_y =
628*fb1b10abSAndroid Build Coastguard Worker cpi->denoiser.yv12_running_avg[LAST_FRAME].y_buffer + recon_yoffset;
629*fb1b10abSAndroid Build Coastguard Worker stride = cpi->denoiser.yv12_running_avg[LAST_FRAME].y_stride;
630*fb1b10abSAndroid Build Coastguard Worker if (uv_denoise) {
631*fb1b10abSAndroid Build Coastguard Worker target_u = cpi->denoiser.yv12_running_avg[LAST_FRAME].u_buffer +
632*fb1b10abSAndroid Build Coastguard Worker recon_uvoffset;
633*fb1b10abSAndroid Build Coastguard Worker target_v = cpi->denoiser.yv12_running_avg[LAST_FRAME].v_buffer +
634*fb1b10abSAndroid Build Coastguard Worker recon_uvoffset;
635*fb1b10abSAndroid Build Coastguard Worker stride_uv = cpi->denoiser.yv12_running_avg[LAST_FRAME].uv_stride;
636*fb1b10abSAndroid Build Coastguard Worker }
637*fb1b10abSAndroid Build Coastguard Worker }
638*fb1b10abSAndroid Build Coastguard Worker #endif
639*fb1b10abSAndroid Build Coastguard Worker assert(plane[LAST_FRAME][0] != NULL);
640*fb1b10abSAndroid Build Coastguard Worker dot_artifact_candidate = check_dot_artifact_candidate(
641*fb1b10abSAndroid Build Coastguard Worker cpi, x, target_y, stride, plane[LAST_FRAME][0], mb_row, mb_col, 0);
642*fb1b10abSAndroid Build Coastguard Worker // If not found in Y channel, check UV channel.
643*fb1b10abSAndroid Build Coastguard Worker if (!dot_artifact_candidate) {
644*fb1b10abSAndroid Build Coastguard Worker assert(plane[LAST_FRAME][1] != NULL);
645*fb1b10abSAndroid Build Coastguard Worker dot_artifact_candidate = check_dot_artifact_candidate(
646*fb1b10abSAndroid Build Coastguard Worker cpi, x, target_u, stride_uv, plane[LAST_FRAME][1], mb_row, mb_col, 1);
647*fb1b10abSAndroid Build Coastguard Worker if (!dot_artifact_candidate) {
648*fb1b10abSAndroid Build Coastguard Worker assert(plane[LAST_FRAME][2] != NULL);
649*fb1b10abSAndroid Build Coastguard Worker dot_artifact_candidate = check_dot_artifact_candidate(
650*fb1b10abSAndroid Build Coastguard Worker cpi, x, target_v, stride_uv, plane[LAST_FRAME][2], mb_row, mb_col,
651*fb1b10abSAndroid Build Coastguard Worker 2);
652*fb1b10abSAndroid Build Coastguard Worker }
653*fb1b10abSAndroid Build Coastguard Worker }
654*fb1b10abSAndroid Build Coastguard Worker }
655*fb1b10abSAndroid Build Coastguard Worker
656*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
657*fb1b10abSAndroid Build Coastguard Worker // |parent_ref_valid| will be set here if potentially we can do mv resue for
658*fb1b10abSAndroid Build Coastguard Worker // this higher resol (|cpi->oxcf.mr_encoder_id| > 0) frame.
659*fb1b10abSAndroid Build Coastguard Worker // |parent_ref_valid| may be reset depending on |parent_ref_frame| for
660*fb1b10abSAndroid Build Coastguard Worker // the current macroblock below.
661*fb1b10abSAndroid Build Coastguard Worker parent_ref_valid = cpi->oxcf.mr_encoder_id && cpi->mr_low_res_mv_avail;
662*fb1b10abSAndroid Build Coastguard Worker if (parent_ref_valid) {
663*fb1b10abSAndroid Build Coastguard Worker int parent_ref_flag;
664*fb1b10abSAndroid Build Coastguard Worker
665*fb1b10abSAndroid Build Coastguard Worker get_lower_res_motion_info(cpi, xd, &dissim, &parent_ref_frame, &parent_mode,
666*fb1b10abSAndroid Build Coastguard Worker &parent_ref_mv, mb_row, mb_col);
667*fb1b10abSAndroid Build Coastguard Worker
668*fb1b10abSAndroid Build Coastguard Worker /* TODO(jkoleszar): The references available (ref_frame_flags) to the
669*fb1b10abSAndroid Build Coastguard Worker * lower res encoder should match those available to this encoder, but
670*fb1b10abSAndroid Build Coastguard Worker * there seems to be a situation where this mismatch can happen in the
671*fb1b10abSAndroid Build Coastguard Worker * case of frame dropping and temporal layers. For example,
672*fb1b10abSAndroid Build Coastguard Worker * GOLD being disallowed in ref_frame_flags, but being returned as
673*fb1b10abSAndroid Build Coastguard Worker * parent_ref_frame.
674*fb1b10abSAndroid Build Coastguard Worker *
675*fb1b10abSAndroid Build Coastguard Worker * In this event, take the conservative approach of disabling the
676*fb1b10abSAndroid Build Coastguard Worker * lower res info for this MB.
677*fb1b10abSAndroid Build Coastguard Worker */
678*fb1b10abSAndroid Build Coastguard Worker
679*fb1b10abSAndroid Build Coastguard Worker parent_ref_flag = 0;
680*fb1b10abSAndroid Build Coastguard Worker // Note availability for mv reuse is only based on last and golden.
681*fb1b10abSAndroid Build Coastguard Worker if (parent_ref_frame == LAST_FRAME)
682*fb1b10abSAndroid Build Coastguard Worker parent_ref_flag = (cpi->ref_frame_flags & VP8_LAST_FRAME);
683*fb1b10abSAndroid Build Coastguard Worker else if (parent_ref_frame == GOLDEN_FRAME)
684*fb1b10abSAndroid Build Coastguard Worker parent_ref_flag = (cpi->ref_frame_flags & VP8_GOLD_FRAME);
685*fb1b10abSAndroid Build Coastguard Worker
686*fb1b10abSAndroid Build Coastguard Worker // assert(!parent_ref_frame || parent_ref_flag);
687*fb1b10abSAndroid Build Coastguard Worker
688*fb1b10abSAndroid Build Coastguard Worker // If |parent_ref_frame| did not match either last or golden then
689*fb1b10abSAndroid Build Coastguard Worker // shut off mv reuse.
690*fb1b10abSAndroid Build Coastguard Worker if (parent_ref_frame && !parent_ref_flag) parent_ref_valid = 0;
691*fb1b10abSAndroid Build Coastguard Worker
692*fb1b10abSAndroid Build Coastguard Worker // Don't do mv reuse since we want to allow for another mode besides
693*fb1b10abSAndroid Build Coastguard Worker // ZEROMV_LAST to remove dot artifact.
694*fb1b10abSAndroid Build Coastguard Worker if (dot_artifact_candidate) parent_ref_valid = 0;
695*fb1b10abSAndroid Build Coastguard Worker }
696*fb1b10abSAndroid Build Coastguard Worker #endif
697*fb1b10abSAndroid Build Coastguard Worker
698*fb1b10abSAndroid Build Coastguard Worker // Check if current macroblock is in skin area.
699*fb1b10abSAndroid Build Coastguard Worker x->is_skin = 0;
700*fb1b10abSAndroid Build Coastguard Worker if (!cpi->oxcf.screen_content_mode) {
701*fb1b10abSAndroid Build Coastguard Worker int block_index = mb_row * cpi->common.mb_cols + mb_col;
702*fb1b10abSAndroid Build Coastguard Worker x->is_skin = cpi->skin_map[block_index];
703*fb1b10abSAndroid Build Coastguard Worker }
704*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
705*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.noise_sensitivity) {
706*fb1b10abSAndroid Build Coastguard Worker // Under aggressive denoising mode, should we use skin map to reduce
707*fb1b10abSAndroid Build Coastguard Worker // denoiser
708*fb1b10abSAndroid Build Coastguard Worker // and ZEROMV bias? Will need to revisit the accuracy of this detection for
709*fb1b10abSAndroid Build Coastguard Worker // very noisy input. For now keep this as is (i.e., don't turn it off).
710*fb1b10abSAndroid Build Coastguard Worker // if (cpi->denoiser.denoiser_mode == kDenoiserOnYUVAggressive)
711*fb1b10abSAndroid Build Coastguard Worker // x->is_skin = 0;
712*fb1b10abSAndroid Build Coastguard Worker }
713*fb1b10abSAndroid Build Coastguard Worker #endif
714*fb1b10abSAndroid Build Coastguard Worker
715*fb1b10abSAndroid Build Coastguard Worker mode_mv = mode_mv_sb[sign_bias];
716*fb1b10abSAndroid Build Coastguard Worker best_ref_mv.as_int = 0;
717*fb1b10abSAndroid Build Coastguard Worker memset(mode_mv_sb, 0, sizeof(mode_mv_sb));
718*fb1b10abSAndroid Build Coastguard Worker memset(&best_mbmode, 0, sizeof(best_mbmode));
719*fb1b10abSAndroid Build Coastguard Worker
720*fb1b10abSAndroid Build Coastguard Worker /* Setup search priorities */
721*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
722*fb1b10abSAndroid Build Coastguard Worker if (parent_ref_valid && parent_ref_frame && dissim < 8) {
723*fb1b10abSAndroid Build Coastguard Worker ref_frame_map[0] = -1;
724*fb1b10abSAndroid Build Coastguard Worker ref_frame_map[1] = parent_ref_frame;
725*fb1b10abSAndroid Build Coastguard Worker ref_frame_map[2] = -1;
726*fb1b10abSAndroid Build Coastguard Worker ref_frame_map[3] = -1;
727*fb1b10abSAndroid Build Coastguard Worker } else
728*fb1b10abSAndroid Build Coastguard Worker #endif
729*fb1b10abSAndroid Build Coastguard Worker get_reference_search_order(cpi, ref_frame_map);
730*fb1b10abSAndroid Build Coastguard Worker
731*fb1b10abSAndroid Build Coastguard Worker /* Check to see if there is at least 1 valid reference frame that we need
732*fb1b10abSAndroid Build Coastguard Worker * to calculate near_mvs.
733*fb1b10abSAndroid Build Coastguard Worker */
734*fb1b10abSAndroid Build Coastguard Worker if (ref_frame_map[1] > 0) {
735*fb1b10abSAndroid Build Coastguard Worker sign_bias = vp8_find_near_mvs_bias(
736*fb1b10abSAndroid Build Coastguard Worker &x->e_mbd, x->e_mbd.mode_info_context, mode_mv_sb, best_ref_mv_sb,
737*fb1b10abSAndroid Build Coastguard Worker mdcounts, ref_frame_map[1], cpi->common.ref_frame_sign_bias);
738*fb1b10abSAndroid Build Coastguard Worker
739*fb1b10abSAndroid Build Coastguard Worker mode_mv = mode_mv_sb[sign_bias];
740*fb1b10abSAndroid Build Coastguard Worker best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
741*fb1b10abSAndroid Build Coastguard Worker }
742*fb1b10abSAndroid Build Coastguard Worker
743*fb1b10abSAndroid Build Coastguard Worker /* Count of the number of MBs tested so far this frame */
744*fb1b10abSAndroid Build Coastguard Worker x->mbs_tested_so_far++;
745*fb1b10abSAndroid Build Coastguard Worker
746*fb1b10abSAndroid Build Coastguard Worker *returnintra = INT_MAX;
747*fb1b10abSAndroid Build Coastguard Worker x->skip = 0;
748*fb1b10abSAndroid Build Coastguard Worker
749*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
750*fb1b10abSAndroid Build Coastguard Worker
751*fb1b10abSAndroid Build Coastguard Worker /* If the frame has big static background and current MB is in low
752*fb1b10abSAndroid Build Coastguard Worker * motion area, its mode decision is biased to ZEROMV mode.
753*fb1b10abSAndroid Build Coastguard Worker * No adjustment if cpu_used is <= -12 (i.e., cpi->Speed >= 12).
754*fb1b10abSAndroid Build Coastguard Worker * At such speed settings, ZEROMV is already heavily favored.
755*fb1b10abSAndroid Build Coastguard Worker */
756*fb1b10abSAndroid Build Coastguard Worker if (cpi->Speed < 12) {
757*fb1b10abSAndroid Build Coastguard Worker calculate_zeromv_rd_adjustment(cpi, x, &rd_adjustment);
758*fb1b10abSAndroid Build Coastguard Worker }
759*fb1b10abSAndroid Build Coastguard Worker
760*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
761*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.noise_sensitivity) {
762*fb1b10abSAndroid Build Coastguard Worker rd_adjustment = (int)(rd_adjustment *
763*fb1b10abSAndroid Build Coastguard Worker cpi->denoiser.denoise_pars.pickmode_mv_bias / 100);
764*fb1b10abSAndroid Build Coastguard Worker }
765*fb1b10abSAndroid Build Coastguard Worker #endif
766*fb1b10abSAndroid Build Coastguard Worker
767*fb1b10abSAndroid Build Coastguard Worker if (dot_artifact_candidate) {
768*fb1b10abSAndroid Build Coastguard Worker // Bias against ZEROMV_LAST mode.
769*fb1b10abSAndroid Build Coastguard Worker rd_adjustment = 150;
770*fb1b10abSAndroid Build Coastguard Worker }
771*fb1b10abSAndroid Build Coastguard Worker
772*fb1b10abSAndroid Build Coastguard Worker /* if we encode a new mv this is important
773*fb1b10abSAndroid Build Coastguard Worker * find the best new motion vector
774*fb1b10abSAndroid Build Coastguard Worker */
775*fb1b10abSAndroid Build Coastguard Worker for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
776*fb1b10abSAndroid Build Coastguard Worker int frame_cost;
777*fb1b10abSAndroid Build Coastguard Worker int this_rd = INT_MAX;
778*fb1b10abSAndroid Build Coastguard Worker int this_ref_frame = ref_frame_map[vp8_ref_frame_order[mode_index]];
779*fb1b10abSAndroid Build Coastguard Worker
780*fb1b10abSAndroid Build Coastguard Worker if (best_rd <= x->rd_threshes[mode_index]) continue;
781*fb1b10abSAndroid Build Coastguard Worker
782*fb1b10abSAndroid Build Coastguard Worker if (this_ref_frame < 0) continue;
783*fb1b10abSAndroid Build Coastguard Worker
784*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame = this_ref_frame;
785*fb1b10abSAndroid Build Coastguard Worker
786*fb1b10abSAndroid Build Coastguard Worker /* everything but intra */
787*fb1b10abSAndroid Build Coastguard Worker if (x->e_mbd.mode_info_context->mbmi.ref_frame) {
788*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.pre.y_buffer = plane[this_ref_frame][0];
789*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.pre.u_buffer = plane[this_ref_frame][1];
790*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.pre.v_buffer = plane[this_ref_frame][2];
791*fb1b10abSAndroid Build Coastguard Worker
792*fb1b10abSAndroid Build Coastguard Worker if (sign_bias != cpi->common.ref_frame_sign_bias[this_ref_frame]) {
793*fb1b10abSAndroid Build Coastguard Worker sign_bias = cpi->common.ref_frame_sign_bias[this_ref_frame];
794*fb1b10abSAndroid Build Coastguard Worker mode_mv = mode_mv_sb[sign_bias];
795*fb1b10abSAndroid Build Coastguard Worker best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int;
796*fb1b10abSAndroid Build Coastguard Worker }
797*fb1b10abSAndroid Build Coastguard Worker
798*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
799*fb1b10abSAndroid Build Coastguard Worker if (parent_ref_valid) {
800*fb1b10abSAndroid Build Coastguard Worker if (vp8_mode_order[mode_index] == NEARESTMV &&
801*fb1b10abSAndroid Build Coastguard Worker mode_mv[NEARESTMV].as_int == 0)
802*fb1b10abSAndroid Build Coastguard Worker continue;
803*fb1b10abSAndroid Build Coastguard Worker if (vp8_mode_order[mode_index] == NEARMV && mode_mv[NEARMV].as_int == 0)
804*fb1b10abSAndroid Build Coastguard Worker continue;
805*fb1b10abSAndroid Build Coastguard Worker
806*fb1b10abSAndroid Build Coastguard Worker if (vp8_mode_order[mode_index] == NEWMV && parent_mode == ZEROMV &&
807*fb1b10abSAndroid Build Coastguard Worker best_ref_mv.as_int == 0)
808*fb1b10abSAndroid Build Coastguard Worker continue;
809*fb1b10abSAndroid Build Coastguard Worker else if (vp8_mode_order[mode_index] == NEWMV && dissim == 0 &&
810*fb1b10abSAndroid Build Coastguard Worker best_ref_mv.as_int == parent_ref_mv.as_int)
811*fb1b10abSAndroid Build Coastguard Worker continue;
812*fb1b10abSAndroid Build Coastguard Worker }
813*fb1b10abSAndroid Build Coastguard Worker #endif
814*fb1b10abSAndroid Build Coastguard Worker }
815*fb1b10abSAndroid Build Coastguard Worker
816*fb1b10abSAndroid Build Coastguard Worker /* Check to see if the testing frequency for this mode is at its max
817*fb1b10abSAndroid Build Coastguard Worker * If so then prevent it from being tested and increase the threshold
818*fb1b10abSAndroid Build Coastguard Worker * for its testing */
819*fb1b10abSAndroid Build Coastguard Worker if (x->mode_test_hit_counts[mode_index] &&
820*fb1b10abSAndroid Build Coastguard Worker (cpi->mode_check_freq[mode_index] > 1)) {
821*fb1b10abSAndroid Build Coastguard Worker if (x->mbs_tested_so_far <= (cpi->mode_check_freq[mode_index] *
822*fb1b10abSAndroid Build Coastguard Worker x->mode_test_hit_counts[mode_index])) {
823*fb1b10abSAndroid Build Coastguard Worker /* Increase the threshold for coding this mode to make it less
824*fb1b10abSAndroid Build Coastguard Worker * likely to be chosen */
825*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index] += 4;
826*fb1b10abSAndroid Build Coastguard Worker
827*fb1b10abSAndroid Build Coastguard Worker if (x->rd_thresh_mult[mode_index] > MAX_THRESHMULT) {
828*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
829*fb1b10abSAndroid Build Coastguard Worker }
830*fb1b10abSAndroid Build Coastguard Worker
831*fb1b10abSAndroid Build Coastguard Worker x->rd_threshes[mode_index] =
832*fb1b10abSAndroid Build Coastguard Worker (cpi->rd_baseline_thresh[mode_index] >> 7) *
833*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index];
834*fb1b10abSAndroid Build Coastguard Worker continue;
835*fb1b10abSAndroid Build Coastguard Worker }
836*fb1b10abSAndroid Build Coastguard Worker }
837*fb1b10abSAndroid Build Coastguard Worker
838*fb1b10abSAndroid Build Coastguard Worker /* We have now reached the point where we are going to test the current
839*fb1b10abSAndroid Build Coastguard Worker * mode so increment the counter for the number of times it has been
840*fb1b10abSAndroid Build Coastguard Worker * tested */
841*fb1b10abSAndroid Build Coastguard Worker x->mode_test_hit_counts[mode_index]++;
842*fb1b10abSAndroid Build Coastguard Worker
843*fb1b10abSAndroid Build Coastguard Worker rate2 = 0;
844*fb1b10abSAndroid Build Coastguard Worker distortion2 = 0;
845*fb1b10abSAndroid Build Coastguard Worker
846*fb1b10abSAndroid Build Coastguard Worker this_mode = vp8_mode_order[mode_index];
847*fb1b10abSAndroid Build Coastguard Worker
848*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.mode = this_mode;
849*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
850*fb1b10abSAndroid Build Coastguard Worker
851*fb1b10abSAndroid Build Coastguard Worker /* Work out the cost assosciated with selecting the reference frame */
852*fb1b10abSAndroid Build Coastguard Worker frame_cost = x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
853*fb1b10abSAndroid Build Coastguard Worker rate2 += frame_cost;
854*fb1b10abSAndroid Build Coastguard Worker
855*fb1b10abSAndroid Build Coastguard Worker /* Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
856*fb1b10abSAndroid Build Coastguard Worker * unless ARNR filtering is enabled in which case we want
857*fb1b10abSAndroid Build Coastguard Worker * an unfiltered alternative */
858*fb1b10abSAndroid Build Coastguard Worker if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
859*fb1b10abSAndroid Build Coastguard Worker if (this_mode != ZEROMV ||
860*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME) {
861*fb1b10abSAndroid Build Coastguard Worker continue;
862*fb1b10abSAndroid Build Coastguard Worker }
863*fb1b10abSAndroid Build Coastguard Worker }
864*fb1b10abSAndroid Build Coastguard Worker
865*fb1b10abSAndroid Build Coastguard Worker switch (this_mode) {
866*fb1b10abSAndroid Build Coastguard Worker case B_PRED:
867*fb1b10abSAndroid Build Coastguard Worker /* Pass best so far to pick_intra4x4mby_modes to use as breakout */
868*fb1b10abSAndroid Build Coastguard Worker distortion2 = best_rd_sse;
869*fb1b10abSAndroid Build Coastguard Worker pick_intra4x4mby_modes(x, &rate, &distortion2);
870*fb1b10abSAndroid Build Coastguard Worker
871*fb1b10abSAndroid Build Coastguard Worker if (distortion2 == INT_MAX) {
872*fb1b10abSAndroid Build Coastguard Worker this_rd = INT_MAX;
873*fb1b10abSAndroid Build Coastguard Worker } else {
874*fb1b10abSAndroid Build Coastguard Worker rate2 += rate;
875*fb1b10abSAndroid Build Coastguard Worker distortion2 = vpx_variance16x16(*(b->base_src), b->src_stride,
876*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.predictor, 16, &sse);
877*fb1b10abSAndroid Build Coastguard Worker this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
878*fb1b10abSAndroid Build Coastguard Worker
879*fb1b10abSAndroid Build Coastguard Worker if (this_rd < best_intra_rd) {
880*fb1b10abSAndroid Build Coastguard Worker best_intra_rd = this_rd;
881*fb1b10abSAndroid Build Coastguard Worker *returnintra = distortion2;
882*fb1b10abSAndroid Build Coastguard Worker }
883*fb1b10abSAndroid Build Coastguard Worker }
884*fb1b10abSAndroid Build Coastguard Worker
885*fb1b10abSAndroid Build Coastguard Worker break;
886*fb1b10abSAndroid Build Coastguard Worker
887*fb1b10abSAndroid Build Coastguard Worker case SPLITMV:
888*fb1b10abSAndroid Build Coastguard Worker
889*fb1b10abSAndroid Build Coastguard Worker /* Split MV modes currently not supported when RD is not enabled. */
890*fb1b10abSAndroid Build Coastguard Worker break;
891*fb1b10abSAndroid Build Coastguard Worker
892*fb1b10abSAndroid Build Coastguard Worker case DC_PRED:
893*fb1b10abSAndroid Build Coastguard Worker case V_PRED:
894*fb1b10abSAndroid Build Coastguard Worker case H_PRED:
895*fb1b10abSAndroid Build Coastguard Worker case TM_PRED:
896*fb1b10abSAndroid Build Coastguard Worker vp8_build_intra_predictors_mby_s(
897*fb1b10abSAndroid Build Coastguard Worker xd, xd->dst.y_buffer - xd->dst.y_stride, xd->dst.y_buffer - 1,
898*fb1b10abSAndroid Build Coastguard Worker xd->dst.y_stride, xd->predictor, 16);
899*fb1b10abSAndroid Build Coastguard Worker distortion2 = vpx_variance16x16(*(b->base_src), b->src_stride,
900*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.predictor, 16, &sse);
901*fb1b10abSAndroid Build Coastguard Worker rate2 += x->mbmode_cost[x->e_mbd.frame_type]
902*fb1b10abSAndroid Build Coastguard Worker [x->e_mbd.mode_info_context->mbmi.mode];
903*fb1b10abSAndroid Build Coastguard Worker this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
904*fb1b10abSAndroid Build Coastguard Worker
905*fb1b10abSAndroid Build Coastguard Worker if (this_rd < best_intra_rd) {
906*fb1b10abSAndroid Build Coastguard Worker best_intra_rd = this_rd;
907*fb1b10abSAndroid Build Coastguard Worker *returnintra = distortion2;
908*fb1b10abSAndroid Build Coastguard Worker }
909*fb1b10abSAndroid Build Coastguard Worker break;
910*fb1b10abSAndroid Build Coastguard Worker
911*fb1b10abSAndroid Build Coastguard Worker case NEWMV: {
912*fb1b10abSAndroid Build Coastguard Worker int thissme;
913*fb1b10abSAndroid Build Coastguard Worker int step_param;
914*fb1b10abSAndroid Build Coastguard Worker int further_steps;
915*fb1b10abSAndroid Build Coastguard Worker int n = 0;
916*fb1b10abSAndroid Build Coastguard Worker int sadpb = x->sadperbit16;
917*fb1b10abSAndroid Build Coastguard Worker int_mv mvp_full;
918*fb1b10abSAndroid Build Coastguard Worker
919*fb1b10abSAndroid Build Coastguard Worker int col_min = ((best_ref_mv.as_mv.col + 7) >> 3) - MAX_FULL_PEL_VAL;
920*fb1b10abSAndroid Build Coastguard Worker int row_min = ((best_ref_mv.as_mv.row + 7) >> 3) - MAX_FULL_PEL_VAL;
921*fb1b10abSAndroid Build Coastguard Worker int col_max = (best_ref_mv.as_mv.col >> 3) + MAX_FULL_PEL_VAL;
922*fb1b10abSAndroid Build Coastguard Worker int row_max = (best_ref_mv.as_mv.row >> 3) + MAX_FULL_PEL_VAL;
923*fb1b10abSAndroid Build Coastguard Worker
924*fb1b10abSAndroid Build Coastguard Worker int tmp_col_min = x->mv_col_min;
925*fb1b10abSAndroid Build Coastguard Worker int tmp_col_max = x->mv_col_max;
926*fb1b10abSAndroid Build Coastguard Worker int tmp_row_min = x->mv_row_min;
927*fb1b10abSAndroid Build Coastguard Worker int tmp_row_max = x->mv_row_max;
928*fb1b10abSAndroid Build Coastguard Worker
929*fb1b10abSAndroid Build Coastguard Worker int speed_adjust = (cpi->Speed > 5) ? ((cpi->Speed >= 8) ? 3 : 2) : 1;
930*fb1b10abSAndroid Build Coastguard Worker
931*fb1b10abSAndroid Build Coastguard Worker /* Further step/diamond searches as necessary */
932*fb1b10abSAndroid Build Coastguard Worker step_param = cpi->sf.first_step + speed_adjust;
933*fb1b10abSAndroid Build Coastguard Worker
934*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
935*fb1b10abSAndroid Build Coastguard Worker /* If lower-res frame is not available for mv reuse (because of
936*fb1b10abSAndroid Build Coastguard Worker frame dropping or different temporal layer pattern), then higher
937*fb1b10abSAndroid Build Coastguard Worker resol encoder does motion search without any previous knowledge.
938*fb1b10abSAndroid Build Coastguard Worker Also, since last frame motion info is not stored, then we can not
939*fb1b10abSAndroid Build Coastguard Worker use improved_mv_pred. */
940*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.mr_encoder_id) sf_improved_mv_pred = 0;
941*fb1b10abSAndroid Build Coastguard Worker
942*fb1b10abSAndroid Build Coastguard Worker // Only use parent MV as predictor if this candidate reference frame
943*fb1b10abSAndroid Build Coastguard Worker // (|this_ref_frame|) is equal to |parent_ref_frame|.
944*fb1b10abSAndroid Build Coastguard Worker if (parent_ref_valid && (parent_ref_frame == this_ref_frame)) {
945*fb1b10abSAndroid Build Coastguard Worker /* Use parent MV as predictor. Adjust search range
946*fb1b10abSAndroid Build Coastguard Worker * accordingly.
947*fb1b10abSAndroid Build Coastguard Worker */
948*fb1b10abSAndroid Build Coastguard Worker mvp.as_int = parent_ref_mv.as_int;
949*fb1b10abSAndroid Build Coastguard Worker mvp_full.as_mv.col = parent_ref_mv.as_mv.col >> 3;
950*fb1b10abSAndroid Build Coastguard Worker mvp_full.as_mv.row = parent_ref_mv.as_mv.row >> 3;
951*fb1b10abSAndroid Build Coastguard Worker
952*fb1b10abSAndroid Build Coastguard Worker if (dissim <= 32)
953*fb1b10abSAndroid Build Coastguard Worker step_param += 3;
954*fb1b10abSAndroid Build Coastguard Worker else if (dissim <= 128)
955*fb1b10abSAndroid Build Coastguard Worker step_param += 2;
956*fb1b10abSAndroid Build Coastguard Worker else
957*fb1b10abSAndroid Build Coastguard Worker step_param += 1;
958*fb1b10abSAndroid Build Coastguard Worker } else
959*fb1b10abSAndroid Build Coastguard Worker #endif
960*fb1b10abSAndroid Build Coastguard Worker {
961*fb1b10abSAndroid Build Coastguard Worker if (sf_improved_mv_pred) {
962*fb1b10abSAndroid Build Coastguard Worker if (!saddone) {
963*fb1b10abSAndroid Build Coastguard Worker vp8_cal_sad(cpi, xd, x, recon_yoffset, &near_sadidx[0]);
964*fb1b10abSAndroid Build Coastguard Worker saddone = 1;
965*fb1b10abSAndroid Build Coastguard Worker }
966*fb1b10abSAndroid Build Coastguard Worker
967*fb1b10abSAndroid Build Coastguard Worker vp8_mv_pred(cpi, &x->e_mbd, x->e_mbd.mode_info_context, &mvp,
968*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame,
969*fb1b10abSAndroid Build Coastguard Worker cpi->common.ref_frame_sign_bias, &sr, &near_sadidx[0]);
970*fb1b10abSAndroid Build Coastguard Worker
971*fb1b10abSAndroid Build Coastguard Worker sr += speed_adjust;
972*fb1b10abSAndroid Build Coastguard Worker /* adjust search range according to sr from mv prediction */
973*fb1b10abSAndroid Build Coastguard Worker if (sr > step_param) step_param = sr;
974*fb1b10abSAndroid Build Coastguard Worker
975*fb1b10abSAndroid Build Coastguard Worker mvp_full.as_mv.col = mvp.as_mv.col >> 3;
976*fb1b10abSAndroid Build Coastguard Worker mvp_full.as_mv.row = mvp.as_mv.row >> 3;
977*fb1b10abSAndroid Build Coastguard Worker } else {
978*fb1b10abSAndroid Build Coastguard Worker mvp.as_int = best_ref_mv.as_int;
979*fb1b10abSAndroid Build Coastguard Worker mvp_full.as_mv.col = best_ref_mv.as_mv.col >> 3;
980*fb1b10abSAndroid Build Coastguard Worker mvp_full.as_mv.row = best_ref_mv.as_mv.row >> 3;
981*fb1b10abSAndroid Build Coastguard Worker }
982*fb1b10abSAndroid Build Coastguard Worker }
983*fb1b10abSAndroid Build Coastguard Worker
984*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
985*fb1b10abSAndroid Build Coastguard Worker if (parent_ref_valid && (parent_ref_frame == this_ref_frame) &&
986*fb1b10abSAndroid Build Coastguard Worker dissim <= 2 &&
987*fb1b10abSAndroid Build Coastguard Worker VPXMAX(abs(best_ref_mv.as_mv.row - parent_ref_mv.as_mv.row),
988*fb1b10abSAndroid Build Coastguard Worker abs(best_ref_mv.as_mv.col - parent_ref_mv.as_mv.col)) <= 4) {
989*fb1b10abSAndroid Build Coastguard Worker d->bmi.mv.as_int = mvp_full.as_int;
990*fb1b10abSAndroid Build Coastguard Worker mode_mv[NEWMV].as_int = mvp_full.as_int;
991*fb1b10abSAndroid Build Coastguard Worker
992*fb1b10abSAndroid Build Coastguard Worker cpi->find_fractional_mv_step(
993*fb1b10abSAndroid Build Coastguard Worker x, b, d, &d->bmi.mv, &best_ref_mv, x->errorperbit,
994*fb1b10abSAndroid Build Coastguard Worker &cpi->fn_ptr[BLOCK_16X16], cpi->mb.mvcost, &distortion2, &sse);
995*fb1b10abSAndroid Build Coastguard Worker } else
996*fb1b10abSAndroid Build Coastguard Worker #endif
997*fb1b10abSAndroid Build Coastguard Worker {
998*fb1b10abSAndroid Build Coastguard Worker /* Get intersection of UMV window and valid MV window to
999*fb1b10abSAndroid Build Coastguard Worker * reduce # of checks in diamond search. */
1000*fb1b10abSAndroid Build Coastguard Worker if (x->mv_col_min < col_min) x->mv_col_min = col_min;
1001*fb1b10abSAndroid Build Coastguard Worker if (x->mv_col_max > col_max) x->mv_col_max = col_max;
1002*fb1b10abSAndroid Build Coastguard Worker if (x->mv_row_min < row_min) x->mv_row_min = row_min;
1003*fb1b10abSAndroid Build Coastguard Worker if (x->mv_row_max > row_max) x->mv_row_max = row_max;
1004*fb1b10abSAndroid Build Coastguard Worker
1005*fb1b10abSAndroid Build Coastguard Worker further_steps =
1006*fb1b10abSAndroid Build Coastguard Worker (cpi->Speed >= 8)
1007*fb1b10abSAndroid Build Coastguard Worker ? 0
1008*fb1b10abSAndroid Build Coastguard Worker : (cpi->sf.max_step_search_steps - 1 - step_param);
1009*fb1b10abSAndroid Build Coastguard Worker
1010*fb1b10abSAndroid Build Coastguard Worker if (cpi->sf.search_method == HEX) {
1011*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
1012*fb1b10abSAndroid Build Coastguard Worker /* TODO: In higher-res pick_inter_mode, step_param is used to
1013*fb1b10abSAndroid Build Coastguard Worker * modify hex search range. Here, set step_param to 0 not to
1014*fb1b10abSAndroid Build Coastguard Worker * change the behavior in lowest-resolution encoder.
1015*fb1b10abSAndroid Build Coastguard Worker * Will improve it later.
1016*fb1b10abSAndroid Build Coastguard Worker */
1017*fb1b10abSAndroid Build Coastguard Worker /* Set step_param to 0 to ensure large-range motion search
1018*fb1b10abSAndroid Build Coastguard Worker * when mv reuse if not valid (i.e. |parent_ref_valid| = 0),
1019*fb1b10abSAndroid Build Coastguard Worker * or if this candidate reference frame (|this_ref_frame|) is
1020*fb1b10abSAndroid Build Coastguard Worker * not equal to |parent_ref_frame|.
1021*fb1b10abSAndroid Build Coastguard Worker */
1022*fb1b10abSAndroid Build Coastguard Worker if (!parent_ref_valid || (parent_ref_frame != this_ref_frame))
1023*fb1b10abSAndroid Build Coastguard Worker step_param = 0;
1024*fb1b10abSAndroid Build Coastguard Worker #endif
1025*fb1b10abSAndroid Build Coastguard Worker bestsme = vp8_hex_search(x, b, d, &mvp_full, &d->bmi.mv, step_param,
1026*fb1b10abSAndroid Build Coastguard Worker sadpb, &cpi->fn_ptr[BLOCK_16X16],
1027*fb1b10abSAndroid Build Coastguard Worker x->mvsadcost, &best_ref_mv);
1028*fb1b10abSAndroid Build Coastguard Worker mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
1029*fb1b10abSAndroid Build Coastguard Worker } else {
1030*fb1b10abSAndroid Build Coastguard Worker bestsme = cpi->diamond_search_sad(
1031*fb1b10abSAndroid Build Coastguard Worker x, b, d, &mvp_full, &d->bmi.mv, step_param, sadpb, &num00,
1032*fb1b10abSAndroid Build Coastguard Worker &cpi->fn_ptr[BLOCK_16X16], x->mvcost, &best_ref_mv);
1033*fb1b10abSAndroid Build Coastguard Worker mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
1034*fb1b10abSAndroid Build Coastguard Worker
1035*fb1b10abSAndroid Build Coastguard Worker /* Further step/diamond searches as necessary */
1036*fb1b10abSAndroid Build Coastguard Worker n = num00;
1037*fb1b10abSAndroid Build Coastguard Worker num00 = 0;
1038*fb1b10abSAndroid Build Coastguard Worker
1039*fb1b10abSAndroid Build Coastguard Worker while (n < further_steps) {
1040*fb1b10abSAndroid Build Coastguard Worker n++;
1041*fb1b10abSAndroid Build Coastguard Worker
1042*fb1b10abSAndroid Build Coastguard Worker if (num00) {
1043*fb1b10abSAndroid Build Coastguard Worker num00--;
1044*fb1b10abSAndroid Build Coastguard Worker } else {
1045*fb1b10abSAndroid Build Coastguard Worker thissme = cpi->diamond_search_sad(
1046*fb1b10abSAndroid Build Coastguard Worker x, b, d, &mvp_full, &d->bmi.mv, step_param + n, sadpb,
1047*fb1b10abSAndroid Build Coastguard Worker &num00, &cpi->fn_ptr[BLOCK_16X16], x->mvcost, &best_ref_mv);
1048*fb1b10abSAndroid Build Coastguard Worker if (thissme < bestsme) {
1049*fb1b10abSAndroid Build Coastguard Worker bestsme = thissme;
1050*fb1b10abSAndroid Build Coastguard Worker mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
1051*fb1b10abSAndroid Build Coastguard Worker } else {
1052*fb1b10abSAndroid Build Coastguard Worker d->bmi.mv.as_int = mode_mv[NEWMV].as_int;
1053*fb1b10abSAndroid Build Coastguard Worker }
1054*fb1b10abSAndroid Build Coastguard Worker }
1055*fb1b10abSAndroid Build Coastguard Worker }
1056*fb1b10abSAndroid Build Coastguard Worker }
1057*fb1b10abSAndroid Build Coastguard Worker
1058*fb1b10abSAndroid Build Coastguard Worker x->mv_col_min = tmp_col_min;
1059*fb1b10abSAndroid Build Coastguard Worker x->mv_col_max = tmp_col_max;
1060*fb1b10abSAndroid Build Coastguard Worker x->mv_row_min = tmp_row_min;
1061*fb1b10abSAndroid Build Coastguard Worker x->mv_row_max = tmp_row_max;
1062*fb1b10abSAndroid Build Coastguard Worker
1063*fb1b10abSAndroid Build Coastguard Worker if (bestsme < INT_MAX) {
1064*fb1b10abSAndroid Build Coastguard Worker cpi->find_fractional_mv_step(
1065*fb1b10abSAndroid Build Coastguard Worker x, b, d, &d->bmi.mv, &best_ref_mv, x->errorperbit,
1066*fb1b10abSAndroid Build Coastguard Worker &cpi->fn_ptr[BLOCK_16X16], cpi->mb.mvcost, &distortion2, &sse);
1067*fb1b10abSAndroid Build Coastguard Worker }
1068*fb1b10abSAndroid Build Coastguard Worker }
1069*fb1b10abSAndroid Build Coastguard Worker
1070*fb1b10abSAndroid Build Coastguard Worker mode_mv[NEWMV].as_int = d->bmi.mv.as_int;
1071*fb1b10abSAndroid Build Coastguard Worker // The clamp below is not necessary from the perspective
1072*fb1b10abSAndroid Build Coastguard Worker // of VP8 bitstream, but is added to improve ChromeCast
1073*fb1b10abSAndroid Build Coastguard Worker // mirroring's robustness. Please do not remove.
1074*fb1b10abSAndroid Build Coastguard Worker vp8_clamp_mv2(&mode_mv[this_mode], xd);
1075*fb1b10abSAndroid Build Coastguard Worker /* mv cost; */
1076*fb1b10abSAndroid Build Coastguard Worker rate2 +=
1077*fb1b10abSAndroid Build Coastguard Worker vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv, cpi->mb.mvcost, 128);
1078*fb1b10abSAndroid Build Coastguard Worker }
1079*fb1b10abSAndroid Build Coastguard Worker // fall through
1080*fb1b10abSAndroid Build Coastguard Worker
1081*fb1b10abSAndroid Build Coastguard Worker case NEARESTMV:
1082*fb1b10abSAndroid Build Coastguard Worker case NEARMV:
1083*fb1b10abSAndroid Build Coastguard Worker if (mode_mv[this_mode].as_int == 0) continue;
1084*fb1b10abSAndroid Build Coastguard Worker // fall through
1085*fb1b10abSAndroid Build Coastguard Worker
1086*fb1b10abSAndroid Build Coastguard Worker case ZEROMV:
1087*fb1b10abSAndroid Build Coastguard Worker
1088*fb1b10abSAndroid Build Coastguard Worker /* Trap vectors that reach beyond the UMV borders
1089*fb1b10abSAndroid Build Coastguard Worker * Note that ALL New MV, Nearest MV Near MV and Zero MV code drops
1090*fb1b10abSAndroid Build Coastguard Worker * through to this point because of the lack of break statements
1091*fb1b10abSAndroid Build Coastguard Worker * in the previous two cases.
1092*fb1b10abSAndroid Build Coastguard Worker */
1093*fb1b10abSAndroid Build Coastguard Worker if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) ||
1094*fb1b10abSAndroid Build Coastguard Worker ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) ||
1095*fb1b10abSAndroid Build Coastguard Worker ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) ||
1096*fb1b10abSAndroid Build Coastguard Worker ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) {
1097*fb1b10abSAndroid Build Coastguard Worker continue;
1098*fb1b10abSAndroid Build Coastguard Worker }
1099*fb1b10abSAndroid Build Coastguard Worker
1100*fb1b10abSAndroid Build Coastguard Worker rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
1101*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.mv.as_int = mode_mv[this_mode].as_int;
1102*fb1b10abSAndroid Build Coastguard Worker this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x,
1103*fb1b10abSAndroid Build Coastguard Worker rd_adjustment);
1104*fb1b10abSAndroid Build Coastguard Worker
1105*fb1b10abSAndroid Build Coastguard Worker break;
1106*fb1b10abSAndroid Build Coastguard Worker default: break;
1107*fb1b10abSAndroid Build Coastguard Worker }
1108*fb1b10abSAndroid Build Coastguard Worker
1109*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
1110*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.noise_sensitivity) {
1111*fb1b10abSAndroid Build Coastguard Worker /* Store for later use by denoiser. */
1112*fb1b10abSAndroid Build Coastguard Worker // Don't denoise with GOLDEN OR ALTREF is they are old reference
1113*fb1b10abSAndroid Build Coastguard Worker // frames (greater than MAX_GF_ARF_DENOISE_RANGE frames in past).
1114*fb1b10abSAndroid Build Coastguard Worker int skip_old_reference = ((this_ref_frame != LAST_FRAME) &&
1115*fb1b10abSAndroid Build Coastguard Worker (cpi->common.current_video_frame -
1116*fb1b10abSAndroid Build Coastguard Worker cpi->current_ref_frames[this_ref_frame] >
1117*fb1b10abSAndroid Build Coastguard Worker MAX_GF_ARF_DENOISE_RANGE))
1118*fb1b10abSAndroid Build Coastguard Worker ? 1
1119*fb1b10abSAndroid Build Coastguard Worker : 0;
1120*fb1b10abSAndroid Build Coastguard Worker if (this_mode == ZEROMV && sse < zero_mv_sse && !skip_old_reference) {
1121*fb1b10abSAndroid Build Coastguard Worker zero_mv_sse = sse;
1122*fb1b10abSAndroid Build Coastguard Worker x->best_zeromv_reference_frame =
1123*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame;
1124*fb1b10abSAndroid Build Coastguard Worker }
1125*fb1b10abSAndroid Build Coastguard Worker
1126*fb1b10abSAndroid Build Coastguard Worker // Store the best NEWMV in x for later use in the denoiser.
1127*fb1b10abSAndroid Build Coastguard Worker if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV && sse < best_sse &&
1128*fb1b10abSAndroid Build Coastguard Worker !skip_old_reference) {
1129*fb1b10abSAndroid Build Coastguard Worker best_sse = sse;
1130*fb1b10abSAndroid Build Coastguard Worker x->best_sse_inter_mode = NEWMV;
1131*fb1b10abSAndroid Build Coastguard Worker x->best_sse_mv = x->e_mbd.mode_info_context->mbmi.mv;
1132*fb1b10abSAndroid Build Coastguard Worker x->need_to_clamp_best_mvs =
1133*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.need_to_clamp_mvs;
1134*fb1b10abSAndroid Build Coastguard Worker x->best_reference_frame = x->e_mbd.mode_info_context->mbmi.ref_frame;
1135*fb1b10abSAndroid Build Coastguard Worker }
1136*fb1b10abSAndroid Build Coastguard Worker }
1137*fb1b10abSAndroid Build Coastguard Worker #endif
1138*fb1b10abSAndroid Build Coastguard Worker
1139*fb1b10abSAndroid Build Coastguard Worker if (this_rd < best_rd || x->skip) {
1140*fb1b10abSAndroid Build Coastguard Worker /* Note index of best mode */
1141*fb1b10abSAndroid Build Coastguard Worker best_mode_index = mode_index;
1142*fb1b10abSAndroid Build Coastguard Worker
1143*fb1b10abSAndroid Build Coastguard Worker *returnrate = rate2;
1144*fb1b10abSAndroid Build Coastguard Worker *returndistortion = distortion2;
1145*fb1b10abSAndroid Build Coastguard Worker best_rd_sse = sse;
1146*fb1b10abSAndroid Build Coastguard Worker best_rd = this_rd;
1147*fb1b10abSAndroid Build Coastguard Worker memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
1148*fb1b10abSAndroid Build Coastguard Worker sizeof(MB_MODE_INFO));
1149*fb1b10abSAndroid Build Coastguard Worker
1150*fb1b10abSAndroid Build Coastguard Worker /* Testing this mode gave rise to an improvement in best error
1151*fb1b10abSAndroid Build Coastguard Worker * score. Lower threshold a bit for next time
1152*fb1b10abSAndroid Build Coastguard Worker */
1153*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index] =
1154*fb1b10abSAndroid Build Coastguard Worker (x->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2))
1155*fb1b10abSAndroid Build Coastguard Worker ? x->rd_thresh_mult[mode_index] - 2
1156*fb1b10abSAndroid Build Coastguard Worker : MIN_THRESHMULT;
1157*fb1b10abSAndroid Build Coastguard Worker x->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) *
1158*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index];
1159*fb1b10abSAndroid Build Coastguard Worker }
1160*fb1b10abSAndroid Build Coastguard Worker
1161*fb1b10abSAndroid Build Coastguard Worker /* If the mode did not help improve the best error case then raise the
1162*fb1b10abSAndroid Build Coastguard Worker * threshold for testing that mode next time around.
1163*fb1b10abSAndroid Build Coastguard Worker */
1164*fb1b10abSAndroid Build Coastguard Worker else {
1165*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index] += 4;
1166*fb1b10abSAndroid Build Coastguard Worker
1167*fb1b10abSAndroid Build Coastguard Worker if (x->rd_thresh_mult[mode_index] > MAX_THRESHMULT) {
1168*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
1169*fb1b10abSAndroid Build Coastguard Worker }
1170*fb1b10abSAndroid Build Coastguard Worker
1171*fb1b10abSAndroid Build Coastguard Worker x->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) *
1172*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[mode_index];
1173*fb1b10abSAndroid Build Coastguard Worker }
1174*fb1b10abSAndroid Build Coastguard Worker
1175*fb1b10abSAndroid Build Coastguard Worker if (x->skip) break;
1176*fb1b10abSAndroid Build Coastguard Worker }
1177*fb1b10abSAndroid Build Coastguard Worker
1178*fb1b10abSAndroid Build Coastguard Worker /* Reduce the activation RD thresholds for the best choice mode */
1179*fb1b10abSAndroid Build Coastguard Worker if ((cpi->rd_baseline_thresh[best_mode_index] > 0) &&
1180*fb1b10abSAndroid Build Coastguard Worker (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2))) {
1181*fb1b10abSAndroid Build Coastguard Worker int best_adjustment = (x->rd_thresh_mult[best_mode_index] >> 3);
1182*fb1b10abSAndroid Build Coastguard Worker
1183*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[best_mode_index] =
1184*fb1b10abSAndroid Build Coastguard Worker (x->rd_thresh_mult[best_mode_index] >=
1185*fb1b10abSAndroid Build Coastguard Worker (MIN_THRESHMULT + best_adjustment))
1186*fb1b10abSAndroid Build Coastguard Worker ? x->rd_thresh_mult[best_mode_index] - best_adjustment
1187*fb1b10abSAndroid Build Coastguard Worker : MIN_THRESHMULT;
1188*fb1b10abSAndroid Build Coastguard Worker x->rd_threshes[best_mode_index] =
1189*fb1b10abSAndroid Build Coastguard Worker (cpi->rd_baseline_thresh[best_mode_index] >> 7) *
1190*fb1b10abSAndroid Build Coastguard Worker x->rd_thresh_mult[best_mode_index];
1191*fb1b10abSAndroid Build Coastguard Worker }
1192*fb1b10abSAndroid Build Coastguard Worker
1193*fb1b10abSAndroid Build Coastguard Worker {
1194*fb1b10abSAndroid Build Coastguard Worker int this_rdbin = (*returndistortion >> 7);
1195*fb1b10abSAndroid Build Coastguard Worker
1196*fb1b10abSAndroid Build Coastguard Worker if (this_rdbin >= 1024) {
1197*fb1b10abSAndroid Build Coastguard Worker this_rdbin = 1023;
1198*fb1b10abSAndroid Build Coastguard Worker }
1199*fb1b10abSAndroid Build Coastguard Worker
1200*fb1b10abSAndroid Build Coastguard Worker x->error_bins[this_rdbin]++;
1201*fb1b10abSAndroid Build Coastguard Worker }
1202*fb1b10abSAndroid Build Coastguard Worker
1203*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_TEMPORAL_DENOISING
1204*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.noise_sensitivity) {
1205*fb1b10abSAndroid Build Coastguard Worker int block_index = mb_row * cpi->common.mb_cols + mb_col;
1206*fb1b10abSAndroid Build Coastguard Worker int reevaluate = 0;
1207*fb1b10abSAndroid Build Coastguard Worker int is_noisy = 0;
1208*fb1b10abSAndroid Build Coastguard Worker if (x->best_sse_inter_mode == DC_PRED) {
1209*fb1b10abSAndroid Build Coastguard Worker /* No best MV found. */
1210*fb1b10abSAndroid Build Coastguard Worker x->best_sse_inter_mode = best_mbmode.mode;
1211*fb1b10abSAndroid Build Coastguard Worker x->best_sse_mv = best_mbmode.mv;
1212*fb1b10abSAndroid Build Coastguard Worker x->need_to_clamp_best_mvs = best_mbmode.need_to_clamp_mvs;
1213*fb1b10abSAndroid Build Coastguard Worker x->best_reference_frame = best_mbmode.ref_frame;
1214*fb1b10abSAndroid Build Coastguard Worker best_sse = best_rd_sse;
1215*fb1b10abSAndroid Build Coastguard Worker }
1216*fb1b10abSAndroid Build Coastguard Worker // For non-skin blocks that have selected ZEROMV for this current frame,
1217*fb1b10abSAndroid Build Coastguard Worker // and have been selecting ZEROMV_LAST (on the base layer frame) at
1218*fb1b10abSAndroid Build Coastguard Worker // least |x~20| consecutive past frames in a row, label the block for
1219*fb1b10abSAndroid Build Coastguard Worker // possible increase in denoising strength. We also condition this
1220*fb1b10abSAndroid Build Coastguard Worker // labeling on there being significant denoising in the scene
1221*fb1b10abSAndroid Build Coastguard Worker if (cpi->oxcf.noise_sensitivity == 4) {
1222*fb1b10abSAndroid Build Coastguard Worker if (cpi->denoiser.nmse_source_diff >
1223*fb1b10abSAndroid Build Coastguard Worker 70 * cpi->denoiser.threshold_aggressive_mode / 100) {
1224*fb1b10abSAndroid Build Coastguard Worker is_noisy = 1;
1225*fb1b10abSAndroid Build Coastguard Worker }
1226*fb1b10abSAndroid Build Coastguard Worker } else {
1227*fb1b10abSAndroid Build Coastguard Worker if (cpi->mse_source_denoised > 1000) is_noisy = 1;
1228*fb1b10abSAndroid Build Coastguard Worker }
1229*fb1b10abSAndroid Build Coastguard Worker x->increase_denoising = 0;
1230*fb1b10abSAndroid Build Coastguard Worker if (!x->is_skin && x->best_sse_inter_mode == ZEROMV &&
1231*fb1b10abSAndroid Build Coastguard Worker (x->best_reference_frame == LAST_FRAME ||
1232*fb1b10abSAndroid Build Coastguard Worker x->best_reference_frame == cpi->closest_reference_frame) &&
1233*fb1b10abSAndroid Build Coastguard Worker cpi->consec_zero_last[block_index] >= 20 && is_noisy) {
1234*fb1b10abSAndroid Build Coastguard Worker x->increase_denoising = 1;
1235*fb1b10abSAndroid Build Coastguard Worker }
1236*fb1b10abSAndroid Build Coastguard Worker x->denoise_zeromv = 0;
1237*fb1b10abSAndroid Build Coastguard Worker vp8_denoiser_denoise_mb(&cpi->denoiser, x, best_sse, zero_mv_sse,
1238*fb1b10abSAndroid Build Coastguard Worker recon_yoffset, recon_uvoffset, &cpi->common.lf_info,
1239*fb1b10abSAndroid Build Coastguard Worker mb_row, mb_col, block_index,
1240*fb1b10abSAndroid Build Coastguard Worker cpi->consec_zero_last_mvbias[block_index]);
1241*fb1b10abSAndroid Build Coastguard Worker
1242*fb1b10abSAndroid Build Coastguard Worker // Reevaluate ZEROMV after denoising: for large noise content
1243*fb1b10abSAndroid Build Coastguard Worker // (i.e., cpi->mse_source_denoised is above threshold), do this for all
1244*fb1b10abSAndroid Build Coastguard Worker // blocks that did not pick ZEROMV as best mode but are using ZEROMV
1245*fb1b10abSAndroid Build Coastguard Worker // for denoising. Otherwise, always re-evaluate for blocks that picked
1246*fb1b10abSAndroid Build Coastguard Worker // INTRA mode as best mode.
1247*fb1b10abSAndroid Build Coastguard Worker // Avoid blocks that have been biased against ZERO_LAST
1248*fb1b10abSAndroid Build Coastguard Worker // (i.e., dot artifact candidate blocks).
1249*fb1b10abSAndroid Build Coastguard Worker reevaluate = (best_mbmode.ref_frame == INTRA_FRAME) ||
1250*fb1b10abSAndroid Build Coastguard Worker (best_mbmode.mode != ZEROMV && x->denoise_zeromv &&
1251*fb1b10abSAndroid Build Coastguard Worker cpi->mse_source_denoised > 2000);
1252*fb1b10abSAndroid Build Coastguard Worker if (!dot_artifact_candidate && reevaluate &&
1253*fb1b10abSAndroid Build Coastguard Worker x->best_zeromv_reference_frame != INTRA_FRAME) {
1254*fb1b10abSAndroid Build Coastguard Worker int this_rd = 0;
1255*fb1b10abSAndroid Build Coastguard Worker int this_ref_frame = x->best_zeromv_reference_frame;
1256*fb1b10abSAndroid Build Coastguard Worker rd_adjustment = 100;
1257*fb1b10abSAndroid Build Coastguard Worker rate2 =
1258*fb1b10abSAndroid Build Coastguard Worker x->ref_frame_cost[this_ref_frame] + vp8_cost_mv_ref(ZEROMV, mdcounts);
1259*fb1b10abSAndroid Build Coastguard Worker distortion2 = 0;
1260*fb1b10abSAndroid Build Coastguard Worker
1261*fb1b10abSAndroid Build Coastguard Worker /* set up the proper prediction buffers for the frame */
1262*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame = this_ref_frame;
1263*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.pre.y_buffer = plane[this_ref_frame][0];
1264*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.pre.u_buffer = plane[this_ref_frame][1];
1265*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.pre.v_buffer = plane[this_ref_frame][2];
1266*fb1b10abSAndroid Build Coastguard Worker
1267*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
1268*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
1269*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
1270*fb1b10abSAndroid Build Coastguard Worker this_rd =
1271*fb1b10abSAndroid Build Coastguard Worker evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x, rd_adjustment);
1272*fb1b10abSAndroid Build Coastguard Worker
1273*fb1b10abSAndroid Build Coastguard Worker if (this_rd < best_rd) {
1274*fb1b10abSAndroid Build Coastguard Worker memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
1275*fb1b10abSAndroid Build Coastguard Worker sizeof(MB_MODE_INFO));
1276*fb1b10abSAndroid Build Coastguard Worker }
1277*fb1b10abSAndroid Build Coastguard Worker }
1278*fb1b10abSAndroid Build Coastguard Worker }
1279*fb1b10abSAndroid Build Coastguard Worker #endif
1280*fb1b10abSAndroid Build Coastguard Worker
1281*fb1b10abSAndroid Build Coastguard Worker if (cpi->is_src_frame_alt_ref &&
1282*fb1b10abSAndroid Build Coastguard Worker (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME)) {
1283*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
1284*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.ref_frame = ALTREF_FRAME;
1285*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
1286*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
1287*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.mb_skip_coeff =
1288*fb1b10abSAndroid Build Coastguard Worker (cpi->common.mb_no_coeff_skip);
1289*fb1b10abSAndroid Build Coastguard Worker x->e_mbd.mode_info_context->mbmi.partitioning = 0;
1290*fb1b10abSAndroid Build Coastguard Worker
1291*fb1b10abSAndroid Build Coastguard Worker return;
1292*fb1b10abSAndroid Build Coastguard Worker }
1293*fb1b10abSAndroid Build Coastguard Worker
1294*fb1b10abSAndroid Build Coastguard Worker /* set to the best mb mode, this copy can be skip if x->skip since it
1295*fb1b10abSAndroid Build Coastguard Worker * already has the right content */
1296*fb1b10abSAndroid Build Coastguard Worker if (!x->skip) {
1297*fb1b10abSAndroid Build Coastguard Worker memcpy(&x->e_mbd.mode_info_context->mbmi, &best_mbmode,
1298*fb1b10abSAndroid Build Coastguard Worker sizeof(MB_MODE_INFO));
1299*fb1b10abSAndroid Build Coastguard Worker }
1300*fb1b10abSAndroid Build Coastguard Worker
1301*fb1b10abSAndroid Build Coastguard Worker if (best_mbmode.mode <= B_PRED) {
1302*fb1b10abSAndroid Build Coastguard Worker /* set mode_info_context->mbmi.uv_mode */
1303*fb1b10abSAndroid Build Coastguard Worker pick_intra_mbuv_mode(x);
1304*fb1b10abSAndroid Build Coastguard Worker }
1305*fb1b10abSAndroid Build Coastguard Worker
1306*fb1b10abSAndroid Build Coastguard Worker if (sign_bias !=
1307*fb1b10abSAndroid Build Coastguard Worker cpi->common.ref_frame_sign_bias[xd->mode_info_context->mbmi.ref_frame]) {
1308*fb1b10abSAndroid Build Coastguard Worker best_ref_mv.as_int = best_ref_mv_sb[!sign_bias].as_int;
1309*fb1b10abSAndroid Build Coastguard Worker }
1310*fb1b10abSAndroid Build Coastguard Worker
1311*fb1b10abSAndroid Build Coastguard Worker update_mvcount(x, &best_ref_mv);
1312*fb1b10abSAndroid Build Coastguard Worker }
1313*fb1b10abSAndroid Build Coastguard Worker
vp8_pick_intra_mode(MACROBLOCK * x,int * rate)1314*fb1b10abSAndroid Build Coastguard Worker void vp8_pick_intra_mode(MACROBLOCK *x, int *rate) {
1315*fb1b10abSAndroid Build Coastguard Worker int error4x4, error16x16 = INT_MAX;
1316*fb1b10abSAndroid Build Coastguard Worker int rate_, best_rate = 0, distortion, best_sse;
1317*fb1b10abSAndroid Build Coastguard Worker MB_PREDICTION_MODE mode, best_mode = DC_PRED;
1318*fb1b10abSAndroid Build Coastguard Worker int this_rd;
1319*fb1b10abSAndroid Build Coastguard Worker unsigned int sse;
1320*fb1b10abSAndroid Build Coastguard Worker BLOCK *b = &x->block[0];
1321*fb1b10abSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
1322*fb1b10abSAndroid Build Coastguard Worker
1323*fb1b10abSAndroid Build Coastguard Worker xd->mode_info_context->mbmi.ref_frame = INTRA_FRAME;
1324*fb1b10abSAndroid Build Coastguard Worker
1325*fb1b10abSAndroid Build Coastguard Worker pick_intra_mbuv_mode(x);
1326*fb1b10abSAndroid Build Coastguard Worker
1327*fb1b10abSAndroid Build Coastguard Worker for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
1328*fb1b10abSAndroid Build Coastguard Worker xd->mode_info_context->mbmi.mode = mode;
1329*fb1b10abSAndroid Build Coastguard Worker vp8_build_intra_predictors_mby_s(xd, xd->dst.y_buffer - xd->dst.y_stride,
1330*fb1b10abSAndroid Build Coastguard Worker xd->dst.y_buffer - 1, xd->dst.y_stride,
1331*fb1b10abSAndroid Build Coastguard Worker xd->predictor, 16);
1332*fb1b10abSAndroid Build Coastguard Worker distortion = vpx_variance16x16(*(b->base_src), b->src_stride, xd->predictor,
1333*fb1b10abSAndroid Build Coastguard Worker 16, &sse);
1334*fb1b10abSAndroid Build Coastguard Worker rate_ = x->mbmode_cost[xd->frame_type][mode];
1335*fb1b10abSAndroid Build Coastguard Worker this_rd = RDCOST(x->rdmult, x->rddiv, rate_, distortion);
1336*fb1b10abSAndroid Build Coastguard Worker
1337*fb1b10abSAndroid Build Coastguard Worker if (error16x16 > this_rd) {
1338*fb1b10abSAndroid Build Coastguard Worker error16x16 = this_rd;
1339*fb1b10abSAndroid Build Coastguard Worker best_mode = mode;
1340*fb1b10abSAndroid Build Coastguard Worker best_sse = sse;
1341*fb1b10abSAndroid Build Coastguard Worker best_rate = rate_;
1342*fb1b10abSAndroid Build Coastguard Worker }
1343*fb1b10abSAndroid Build Coastguard Worker }
1344*fb1b10abSAndroid Build Coastguard Worker xd->mode_info_context->mbmi.mode = best_mode;
1345*fb1b10abSAndroid Build Coastguard Worker
1346*fb1b10abSAndroid Build Coastguard Worker error4x4 = pick_intra4x4mby_modes(x, &rate_, &best_sse);
1347*fb1b10abSAndroid Build Coastguard Worker if (error4x4 < error16x16) {
1348*fb1b10abSAndroid Build Coastguard Worker xd->mode_info_context->mbmi.mode = B_PRED;
1349*fb1b10abSAndroid Build Coastguard Worker best_rate = rate_;
1350*fb1b10abSAndroid Build Coastguard Worker }
1351*fb1b10abSAndroid Build Coastguard Worker
1352*fb1b10abSAndroid Build Coastguard Worker *rate = best_rate;
1353*fb1b10abSAndroid Build Coastguard Worker }
1354