xref: /aosp_15_r20/external/libvpx/vp8/encoder/pickinter.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
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