xref: /aosp_15_r20/external/libvpx/vp9/encoder/vp9_mcomp.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 <math.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
15*fb1b10abSAndroid Build Coastguard Worker 
16*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
18*fb1b10abSAndroid Build Coastguard Worker 
19*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
22*fb1b10abSAndroid Build Coastguard Worker 
23*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_common.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_mvref_common.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_reconinter.h"
26*fb1b10abSAndroid Build Coastguard Worker 
27*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
28*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_mcomp.h"
29*fb1b10abSAndroid Build Coastguard Worker 
30*fb1b10abSAndroid Build Coastguard Worker // #define NEW_DIAMOND_SEARCH
31*fb1b10abSAndroid Build Coastguard Worker 
vp9_set_mv_search_range(MvLimits * mv_limits,const MV * mv)32*fb1b10abSAndroid Build Coastguard Worker void vp9_set_mv_search_range(MvLimits *mv_limits, const MV *mv) {
33*fb1b10abSAndroid Build Coastguard Worker   int col_min = (mv->col >> 3) - MAX_FULL_PEL_VAL + (mv->col & 7 ? 1 : 0);
34*fb1b10abSAndroid Build Coastguard Worker   int row_min = (mv->row >> 3) - MAX_FULL_PEL_VAL + (mv->row & 7 ? 1 : 0);
35*fb1b10abSAndroid Build Coastguard Worker   int col_max = (mv->col >> 3) + MAX_FULL_PEL_VAL;
36*fb1b10abSAndroid Build Coastguard Worker   int row_max = (mv->row >> 3) + MAX_FULL_PEL_VAL;
37*fb1b10abSAndroid Build Coastguard Worker 
38*fb1b10abSAndroid Build Coastguard Worker   col_min = VPXMAX(col_min, (MV_LOW >> 3) + 1);
39*fb1b10abSAndroid Build Coastguard Worker   row_min = VPXMAX(row_min, (MV_LOW >> 3) + 1);
40*fb1b10abSAndroid Build Coastguard Worker   col_max = VPXMIN(col_max, (MV_UPP >> 3) - 1);
41*fb1b10abSAndroid Build Coastguard Worker   row_max = VPXMIN(row_max, (MV_UPP >> 3) - 1);
42*fb1b10abSAndroid Build Coastguard Worker 
43*fb1b10abSAndroid Build Coastguard Worker   // Get intersection of UMV window and valid MV window to reduce # of checks
44*fb1b10abSAndroid Build Coastguard Worker   // in diamond search.
45*fb1b10abSAndroid Build Coastguard Worker   if (mv_limits->col_min < col_min) mv_limits->col_min = col_min;
46*fb1b10abSAndroid Build Coastguard Worker   if (mv_limits->col_max > col_max) mv_limits->col_max = col_max;
47*fb1b10abSAndroid Build Coastguard Worker   if (mv_limits->row_min < row_min) mv_limits->row_min = row_min;
48*fb1b10abSAndroid Build Coastguard Worker   if (mv_limits->row_max > row_max) mv_limits->row_max = row_max;
49*fb1b10abSAndroid Build Coastguard Worker }
50*fb1b10abSAndroid Build Coastguard Worker 
vp9_set_subpel_mv_search_range(MvLimits * subpel_mv_limits,const MvLimits * umv_window_limits,const MV * ref_mv)51*fb1b10abSAndroid Build Coastguard Worker void vp9_set_subpel_mv_search_range(MvLimits *subpel_mv_limits,
52*fb1b10abSAndroid Build Coastguard Worker                                     const MvLimits *umv_window_limits,
53*fb1b10abSAndroid Build Coastguard Worker                                     const MV *ref_mv) {
54*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->col_min = VPXMAX(umv_window_limits->col_min * 8,
55*fb1b10abSAndroid Build Coastguard Worker                                      ref_mv->col - MAX_FULL_PEL_VAL * 8);
56*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->col_max = VPXMIN(umv_window_limits->col_max * 8,
57*fb1b10abSAndroid Build Coastguard Worker                                      ref_mv->col + MAX_FULL_PEL_VAL * 8);
58*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->row_min = VPXMAX(umv_window_limits->row_min * 8,
59*fb1b10abSAndroid Build Coastguard Worker                                      ref_mv->row - MAX_FULL_PEL_VAL * 8);
60*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->row_max = VPXMIN(umv_window_limits->row_max * 8,
61*fb1b10abSAndroid Build Coastguard Worker                                      ref_mv->row + MAX_FULL_PEL_VAL * 8);
62*fb1b10abSAndroid Build Coastguard Worker 
63*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->col_min = VPXMAX(MV_LOW + 1, subpel_mv_limits->col_min);
64*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->col_max = VPXMIN(MV_UPP - 1, subpel_mv_limits->col_max);
65*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->row_min = VPXMAX(MV_LOW + 1, subpel_mv_limits->row_min);
66*fb1b10abSAndroid Build Coastguard Worker   subpel_mv_limits->row_max = VPXMIN(MV_UPP - 1, subpel_mv_limits->row_max);
67*fb1b10abSAndroid Build Coastguard Worker }
68*fb1b10abSAndroid Build Coastguard Worker 
vp9_init_search_range(int size)69*fb1b10abSAndroid Build Coastguard Worker int vp9_init_search_range(int size) {
70*fb1b10abSAndroid Build Coastguard Worker   int sr = 0;
71*fb1b10abSAndroid Build Coastguard Worker   // Minimum search size no matter what the passed in value.
72*fb1b10abSAndroid Build Coastguard Worker   size = VPXMAX(16, size);
73*fb1b10abSAndroid Build Coastguard Worker 
74*fb1b10abSAndroid Build Coastguard Worker   while ((size << sr) < MAX_FULL_PEL_VAL) sr++;
75*fb1b10abSAndroid Build Coastguard Worker 
76*fb1b10abSAndroid Build Coastguard Worker   sr = VPXMIN(sr, MAX_MVSEARCH_STEPS - 2);
77*fb1b10abSAndroid Build Coastguard Worker   return sr;
78*fb1b10abSAndroid Build Coastguard Worker }
79*fb1b10abSAndroid Build Coastguard Worker 
vp9_mv_bit_cost(const MV * mv,const MV * ref,const int * mvjcost,int * mvcost[2],int weight)80*fb1b10abSAndroid Build Coastguard Worker int vp9_mv_bit_cost(const MV *mv, const MV *ref, const int *mvjcost,
81*fb1b10abSAndroid Build Coastguard Worker                     int *mvcost[2], int weight) {
82*fb1b10abSAndroid Build Coastguard Worker   const MV diff = { mv->row - ref->row, mv->col - ref->col };
83*fb1b10abSAndroid Build Coastguard Worker   return ROUND_POWER_OF_TWO(mv_cost(&diff, mvjcost, mvcost) * weight, 7);
84*fb1b10abSAndroid Build Coastguard Worker }
85*fb1b10abSAndroid Build Coastguard Worker 
86*fb1b10abSAndroid Build Coastguard Worker #define PIXEL_TRANSFORM_ERROR_SCALE 4
mv_err_cost(const MV * mv,const MV * ref,const int * mvjcost,int * mvcost[2],int error_per_bit)87*fb1b10abSAndroid Build Coastguard Worker static int mv_err_cost(const MV *mv, const MV *ref, const int *mvjcost,
88*fb1b10abSAndroid Build Coastguard Worker                        int *mvcost[2], int error_per_bit) {
89*fb1b10abSAndroid Build Coastguard Worker   if (mvcost) {
90*fb1b10abSAndroid Build Coastguard Worker     const MV diff = { mv->row - ref->row, mv->col - ref->col };
91*fb1b10abSAndroid Build Coastguard Worker     return (int)ROUND64_POWER_OF_TWO(
92*fb1b10abSAndroid Build Coastguard Worker         (int64_t)mv_cost(&diff, mvjcost, mvcost) * error_per_bit,
93*fb1b10abSAndroid Build Coastguard Worker         RDDIV_BITS + VP9_PROB_COST_SHIFT - RD_EPB_SHIFT +
94*fb1b10abSAndroid Build Coastguard Worker             PIXEL_TRANSFORM_ERROR_SCALE);
95*fb1b10abSAndroid Build Coastguard Worker   }
96*fb1b10abSAndroid Build Coastguard Worker   return 0;
97*fb1b10abSAndroid Build Coastguard Worker }
vp9_init_dsmotion_compensation(search_site_config * cfg,int stride)98*fb1b10abSAndroid Build Coastguard Worker void vp9_init_dsmotion_compensation(search_site_config *cfg, int stride) {
99*fb1b10abSAndroid Build Coastguard Worker   int len;
100*fb1b10abSAndroid Build Coastguard Worker   int ss_count = 0;
101*fb1b10abSAndroid Build Coastguard Worker 
102*fb1b10abSAndroid Build Coastguard Worker   for (len = MAX_FIRST_STEP; len > 0; len /= 2) {
103*fb1b10abSAndroid Build Coastguard Worker     // Generate offsets for 4 search sites per step.
104*fb1b10abSAndroid Build Coastguard Worker     const MV ss_mvs[] = { { -len, 0 }, { len, 0 }, { 0, -len }, { 0, len } };
105*fb1b10abSAndroid Build Coastguard Worker     int i;
106*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 4; ++i, ++ss_count) {
107*fb1b10abSAndroid Build Coastguard Worker       cfg->ss_mv[ss_count] = ss_mvs[i];
108*fb1b10abSAndroid Build Coastguard Worker       cfg->ss_os[ss_count] = ss_mvs[i].row * stride + ss_mvs[i].col;
109*fb1b10abSAndroid Build Coastguard Worker     }
110*fb1b10abSAndroid Build Coastguard Worker   }
111*fb1b10abSAndroid Build Coastguard Worker 
112*fb1b10abSAndroid Build Coastguard Worker   cfg->searches_per_step = 4;
113*fb1b10abSAndroid Build Coastguard Worker   cfg->total_steps = ss_count / cfg->searches_per_step;
114*fb1b10abSAndroid Build Coastguard Worker }
115*fb1b10abSAndroid Build Coastguard Worker 
vp9_init3smotion_compensation(search_site_config * cfg,int stride)116*fb1b10abSAndroid Build Coastguard Worker void vp9_init3smotion_compensation(search_site_config *cfg, int stride) {
117*fb1b10abSAndroid Build Coastguard Worker   int len;
118*fb1b10abSAndroid Build Coastguard Worker   int ss_count = 0;
119*fb1b10abSAndroid Build Coastguard Worker 
120*fb1b10abSAndroid Build Coastguard Worker   for (len = MAX_FIRST_STEP; len > 0; len /= 2) {
121*fb1b10abSAndroid Build Coastguard Worker     // Generate offsets for 8 search sites per step.
122*fb1b10abSAndroid Build Coastguard Worker     const MV ss_mvs[8] = { { -len, 0 },   { len, 0 },     { 0, -len },
123*fb1b10abSAndroid Build Coastguard Worker                            { 0, len },    { -len, -len }, { -len, len },
124*fb1b10abSAndroid Build Coastguard Worker                            { len, -len }, { len, len } };
125*fb1b10abSAndroid Build Coastguard Worker     int i;
126*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 8; ++i, ++ss_count) {
127*fb1b10abSAndroid Build Coastguard Worker       cfg->ss_mv[ss_count] = ss_mvs[i];
128*fb1b10abSAndroid Build Coastguard Worker       cfg->ss_os[ss_count] = ss_mvs[i].row * stride + ss_mvs[i].col;
129*fb1b10abSAndroid Build Coastguard Worker     }
130*fb1b10abSAndroid Build Coastguard Worker   }
131*fb1b10abSAndroid Build Coastguard Worker 
132*fb1b10abSAndroid Build Coastguard Worker   cfg->searches_per_step = 8;
133*fb1b10abSAndroid Build Coastguard Worker   cfg->total_steps = ss_count / cfg->searches_per_step;
134*fb1b10abSAndroid Build Coastguard Worker }
135*fb1b10abSAndroid Build Coastguard Worker 
136*fb1b10abSAndroid Build Coastguard Worker // convert motion vector component to offset for sv[a]f calc
sp(int x)137*fb1b10abSAndroid Build Coastguard Worker static INLINE int sp(int x) { return x & 7; }
138*fb1b10abSAndroid Build Coastguard Worker 
pre(const uint8_t * buf,int stride,int r,int c)139*fb1b10abSAndroid Build Coastguard Worker static INLINE const uint8_t *pre(const uint8_t *buf, int stride, int r, int c) {
140*fb1b10abSAndroid Build Coastguard Worker   return &buf[(r >> 3) * stride + (c >> 3)];
141*fb1b10abSAndroid Build Coastguard Worker }
142*fb1b10abSAndroid Build Coastguard Worker 
143*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
144*fb1b10abSAndroid Build Coastguard Worker /* checks if (r, c) has better score than previous best */
145*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BETTER(v, r, c)                                                  \
146*fb1b10abSAndroid Build Coastguard Worker   do {                                                                         \
147*fb1b10abSAndroid Build Coastguard Worker     if (c >= minc && c <= maxc && r >= minr && r <= maxr) {                    \
148*fb1b10abSAndroid Build Coastguard Worker       int64_t tmpmse;                                                          \
149*fb1b10abSAndroid Build Coastguard Worker       const MV cb_mv = { r, c };                                               \
150*fb1b10abSAndroid Build Coastguard Worker       const MV cb_ref_mv = { rr, rc };                                         \
151*fb1b10abSAndroid Build Coastguard Worker       if (second_pred == NULL) {                                               \
152*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z,  \
153*fb1b10abSAndroid Build Coastguard Worker                            src_stride, &sse);                                  \
154*fb1b10abSAndroid Build Coastguard Worker       } else {                                                                 \
155*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svaf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
156*fb1b10abSAndroid Build Coastguard Worker                             src_stride, &sse, second_pred);                    \
157*fb1b10abSAndroid Build Coastguard Worker       }                                                                        \
158*fb1b10abSAndroid Build Coastguard Worker       tmpmse = thismse;                                                        \
159*fb1b10abSAndroid Build Coastguard Worker       tmpmse +=                                                                \
160*fb1b10abSAndroid Build Coastguard Worker           mv_err_cost(&cb_mv, &cb_ref_mv, mvjcost, mvcost, error_per_bit);     \
161*fb1b10abSAndroid Build Coastguard Worker       if (tmpmse >= INT_MAX) {                                                 \
162*fb1b10abSAndroid Build Coastguard Worker         v = INT_MAX;                                                           \
163*fb1b10abSAndroid Build Coastguard Worker       } else if ((v = (uint32_t)tmpmse) < besterr) {                           \
164*fb1b10abSAndroid Build Coastguard Worker         besterr = v;                                                           \
165*fb1b10abSAndroid Build Coastguard Worker         br = r;                                                                \
166*fb1b10abSAndroid Build Coastguard Worker         bc = c;                                                                \
167*fb1b10abSAndroid Build Coastguard Worker         *distortion = thismse;                                                 \
168*fb1b10abSAndroid Build Coastguard Worker         *sse1 = sse;                                                           \
169*fb1b10abSAndroid Build Coastguard Worker       }                                                                        \
170*fb1b10abSAndroid Build Coastguard Worker     } else {                                                                   \
171*fb1b10abSAndroid Build Coastguard Worker       v = INT_MAX;                                                             \
172*fb1b10abSAndroid Build Coastguard Worker     }                                                                          \
173*fb1b10abSAndroid Build Coastguard Worker   } while (0)
174*fb1b10abSAndroid Build Coastguard Worker #else
175*fb1b10abSAndroid Build Coastguard Worker /* checks if (r, c) has better score than previous best */
176*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BETTER(v, r, c)                                                  \
177*fb1b10abSAndroid Build Coastguard Worker   do {                                                                         \
178*fb1b10abSAndroid Build Coastguard Worker     if (c >= minc && c <= maxc && r >= minr && r <= maxr) {                    \
179*fb1b10abSAndroid Build Coastguard Worker       const MV cb_mv = { r, c };                                               \
180*fb1b10abSAndroid Build Coastguard Worker       const MV cb_ref_mv = { rr, rc };                                         \
181*fb1b10abSAndroid Build Coastguard Worker       if (second_pred == NULL)                                                 \
182*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z,  \
183*fb1b10abSAndroid Build Coastguard Worker                            src_stride, &sse);                                  \
184*fb1b10abSAndroid Build Coastguard Worker       else                                                                     \
185*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svaf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
186*fb1b10abSAndroid Build Coastguard Worker                             src_stride, &sse, second_pred);                    \
187*fb1b10abSAndroid Build Coastguard Worker       if ((v = mv_err_cost(&cb_mv, &cb_ref_mv, mvjcost, mvcost,                \
188*fb1b10abSAndroid Build Coastguard Worker                            error_per_bit) +                                    \
189*fb1b10abSAndroid Build Coastguard Worker                thismse) < besterr) {                                           \
190*fb1b10abSAndroid Build Coastguard Worker         besterr = v;                                                           \
191*fb1b10abSAndroid Build Coastguard Worker         br = r;                                                                \
192*fb1b10abSAndroid Build Coastguard Worker         bc = c;                                                                \
193*fb1b10abSAndroid Build Coastguard Worker         *distortion = thismse;                                                 \
194*fb1b10abSAndroid Build Coastguard Worker         *sse1 = sse;                                                           \
195*fb1b10abSAndroid Build Coastguard Worker       }                                                                        \
196*fb1b10abSAndroid Build Coastguard Worker     } else {                                                                   \
197*fb1b10abSAndroid Build Coastguard Worker       v = INT_MAX;                                                             \
198*fb1b10abSAndroid Build Coastguard Worker     }                                                                          \
199*fb1b10abSAndroid Build Coastguard Worker   } while (0)
200*fb1b10abSAndroid Build Coastguard Worker 
201*fb1b10abSAndroid Build Coastguard Worker #endif
202*fb1b10abSAndroid Build Coastguard Worker #define FIRST_LEVEL_CHECKS                                       \
203*fb1b10abSAndroid Build Coastguard Worker   do {                                                           \
204*fb1b10abSAndroid Build Coastguard Worker     unsigned int left, right, up, down, diag;                    \
205*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(left, tr, tc - hstep);                          \
206*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(right, tr, tc + hstep);                         \
207*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(up, tr - hstep, tc);                            \
208*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(down, tr + hstep, tc);                          \
209*fb1b10abSAndroid Build Coastguard Worker     whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);     \
210*fb1b10abSAndroid Build Coastguard Worker     switch (whichdir) {                                          \
211*fb1b10abSAndroid Build Coastguard Worker       case 0: CHECK_BETTER(diag, tr - hstep, tc - hstep); break; \
212*fb1b10abSAndroid Build Coastguard Worker       case 1: CHECK_BETTER(diag, tr - hstep, tc + hstep); break; \
213*fb1b10abSAndroid Build Coastguard Worker       case 2: CHECK_BETTER(diag, tr + hstep, tc - hstep); break; \
214*fb1b10abSAndroid Build Coastguard Worker       case 3: CHECK_BETTER(diag, tr + hstep, tc + hstep); break; \
215*fb1b10abSAndroid Build Coastguard Worker     }                                                            \
216*fb1b10abSAndroid Build Coastguard Worker   } while (0)
217*fb1b10abSAndroid Build Coastguard Worker 
218*fb1b10abSAndroid Build Coastguard Worker #define SECOND_LEVEL_CHECKS                                       \
219*fb1b10abSAndroid Build Coastguard Worker   do {                                                            \
220*fb1b10abSAndroid Build Coastguard Worker     int kr, kc;                                                   \
221*fb1b10abSAndroid Build Coastguard Worker     unsigned int second;                                          \
222*fb1b10abSAndroid Build Coastguard Worker     if (tr != br && tc != bc) {                                   \
223*fb1b10abSAndroid Build Coastguard Worker       kr = br - tr;                                               \
224*fb1b10abSAndroid Build Coastguard Worker       kc = bc - tc;                                               \
225*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(second, tr + kr, tc + 2 * kc);                 \
226*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(second, tr + 2 * kr, tc + kc);                 \
227*fb1b10abSAndroid Build Coastguard Worker     } else if (tr == br && tc != bc) {                            \
228*fb1b10abSAndroid Build Coastguard Worker       kc = bc - tc;                                               \
229*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(second, tr + hstep, tc + 2 * kc);              \
230*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(second, tr - hstep, tc + 2 * kc);              \
231*fb1b10abSAndroid Build Coastguard Worker       switch (whichdir) {                                         \
232*fb1b10abSAndroid Build Coastguard Worker         case 0:                                                   \
233*fb1b10abSAndroid Build Coastguard Worker         case 1: CHECK_BETTER(second, tr + hstep, tc + kc); break; \
234*fb1b10abSAndroid Build Coastguard Worker         case 2:                                                   \
235*fb1b10abSAndroid Build Coastguard Worker         case 3: CHECK_BETTER(second, tr - hstep, tc + kc); break; \
236*fb1b10abSAndroid Build Coastguard Worker       }                                                           \
237*fb1b10abSAndroid Build Coastguard Worker     } else if (tr != br && tc == bc) {                            \
238*fb1b10abSAndroid Build Coastguard Worker       kr = br - tr;                                               \
239*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(second, tr + 2 * kr, tc + hstep);              \
240*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(second, tr + 2 * kr, tc - hstep);              \
241*fb1b10abSAndroid Build Coastguard Worker       switch (whichdir) {                                         \
242*fb1b10abSAndroid Build Coastguard Worker         case 0:                                                   \
243*fb1b10abSAndroid Build Coastguard Worker         case 2: CHECK_BETTER(second, tr + kr, tc + hstep); break; \
244*fb1b10abSAndroid Build Coastguard Worker         case 1:                                                   \
245*fb1b10abSAndroid Build Coastguard Worker         case 3: CHECK_BETTER(second, tr + kr, tc - hstep); break; \
246*fb1b10abSAndroid Build Coastguard Worker       }                                                           \
247*fb1b10abSAndroid Build Coastguard Worker     }                                                             \
248*fb1b10abSAndroid Build Coastguard Worker   } while (0)
249*fb1b10abSAndroid Build Coastguard Worker 
250*fb1b10abSAndroid Build Coastguard Worker #define SETUP_SUBPEL_SEARCH                                                 \
251*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *const z = x->plane[0].src.buf;                             \
252*fb1b10abSAndroid Build Coastguard Worker   const int src_stride = x->plane[0].src.stride;                            \
253*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *xd = &x->e_mbd;                                        \
254*fb1b10abSAndroid Build Coastguard Worker   unsigned int besterr = UINT_MAX;                                          \
255*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;                                                         \
256*fb1b10abSAndroid Build Coastguard Worker   unsigned int whichdir;                                                    \
257*fb1b10abSAndroid Build Coastguard Worker   int thismse;                                                              \
258*fb1b10abSAndroid Build Coastguard Worker   const unsigned int halfiters = iters_per_step;                            \
259*fb1b10abSAndroid Build Coastguard Worker   const unsigned int quarteriters = iters_per_step;                         \
260*fb1b10abSAndroid Build Coastguard Worker   const unsigned int eighthiters = iters_per_step;                          \
261*fb1b10abSAndroid Build Coastguard Worker   const int y_stride = xd->plane[0].pre[0].stride;                          \
262*fb1b10abSAndroid Build Coastguard Worker   const int offset = bestmv->row * y_stride + bestmv->col;                  \
263*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *const y = xd->plane[0].pre[0].buf;                         \
264*fb1b10abSAndroid Build Coastguard Worker                                                                             \
265*fb1b10abSAndroid Build Coastguard Worker   int rr = ref_mv->row;                                                     \
266*fb1b10abSAndroid Build Coastguard Worker   int rc = ref_mv->col;                                                     \
267*fb1b10abSAndroid Build Coastguard Worker   int br = bestmv->row * 8;                                                 \
268*fb1b10abSAndroid Build Coastguard Worker   int bc = bestmv->col * 8;                                                 \
269*fb1b10abSAndroid Build Coastguard Worker   int hstep = 4;                                                            \
270*fb1b10abSAndroid Build Coastguard Worker   int minc, maxc, minr, maxr;                                               \
271*fb1b10abSAndroid Build Coastguard Worker   int tr = br;                                                              \
272*fb1b10abSAndroid Build Coastguard Worker   int tc = bc;                                                              \
273*fb1b10abSAndroid Build Coastguard Worker   MvLimits subpel_mv_limits;                                                \
274*fb1b10abSAndroid Build Coastguard Worker                                                                             \
275*fb1b10abSAndroid Build Coastguard Worker   vp9_set_subpel_mv_search_range(&subpel_mv_limits, &x->mv_limits, ref_mv); \
276*fb1b10abSAndroid Build Coastguard Worker   minc = subpel_mv_limits.col_min;                                          \
277*fb1b10abSAndroid Build Coastguard Worker   maxc = subpel_mv_limits.col_max;                                          \
278*fb1b10abSAndroid Build Coastguard Worker   minr = subpel_mv_limits.row_min;                                          \
279*fb1b10abSAndroid Build Coastguard Worker   maxr = subpel_mv_limits.row_max;                                          \
280*fb1b10abSAndroid Build Coastguard Worker                                                                             \
281*fb1b10abSAndroid Build Coastguard Worker   bestmv->row *= 8;                                                         \
282*fb1b10abSAndroid Build Coastguard Worker   bestmv->col *= 8
283*fb1b10abSAndroid Build Coastguard Worker 
setup_center_error(const MACROBLOCKD * xd,const MV * bestmv,const MV * ref_mv,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,const uint8_t * const src,const int src_stride,const uint8_t * const y,int y_stride,const uint8_t * second_pred,int w,int h,int offset,int * mvjcost,int * mvcost[2],uint32_t * sse1,uint32_t * distortion)284*fb1b10abSAndroid Build Coastguard Worker static unsigned int setup_center_error(
285*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCKD *xd, const MV *bestmv, const MV *ref_mv,
286*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp,
287*fb1b10abSAndroid Build Coastguard Worker     const uint8_t *const src, const int src_stride, const uint8_t *const y,
288*fb1b10abSAndroid Build Coastguard Worker     int y_stride, const uint8_t *second_pred, int w, int h, int offset,
289*fb1b10abSAndroid Build Coastguard Worker     int *mvjcost, int *mvcost[2], uint32_t *sse1, uint32_t *distortion) {
290*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
291*fb1b10abSAndroid Build Coastguard Worker   uint64_t besterr;
292*fb1b10abSAndroid Build Coastguard Worker   if (second_pred != NULL) {
293*fb1b10abSAndroid Build Coastguard Worker     if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
294*fb1b10abSAndroid Build Coastguard Worker       DECLARE_ALIGNED(16, uint16_t, comp_pred16[64 * 64]);
295*fb1b10abSAndroid Build Coastguard Worker       vpx_highbd_comp_avg_pred(comp_pred16, CONVERT_TO_SHORTPTR(second_pred), w,
296*fb1b10abSAndroid Build Coastguard Worker                                h, CONVERT_TO_SHORTPTR(y + offset), y_stride);
297*fb1b10abSAndroid Build Coastguard Worker       besterr =
298*fb1b10abSAndroid Build Coastguard Worker           vfp->vf(CONVERT_TO_BYTEPTR(comp_pred16), w, src, src_stride, sse1);
299*fb1b10abSAndroid Build Coastguard Worker     } else {
300*fb1b10abSAndroid Build Coastguard Worker       DECLARE_ALIGNED(32, uint8_t, comp_pred[64 * 64]);
301*fb1b10abSAndroid Build Coastguard Worker       vpx_comp_avg_pred(comp_pred, second_pred, w, h, y + offset, y_stride);
302*fb1b10abSAndroid Build Coastguard Worker       besterr = vfp->vf(comp_pred, w, src, src_stride, sse1);
303*fb1b10abSAndroid Build Coastguard Worker     }
304*fb1b10abSAndroid Build Coastguard Worker   } else {
305*fb1b10abSAndroid Build Coastguard Worker     besterr = vfp->vf(y + offset, y_stride, src, src_stride, sse1);
306*fb1b10abSAndroid Build Coastguard Worker   }
307*fb1b10abSAndroid Build Coastguard Worker   *distortion = (uint32_t)besterr;
308*fb1b10abSAndroid Build Coastguard Worker   besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
309*fb1b10abSAndroid Build Coastguard Worker   if (besterr >= UINT_MAX) return UINT_MAX;
310*fb1b10abSAndroid Build Coastguard Worker   return (uint32_t)besterr;
311*fb1b10abSAndroid Build Coastguard Worker #else
312*fb1b10abSAndroid Build Coastguard Worker   uint32_t besterr;
313*fb1b10abSAndroid Build Coastguard Worker   (void)xd;
314*fb1b10abSAndroid Build Coastguard Worker   if (second_pred != NULL) {
315*fb1b10abSAndroid Build Coastguard Worker     DECLARE_ALIGNED(32, uint8_t, comp_pred[64 * 64]);
316*fb1b10abSAndroid Build Coastguard Worker     vpx_comp_avg_pred(comp_pred, second_pred, w, h, y + offset, y_stride);
317*fb1b10abSAndroid Build Coastguard Worker     besterr = vfp->vf(comp_pred, w, src, src_stride, sse1);
318*fb1b10abSAndroid Build Coastguard Worker   } else {
319*fb1b10abSAndroid Build Coastguard Worker     besterr = vfp->vf(y + offset, y_stride, src, src_stride, sse1);
320*fb1b10abSAndroid Build Coastguard Worker   }
321*fb1b10abSAndroid Build Coastguard Worker   *distortion = besterr;
322*fb1b10abSAndroid Build Coastguard Worker   besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
323*fb1b10abSAndroid Build Coastguard Worker   return besterr;
324*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
325*fb1b10abSAndroid Build Coastguard Worker }
326*fb1b10abSAndroid Build Coastguard Worker 
divide_and_round(const int64_t n,const int64_t d)327*fb1b10abSAndroid Build Coastguard Worker static INLINE int64_t divide_and_round(const int64_t n, const int64_t d) {
328*fb1b10abSAndroid Build Coastguard Worker   return ((n < 0) ^ (d < 0)) ? ((n - d / 2) / d) : ((n + d / 2) / d);
329*fb1b10abSAndroid Build Coastguard Worker }
330*fb1b10abSAndroid Build Coastguard Worker 
is_cost_list_wellbehaved(int * cost_list)331*fb1b10abSAndroid Build Coastguard Worker static INLINE int is_cost_list_wellbehaved(int *cost_list) {
332*fb1b10abSAndroid Build Coastguard Worker   return cost_list[0] < cost_list[1] && cost_list[0] < cost_list[2] &&
333*fb1b10abSAndroid Build Coastguard Worker          cost_list[0] < cost_list[3] && cost_list[0] < cost_list[4];
334*fb1b10abSAndroid Build Coastguard Worker }
335*fb1b10abSAndroid Build Coastguard Worker 
336*fb1b10abSAndroid Build Coastguard Worker // Returns surface minima estimate at given precision in 1/2^n bits.
337*fb1b10abSAndroid Build Coastguard Worker // Assume a model for the cost surface: S = A(x - x0)^2 + B(y - y0)^2 + C
338*fb1b10abSAndroid Build Coastguard Worker // For a given set of costs S0, S1, S2, S3, S4 at points
339*fb1b10abSAndroid Build Coastguard Worker // (y, x) = (0, 0), (0, -1), (1, 0), (0, 1) and (-1, 0) respectively,
340*fb1b10abSAndroid Build Coastguard Worker // the solution for the location of the minima (x0, y0) is given by:
341*fb1b10abSAndroid Build Coastguard Worker // x0 = 1/2 (S1 - S3)/(S1 + S3 - 2*S0),
342*fb1b10abSAndroid Build Coastguard Worker // y0 = 1/2 (S4 - S2)/(S4 + S2 - 2*S0).
343*fb1b10abSAndroid Build Coastguard Worker // The code below is an integerized version of that.
get_cost_surf_min(int * cost_list,int * ir,int * ic,int bits)344*fb1b10abSAndroid Build Coastguard Worker static void get_cost_surf_min(int *cost_list, int *ir, int *ic, int bits) {
345*fb1b10abSAndroid Build Coastguard Worker   const int64_t x0 = (int64_t)cost_list[1] - cost_list[3];
346*fb1b10abSAndroid Build Coastguard Worker   const int64_t y0 = cost_list[1] - 2 * (int64_t)cost_list[0] + cost_list[3];
347*fb1b10abSAndroid Build Coastguard Worker   const int64_t x1 = (int64_t)cost_list[4] - cost_list[2];
348*fb1b10abSAndroid Build Coastguard Worker   const int64_t y1 = cost_list[4] - 2 * (int64_t)cost_list[0] + cost_list[2];
349*fb1b10abSAndroid Build Coastguard Worker   const int b = 1 << (bits - 1);
350*fb1b10abSAndroid Build Coastguard Worker   *ic = (int)divide_and_round(x0 * b, y0);
351*fb1b10abSAndroid Build Coastguard Worker   *ir = (int)divide_and_round(x1 * b, y1);
352*fb1b10abSAndroid Build Coastguard Worker }
353*fb1b10abSAndroid Build Coastguard Worker 
vp9_skip_sub_pixel_tree(const MACROBLOCK * x,MV * bestmv,const MV * ref_mv,int allow_hp,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,int forced_stop,int iters_per_step,int * cost_list,int * mvjcost,int * mvcost[2],uint32_t * distortion,uint32_t * sse1,const uint8_t * second_pred,int w,int h,int use_accurate_subpel_search)354*fb1b10abSAndroid Build Coastguard Worker uint32_t vp9_skip_sub_pixel_tree(
355*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
356*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
357*fb1b10abSAndroid Build Coastguard Worker     int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
358*fb1b10abSAndroid Build Coastguard Worker     uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
359*fb1b10abSAndroid Build Coastguard Worker     int h, int use_accurate_subpel_search) {
360*fb1b10abSAndroid Build Coastguard Worker   SETUP_SUBPEL_SEARCH;
361*fb1b10abSAndroid Build Coastguard Worker   besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp, z,
362*fb1b10abSAndroid Build Coastguard Worker                                src_stride, y, y_stride, second_pred, w, h,
363*fb1b10abSAndroid Build Coastguard Worker                                offset, mvjcost, mvcost, sse1, distortion);
364*fb1b10abSAndroid Build Coastguard Worker   (void)halfiters;
365*fb1b10abSAndroid Build Coastguard Worker   (void)quarteriters;
366*fb1b10abSAndroid Build Coastguard Worker   (void)eighthiters;
367*fb1b10abSAndroid Build Coastguard Worker   (void)whichdir;
368*fb1b10abSAndroid Build Coastguard Worker   (void)allow_hp;
369*fb1b10abSAndroid Build Coastguard Worker   (void)forced_stop;
370*fb1b10abSAndroid Build Coastguard Worker   (void)hstep;
371*fb1b10abSAndroid Build Coastguard Worker   (void)rr;
372*fb1b10abSAndroid Build Coastguard Worker   (void)rc;
373*fb1b10abSAndroid Build Coastguard Worker   (void)minr;
374*fb1b10abSAndroid Build Coastguard Worker   (void)minc;
375*fb1b10abSAndroid Build Coastguard Worker   (void)maxr;
376*fb1b10abSAndroid Build Coastguard Worker   (void)maxc;
377*fb1b10abSAndroid Build Coastguard Worker   (void)tr;
378*fb1b10abSAndroid Build Coastguard Worker   (void)tc;
379*fb1b10abSAndroid Build Coastguard Worker   (void)sse;
380*fb1b10abSAndroid Build Coastguard Worker   (void)thismse;
381*fb1b10abSAndroid Build Coastguard Worker   (void)cost_list;
382*fb1b10abSAndroid Build Coastguard Worker   (void)use_accurate_subpel_search;
383*fb1b10abSAndroid Build Coastguard Worker 
384*fb1b10abSAndroid Build Coastguard Worker   return besterr;
385*fb1b10abSAndroid Build Coastguard Worker }
386*fb1b10abSAndroid Build Coastguard Worker 
vp9_find_best_sub_pixel_tree_pruned_evenmore(const MACROBLOCK * x,MV * bestmv,const MV * ref_mv,int allow_hp,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,int forced_stop,int iters_per_step,int * cost_list,int * mvjcost,int * mvcost[2],uint32_t * distortion,uint32_t * sse1,const uint8_t * second_pred,int w,int h,int use_accurate_subpel_search)387*fb1b10abSAndroid Build Coastguard Worker uint32_t vp9_find_best_sub_pixel_tree_pruned_evenmore(
388*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
389*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
390*fb1b10abSAndroid Build Coastguard Worker     int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
391*fb1b10abSAndroid Build Coastguard Worker     uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
392*fb1b10abSAndroid Build Coastguard Worker     int h, int use_accurate_subpel_search) {
393*fb1b10abSAndroid Build Coastguard Worker   SETUP_SUBPEL_SEARCH;
394*fb1b10abSAndroid Build Coastguard Worker   besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp, z,
395*fb1b10abSAndroid Build Coastguard Worker                                src_stride, y, y_stride, second_pred, w, h,
396*fb1b10abSAndroid Build Coastguard Worker                                offset, mvjcost, mvcost, sse1, distortion);
397*fb1b10abSAndroid Build Coastguard Worker   (void)halfiters;
398*fb1b10abSAndroid Build Coastguard Worker   (void)quarteriters;
399*fb1b10abSAndroid Build Coastguard Worker   (void)eighthiters;
400*fb1b10abSAndroid Build Coastguard Worker   (void)whichdir;
401*fb1b10abSAndroid Build Coastguard Worker   (void)allow_hp;
402*fb1b10abSAndroid Build Coastguard Worker   (void)forced_stop;
403*fb1b10abSAndroid Build Coastguard Worker   (void)hstep;
404*fb1b10abSAndroid Build Coastguard Worker   (void)use_accurate_subpel_search;
405*fb1b10abSAndroid Build Coastguard Worker 
406*fb1b10abSAndroid Build Coastguard Worker   if (cost_list && cost_list[0] != INT_MAX && cost_list[1] != INT_MAX &&
407*fb1b10abSAndroid Build Coastguard Worker       cost_list[2] != INT_MAX && cost_list[3] != INT_MAX &&
408*fb1b10abSAndroid Build Coastguard Worker       cost_list[4] != INT_MAX && is_cost_list_wellbehaved(cost_list)) {
409*fb1b10abSAndroid Build Coastguard Worker     int ir, ic;
410*fb1b10abSAndroid Build Coastguard Worker     unsigned int minpt = INT_MAX;
411*fb1b10abSAndroid Build Coastguard Worker     get_cost_surf_min(cost_list, &ir, &ic, 2);
412*fb1b10abSAndroid Build Coastguard Worker     if (ir != 0 || ic != 0) {
413*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(minpt, tr + 2 * ir, tc + 2 * ic);
414*fb1b10abSAndroid Build Coastguard Worker     }
415*fb1b10abSAndroid Build Coastguard Worker   } else {
416*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
417*fb1b10abSAndroid Build Coastguard Worker     if (halfiters > 1) {
418*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
419*fb1b10abSAndroid Build Coastguard Worker     }
420*fb1b10abSAndroid Build Coastguard Worker 
421*fb1b10abSAndroid Build Coastguard Worker     tr = br;
422*fb1b10abSAndroid Build Coastguard Worker     tc = bc;
423*fb1b10abSAndroid Build Coastguard Worker 
424*fb1b10abSAndroid Build Coastguard Worker     // Each subsequent iteration checks at least one point in common with
425*fb1b10abSAndroid Build Coastguard Worker     // the last iteration could be 2 ( if diag selected) 1/4 pel
426*fb1b10abSAndroid Build Coastguard Worker     // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
427*fb1b10abSAndroid Build Coastguard Worker     if (forced_stop != 2) {
428*fb1b10abSAndroid Build Coastguard Worker       hstep >>= 1;
429*fb1b10abSAndroid Build Coastguard Worker       FIRST_LEVEL_CHECKS;
430*fb1b10abSAndroid Build Coastguard Worker       if (quarteriters > 1) {
431*fb1b10abSAndroid Build Coastguard Worker         SECOND_LEVEL_CHECKS;
432*fb1b10abSAndroid Build Coastguard Worker       }
433*fb1b10abSAndroid Build Coastguard Worker     }
434*fb1b10abSAndroid Build Coastguard Worker   }
435*fb1b10abSAndroid Build Coastguard Worker 
436*fb1b10abSAndroid Build Coastguard Worker   tr = br;
437*fb1b10abSAndroid Build Coastguard Worker   tc = bc;
438*fb1b10abSAndroid Build Coastguard Worker 
439*fb1b10abSAndroid Build Coastguard Worker   if (allow_hp && use_mv_hp(ref_mv) && forced_stop == 0) {
440*fb1b10abSAndroid Build Coastguard Worker     hstep >>= 1;
441*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
442*fb1b10abSAndroid Build Coastguard Worker     if (eighthiters > 1) {
443*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
444*fb1b10abSAndroid Build Coastguard Worker     }
445*fb1b10abSAndroid Build Coastguard Worker   }
446*fb1b10abSAndroid Build Coastguard Worker 
447*fb1b10abSAndroid Build Coastguard Worker   bestmv->row = br;
448*fb1b10abSAndroid Build Coastguard Worker   bestmv->col = bc;
449*fb1b10abSAndroid Build Coastguard Worker 
450*fb1b10abSAndroid Build Coastguard Worker   return besterr;
451*fb1b10abSAndroid Build Coastguard Worker }
452*fb1b10abSAndroid Build Coastguard Worker 
vp9_find_best_sub_pixel_tree_pruned_more(const MACROBLOCK * x,MV * bestmv,const MV * ref_mv,int allow_hp,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,int forced_stop,int iters_per_step,int * cost_list,int * mvjcost,int * mvcost[2],uint32_t * distortion,uint32_t * sse1,const uint8_t * second_pred,int w,int h,int use_accurate_subpel_search)453*fb1b10abSAndroid Build Coastguard Worker uint32_t vp9_find_best_sub_pixel_tree_pruned_more(
454*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
455*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
456*fb1b10abSAndroid Build Coastguard Worker     int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
457*fb1b10abSAndroid Build Coastguard Worker     uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
458*fb1b10abSAndroid Build Coastguard Worker     int h, int use_accurate_subpel_search) {
459*fb1b10abSAndroid Build Coastguard Worker   SETUP_SUBPEL_SEARCH;
460*fb1b10abSAndroid Build Coastguard Worker   (void)use_accurate_subpel_search;
461*fb1b10abSAndroid Build Coastguard Worker 
462*fb1b10abSAndroid Build Coastguard Worker   besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp, z,
463*fb1b10abSAndroid Build Coastguard Worker                                src_stride, y, y_stride, second_pred, w, h,
464*fb1b10abSAndroid Build Coastguard Worker                                offset, mvjcost, mvcost, sse1, distortion);
465*fb1b10abSAndroid Build Coastguard Worker   if (cost_list && cost_list[0] != INT_MAX && cost_list[1] != INT_MAX &&
466*fb1b10abSAndroid Build Coastguard Worker       cost_list[2] != INT_MAX && cost_list[3] != INT_MAX &&
467*fb1b10abSAndroid Build Coastguard Worker       cost_list[4] != INT_MAX && is_cost_list_wellbehaved(cost_list)) {
468*fb1b10abSAndroid Build Coastguard Worker     unsigned int minpt;
469*fb1b10abSAndroid Build Coastguard Worker     int ir, ic;
470*fb1b10abSAndroid Build Coastguard Worker     get_cost_surf_min(cost_list, &ir, &ic, 1);
471*fb1b10abSAndroid Build Coastguard Worker     if (ir != 0 || ic != 0) {
472*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER(minpt, tr + ir * hstep, tc + ic * hstep);
473*fb1b10abSAndroid Build Coastguard Worker     }
474*fb1b10abSAndroid Build Coastguard Worker   } else {
475*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
476*fb1b10abSAndroid Build Coastguard Worker     if (halfiters > 1) {
477*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
478*fb1b10abSAndroid Build Coastguard Worker     }
479*fb1b10abSAndroid Build Coastguard Worker   }
480*fb1b10abSAndroid Build Coastguard Worker 
481*fb1b10abSAndroid Build Coastguard Worker   // Each subsequent iteration checks at least one point in common with
482*fb1b10abSAndroid Build Coastguard Worker   // the last iteration could be 2 ( if diag selected) 1/4 pel
483*fb1b10abSAndroid Build Coastguard Worker 
484*fb1b10abSAndroid Build Coastguard Worker   // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
485*fb1b10abSAndroid Build Coastguard Worker   if (forced_stop != 2) {
486*fb1b10abSAndroid Build Coastguard Worker     tr = br;
487*fb1b10abSAndroid Build Coastguard Worker     tc = bc;
488*fb1b10abSAndroid Build Coastguard Worker     hstep >>= 1;
489*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
490*fb1b10abSAndroid Build Coastguard Worker     if (quarteriters > 1) {
491*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
492*fb1b10abSAndroid Build Coastguard Worker     }
493*fb1b10abSAndroid Build Coastguard Worker   }
494*fb1b10abSAndroid Build Coastguard Worker 
495*fb1b10abSAndroid Build Coastguard Worker   if (allow_hp && use_mv_hp(ref_mv) && forced_stop == 0) {
496*fb1b10abSAndroid Build Coastguard Worker     tr = br;
497*fb1b10abSAndroid Build Coastguard Worker     tc = bc;
498*fb1b10abSAndroid Build Coastguard Worker     hstep >>= 1;
499*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
500*fb1b10abSAndroid Build Coastguard Worker     if (eighthiters > 1) {
501*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
502*fb1b10abSAndroid Build Coastguard Worker     }
503*fb1b10abSAndroid Build Coastguard Worker   }
504*fb1b10abSAndroid Build Coastguard Worker   // These lines insure static analysis doesn't warn that
505*fb1b10abSAndroid Build Coastguard Worker   // tr and tc aren't used after the above point.
506*fb1b10abSAndroid Build Coastguard Worker   (void)tr;
507*fb1b10abSAndroid Build Coastguard Worker   (void)tc;
508*fb1b10abSAndroid Build Coastguard Worker 
509*fb1b10abSAndroid Build Coastguard Worker   bestmv->row = br;
510*fb1b10abSAndroid Build Coastguard Worker   bestmv->col = bc;
511*fb1b10abSAndroid Build Coastguard Worker 
512*fb1b10abSAndroid Build Coastguard Worker   return besterr;
513*fb1b10abSAndroid Build Coastguard Worker }
514*fb1b10abSAndroid Build Coastguard Worker 
vp9_find_best_sub_pixel_tree_pruned(const MACROBLOCK * x,MV * bestmv,const MV * ref_mv,int allow_hp,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,int forced_stop,int iters_per_step,int * cost_list,int * mvjcost,int * mvcost[2],uint32_t * distortion,uint32_t * sse1,const uint8_t * second_pred,int w,int h,int use_accurate_subpel_search)515*fb1b10abSAndroid Build Coastguard Worker uint32_t vp9_find_best_sub_pixel_tree_pruned(
516*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
517*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
518*fb1b10abSAndroid Build Coastguard Worker     int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
519*fb1b10abSAndroid Build Coastguard Worker     uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
520*fb1b10abSAndroid Build Coastguard Worker     int h, int use_accurate_subpel_search) {
521*fb1b10abSAndroid Build Coastguard Worker   SETUP_SUBPEL_SEARCH;
522*fb1b10abSAndroid Build Coastguard Worker   (void)use_accurate_subpel_search;
523*fb1b10abSAndroid Build Coastguard Worker 
524*fb1b10abSAndroid Build Coastguard Worker   besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp, z,
525*fb1b10abSAndroid Build Coastguard Worker                                src_stride, y, y_stride, second_pred, w, h,
526*fb1b10abSAndroid Build Coastguard Worker                                offset, mvjcost, mvcost, sse1, distortion);
527*fb1b10abSAndroid Build Coastguard Worker   if (cost_list && cost_list[0] != INT_MAX && cost_list[1] != INT_MAX &&
528*fb1b10abSAndroid Build Coastguard Worker       cost_list[2] != INT_MAX && cost_list[3] != INT_MAX &&
529*fb1b10abSAndroid Build Coastguard Worker       cost_list[4] != INT_MAX) {
530*fb1b10abSAndroid Build Coastguard Worker     unsigned int left, right, up, down, diag;
531*fb1b10abSAndroid Build Coastguard Worker     whichdir = (cost_list[1] < cost_list[3] ? 0 : 1) +
532*fb1b10abSAndroid Build Coastguard Worker                (cost_list[2] < cost_list[4] ? 0 : 2);
533*fb1b10abSAndroid Build Coastguard Worker     switch (whichdir) {
534*fb1b10abSAndroid Build Coastguard Worker       case 0:
535*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(left, tr, tc - hstep);
536*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(down, tr + hstep, tc);
537*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(diag, tr + hstep, tc - hstep);
538*fb1b10abSAndroid Build Coastguard Worker         break;
539*fb1b10abSAndroid Build Coastguard Worker       case 1:
540*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(right, tr, tc + hstep);
541*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(down, tr + hstep, tc);
542*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(diag, tr + hstep, tc + hstep);
543*fb1b10abSAndroid Build Coastguard Worker         break;
544*fb1b10abSAndroid Build Coastguard Worker       case 2:
545*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(left, tr, tc - hstep);
546*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(up, tr - hstep, tc);
547*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(diag, tr - hstep, tc - hstep);
548*fb1b10abSAndroid Build Coastguard Worker         break;
549*fb1b10abSAndroid Build Coastguard Worker       case 3:
550*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(right, tr, tc + hstep);
551*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(up, tr - hstep, tc);
552*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER(diag, tr - hstep, tc + hstep);
553*fb1b10abSAndroid Build Coastguard Worker         break;
554*fb1b10abSAndroid Build Coastguard Worker     }
555*fb1b10abSAndroid Build Coastguard Worker   } else {
556*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
557*fb1b10abSAndroid Build Coastguard Worker     if (halfiters > 1) {
558*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
559*fb1b10abSAndroid Build Coastguard Worker     }
560*fb1b10abSAndroid Build Coastguard Worker   }
561*fb1b10abSAndroid Build Coastguard Worker 
562*fb1b10abSAndroid Build Coastguard Worker   tr = br;
563*fb1b10abSAndroid Build Coastguard Worker   tc = bc;
564*fb1b10abSAndroid Build Coastguard Worker 
565*fb1b10abSAndroid Build Coastguard Worker   // Each subsequent iteration checks at least one point in common with
566*fb1b10abSAndroid Build Coastguard Worker   // the last iteration could be 2 ( if diag selected) 1/4 pel
567*fb1b10abSAndroid Build Coastguard Worker 
568*fb1b10abSAndroid Build Coastguard Worker   // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
569*fb1b10abSAndroid Build Coastguard Worker   if (forced_stop != 2) {
570*fb1b10abSAndroid Build Coastguard Worker     hstep >>= 1;
571*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
572*fb1b10abSAndroid Build Coastguard Worker     if (quarteriters > 1) {
573*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
574*fb1b10abSAndroid Build Coastguard Worker     }
575*fb1b10abSAndroid Build Coastguard Worker     tr = br;
576*fb1b10abSAndroid Build Coastguard Worker     tc = bc;
577*fb1b10abSAndroid Build Coastguard Worker   }
578*fb1b10abSAndroid Build Coastguard Worker 
579*fb1b10abSAndroid Build Coastguard Worker   if (allow_hp && use_mv_hp(ref_mv) && forced_stop == 0) {
580*fb1b10abSAndroid Build Coastguard Worker     hstep >>= 1;
581*fb1b10abSAndroid Build Coastguard Worker     FIRST_LEVEL_CHECKS;
582*fb1b10abSAndroid Build Coastguard Worker     if (eighthiters > 1) {
583*fb1b10abSAndroid Build Coastguard Worker       SECOND_LEVEL_CHECKS;
584*fb1b10abSAndroid Build Coastguard Worker     }
585*fb1b10abSAndroid Build Coastguard Worker     tr = br;
586*fb1b10abSAndroid Build Coastguard Worker     tc = bc;
587*fb1b10abSAndroid Build Coastguard Worker   }
588*fb1b10abSAndroid Build Coastguard Worker   // These lines insure static analysis doesn't warn that
589*fb1b10abSAndroid Build Coastguard Worker   // tr and tc aren't used after the above point.
590*fb1b10abSAndroid Build Coastguard Worker   (void)tr;
591*fb1b10abSAndroid Build Coastguard Worker   (void)tc;
592*fb1b10abSAndroid Build Coastguard Worker 
593*fb1b10abSAndroid Build Coastguard Worker   bestmv->row = br;
594*fb1b10abSAndroid Build Coastguard Worker   bestmv->col = bc;
595*fb1b10abSAndroid Build Coastguard Worker 
596*fb1b10abSAndroid Build Coastguard Worker   return besterr;
597*fb1b10abSAndroid Build Coastguard Worker }
598*fb1b10abSAndroid Build Coastguard Worker 
599*fb1b10abSAndroid Build Coastguard Worker /* clang-format off */
600*fb1b10abSAndroid Build Coastguard Worker static const MV search_step_table[12] = {
601*fb1b10abSAndroid Build Coastguard Worker   // left, right, up, down
602*fb1b10abSAndroid Build Coastguard Worker   { 0, -4 }, { 0, 4 }, { -4, 0 }, { 4, 0 },
603*fb1b10abSAndroid Build Coastguard Worker   { 0, -2 }, { 0, 2 }, { -2, 0 }, { 2, 0 },
604*fb1b10abSAndroid Build Coastguard Worker   { 0, -1 }, { 0, 1 }, { -1, 0 }, { 1, 0 }
605*fb1b10abSAndroid Build Coastguard Worker };
606*fb1b10abSAndroid Build Coastguard Worker /* clang-format on */
607*fb1b10abSAndroid Build Coastguard Worker 
accurate_sub_pel_search(const MACROBLOCKD * xd,const MV * this_mv,const struct scale_factors * sf,const InterpKernel * kernel,const vp9_variance_fn_ptr_t * vfp,const uint8_t * const src_address,const int src_stride,const uint8_t * const pre_address,int y_stride,const uint8_t * second_pred,int w,int h,uint32_t * sse)608*fb1b10abSAndroid Build Coastguard Worker static int accurate_sub_pel_search(
609*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCKD *xd, const MV *this_mv, const struct scale_factors *sf,
610*fb1b10abSAndroid Build Coastguard Worker     const InterpKernel *kernel, const vp9_variance_fn_ptr_t *vfp,
611*fb1b10abSAndroid Build Coastguard Worker     const uint8_t *const src_address, const int src_stride,
612*fb1b10abSAndroid Build Coastguard Worker     const uint8_t *const pre_address, int y_stride, const uint8_t *second_pred,
613*fb1b10abSAndroid Build Coastguard Worker     int w, int h, uint32_t *sse) {
614*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
615*fb1b10abSAndroid Build Coastguard Worker   uint64_t besterr;
616*fb1b10abSAndroid Build Coastguard Worker   assert(sf->x_step_q4 == 16 && sf->y_step_q4 == 16);
617*fb1b10abSAndroid Build Coastguard Worker   assert(w != 0 && h != 0);
618*fb1b10abSAndroid Build Coastguard Worker   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
619*fb1b10abSAndroid Build Coastguard Worker     DECLARE_ALIGNED(16, uint16_t, pred16[64 * 64]);
620*fb1b10abSAndroid Build Coastguard Worker     vp9_highbd_build_inter_predictor(CONVERT_TO_SHORTPTR(pre_address), y_stride,
621*fb1b10abSAndroid Build Coastguard Worker                                      pred16, w, this_mv, sf, w, h, 0, kernel,
622*fb1b10abSAndroid Build Coastguard Worker                                      MV_PRECISION_Q3, 0, 0, xd->bd);
623*fb1b10abSAndroid Build Coastguard Worker     if (second_pred != NULL) {
624*fb1b10abSAndroid Build Coastguard Worker       DECLARE_ALIGNED(16, uint16_t, comp_pred16[64 * 64]);
625*fb1b10abSAndroid Build Coastguard Worker       vpx_highbd_comp_avg_pred(comp_pred16, CONVERT_TO_SHORTPTR(second_pred), w,
626*fb1b10abSAndroid Build Coastguard Worker                                h, pred16, w);
627*fb1b10abSAndroid Build Coastguard Worker       besterr = vfp->vf(CONVERT_TO_BYTEPTR(comp_pred16), w, src_address,
628*fb1b10abSAndroid Build Coastguard Worker                         src_stride, sse);
629*fb1b10abSAndroid Build Coastguard Worker     } else {
630*fb1b10abSAndroid Build Coastguard Worker       besterr =
631*fb1b10abSAndroid Build Coastguard Worker           vfp->vf(CONVERT_TO_BYTEPTR(pred16), w, src_address, src_stride, sse);
632*fb1b10abSAndroid Build Coastguard Worker     }
633*fb1b10abSAndroid Build Coastguard Worker   } else {
634*fb1b10abSAndroid Build Coastguard Worker     DECLARE_ALIGNED(16, uint8_t, pred[64 * 64]);
635*fb1b10abSAndroid Build Coastguard Worker     vp9_build_inter_predictor(pre_address, y_stride, pred, w, this_mv, sf, w, h,
636*fb1b10abSAndroid Build Coastguard Worker                               0, kernel, MV_PRECISION_Q3, 0, 0);
637*fb1b10abSAndroid Build Coastguard Worker     if (second_pred != NULL) {
638*fb1b10abSAndroid Build Coastguard Worker       DECLARE_ALIGNED(32, uint8_t, comp_pred[64 * 64]);
639*fb1b10abSAndroid Build Coastguard Worker       vpx_comp_avg_pred(comp_pred, second_pred, w, h, pred, w);
640*fb1b10abSAndroid Build Coastguard Worker       besterr = vfp->vf(comp_pred, w, src_address, src_stride, sse);
641*fb1b10abSAndroid Build Coastguard Worker     } else {
642*fb1b10abSAndroid Build Coastguard Worker       besterr = vfp->vf(pred, w, src_address, src_stride, sse);
643*fb1b10abSAndroid Build Coastguard Worker     }
644*fb1b10abSAndroid Build Coastguard Worker   }
645*fb1b10abSAndroid Build Coastguard Worker   if (besterr >= UINT_MAX) return UINT_MAX;
646*fb1b10abSAndroid Build Coastguard Worker   return (int)besterr;
647*fb1b10abSAndroid Build Coastguard Worker #else
648*fb1b10abSAndroid Build Coastguard Worker   int besterr;
649*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, uint8_t, pred[64 * 64]);
650*fb1b10abSAndroid Build Coastguard Worker   assert(sf->x_step_q4 == 16 && sf->y_step_q4 == 16);
651*fb1b10abSAndroid Build Coastguard Worker   assert(w != 0 && h != 0);
652*fb1b10abSAndroid Build Coastguard Worker   (void)xd;
653*fb1b10abSAndroid Build Coastguard Worker 
654*fb1b10abSAndroid Build Coastguard Worker   vp9_build_inter_predictor(pre_address, y_stride, pred, w, this_mv, sf, w, h,
655*fb1b10abSAndroid Build Coastguard Worker                             0, kernel, MV_PRECISION_Q3, 0, 0);
656*fb1b10abSAndroid Build Coastguard Worker   if (second_pred != NULL) {
657*fb1b10abSAndroid Build Coastguard Worker     DECLARE_ALIGNED(32, uint8_t, comp_pred[64 * 64]);
658*fb1b10abSAndroid Build Coastguard Worker     vpx_comp_avg_pred(comp_pred, second_pred, w, h, pred, w);
659*fb1b10abSAndroid Build Coastguard Worker     besterr = vfp->vf(comp_pred, w, src_address, src_stride, sse);
660*fb1b10abSAndroid Build Coastguard Worker   } else {
661*fb1b10abSAndroid Build Coastguard Worker     besterr = vfp->vf(pred, w, src_address, src_stride, sse);
662*fb1b10abSAndroid Build Coastguard Worker   }
663*fb1b10abSAndroid Build Coastguard Worker   return besterr;
664*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
665*fb1b10abSAndroid Build Coastguard Worker }
666*fb1b10abSAndroid Build Coastguard Worker 
667*fb1b10abSAndroid Build Coastguard Worker // TODO(yunqing): this part can be further refactored.
668*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
669*fb1b10abSAndroid Build Coastguard Worker /* checks if (r, c) has better score than previous best */
670*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BETTER1(v, r, c)                                                \
671*fb1b10abSAndroid Build Coastguard Worker   do {                                                                        \
672*fb1b10abSAndroid Build Coastguard Worker     if (c >= minc && c <= maxc && r >= minr && r <= maxr) {                   \
673*fb1b10abSAndroid Build Coastguard Worker       int64_t tmpmse;                                                         \
674*fb1b10abSAndroid Build Coastguard Worker       const MV cb_mv = { r, c };                                              \
675*fb1b10abSAndroid Build Coastguard Worker       const MV cb_ref_mv = { rr, rc };                                        \
676*fb1b10abSAndroid Build Coastguard Worker       thismse = accurate_sub_pel_search(xd, &cb_mv, x->me_sf, kernel, vfp, z, \
677*fb1b10abSAndroid Build Coastguard Worker                                         src_stride, y, y_stride, second_pred, \
678*fb1b10abSAndroid Build Coastguard Worker                                         w, h, &sse);                          \
679*fb1b10abSAndroid Build Coastguard Worker       tmpmse = thismse;                                                       \
680*fb1b10abSAndroid Build Coastguard Worker       tmpmse +=                                                               \
681*fb1b10abSAndroid Build Coastguard Worker           mv_err_cost(&cb_mv, &cb_ref_mv, mvjcost, mvcost, error_per_bit);    \
682*fb1b10abSAndroid Build Coastguard Worker       if (tmpmse >= INT_MAX) {                                                \
683*fb1b10abSAndroid Build Coastguard Worker         v = INT_MAX;                                                          \
684*fb1b10abSAndroid Build Coastguard Worker       } else if ((v = (uint32_t)tmpmse) < besterr) {                          \
685*fb1b10abSAndroid Build Coastguard Worker         besterr = v;                                                          \
686*fb1b10abSAndroid Build Coastguard Worker         br = r;                                                               \
687*fb1b10abSAndroid Build Coastguard Worker         bc = c;                                                               \
688*fb1b10abSAndroid Build Coastguard Worker         *distortion = thismse;                                                \
689*fb1b10abSAndroid Build Coastguard Worker         *sse1 = sse;                                                          \
690*fb1b10abSAndroid Build Coastguard Worker       }                                                                       \
691*fb1b10abSAndroid Build Coastguard Worker     } else {                                                                  \
692*fb1b10abSAndroid Build Coastguard Worker       v = INT_MAX;                                                            \
693*fb1b10abSAndroid Build Coastguard Worker     }                                                                         \
694*fb1b10abSAndroid Build Coastguard Worker   } while (0)
695*fb1b10abSAndroid Build Coastguard Worker #else
696*fb1b10abSAndroid Build Coastguard Worker /* checks if (r, c) has better score than previous best */
697*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BETTER1(v, r, c)                                                \
698*fb1b10abSAndroid Build Coastguard Worker   do {                                                                        \
699*fb1b10abSAndroid Build Coastguard Worker     if (c >= minc && c <= maxc && r >= minr && r <= maxr) {                   \
700*fb1b10abSAndroid Build Coastguard Worker       const MV cb_mv = { r, c };                                              \
701*fb1b10abSAndroid Build Coastguard Worker       const MV cb_ref_mv = { rr, rc };                                        \
702*fb1b10abSAndroid Build Coastguard Worker       thismse = accurate_sub_pel_search(xd, &cb_mv, x->me_sf, kernel, vfp, z, \
703*fb1b10abSAndroid Build Coastguard Worker                                         src_stride, y, y_stride, second_pred, \
704*fb1b10abSAndroid Build Coastguard Worker                                         w, h, &sse);                          \
705*fb1b10abSAndroid Build Coastguard Worker       if ((v = mv_err_cost(&cb_mv, &cb_ref_mv, mvjcost, mvcost,               \
706*fb1b10abSAndroid Build Coastguard Worker                            error_per_bit) +                                   \
707*fb1b10abSAndroid Build Coastguard Worker                thismse) < besterr) {                                          \
708*fb1b10abSAndroid Build Coastguard Worker         besterr = v;                                                          \
709*fb1b10abSAndroid Build Coastguard Worker         br = r;                                                               \
710*fb1b10abSAndroid Build Coastguard Worker         bc = c;                                                               \
711*fb1b10abSAndroid Build Coastguard Worker         *distortion = thismse;                                                \
712*fb1b10abSAndroid Build Coastguard Worker         *sse1 = sse;                                                          \
713*fb1b10abSAndroid Build Coastguard Worker       }                                                                       \
714*fb1b10abSAndroid Build Coastguard Worker     } else {                                                                  \
715*fb1b10abSAndroid Build Coastguard Worker       v = INT_MAX;                                                            \
716*fb1b10abSAndroid Build Coastguard Worker     }                                                                         \
717*fb1b10abSAndroid Build Coastguard Worker   } while (0)
718*fb1b10abSAndroid Build Coastguard Worker 
719*fb1b10abSAndroid Build Coastguard Worker #endif
720*fb1b10abSAndroid Build Coastguard Worker 
vp9_find_best_sub_pixel_tree(const MACROBLOCK * x,MV * bestmv,const MV * ref_mv,int allow_hp,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,int forced_stop,int iters_per_step,int * cost_list,int * mvjcost,int * mvcost[2],uint32_t * distortion,uint32_t * sse1,const uint8_t * second_pred,int w,int h,int use_accurate_subpel_search)721*fb1b10abSAndroid Build Coastguard Worker uint32_t vp9_find_best_sub_pixel_tree(
722*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
723*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
724*fb1b10abSAndroid Build Coastguard Worker     int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
725*fb1b10abSAndroid Build Coastguard Worker     uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
726*fb1b10abSAndroid Build Coastguard Worker     int h, int use_accurate_subpel_search) {
727*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *const z = x->plane[0].src.buf;
728*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *const src_address = z;
729*fb1b10abSAndroid Build Coastguard Worker   const int src_stride = x->plane[0].src.stride;
730*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *xd = &x->e_mbd;
731*fb1b10abSAndroid Build Coastguard Worker   unsigned int besterr = UINT_MAX;
732*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;
733*fb1b10abSAndroid Build Coastguard Worker   int thismse;
734*fb1b10abSAndroid Build Coastguard Worker   const int y_stride = xd->plane[0].pre[0].stride;
735*fb1b10abSAndroid Build Coastguard Worker   const int offset = bestmv->row * y_stride + bestmv->col;
736*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *const y = xd->plane[0].pre[0].buf;
737*fb1b10abSAndroid Build Coastguard Worker 
738*fb1b10abSAndroid Build Coastguard Worker   int rr = ref_mv->row;
739*fb1b10abSAndroid Build Coastguard Worker   int rc = ref_mv->col;
740*fb1b10abSAndroid Build Coastguard Worker   int br = bestmv->row * 8;
741*fb1b10abSAndroid Build Coastguard Worker   int bc = bestmv->col * 8;
742*fb1b10abSAndroid Build Coastguard Worker   int hstep = 4;
743*fb1b10abSAndroid Build Coastguard Worker   int iter, round = 3 - forced_stop;
744*fb1b10abSAndroid Build Coastguard Worker 
745*fb1b10abSAndroid Build Coastguard Worker   int minc, maxc, minr, maxr;
746*fb1b10abSAndroid Build Coastguard Worker   int tr = br;
747*fb1b10abSAndroid Build Coastguard Worker   int tc = bc;
748*fb1b10abSAndroid Build Coastguard Worker   const MV *search_step = search_step_table;
749*fb1b10abSAndroid Build Coastguard Worker   int idx, best_idx = -1;
750*fb1b10abSAndroid Build Coastguard Worker   unsigned int cost_array[5];
751*fb1b10abSAndroid Build Coastguard Worker   int kr, kc;
752*fb1b10abSAndroid Build Coastguard Worker   MvLimits subpel_mv_limits;
753*fb1b10abSAndroid Build Coastguard Worker 
754*fb1b10abSAndroid Build Coastguard Worker   // TODO(yunqing): need to add 4-tap filter optimization to speed up the
755*fb1b10abSAndroid Build Coastguard Worker   // encoder.
756*fb1b10abSAndroid Build Coastguard Worker   const InterpKernel *kernel =
757*fb1b10abSAndroid Build Coastguard Worker       (use_accurate_subpel_search > 0)
758*fb1b10abSAndroid Build Coastguard Worker           ? ((use_accurate_subpel_search == USE_4_TAPS)
759*fb1b10abSAndroid Build Coastguard Worker                  ? vp9_filter_kernels[FOURTAP]
760*fb1b10abSAndroid Build Coastguard Worker                  : ((use_accurate_subpel_search == USE_8_TAPS)
761*fb1b10abSAndroid Build Coastguard Worker                         ? vp9_filter_kernels[EIGHTTAP]
762*fb1b10abSAndroid Build Coastguard Worker                         : vp9_filter_kernels[EIGHTTAP_SHARP]))
763*fb1b10abSAndroid Build Coastguard Worker           : vp9_filter_kernels[BILINEAR];
764*fb1b10abSAndroid Build Coastguard Worker 
765*fb1b10abSAndroid Build Coastguard Worker   vp9_set_subpel_mv_search_range(&subpel_mv_limits, &x->mv_limits, ref_mv);
766*fb1b10abSAndroid Build Coastguard Worker   minc = subpel_mv_limits.col_min;
767*fb1b10abSAndroid Build Coastguard Worker   maxc = subpel_mv_limits.col_max;
768*fb1b10abSAndroid Build Coastguard Worker   minr = subpel_mv_limits.row_min;
769*fb1b10abSAndroid Build Coastguard Worker   maxr = subpel_mv_limits.row_max;
770*fb1b10abSAndroid Build Coastguard Worker 
771*fb1b10abSAndroid Build Coastguard Worker   if (!(allow_hp && use_mv_hp(ref_mv)))
772*fb1b10abSAndroid Build Coastguard Worker     if (round == 3) round = 2;
773*fb1b10abSAndroid Build Coastguard Worker 
774*fb1b10abSAndroid Build Coastguard Worker   bestmv->row *= 8;
775*fb1b10abSAndroid Build Coastguard Worker   bestmv->col *= 8;
776*fb1b10abSAndroid Build Coastguard Worker 
777*fb1b10abSAndroid Build Coastguard Worker   besterr = setup_center_error(xd, bestmv, ref_mv, error_per_bit, vfp, z,
778*fb1b10abSAndroid Build Coastguard Worker                                src_stride, y, y_stride, second_pred, w, h,
779*fb1b10abSAndroid Build Coastguard Worker                                offset, mvjcost, mvcost, sse1, distortion);
780*fb1b10abSAndroid Build Coastguard Worker 
781*fb1b10abSAndroid Build Coastguard Worker   (void)cost_list;  // to silence compiler warning
782*fb1b10abSAndroid Build Coastguard Worker 
783*fb1b10abSAndroid Build Coastguard Worker   for (iter = 0; iter < round; ++iter) {
784*fb1b10abSAndroid Build Coastguard Worker     // Check vertical and horizontal sub-pixel positions.
785*fb1b10abSAndroid Build Coastguard Worker     for (idx = 0; idx < 4; ++idx) {
786*fb1b10abSAndroid Build Coastguard Worker       tr = br + search_step[idx].row;
787*fb1b10abSAndroid Build Coastguard Worker       tc = bc + search_step[idx].col;
788*fb1b10abSAndroid Build Coastguard Worker       if (tc >= minc && tc <= maxc && tr >= minr && tr <= maxr) {
789*fb1b10abSAndroid Build Coastguard Worker         MV this_mv;
790*fb1b10abSAndroid Build Coastguard Worker         this_mv.row = tr;
791*fb1b10abSAndroid Build Coastguard Worker         this_mv.col = tc;
792*fb1b10abSAndroid Build Coastguard Worker 
793*fb1b10abSAndroid Build Coastguard Worker         if (use_accurate_subpel_search) {
794*fb1b10abSAndroid Build Coastguard Worker           thismse = accurate_sub_pel_search(xd, &this_mv, x->me_sf, kernel, vfp,
795*fb1b10abSAndroid Build Coastguard Worker                                             src_address, src_stride, y,
796*fb1b10abSAndroid Build Coastguard Worker                                             y_stride, second_pred, w, h, &sse);
797*fb1b10abSAndroid Build Coastguard Worker         } else {
798*fb1b10abSAndroid Build Coastguard Worker           const uint8_t *const pre_address =
799*fb1b10abSAndroid Build Coastguard Worker               y + (tr >> 3) * y_stride + (tc >> 3);
800*fb1b10abSAndroid Build Coastguard Worker           if (second_pred == NULL)
801*fb1b10abSAndroid Build Coastguard Worker             thismse = vfp->svf(pre_address, y_stride, sp(tc), sp(tr),
802*fb1b10abSAndroid Build Coastguard Worker                                src_address, src_stride, &sse);
803*fb1b10abSAndroid Build Coastguard Worker           else
804*fb1b10abSAndroid Build Coastguard Worker             thismse = vfp->svaf(pre_address, y_stride, sp(tc), sp(tr),
805*fb1b10abSAndroid Build Coastguard Worker                                 src_address, src_stride, &sse, second_pred);
806*fb1b10abSAndroid Build Coastguard Worker         }
807*fb1b10abSAndroid Build Coastguard Worker 
808*fb1b10abSAndroid Build Coastguard Worker         cost_array[idx] = thismse + mv_err_cost(&this_mv, ref_mv, mvjcost,
809*fb1b10abSAndroid Build Coastguard Worker                                                 mvcost, error_per_bit);
810*fb1b10abSAndroid Build Coastguard Worker 
811*fb1b10abSAndroid Build Coastguard Worker         if (cost_array[idx] < besterr) {
812*fb1b10abSAndroid Build Coastguard Worker           best_idx = idx;
813*fb1b10abSAndroid Build Coastguard Worker           besterr = cost_array[idx];
814*fb1b10abSAndroid Build Coastguard Worker           *distortion = thismse;
815*fb1b10abSAndroid Build Coastguard Worker           *sse1 = sse;
816*fb1b10abSAndroid Build Coastguard Worker         }
817*fb1b10abSAndroid Build Coastguard Worker       } else {
818*fb1b10abSAndroid Build Coastguard Worker         cost_array[idx] = UINT_MAX;
819*fb1b10abSAndroid Build Coastguard Worker       }
820*fb1b10abSAndroid Build Coastguard Worker     }
821*fb1b10abSAndroid Build Coastguard Worker 
822*fb1b10abSAndroid Build Coastguard Worker     // Check diagonal sub-pixel position
823*fb1b10abSAndroid Build Coastguard Worker     kc = (cost_array[0] <= cost_array[1] ? -hstep : hstep);
824*fb1b10abSAndroid Build Coastguard Worker     kr = (cost_array[2] <= cost_array[3] ? -hstep : hstep);
825*fb1b10abSAndroid Build Coastguard Worker 
826*fb1b10abSAndroid Build Coastguard Worker     tc = bc + kc;
827*fb1b10abSAndroid Build Coastguard Worker     tr = br + kr;
828*fb1b10abSAndroid Build Coastguard Worker     if (tc >= minc && tc <= maxc && tr >= minr && tr <= maxr) {
829*fb1b10abSAndroid Build Coastguard Worker       MV this_mv = { tr, tc };
830*fb1b10abSAndroid Build Coastguard Worker       if (use_accurate_subpel_search) {
831*fb1b10abSAndroid Build Coastguard Worker         thismse = accurate_sub_pel_search(xd, &this_mv, x->me_sf, kernel, vfp,
832*fb1b10abSAndroid Build Coastguard Worker                                           src_address, src_stride, y, y_stride,
833*fb1b10abSAndroid Build Coastguard Worker                                           second_pred, w, h, &sse);
834*fb1b10abSAndroid Build Coastguard Worker       } else {
835*fb1b10abSAndroid Build Coastguard Worker         const uint8_t *const pre_address = y + (tr >> 3) * y_stride + (tc >> 3);
836*fb1b10abSAndroid Build Coastguard Worker         if (second_pred == NULL)
837*fb1b10abSAndroid Build Coastguard Worker           thismse = vfp->svf(pre_address, y_stride, sp(tc), sp(tr), src_address,
838*fb1b10abSAndroid Build Coastguard Worker                              src_stride, &sse);
839*fb1b10abSAndroid Build Coastguard Worker         else
840*fb1b10abSAndroid Build Coastguard Worker           thismse = vfp->svaf(pre_address, y_stride, sp(tc), sp(tr),
841*fb1b10abSAndroid Build Coastguard Worker                               src_address, src_stride, &sse, second_pred);
842*fb1b10abSAndroid Build Coastguard Worker       }
843*fb1b10abSAndroid Build Coastguard Worker 
844*fb1b10abSAndroid Build Coastguard Worker       cost_array[4] = thismse + mv_err_cost(&this_mv, ref_mv, mvjcost, mvcost,
845*fb1b10abSAndroid Build Coastguard Worker                                             error_per_bit);
846*fb1b10abSAndroid Build Coastguard Worker 
847*fb1b10abSAndroid Build Coastguard Worker       if (cost_array[4] < besterr) {
848*fb1b10abSAndroid Build Coastguard Worker         best_idx = 4;
849*fb1b10abSAndroid Build Coastguard Worker         besterr = cost_array[4];
850*fb1b10abSAndroid Build Coastguard Worker         *distortion = thismse;
851*fb1b10abSAndroid Build Coastguard Worker         *sse1 = sse;
852*fb1b10abSAndroid Build Coastguard Worker       }
853*fb1b10abSAndroid Build Coastguard Worker     } else {
854*fb1b10abSAndroid Build Coastguard Worker       cost_array[idx] = UINT_MAX;
855*fb1b10abSAndroid Build Coastguard Worker     }
856*fb1b10abSAndroid Build Coastguard Worker 
857*fb1b10abSAndroid Build Coastguard Worker     if (best_idx < 4 && best_idx >= 0) {
858*fb1b10abSAndroid Build Coastguard Worker       br += search_step[best_idx].row;
859*fb1b10abSAndroid Build Coastguard Worker       bc += search_step[best_idx].col;
860*fb1b10abSAndroid Build Coastguard Worker     } else if (best_idx == 4) {
861*fb1b10abSAndroid Build Coastguard Worker       br = tr;
862*fb1b10abSAndroid Build Coastguard Worker       bc = tc;
863*fb1b10abSAndroid Build Coastguard Worker     }
864*fb1b10abSAndroid Build Coastguard Worker 
865*fb1b10abSAndroid Build Coastguard Worker     if (iters_per_step > 0 && best_idx != -1) {
866*fb1b10abSAndroid Build Coastguard Worker       unsigned int second;
867*fb1b10abSAndroid Build Coastguard Worker       const int br0 = br;
868*fb1b10abSAndroid Build Coastguard Worker       const int bc0 = bc;
869*fb1b10abSAndroid Build Coastguard Worker       assert(tr == br || tc == bc);
870*fb1b10abSAndroid Build Coastguard Worker 
871*fb1b10abSAndroid Build Coastguard Worker       if (tr == br && tc != bc) {
872*fb1b10abSAndroid Build Coastguard Worker         kc = bc - tc;
873*fb1b10abSAndroid Build Coastguard Worker         if (iters_per_step == 1) {
874*fb1b10abSAndroid Build Coastguard Worker           if (use_accurate_subpel_search) {
875*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER1(second, br0, bc0 + kc);
876*fb1b10abSAndroid Build Coastguard Worker           } else {
877*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER(second, br0, bc0 + kc);
878*fb1b10abSAndroid Build Coastguard Worker           }
879*fb1b10abSAndroid Build Coastguard Worker         }
880*fb1b10abSAndroid Build Coastguard Worker       } else if (tr != br && tc == bc) {
881*fb1b10abSAndroid Build Coastguard Worker         kr = br - tr;
882*fb1b10abSAndroid Build Coastguard Worker         if (iters_per_step == 1) {
883*fb1b10abSAndroid Build Coastguard Worker           if (use_accurate_subpel_search) {
884*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER1(second, br0 + kr, bc0);
885*fb1b10abSAndroid Build Coastguard Worker           } else {
886*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER(second, br0 + kr, bc0);
887*fb1b10abSAndroid Build Coastguard Worker           }
888*fb1b10abSAndroid Build Coastguard Worker         }
889*fb1b10abSAndroid Build Coastguard Worker       }
890*fb1b10abSAndroid Build Coastguard Worker 
891*fb1b10abSAndroid Build Coastguard Worker       if (iters_per_step > 1) {
892*fb1b10abSAndroid Build Coastguard Worker         if (use_accurate_subpel_search) {
893*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER1(second, br0 + kr, bc0);
894*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER1(second, br0, bc0 + kc);
895*fb1b10abSAndroid Build Coastguard Worker           if (br0 != br || bc0 != bc) {
896*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER1(second, br0 + kr, bc0 + kc);
897*fb1b10abSAndroid Build Coastguard Worker           }
898*fb1b10abSAndroid Build Coastguard Worker         } else {
899*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER(second, br0 + kr, bc0);
900*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER(second, br0, bc0 + kc);
901*fb1b10abSAndroid Build Coastguard Worker           if (br0 != br || bc0 != bc) {
902*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER(second, br0 + kr, bc0 + kc);
903*fb1b10abSAndroid Build Coastguard Worker           }
904*fb1b10abSAndroid Build Coastguard Worker         }
905*fb1b10abSAndroid Build Coastguard Worker       }
906*fb1b10abSAndroid Build Coastguard Worker     }
907*fb1b10abSAndroid Build Coastguard Worker 
908*fb1b10abSAndroid Build Coastguard Worker     search_step += 4;
909*fb1b10abSAndroid Build Coastguard Worker     hstep >>= 1;
910*fb1b10abSAndroid Build Coastguard Worker     best_idx = -1;
911*fb1b10abSAndroid Build Coastguard Worker   }
912*fb1b10abSAndroid Build Coastguard Worker 
913*fb1b10abSAndroid Build Coastguard Worker   // Each subsequent iteration checks at least one point in common with
914*fb1b10abSAndroid Build Coastguard Worker   // the last iteration could be 2 ( if diag selected) 1/4 pel
915*fb1b10abSAndroid Build Coastguard Worker 
916*fb1b10abSAndroid Build Coastguard Worker   // These lines insure static analysis doesn't warn that
917*fb1b10abSAndroid Build Coastguard Worker   // tr and tc aren't used after the above point.
918*fb1b10abSAndroid Build Coastguard Worker   (void)tr;
919*fb1b10abSAndroid Build Coastguard Worker   (void)tc;
920*fb1b10abSAndroid Build Coastguard Worker 
921*fb1b10abSAndroid Build Coastguard Worker   bestmv->row = br;
922*fb1b10abSAndroid Build Coastguard Worker   bestmv->col = bc;
923*fb1b10abSAndroid Build Coastguard Worker 
924*fb1b10abSAndroid Build Coastguard Worker   return besterr;
925*fb1b10abSAndroid Build Coastguard Worker }
926*fb1b10abSAndroid Build Coastguard Worker 
927*fb1b10abSAndroid Build Coastguard Worker #undef CHECK_BETTER
928*fb1b10abSAndroid Build Coastguard Worker #undef CHECK_BETTER1
929*fb1b10abSAndroid Build Coastguard Worker 
check_bounds(const MvLimits * mv_limits,int row,int col,int range)930*fb1b10abSAndroid Build Coastguard Worker static INLINE int check_bounds(const MvLimits *mv_limits, int row, int col,
931*fb1b10abSAndroid Build Coastguard Worker                                int range) {
932*fb1b10abSAndroid Build Coastguard Worker   return ((row - range) >= mv_limits->row_min) &
933*fb1b10abSAndroid Build Coastguard Worker          ((row + range) <= mv_limits->row_max) &
934*fb1b10abSAndroid Build Coastguard Worker          ((col - range) >= mv_limits->col_min) &
935*fb1b10abSAndroid Build Coastguard Worker          ((col + range) <= mv_limits->col_max);
936*fb1b10abSAndroid Build Coastguard Worker }
937*fb1b10abSAndroid Build Coastguard Worker 
is_mv_in(const MvLimits * mv_limits,const MV * mv)938*fb1b10abSAndroid Build Coastguard Worker static INLINE int is_mv_in(const MvLimits *mv_limits, const MV *mv) {
939*fb1b10abSAndroid Build Coastguard Worker   return (mv->col >= mv_limits->col_min) && (mv->col <= mv_limits->col_max) &&
940*fb1b10abSAndroid Build Coastguard Worker          (mv->row >= mv_limits->row_min) && (mv->row <= mv_limits->row_max);
941*fb1b10abSAndroid Build Coastguard Worker }
942*fb1b10abSAndroid Build Coastguard Worker 
943*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BETTER                                                      \
944*fb1b10abSAndroid Build Coastguard Worker   {                                                                       \
945*fb1b10abSAndroid Build Coastguard Worker     if (thissad < bestsad) {                                              \
946*fb1b10abSAndroid Build Coastguard Worker       if (use_mvcost)                                                     \
947*fb1b10abSAndroid Build Coastguard Worker         thissad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit); \
948*fb1b10abSAndroid Build Coastguard Worker       if (thissad < bestsad) {                                            \
949*fb1b10abSAndroid Build Coastguard Worker         bestsad = thissad;                                                \
950*fb1b10abSAndroid Build Coastguard Worker         best_site = i;                                                    \
951*fb1b10abSAndroid Build Coastguard Worker       }                                                                   \
952*fb1b10abSAndroid Build Coastguard Worker     }                                                                     \
953*fb1b10abSAndroid Build Coastguard Worker   }
954*fb1b10abSAndroid Build Coastguard Worker 
955*fb1b10abSAndroid Build Coastguard Worker #define MAX_PATTERN_SCALES 11
956*fb1b10abSAndroid Build Coastguard Worker #define MAX_PATTERN_CANDIDATES 8  // max number of candidates per scale
957*fb1b10abSAndroid Build Coastguard Worker #define PATTERN_CANDIDATES_REF 3  // number of refinement candidates
958*fb1b10abSAndroid Build Coastguard Worker 
959*fb1b10abSAndroid Build Coastguard Worker // Calculate and return a sad+mvcost list around an integer best pel.
calc_int_cost_list(const MACROBLOCK * x,const MV * ref_mv,int sadpb,const vp9_variance_fn_ptr_t * fn_ptr,const MV * best_mv,int * cost_list)960*fb1b10abSAndroid Build Coastguard Worker static INLINE void calc_int_cost_list(const MACROBLOCK *x, const MV *ref_mv,
961*fb1b10abSAndroid Build Coastguard Worker                                       int sadpb,
962*fb1b10abSAndroid Build Coastguard Worker                                       const vp9_variance_fn_ptr_t *fn_ptr,
963*fb1b10abSAndroid Build Coastguard Worker                                       const MV *best_mv, int *cost_list) {
964*fb1b10abSAndroid Build Coastguard Worker   static const MV neighbors[4] = { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 } };
965*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
966*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &x->e_mbd.plane[0].pre[0];
967*fb1b10abSAndroid Build Coastguard Worker   const MV fcenter_mv = { ref_mv->row >> 3, ref_mv->col >> 3 };
968*fb1b10abSAndroid Build Coastguard Worker   int br = best_mv->row;
969*fb1b10abSAndroid Build Coastguard Worker   int bc = best_mv->col;
970*fb1b10abSAndroid Build Coastguard Worker   const MV mv = { br, bc };
971*fb1b10abSAndroid Build Coastguard Worker   int i;
972*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;
973*fb1b10abSAndroid Build Coastguard Worker 
974*fb1b10abSAndroid Build Coastguard Worker   cost_list[0] =
975*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->vf(what->buf, what->stride, get_buf_from_mv(in_what, &mv),
976*fb1b10abSAndroid Build Coastguard Worker                  in_what->stride, &sse) +
977*fb1b10abSAndroid Build Coastguard Worker       mvsad_err_cost(x, &mv, &fcenter_mv, sadpb);
978*fb1b10abSAndroid Build Coastguard Worker   if (check_bounds(&x->mv_limits, br, bc, 1)) {
979*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 4; i++) {
980*fb1b10abSAndroid Build Coastguard Worker       const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
981*fb1b10abSAndroid Build Coastguard Worker       cost_list[i + 1] = fn_ptr->vf(what->buf, what->stride,
982*fb1b10abSAndroid Build Coastguard Worker                                     get_buf_from_mv(in_what, &this_mv),
983*fb1b10abSAndroid Build Coastguard Worker                                     in_what->stride, &sse) +
984*fb1b10abSAndroid Build Coastguard Worker                          mv_err_cost(&this_mv, &fcenter_mv, x->nmvjointcost,
985*fb1b10abSAndroid Build Coastguard Worker                                      x->mvcost, x->errorperbit);
986*fb1b10abSAndroid Build Coastguard Worker     }
987*fb1b10abSAndroid Build Coastguard Worker   } else {
988*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 4; i++) {
989*fb1b10abSAndroid Build Coastguard Worker       const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
990*fb1b10abSAndroid Build Coastguard Worker       if (!is_mv_in(&x->mv_limits, &this_mv))
991*fb1b10abSAndroid Build Coastguard Worker         cost_list[i + 1] = INT_MAX;
992*fb1b10abSAndroid Build Coastguard Worker       else
993*fb1b10abSAndroid Build Coastguard Worker         cost_list[i + 1] = fn_ptr->vf(what->buf, what->stride,
994*fb1b10abSAndroid Build Coastguard Worker                                       get_buf_from_mv(in_what, &this_mv),
995*fb1b10abSAndroid Build Coastguard Worker                                       in_what->stride, &sse) +
996*fb1b10abSAndroid Build Coastguard Worker                            mv_err_cost(&this_mv, &fcenter_mv, x->nmvjointcost,
997*fb1b10abSAndroid Build Coastguard Worker                                        x->mvcost, x->errorperbit);
998*fb1b10abSAndroid Build Coastguard Worker     }
999*fb1b10abSAndroid Build Coastguard Worker   }
1000*fb1b10abSAndroid Build Coastguard Worker }
1001*fb1b10abSAndroid Build Coastguard Worker 
1002*fb1b10abSAndroid Build Coastguard Worker // Generic pattern search function that searches over multiple scales.
1003*fb1b10abSAndroid Build Coastguard Worker // Each scale can have a different number of candidates and shape of
1004*fb1b10abSAndroid Build Coastguard Worker // candidates as indicated in the num_candidates and candidates arrays
1005*fb1b10abSAndroid Build Coastguard Worker // passed into this function
1006*fb1b10abSAndroid Build Coastguard Worker //
vp9_pattern_search(const MACROBLOCK * x,MV * ref_mv,int search_param,int sad_per_bit,int do_init_search,int * cost_list,const vp9_variance_fn_ptr_t * vfp,int use_mvcost,const MV * center_mv,MV * best_mv,const int num_candidates[MAX_PATTERN_SCALES],const MV candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES])1007*fb1b10abSAndroid Build Coastguard Worker static int vp9_pattern_search(
1008*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *ref_mv, int search_param, int sad_per_bit,
1009*fb1b10abSAndroid Build Coastguard Worker     int do_init_search, int *cost_list, const vp9_variance_fn_ptr_t *vfp,
1010*fb1b10abSAndroid Build Coastguard Worker     int use_mvcost, const MV *center_mv, MV *best_mv,
1011*fb1b10abSAndroid Build Coastguard Worker     const int num_candidates[MAX_PATTERN_SCALES],
1012*fb1b10abSAndroid Build Coastguard Worker     const MV candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES]) {
1013*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1014*fb1b10abSAndroid Build Coastguard Worker   static const int search_param_to_steps[MAX_MVSEARCH_STEPS] = {
1015*fb1b10abSAndroid Build Coastguard Worker     10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
1016*fb1b10abSAndroid Build Coastguard Worker   };
1017*fb1b10abSAndroid Build Coastguard Worker   int i, s, t;
1018*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
1019*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
1020*fb1b10abSAndroid Build Coastguard Worker   int br, bc;
1021*fb1b10abSAndroid Build Coastguard Worker   int bestsad = INT_MAX;
1022*fb1b10abSAndroid Build Coastguard Worker   int thissad;
1023*fb1b10abSAndroid Build Coastguard Worker   int k = -1;
1024*fb1b10abSAndroid Build Coastguard Worker   const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
1025*fb1b10abSAndroid Build Coastguard Worker   int best_init_s = search_param_to_steps[search_param];
1026*fb1b10abSAndroid Build Coastguard Worker   // adjust ref_mv to make sure it is within MV range
1027*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(ref_mv, x->mv_limits.col_min, x->mv_limits.col_max,
1028*fb1b10abSAndroid Build Coastguard Worker            x->mv_limits.row_min, x->mv_limits.row_max);
1029*fb1b10abSAndroid Build Coastguard Worker   br = ref_mv->row;
1030*fb1b10abSAndroid Build Coastguard Worker   bc = ref_mv->col;
1031*fb1b10abSAndroid Build Coastguard Worker 
1032*fb1b10abSAndroid Build Coastguard Worker   // Work out the start point for the search
1033*fb1b10abSAndroid Build Coastguard Worker   bestsad = vfp->sdf(what->buf, what->stride, get_buf_from_mv(in_what, ref_mv),
1034*fb1b10abSAndroid Build Coastguard Worker                      in_what->stride) +
1035*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(x, ref_mv, &fcenter_mv, sad_per_bit);
1036*fb1b10abSAndroid Build Coastguard Worker 
1037*fb1b10abSAndroid Build Coastguard Worker   // Search all possible scales up to the search param around the center point
1038*fb1b10abSAndroid Build Coastguard Worker   // pick the scale of the point that is best as the starting scale of
1039*fb1b10abSAndroid Build Coastguard Worker   // further steps around it.
1040*fb1b10abSAndroid Build Coastguard Worker   if (do_init_search) {
1041*fb1b10abSAndroid Build Coastguard Worker     s = best_init_s;
1042*fb1b10abSAndroid Build Coastguard Worker     best_init_s = -1;
1043*fb1b10abSAndroid Build Coastguard Worker     for (t = 0; t <= s; ++t) {
1044*fb1b10abSAndroid Build Coastguard Worker       int best_site = -1;
1045*fb1b10abSAndroid Build Coastguard Worker       if (check_bounds(&x->mv_limits, br, bc, 1 << t)) {
1046*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < num_candidates[t]; i++) {
1047*fb1b10abSAndroid Build Coastguard Worker           const MV this_mv = { br + candidates[t][i].row,
1048*fb1b10abSAndroid Build Coastguard Worker                                bc + candidates[t][i].col };
1049*fb1b10abSAndroid Build Coastguard Worker           thissad =
1050*fb1b10abSAndroid Build Coastguard Worker               vfp->sdf(what->buf, what->stride,
1051*fb1b10abSAndroid Build Coastguard Worker                        get_buf_from_mv(in_what, &this_mv), in_what->stride);
1052*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER
1053*fb1b10abSAndroid Build Coastguard Worker         }
1054*fb1b10abSAndroid Build Coastguard Worker       } else {
1055*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < num_candidates[t]; i++) {
1056*fb1b10abSAndroid Build Coastguard Worker           const MV this_mv = { br + candidates[t][i].row,
1057*fb1b10abSAndroid Build Coastguard Worker                                bc + candidates[t][i].col };
1058*fb1b10abSAndroid Build Coastguard Worker           if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
1059*fb1b10abSAndroid Build Coastguard Worker           thissad =
1060*fb1b10abSAndroid Build Coastguard Worker               vfp->sdf(what->buf, what->stride,
1061*fb1b10abSAndroid Build Coastguard Worker                        get_buf_from_mv(in_what, &this_mv), in_what->stride);
1062*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER
1063*fb1b10abSAndroid Build Coastguard Worker         }
1064*fb1b10abSAndroid Build Coastguard Worker       }
1065*fb1b10abSAndroid Build Coastguard Worker       if (best_site == -1) {
1066*fb1b10abSAndroid Build Coastguard Worker         continue;
1067*fb1b10abSAndroid Build Coastguard Worker       } else {
1068*fb1b10abSAndroid Build Coastguard Worker         best_init_s = t;
1069*fb1b10abSAndroid Build Coastguard Worker         k = best_site;
1070*fb1b10abSAndroid Build Coastguard Worker       }
1071*fb1b10abSAndroid Build Coastguard Worker     }
1072*fb1b10abSAndroid Build Coastguard Worker     if (best_init_s != -1) {
1073*fb1b10abSAndroid Build Coastguard Worker       br += candidates[best_init_s][k].row;
1074*fb1b10abSAndroid Build Coastguard Worker       bc += candidates[best_init_s][k].col;
1075*fb1b10abSAndroid Build Coastguard Worker     }
1076*fb1b10abSAndroid Build Coastguard Worker   }
1077*fb1b10abSAndroid Build Coastguard Worker 
1078*fb1b10abSAndroid Build Coastguard Worker   // If the center point is still the best, just skip this and move to
1079*fb1b10abSAndroid Build Coastguard Worker   // the refinement step.
1080*fb1b10abSAndroid Build Coastguard Worker   if (best_init_s != -1) {
1081*fb1b10abSAndroid Build Coastguard Worker     int best_site = -1;
1082*fb1b10abSAndroid Build Coastguard Worker     s = best_init_s;
1083*fb1b10abSAndroid Build Coastguard Worker 
1084*fb1b10abSAndroid Build Coastguard Worker     do {
1085*fb1b10abSAndroid Build Coastguard Worker       // No need to search all 6 points the 1st time if initial search was used
1086*fb1b10abSAndroid Build Coastguard Worker       if (!do_init_search || s != best_init_s) {
1087*fb1b10abSAndroid Build Coastguard Worker         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
1088*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < num_candidates[s]; i++) {
1089*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { br + candidates[s][i].row,
1090*fb1b10abSAndroid Build Coastguard Worker                                  bc + candidates[s][i].col };
1091*fb1b10abSAndroid Build Coastguard Worker             thissad =
1092*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1093*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1094*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1095*fb1b10abSAndroid Build Coastguard Worker           }
1096*fb1b10abSAndroid Build Coastguard Worker         } else {
1097*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < num_candidates[s]; i++) {
1098*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { br + candidates[s][i].row,
1099*fb1b10abSAndroid Build Coastguard Worker                                  bc + candidates[s][i].col };
1100*fb1b10abSAndroid Build Coastguard Worker             if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
1101*fb1b10abSAndroid Build Coastguard Worker             thissad =
1102*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1103*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1104*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1105*fb1b10abSAndroid Build Coastguard Worker           }
1106*fb1b10abSAndroid Build Coastguard Worker         }
1107*fb1b10abSAndroid Build Coastguard Worker 
1108*fb1b10abSAndroid Build Coastguard Worker         if (best_site == -1) {
1109*fb1b10abSAndroid Build Coastguard Worker           continue;
1110*fb1b10abSAndroid Build Coastguard Worker         } else {
1111*fb1b10abSAndroid Build Coastguard Worker           br += candidates[s][best_site].row;
1112*fb1b10abSAndroid Build Coastguard Worker           bc += candidates[s][best_site].col;
1113*fb1b10abSAndroid Build Coastguard Worker           k = best_site;
1114*fb1b10abSAndroid Build Coastguard Worker         }
1115*fb1b10abSAndroid Build Coastguard Worker       }
1116*fb1b10abSAndroid Build Coastguard Worker 
1117*fb1b10abSAndroid Build Coastguard Worker       do {
1118*fb1b10abSAndroid Build Coastguard Worker         int next_chkpts_indices[PATTERN_CANDIDATES_REF];
1119*fb1b10abSAndroid Build Coastguard Worker         best_site = -1;
1120*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[0] = (k == 0) ? num_candidates[s] - 1 : k - 1;
1121*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[1] = k;
1122*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[2] = (k == num_candidates[s] - 1) ? 0 : k + 1;
1123*fb1b10abSAndroid Build Coastguard Worker 
1124*fb1b10abSAndroid Build Coastguard Worker         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
1125*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
1126*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = {
1127*fb1b10abSAndroid Build Coastguard Worker               br + candidates[s][next_chkpts_indices[i]].row,
1128*fb1b10abSAndroid Build Coastguard Worker               bc + candidates[s][next_chkpts_indices[i]].col
1129*fb1b10abSAndroid Build Coastguard Worker             };
1130*fb1b10abSAndroid Build Coastguard Worker             thissad =
1131*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1132*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1133*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1134*fb1b10abSAndroid Build Coastguard Worker           }
1135*fb1b10abSAndroid Build Coastguard Worker         } else {
1136*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
1137*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = {
1138*fb1b10abSAndroid Build Coastguard Worker               br + candidates[s][next_chkpts_indices[i]].row,
1139*fb1b10abSAndroid Build Coastguard Worker               bc + candidates[s][next_chkpts_indices[i]].col
1140*fb1b10abSAndroid Build Coastguard Worker             };
1141*fb1b10abSAndroid Build Coastguard Worker             if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
1142*fb1b10abSAndroid Build Coastguard Worker             thissad =
1143*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1144*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1145*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1146*fb1b10abSAndroid Build Coastguard Worker           }
1147*fb1b10abSAndroid Build Coastguard Worker         }
1148*fb1b10abSAndroid Build Coastguard Worker 
1149*fb1b10abSAndroid Build Coastguard Worker         if (best_site != -1) {
1150*fb1b10abSAndroid Build Coastguard Worker           k = next_chkpts_indices[best_site];
1151*fb1b10abSAndroid Build Coastguard Worker           br += candidates[s][k].row;
1152*fb1b10abSAndroid Build Coastguard Worker           bc += candidates[s][k].col;
1153*fb1b10abSAndroid Build Coastguard Worker         }
1154*fb1b10abSAndroid Build Coastguard Worker       } while (best_site != -1);
1155*fb1b10abSAndroid Build Coastguard Worker     } while (s--);
1156*fb1b10abSAndroid Build Coastguard Worker   }
1157*fb1b10abSAndroid Build Coastguard Worker 
1158*fb1b10abSAndroid Build Coastguard Worker   best_mv->row = br;
1159*fb1b10abSAndroid Build Coastguard Worker   best_mv->col = bc;
1160*fb1b10abSAndroid Build Coastguard Worker 
1161*fb1b10abSAndroid Build Coastguard Worker   // Returns the one-away integer pel sad values around the best as follows:
1162*fb1b10abSAndroid Build Coastguard Worker   // cost_list[0]: cost at the best integer pel
1163*fb1b10abSAndroid Build Coastguard Worker   // cost_list[1]: cost at delta {0, -1} (left)   from the best integer pel
1164*fb1b10abSAndroid Build Coastguard Worker   // cost_list[2]: cost at delta { 1, 0} (bottom) from the best integer pel
1165*fb1b10abSAndroid Build Coastguard Worker   // cost_list[3]: cost at delta { 0, 1} (right)  from the best integer pel
1166*fb1b10abSAndroid Build Coastguard Worker   // cost_list[4]: cost at delta {-1, 0} (top)    from the best integer pel
1167*fb1b10abSAndroid Build Coastguard Worker   if (cost_list) {
1168*fb1b10abSAndroid Build Coastguard Worker     calc_int_cost_list(x, &fcenter_mv, sad_per_bit, vfp, best_mv, cost_list);
1169*fb1b10abSAndroid Build Coastguard Worker   }
1170*fb1b10abSAndroid Build Coastguard Worker   return bestsad;
1171*fb1b10abSAndroid Build Coastguard Worker }
1172*fb1b10abSAndroid Build Coastguard Worker 
1173*fb1b10abSAndroid Build Coastguard Worker // A specialized function where the smallest scale search candidates
1174*fb1b10abSAndroid Build Coastguard Worker // are 4 1-away neighbors, and cost_list is non-null
1175*fb1b10abSAndroid Build Coastguard Worker // TODO(debargha): Merge this function with the one above. Also remove
1176*fb1b10abSAndroid Build Coastguard Worker // use_mvcost option since it is always 1, to save unnecessary branches.
vp9_pattern_search_sad(const MACROBLOCK * x,MV * ref_mv,int search_param,int sad_per_bit,int do_init_search,int * cost_list,const vp9_variance_fn_ptr_t * vfp,int use_mvcost,const MV * center_mv,MV * best_mv,const int num_candidates[MAX_PATTERN_SCALES],const MV candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES])1177*fb1b10abSAndroid Build Coastguard Worker static int vp9_pattern_search_sad(
1178*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *ref_mv, int search_param, int sad_per_bit,
1179*fb1b10abSAndroid Build Coastguard Worker     int do_init_search, int *cost_list, const vp9_variance_fn_ptr_t *vfp,
1180*fb1b10abSAndroid Build Coastguard Worker     int use_mvcost, const MV *center_mv, MV *best_mv,
1181*fb1b10abSAndroid Build Coastguard Worker     const int num_candidates[MAX_PATTERN_SCALES],
1182*fb1b10abSAndroid Build Coastguard Worker     const MV candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES]) {
1183*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1184*fb1b10abSAndroid Build Coastguard Worker   static const int search_param_to_steps[MAX_MVSEARCH_STEPS] = {
1185*fb1b10abSAndroid Build Coastguard Worker     10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
1186*fb1b10abSAndroid Build Coastguard Worker   };
1187*fb1b10abSAndroid Build Coastguard Worker   int i, s, t;
1188*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
1189*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
1190*fb1b10abSAndroid Build Coastguard Worker   int br, bc;
1191*fb1b10abSAndroid Build Coastguard Worker   int bestsad = INT_MAX;
1192*fb1b10abSAndroid Build Coastguard Worker   int thissad;
1193*fb1b10abSAndroid Build Coastguard Worker   int k = -1;
1194*fb1b10abSAndroid Build Coastguard Worker   const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
1195*fb1b10abSAndroid Build Coastguard Worker   int best_init_s = search_param_to_steps[search_param];
1196*fb1b10abSAndroid Build Coastguard Worker   // adjust ref_mv to make sure it is within MV range
1197*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(ref_mv, x->mv_limits.col_min, x->mv_limits.col_max,
1198*fb1b10abSAndroid Build Coastguard Worker            x->mv_limits.row_min, x->mv_limits.row_max);
1199*fb1b10abSAndroid Build Coastguard Worker   br = ref_mv->row;
1200*fb1b10abSAndroid Build Coastguard Worker   bc = ref_mv->col;
1201*fb1b10abSAndroid Build Coastguard Worker   if (cost_list != NULL) {
1202*fb1b10abSAndroid Build Coastguard Worker     cost_list[0] = cost_list[1] = cost_list[2] = cost_list[3] = cost_list[4] =
1203*fb1b10abSAndroid Build Coastguard Worker         INT_MAX;
1204*fb1b10abSAndroid Build Coastguard Worker   }
1205*fb1b10abSAndroid Build Coastguard Worker 
1206*fb1b10abSAndroid Build Coastguard Worker   // Work out the start point for the search
1207*fb1b10abSAndroid Build Coastguard Worker   bestsad = vfp->sdf(what->buf, what->stride, get_buf_from_mv(in_what, ref_mv),
1208*fb1b10abSAndroid Build Coastguard Worker                      in_what->stride) +
1209*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(x, ref_mv, &fcenter_mv, sad_per_bit);
1210*fb1b10abSAndroid Build Coastguard Worker 
1211*fb1b10abSAndroid Build Coastguard Worker   // Search all possible scales up to the search param around the center point
1212*fb1b10abSAndroid Build Coastguard Worker   // pick the scale of the point that is best as the starting scale of
1213*fb1b10abSAndroid Build Coastguard Worker   // further steps around it.
1214*fb1b10abSAndroid Build Coastguard Worker   if (do_init_search) {
1215*fb1b10abSAndroid Build Coastguard Worker     s = best_init_s;
1216*fb1b10abSAndroid Build Coastguard Worker     best_init_s = -1;
1217*fb1b10abSAndroid Build Coastguard Worker     for (t = 0; t <= s; ++t) {
1218*fb1b10abSAndroid Build Coastguard Worker       int best_site = -1;
1219*fb1b10abSAndroid Build Coastguard Worker       if (check_bounds(&x->mv_limits, br, bc, 1 << t)) {
1220*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < num_candidates[t]; i++) {
1221*fb1b10abSAndroid Build Coastguard Worker           const MV this_mv = { br + candidates[t][i].row,
1222*fb1b10abSAndroid Build Coastguard Worker                                bc + candidates[t][i].col };
1223*fb1b10abSAndroid Build Coastguard Worker           thissad =
1224*fb1b10abSAndroid Build Coastguard Worker               vfp->sdf(what->buf, what->stride,
1225*fb1b10abSAndroid Build Coastguard Worker                        get_buf_from_mv(in_what, &this_mv), in_what->stride);
1226*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER
1227*fb1b10abSAndroid Build Coastguard Worker         }
1228*fb1b10abSAndroid Build Coastguard Worker       } else {
1229*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < num_candidates[t]; i++) {
1230*fb1b10abSAndroid Build Coastguard Worker           const MV this_mv = { br + candidates[t][i].row,
1231*fb1b10abSAndroid Build Coastguard Worker                                bc + candidates[t][i].col };
1232*fb1b10abSAndroid Build Coastguard Worker           if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
1233*fb1b10abSAndroid Build Coastguard Worker           thissad =
1234*fb1b10abSAndroid Build Coastguard Worker               vfp->sdf(what->buf, what->stride,
1235*fb1b10abSAndroid Build Coastguard Worker                        get_buf_from_mv(in_what, &this_mv), in_what->stride);
1236*fb1b10abSAndroid Build Coastguard Worker           CHECK_BETTER
1237*fb1b10abSAndroid Build Coastguard Worker         }
1238*fb1b10abSAndroid Build Coastguard Worker       }
1239*fb1b10abSAndroid Build Coastguard Worker       if (best_site == -1) {
1240*fb1b10abSAndroid Build Coastguard Worker         continue;
1241*fb1b10abSAndroid Build Coastguard Worker       } else {
1242*fb1b10abSAndroid Build Coastguard Worker         best_init_s = t;
1243*fb1b10abSAndroid Build Coastguard Worker         k = best_site;
1244*fb1b10abSAndroid Build Coastguard Worker       }
1245*fb1b10abSAndroid Build Coastguard Worker     }
1246*fb1b10abSAndroid Build Coastguard Worker     if (best_init_s != -1) {
1247*fb1b10abSAndroid Build Coastguard Worker       br += candidates[best_init_s][k].row;
1248*fb1b10abSAndroid Build Coastguard Worker       bc += candidates[best_init_s][k].col;
1249*fb1b10abSAndroid Build Coastguard Worker     }
1250*fb1b10abSAndroid Build Coastguard Worker   }
1251*fb1b10abSAndroid Build Coastguard Worker 
1252*fb1b10abSAndroid Build Coastguard Worker   // If the center point is still the best, just skip this and move to
1253*fb1b10abSAndroid Build Coastguard Worker   // the refinement step.
1254*fb1b10abSAndroid Build Coastguard Worker   if (best_init_s != -1) {
1255*fb1b10abSAndroid Build Coastguard Worker     int do_sad = (num_candidates[0] == 4 && cost_list != NULL);
1256*fb1b10abSAndroid Build Coastguard Worker     int best_site = -1;
1257*fb1b10abSAndroid Build Coastguard Worker     s = best_init_s;
1258*fb1b10abSAndroid Build Coastguard Worker 
1259*fb1b10abSAndroid Build Coastguard Worker     for (; s >= do_sad; s--) {
1260*fb1b10abSAndroid Build Coastguard Worker       if (!do_init_search || s != best_init_s) {
1261*fb1b10abSAndroid Build Coastguard Worker         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
1262*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < num_candidates[s]; i++) {
1263*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { br + candidates[s][i].row,
1264*fb1b10abSAndroid Build Coastguard Worker                                  bc + candidates[s][i].col };
1265*fb1b10abSAndroid Build Coastguard Worker             thissad =
1266*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1267*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1268*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1269*fb1b10abSAndroid Build Coastguard Worker           }
1270*fb1b10abSAndroid Build Coastguard Worker         } else {
1271*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < num_candidates[s]; i++) {
1272*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { br + candidates[s][i].row,
1273*fb1b10abSAndroid Build Coastguard Worker                                  bc + candidates[s][i].col };
1274*fb1b10abSAndroid Build Coastguard Worker             if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
1275*fb1b10abSAndroid Build Coastguard Worker             thissad =
1276*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1277*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1278*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1279*fb1b10abSAndroid Build Coastguard Worker           }
1280*fb1b10abSAndroid Build Coastguard Worker         }
1281*fb1b10abSAndroid Build Coastguard Worker 
1282*fb1b10abSAndroid Build Coastguard Worker         if (best_site == -1) {
1283*fb1b10abSAndroid Build Coastguard Worker           continue;
1284*fb1b10abSAndroid Build Coastguard Worker         } else {
1285*fb1b10abSAndroid Build Coastguard Worker           br += candidates[s][best_site].row;
1286*fb1b10abSAndroid Build Coastguard Worker           bc += candidates[s][best_site].col;
1287*fb1b10abSAndroid Build Coastguard Worker           k = best_site;
1288*fb1b10abSAndroid Build Coastguard Worker         }
1289*fb1b10abSAndroid Build Coastguard Worker       }
1290*fb1b10abSAndroid Build Coastguard Worker 
1291*fb1b10abSAndroid Build Coastguard Worker       do {
1292*fb1b10abSAndroid Build Coastguard Worker         int next_chkpts_indices[PATTERN_CANDIDATES_REF];
1293*fb1b10abSAndroid Build Coastguard Worker         best_site = -1;
1294*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[0] = (k == 0) ? num_candidates[s] - 1 : k - 1;
1295*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[1] = k;
1296*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[2] = (k == num_candidates[s] - 1) ? 0 : k + 1;
1297*fb1b10abSAndroid Build Coastguard Worker 
1298*fb1b10abSAndroid Build Coastguard Worker         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
1299*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
1300*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = {
1301*fb1b10abSAndroid Build Coastguard Worker               br + candidates[s][next_chkpts_indices[i]].row,
1302*fb1b10abSAndroid Build Coastguard Worker               bc + candidates[s][next_chkpts_indices[i]].col
1303*fb1b10abSAndroid Build Coastguard Worker             };
1304*fb1b10abSAndroid Build Coastguard Worker             thissad =
1305*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1306*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1307*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1308*fb1b10abSAndroid Build Coastguard Worker           }
1309*fb1b10abSAndroid Build Coastguard Worker         } else {
1310*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
1311*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = {
1312*fb1b10abSAndroid Build Coastguard Worker               br + candidates[s][next_chkpts_indices[i]].row,
1313*fb1b10abSAndroid Build Coastguard Worker               bc + candidates[s][next_chkpts_indices[i]].col
1314*fb1b10abSAndroid Build Coastguard Worker             };
1315*fb1b10abSAndroid Build Coastguard Worker             if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
1316*fb1b10abSAndroid Build Coastguard Worker             thissad =
1317*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1318*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1319*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1320*fb1b10abSAndroid Build Coastguard Worker           }
1321*fb1b10abSAndroid Build Coastguard Worker         }
1322*fb1b10abSAndroid Build Coastguard Worker 
1323*fb1b10abSAndroid Build Coastguard Worker         if (best_site != -1) {
1324*fb1b10abSAndroid Build Coastguard Worker           k = next_chkpts_indices[best_site];
1325*fb1b10abSAndroid Build Coastguard Worker           br += candidates[s][k].row;
1326*fb1b10abSAndroid Build Coastguard Worker           bc += candidates[s][k].col;
1327*fb1b10abSAndroid Build Coastguard Worker         }
1328*fb1b10abSAndroid Build Coastguard Worker       } while (best_site != -1);
1329*fb1b10abSAndroid Build Coastguard Worker     }
1330*fb1b10abSAndroid Build Coastguard Worker 
1331*fb1b10abSAndroid Build Coastguard Worker     // Note: If we enter the if below, then cost_list must be non-NULL.
1332*fb1b10abSAndroid Build Coastguard Worker     if (s == 0) {
1333*fb1b10abSAndroid Build Coastguard Worker       cost_list[0] = bestsad;
1334*fb1b10abSAndroid Build Coastguard Worker       if (!do_init_search || s != best_init_s) {
1335*fb1b10abSAndroid Build Coastguard Worker         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
1336*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < num_candidates[s]; i++) {
1337*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { br + candidates[s][i].row,
1338*fb1b10abSAndroid Build Coastguard Worker                                  bc + candidates[s][i].col };
1339*fb1b10abSAndroid Build Coastguard Worker             cost_list[i + 1] = thissad =
1340*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1341*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1342*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1343*fb1b10abSAndroid Build Coastguard Worker           }
1344*fb1b10abSAndroid Build Coastguard Worker         } else {
1345*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < num_candidates[s]; i++) {
1346*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { br + candidates[s][i].row,
1347*fb1b10abSAndroid Build Coastguard Worker                                  bc + candidates[s][i].col };
1348*fb1b10abSAndroid Build Coastguard Worker             if (!is_mv_in(&x->mv_limits, &this_mv)) continue;
1349*fb1b10abSAndroid Build Coastguard Worker             cost_list[i + 1] = thissad =
1350*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1351*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1352*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1353*fb1b10abSAndroid Build Coastguard Worker           }
1354*fb1b10abSAndroid Build Coastguard Worker         }
1355*fb1b10abSAndroid Build Coastguard Worker 
1356*fb1b10abSAndroid Build Coastguard Worker         if (best_site != -1) {
1357*fb1b10abSAndroid Build Coastguard Worker           br += candidates[s][best_site].row;
1358*fb1b10abSAndroid Build Coastguard Worker           bc += candidates[s][best_site].col;
1359*fb1b10abSAndroid Build Coastguard Worker           k = best_site;
1360*fb1b10abSAndroid Build Coastguard Worker         }
1361*fb1b10abSAndroid Build Coastguard Worker       }
1362*fb1b10abSAndroid Build Coastguard Worker       while (best_site != -1) {
1363*fb1b10abSAndroid Build Coastguard Worker         int next_chkpts_indices[PATTERN_CANDIDATES_REF];
1364*fb1b10abSAndroid Build Coastguard Worker         best_site = -1;
1365*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[0] = (k == 0) ? num_candidates[s] - 1 : k - 1;
1366*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[1] = k;
1367*fb1b10abSAndroid Build Coastguard Worker         next_chkpts_indices[2] = (k == num_candidates[s] - 1) ? 0 : k + 1;
1368*fb1b10abSAndroid Build Coastguard Worker         cost_list[1] = cost_list[2] = cost_list[3] = cost_list[4] = INT_MAX;
1369*fb1b10abSAndroid Build Coastguard Worker         cost_list[((k + 2) % 4) + 1] = cost_list[0];
1370*fb1b10abSAndroid Build Coastguard Worker         cost_list[0] = bestsad;
1371*fb1b10abSAndroid Build Coastguard Worker 
1372*fb1b10abSAndroid Build Coastguard Worker         if (check_bounds(&x->mv_limits, br, bc, 1 << s)) {
1373*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
1374*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = {
1375*fb1b10abSAndroid Build Coastguard Worker               br + candidates[s][next_chkpts_indices[i]].row,
1376*fb1b10abSAndroid Build Coastguard Worker               bc + candidates[s][next_chkpts_indices[i]].col
1377*fb1b10abSAndroid Build Coastguard Worker             };
1378*fb1b10abSAndroid Build Coastguard Worker             cost_list[next_chkpts_indices[i] + 1] = thissad =
1379*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1380*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1381*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1382*fb1b10abSAndroid Build Coastguard Worker           }
1383*fb1b10abSAndroid Build Coastguard Worker         } else {
1384*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < PATTERN_CANDIDATES_REF; i++) {
1385*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = {
1386*fb1b10abSAndroid Build Coastguard Worker               br + candidates[s][next_chkpts_indices[i]].row,
1387*fb1b10abSAndroid Build Coastguard Worker               bc + candidates[s][next_chkpts_indices[i]].col
1388*fb1b10abSAndroid Build Coastguard Worker             };
1389*fb1b10abSAndroid Build Coastguard Worker             if (!is_mv_in(&x->mv_limits, &this_mv)) {
1390*fb1b10abSAndroid Build Coastguard Worker               cost_list[next_chkpts_indices[i] + 1] = INT_MAX;
1391*fb1b10abSAndroid Build Coastguard Worker               continue;
1392*fb1b10abSAndroid Build Coastguard Worker             }
1393*fb1b10abSAndroid Build Coastguard Worker             cost_list[next_chkpts_indices[i] + 1] = thissad =
1394*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1395*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1396*fb1b10abSAndroid Build Coastguard Worker             CHECK_BETTER
1397*fb1b10abSAndroid Build Coastguard Worker           }
1398*fb1b10abSAndroid Build Coastguard Worker         }
1399*fb1b10abSAndroid Build Coastguard Worker 
1400*fb1b10abSAndroid Build Coastguard Worker         if (best_site != -1) {
1401*fb1b10abSAndroid Build Coastguard Worker           k = next_chkpts_indices[best_site];
1402*fb1b10abSAndroid Build Coastguard Worker           br += candidates[s][k].row;
1403*fb1b10abSAndroid Build Coastguard Worker           bc += candidates[s][k].col;
1404*fb1b10abSAndroid Build Coastguard Worker         }
1405*fb1b10abSAndroid Build Coastguard Worker       }
1406*fb1b10abSAndroid Build Coastguard Worker     }
1407*fb1b10abSAndroid Build Coastguard Worker   }
1408*fb1b10abSAndroid Build Coastguard Worker 
1409*fb1b10abSAndroid Build Coastguard Worker   // Returns the one-away integer pel sad values around the best as follows:
1410*fb1b10abSAndroid Build Coastguard Worker   // cost_list[0]: sad at the best integer pel
1411*fb1b10abSAndroid Build Coastguard Worker   // cost_list[1]: sad at delta {0, -1} (left)   from the best integer pel
1412*fb1b10abSAndroid Build Coastguard Worker   // cost_list[2]: sad at delta { 1, 0} (bottom) from the best integer pel
1413*fb1b10abSAndroid Build Coastguard Worker   // cost_list[3]: sad at delta { 0, 1} (right)  from the best integer pel
1414*fb1b10abSAndroid Build Coastguard Worker   // cost_list[4]: sad at delta {-1, 0} (top)    from the best integer pel
1415*fb1b10abSAndroid Build Coastguard Worker   if (cost_list) {
1416*fb1b10abSAndroid Build Coastguard Worker     static const MV neighbors[4] = { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 } };
1417*fb1b10abSAndroid Build Coastguard Worker     if (cost_list[0] == INT_MAX) {
1418*fb1b10abSAndroid Build Coastguard Worker       cost_list[0] = bestsad;
1419*fb1b10abSAndroid Build Coastguard Worker       if (check_bounds(&x->mv_limits, br, bc, 1)) {
1420*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < 4; i++) {
1421*fb1b10abSAndroid Build Coastguard Worker           const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
1422*fb1b10abSAndroid Build Coastguard Worker           cost_list[i + 1] =
1423*fb1b10abSAndroid Build Coastguard Worker               vfp->sdf(what->buf, what->stride,
1424*fb1b10abSAndroid Build Coastguard Worker                        get_buf_from_mv(in_what, &this_mv), in_what->stride);
1425*fb1b10abSAndroid Build Coastguard Worker         }
1426*fb1b10abSAndroid Build Coastguard Worker       } else {
1427*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < 4; i++) {
1428*fb1b10abSAndroid Build Coastguard Worker           const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
1429*fb1b10abSAndroid Build Coastguard Worker           if (!is_mv_in(&x->mv_limits, &this_mv))
1430*fb1b10abSAndroid Build Coastguard Worker             cost_list[i + 1] = INT_MAX;
1431*fb1b10abSAndroid Build Coastguard Worker           else
1432*fb1b10abSAndroid Build Coastguard Worker             cost_list[i + 1] =
1433*fb1b10abSAndroid Build Coastguard Worker                 vfp->sdf(what->buf, what->stride,
1434*fb1b10abSAndroid Build Coastguard Worker                          get_buf_from_mv(in_what, &this_mv), in_what->stride);
1435*fb1b10abSAndroid Build Coastguard Worker         }
1436*fb1b10abSAndroid Build Coastguard Worker       }
1437*fb1b10abSAndroid Build Coastguard Worker     } else {
1438*fb1b10abSAndroid Build Coastguard Worker       if (use_mvcost) {
1439*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < 4; i++) {
1440*fb1b10abSAndroid Build Coastguard Worker           const MV this_mv = { br + neighbors[i].row, bc + neighbors[i].col };
1441*fb1b10abSAndroid Build Coastguard Worker           if (cost_list[i + 1] != INT_MAX) {
1442*fb1b10abSAndroid Build Coastguard Worker             cost_list[i + 1] +=
1443*fb1b10abSAndroid Build Coastguard Worker                 mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
1444*fb1b10abSAndroid Build Coastguard Worker           }
1445*fb1b10abSAndroid Build Coastguard Worker         }
1446*fb1b10abSAndroid Build Coastguard Worker       }
1447*fb1b10abSAndroid Build Coastguard Worker     }
1448*fb1b10abSAndroid Build Coastguard Worker   }
1449*fb1b10abSAndroid Build Coastguard Worker   best_mv->row = br;
1450*fb1b10abSAndroid Build Coastguard Worker   best_mv->col = bc;
1451*fb1b10abSAndroid Build Coastguard Worker   return bestsad;
1452*fb1b10abSAndroid Build Coastguard Worker }
1453*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_mvpred_var(const MACROBLOCK * x,const MV * best_mv,const MV * center_mv,const vp9_variance_fn_ptr_t * vfp,int use_mvcost)1454*fb1b10abSAndroid Build Coastguard Worker int vp9_get_mvpred_var(const MACROBLOCK *x, const MV *best_mv,
1455*fb1b10abSAndroid Build Coastguard Worker                        const MV *center_mv, const vp9_variance_fn_ptr_t *vfp,
1456*fb1b10abSAndroid Build Coastguard Worker                        int use_mvcost) {
1457*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1458*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
1459*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
1460*fb1b10abSAndroid Build Coastguard Worker   const MV mv = { best_mv->row * 8, best_mv->col * 8 };
1461*fb1b10abSAndroid Build Coastguard Worker   uint32_t unused;
1462*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1463*fb1b10abSAndroid Build Coastguard Worker   uint64_t err =
1464*fb1b10abSAndroid Build Coastguard Worker       vfp->vf(what->buf, what->stride, get_buf_from_mv(in_what, best_mv),
1465*fb1b10abSAndroid Build Coastguard Worker               in_what->stride, &unused);
1466*fb1b10abSAndroid Build Coastguard Worker   err += (use_mvcost ? mv_err_cost(&mv, center_mv, x->nmvjointcost, x->mvcost,
1467*fb1b10abSAndroid Build Coastguard Worker                                    x->errorperbit)
1468*fb1b10abSAndroid Build Coastguard Worker                      : 0);
1469*fb1b10abSAndroid Build Coastguard Worker   if (err >= INT_MAX) return INT_MAX;
1470*fb1b10abSAndroid Build Coastguard Worker   return (int)err;
1471*fb1b10abSAndroid Build Coastguard Worker #else
1472*fb1b10abSAndroid Build Coastguard Worker   return vfp->vf(what->buf, what->stride, get_buf_from_mv(in_what, best_mv),
1473*fb1b10abSAndroid Build Coastguard Worker                  in_what->stride, &unused) +
1474*fb1b10abSAndroid Build Coastguard Worker          (use_mvcost ? mv_err_cost(&mv, center_mv, x->nmvjointcost, x->mvcost,
1475*fb1b10abSAndroid Build Coastguard Worker                                    x->errorperbit)
1476*fb1b10abSAndroid Build Coastguard Worker                      : 0);
1477*fb1b10abSAndroid Build Coastguard Worker #endif
1478*fb1b10abSAndroid Build Coastguard Worker }
1479*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_mvpred_av_var(const MACROBLOCK * x,const MV * best_mv,const MV * center_mv,const uint8_t * second_pred,const vp9_variance_fn_ptr_t * vfp,int use_mvcost)1480*fb1b10abSAndroid Build Coastguard Worker int vp9_get_mvpred_av_var(const MACROBLOCK *x, const MV *best_mv,
1481*fb1b10abSAndroid Build Coastguard Worker                           const MV *center_mv, const uint8_t *second_pred,
1482*fb1b10abSAndroid Build Coastguard Worker                           const vp9_variance_fn_ptr_t *vfp, int use_mvcost) {
1483*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1484*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
1485*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
1486*fb1b10abSAndroid Build Coastguard Worker   const MV mv = { best_mv->row * 8, best_mv->col * 8 };
1487*fb1b10abSAndroid Build Coastguard Worker   unsigned int unused;
1488*fb1b10abSAndroid Build Coastguard Worker 
1489*fb1b10abSAndroid Build Coastguard Worker   return vfp->svaf(get_buf_from_mv(in_what, best_mv), in_what->stride, 0, 0,
1490*fb1b10abSAndroid Build Coastguard Worker                    what->buf, what->stride, &unused, second_pred) +
1491*fb1b10abSAndroid Build Coastguard Worker          (use_mvcost ? mv_err_cost(&mv, center_mv, x->nmvjointcost, x->mvcost,
1492*fb1b10abSAndroid Build Coastguard Worker                                    x->errorperbit)
1493*fb1b10abSAndroid Build Coastguard Worker                      : 0);
1494*fb1b10abSAndroid Build Coastguard Worker }
1495*fb1b10abSAndroid Build Coastguard Worker 
hex_search(const MACROBLOCK * x,MV * ref_mv,int search_param,int sad_per_bit,int do_init_search,int * cost_list,const vp9_variance_fn_ptr_t * vfp,int use_mvcost,const MV * center_mv,MV * best_mv)1496*fb1b10abSAndroid Build Coastguard Worker static int hex_search(const MACROBLOCK *x, MV *ref_mv, int search_param,
1497*fb1b10abSAndroid Build Coastguard Worker                       int sad_per_bit, int do_init_search, int *cost_list,
1498*fb1b10abSAndroid Build Coastguard Worker                       const vp9_variance_fn_ptr_t *vfp, int use_mvcost,
1499*fb1b10abSAndroid Build Coastguard Worker                       const MV *center_mv, MV *best_mv) {
1500*fb1b10abSAndroid Build Coastguard Worker   // First scale has 8-closest points, the rest have 6 points in hex shape
1501*fb1b10abSAndroid Build Coastguard Worker   // at increasing scales
1502*fb1b10abSAndroid Build Coastguard Worker   static const int hex_num_candidates[MAX_PATTERN_SCALES] = { 8, 6, 6, 6, 6, 6,
1503*fb1b10abSAndroid Build Coastguard Worker                                                               6, 6, 6, 6, 6 };
1504*fb1b10abSAndroid Build Coastguard Worker   // Note that the largest candidate step at each scale is 2^scale
1505*fb1b10abSAndroid Build Coastguard Worker   /* clang-format off */
1506*fb1b10abSAndroid Build Coastguard Worker   static const MV hex_candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES] = {
1507*fb1b10abSAndroid Build Coastguard Worker     { { -1, -1 }, { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 },
1508*fb1b10abSAndroid Build Coastguard Worker       { -1, 0 } },
1509*fb1b10abSAndroid Build Coastguard Worker     { { -1, -2 }, { 1, -2 }, { 2, 0 }, { 1, 2 }, { -1, 2 }, { -2, 0 } },
1510*fb1b10abSAndroid Build Coastguard Worker     { { -2, -4 }, { 2, -4 }, { 4, 0 }, { 2, 4 }, { -2, 4 }, { -4, 0 } },
1511*fb1b10abSAndroid Build Coastguard Worker     { { -4, -8 }, { 4, -8 }, { 8, 0 }, { 4, 8 }, { -4, 8 }, { -8, 0 } },
1512*fb1b10abSAndroid Build Coastguard Worker     { { -8, -16 }, { 8, -16 }, { 16, 0 }, { 8, 16 }, { -8, 16 }, { -16, 0 } },
1513*fb1b10abSAndroid Build Coastguard Worker     { { -16, -32 }, { 16, -32 }, { 32, 0 }, { 16, 32 }, { -16, 32 },
1514*fb1b10abSAndroid Build Coastguard Worker       { -32, 0 } },
1515*fb1b10abSAndroid Build Coastguard Worker     { { -32, -64 }, { 32, -64 }, { 64, 0 }, { 32, 64 }, { -32, 64 },
1516*fb1b10abSAndroid Build Coastguard Worker       { -64, 0 } },
1517*fb1b10abSAndroid Build Coastguard Worker     { { -64, -128 }, { 64, -128 }, { 128, 0 }, { 64, 128 }, { -64, 128 },
1518*fb1b10abSAndroid Build Coastguard Worker       { -128, 0 } },
1519*fb1b10abSAndroid Build Coastguard Worker     { { -128, -256 }, { 128, -256 }, { 256, 0 }, { 128, 256 }, { -128, 256 },
1520*fb1b10abSAndroid Build Coastguard Worker       { -256, 0 } },
1521*fb1b10abSAndroid Build Coastguard Worker     { { -256, -512 }, { 256, -512 }, { 512, 0 }, { 256, 512 }, { -256, 512 },
1522*fb1b10abSAndroid Build Coastguard Worker       { -512, 0 } },
1523*fb1b10abSAndroid Build Coastguard Worker     { { -512, -1024 }, { 512, -1024 }, { 1024, 0 }, { 512, 1024 },
1524*fb1b10abSAndroid Build Coastguard Worker       { -512, 1024 }, { -1024, 0 } }
1525*fb1b10abSAndroid Build Coastguard Worker   };
1526*fb1b10abSAndroid Build Coastguard Worker   /* clang-format on */
1527*fb1b10abSAndroid Build Coastguard Worker   return vp9_pattern_search(
1528*fb1b10abSAndroid Build Coastguard Worker       x, ref_mv, search_param, sad_per_bit, do_init_search, cost_list, vfp,
1529*fb1b10abSAndroid Build Coastguard Worker       use_mvcost, center_mv, best_mv, hex_num_candidates, hex_candidates);
1530*fb1b10abSAndroid Build Coastguard Worker }
1531*fb1b10abSAndroid Build Coastguard Worker 
bigdia_search(const MACROBLOCK * x,MV * ref_mv,int search_param,int sad_per_bit,int do_init_search,int * cost_list,const vp9_variance_fn_ptr_t * vfp,int use_mvcost,const MV * center_mv,MV * best_mv)1532*fb1b10abSAndroid Build Coastguard Worker static int bigdia_search(const MACROBLOCK *x, MV *ref_mv, int search_param,
1533*fb1b10abSAndroid Build Coastguard Worker                          int sad_per_bit, int do_init_search, int *cost_list,
1534*fb1b10abSAndroid Build Coastguard Worker                          const vp9_variance_fn_ptr_t *vfp, int use_mvcost,
1535*fb1b10abSAndroid Build Coastguard Worker                          const MV *center_mv, MV *best_mv) {
1536*fb1b10abSAndroid Build Coastguard Worker   // First scale has 4-closest points, the rest have 8 points in diamond
1537*fb1b10abSAndroid Build Coastguard Worker   // shape at increasing scales
1538*fb1b10abSAndroid Build Coastguard Worker   static const int bigdia_num_candidates[MAX_PATTERN_SCALES] = {
1539*fb1b10abSAndroid Build Coastguard Worker     4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
1540*fb1b10abSAndroid Build Coastguard Worker   };
1541*fb1b10abSAndroid Build Coastguard Worker   // Note that the largest candidate step at each scale is 2^scale
1542*fb1b10abSAndroid Build Coastguard Worker   /* clang-format off */
1543*fb1b10abSAndroid Build Coastguard Worker   static const MV
1544*fb1b10abSAndroid Build Coastguard Worker       bigdia_candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES] = {
1545*fb1b10abSAndroid Build Coastguard Worker         { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 } },
1546*fb1b10abSAndroid Build Coastguard Worker         { { -1, -1 }, { 0, -2 }, { 1, -1 }, { 2, 0 }, { 1, 1 }, { 0, 2 },
1547*fb1b10abSAndroid Build Coastguard Worker           { -1, 1 }, { -2, 0 } },
1548*fb1b10abSAndroid Build Coastguard Worker         { { -2, -2 }, { 0, -4 }, { 2, -2 }, { 4, 0 }, { 2, 2 }, { 0, 4 },
1549*fb1b10abSAndroid Build Coastguard Worker           { -2, 2 }, { -4, 0 } },
1550*fb1b10abSAndroid Build Coastguard Worker         { { -4, -4 }, { 0, -8 }, { 4, -4 }, { 8, 0 }, { 4, 4 }, { 0, 8 },
1551*fb1b10abSAndroid Build Coastguard Worker           { -4, 4 }, { -8, 0 } },
1552*fb1b10abSAndroid Build Coastguard Worker         { { -8, -8 }, { 0, -16 }, { 8, -8 }, { 16, 0 }, { 8, 8 }, { 0, 16 },
1553*fb1b10abSAndroid Build Coastguard Worker           { -8, 8 }, { -16, 0 } },
1554*fb1b10abSAndroid Build Coastguard Worker         { { -16, -16 }, { 0, -32 }, { 16, -16 }, { 32, 0 }, { 16, 16 },
1555*fb1b10abSAndroid Build Coastguard Worker           { 0, 32 }, { -16, 16 }, { -32, 0 } },
1556*fb1b10abSAndroid Build Coastguard Worker         { { -32, -32 }, { 0, -64 }, { 32, -32 }, { 64, 0 }, { 32, 32 },
1557*fb1b10abSAndroid Build Coastguard Worker           { 0, 64 }, { -32, 32 }, { -64, 0 } },
1558*fb1b10abSAndroid Build Coastguard Worker         { { -64, -64 }, { 0, -128 }, { 64, -64 }, { 128, 0 }, { 64, 64 },
1559*fb1b10abSAndroid Build Coastguard Worker           { 0, 128 }, { -64, 64 }, { -128, 0 } },
1560*fb1b10abSAndroid Build Coastguard Worker         { { -128, -128 }, { 0, -256 }, { 128, -128 }, { 256, 0 }, { 128, 128 },
1561*fb1b10abSAndroid Build Coastguard Worker           { 0, 256 }, { -128, 128 }, { -256, 0 } },
1562*fb1b10abSAndroid Build Coastguard Worker         { { -256, -256 }, { 0, -512 }, { 256, -256 }, { 512, 0 }, { 256, 256 },
1563*fb1b10abSAndroid Build Coastguard Worker           { 0, 512 }, { -256, 256 }, { -512, 0 } },
1564*fb1b10abSAndroid Build Coastguard Worker         { { -512, -512 }, { 0, -1024 }, { 512, -512 }, { 1024, 0 },
1565*fb1b10abSAndroid Build Coastguard Worker           { 512, 512 }, { 0, 1024 }, { -512, 512 }, { -1024, 0 } }
1566*fb1b10abSAndroid Build Coastguard Worker       };
1567*fb1b10abSAndroid Build Coastguard Worker   /* clang-format on */
1568*fb1b10abSAndroid Build Coastguard Worker   return vp9_pattern_search_sad(
1569*fb1b10abSAndroid Build Coastguard Worker       x, ref_mv, search_param, sad_per_bit, do_init_search, cost_list, vfp,
1570*fb1b10abSAndroid Build Coastguard Worker       use_mvcost, center_mv, best_mv, bigdia_num_candidates, bigdia_candidates);
1571*fb1b10abSAndroid Build Coastguard Worker }
1572*fb1b10abSAndroid Build Coastguard Worker 
square_search(const MACROBLOCK * x,MV * ref_mv,int search_param,int sad_per_bit,int do_init_search,int * cost_list,const vp9_variance_fn_ptr_t * vfp,int use_mvcost,const MV * center_mv,MV * best_mv)1573*fb1b10abSAndroid Build Coastguard Worker static int square_search(const MACROBLOCK *x, MV *ref_mv, int search_param,
1574*fb1b10abSAndroid Build Coastguard Worker                          int sad_per_bit, int do_init_search, int *cost_list,
1575*fb1b10abSAndroid Build Coastguard Worker                          const vp9_variance_fn_ptr_t *vfp, int use_mvcost,
1576*fb1b10abSAndroid Build Coastguard Worker                          const MV *center_mv, MV *best_mv) {
1577*fb1b10abSAndroid Build Coastguard Worker   // All scales have 8 closest points in square shape
1578*fb1b10abSAndroid Build Coastguard Worker   static const int square_num_candidates[MAX_PATTERN_SCALES] = {
1579*fb1b10abSAndroid Build Coastguard Worker     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
1580*fb1b10abSAndroid Build Coastguard Worker   };
1581*fb1b10abSAndroid Build Coastguard Worker   // Note that the largest candidate step at each scale is 2^scale
1582*fb1b10abSAndroid Build Coastguard Worker   /* clang-format off */
1583*fb1b10abSAndroid Build Coastguard Worker   static const MV
1584*fb1b10abSAndroid Build Coastguard Worker       square_candidates[MAX_PATTERN_SCALES][MAX_PATTERN_CANDIDATES] = {
1585*fb1b10abSAndroid Build Coastguard Worker         { { -1, -1 }, { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
1586*fb1b10abSAndroid Build Coastguard Worker           { -1, 1 }, { -1, 0 } },
1587*fb1b10abSAndroid Build Coastguard Worker         { { -2, -2 }, { 0, -2 }, { 2, -2 }, { 2, 0 }, { 2, 2 }, { 0, 2 },
1588*fb1b10abSAndroid Build Coastguard Worker           { -2, 2 }, { -2, 0 } },
1589*fb1b10abSAndroid Build Coastguard Worker         { { -4, -4 }, { 0, -4 }, { 4, -4 }, { 4, 0 }, { 4, 4 }, { 0, 4 },
1590*fb1b10abSAndroid Build Coastguard Worker           { -4, 4 }, { -4, 0 } },
1591*fb1b10abSAndroid Build Coastguard Worker         { { -8, -8 }, { 0, -8 }, { 8, -8 }, { 8, 0 }, { 8, 8 }, { 0, 8 },
1592*fb1b10abSAndroid Build Coastguard Worker           { -8, 8 }, { -8, 0 } },
1593*fb1b10abSAndroid Build Coastguard Worker         { { -16, -16 }, { 0, -16 }, { 16, -16 }, { 16, 0 }, { 16, 16 },
1594*fb1b10abSAndroid Build Coastguard Worker           { 0, 16 }, { -16, 16 }, { -16, 0 } },
1595*fb1b10abSAndroid Build Coastguard Worker         { { -32, -32 }, { 0, -32 }, { 32, -32 }, { 32, 0 }, { 32, 32 },
1596*fb1b10abSAndroid Build Coastguard Worker           { 0, 32 }, { -32, 32 }, { -32, 0 } },
1597*fb1b10abSAndroid Build Coastguard Worker         { { -64, -64 }, { 0, -64 }, { 64, -64 }, { 64, 0 }, { 64, 64 },
1598*fb1b10abSAndroid Build Coastguard Worker           { 0, 64 }, { -64, 64 }, { -64, 0 } },
1599*fb1b10abSAndroid Build Coastguard Worker         { { -128, -128 }, { 0, -128 }, { 128, -128 }, { 128, 0 }, { 128, 128 },
1600*fb1b10abSAndroid Build Coastguard Worker           { 0, 128 }, { -128, 128 }, { -128, 0 } },
1601*fb1b10abSAndroid Build Coastguard Worker         { { -256, -256 }, { 0, -256 }, { 256, -256 }, { 256, 0 }, { 256, 256 },
1602*fb1b10abSAndroid Build Coastguard Worker           { 0, 256 }, { -256, 256 }, { -256, 0 } },
1603*fb1b10abSAndroid Build Coastguard Worker         { { -512, -512 }, { 0, -512 }, { 512, -512 }, { 512, 0 }, { 512, 512 },
1604*fb1b10abSAndroid Build Coastguard Worker           { 0, 512 }, { -512, 512 }, { -512, 0 } },
1605*fb1b10abSAndroid Build Coastguard Worker         { { -1024, -1024 }, { 0, -1024 }, { 1024, -1024 }, { 1024, 0 },
1606*fb1b10abSAndroid Build Coastguard Worker           { 1024, 1024 }, { 0, 1024 }, { -1024, 1024 }, { -1024, 0 } }
1607*fb1b10abSAndroid Build Coastguard Worker       };
1608*fb1b10abSAndroid Build Coastguard Worker   /* clang-format on */
1609*fb1b10abSAndroid Build Coastguard Worker   return vp9_pattern_search(
1610*fb1b10abSAndroid Build Coastguard Worker       x, ref_mv, search_param, sad_per_bit, do_init_search, cost_list, vfp,
1611*fb1b10abSAndroid Build Coastguard Worker       use_mvcost, center_mv, best_mv, square_num_candidates, square_candidates);
1612*fb1b10abSAndroid Build Coastguard Worker }
1613*fb1b10abSAndroid Build Coastguard Worker 
fast_hex_search(const MACROBLOCK * x,MV * ref_mv,int search_param,int sad_per_bit,int do_init_search,int * cost_list,const vp9_variance_fn_ptr_t * vfp,int use_mvcost,const MV * center_mv,MV * best_mv)1614*fb1b10abSAndroid Build Coastguard Worker static int fast_hex_search(const MACROBLOCK *x, MV *ref_mv, int search_param,
1615*fb1b10abSAndroid Build Coastguard Worker                            int sad_per_bit,
1616*fb1b10abSAndroid Build Coastguard Worker                            int do_init_search,  // must be zero for fast_hex
1617*fb1b10abSAndroid Build Coastguard Worker                            int *cost_list, const vp9_variance_fn_ptr_t *vfp,
1618*fb1b10abSAndroid Build Coastguard Worker                            int use_mvcost, const MV *center_mv, MV *best_mv) {
1619*fb1b10abSAndroid Build Coastguard Worker   return hex_search(x, ref_mv, VPXMAX(MAX_MVSEARCH_STEPS - 2, search_param),
1620*fb1b10abSAndroid Build Coastguard Worker                     sad_per_bit, do_init_search, cost_list, vfp, use_mvcost,
1621*fb1b10abSAndroid Build Coastguard Worker                     center_mv, best_mv);
1622*fb1b10abSAndroid Build Coastguard Worker }
1623*fb1b10abSAndroid Build Coastguard Worker 
fast_dia_search(const MACROBLOCK * x,MV * ref_mv,int search_param,int sad_per_bit,int do_init_search,int * cost_list,const vp9_variance_fn_ptr_t * vfp,int use_mvcost,const MV * center_mv,MV * best_mv)1624*fb1b10abSAndroid Build Coastguard Worker static int fast_dia_search(const MACROBLOCK *x, MV *ref_mv, int search_param,
1625*fb1b10abSAndroid Build Coastguard Worker                            int sad_per_bit, int do_init_search, int *cost_list,
1626*fb1b10abSAndroid Build Coastguard Worker                            const vp9_variance_fn_ptr_t *vfp, int use_mvcost,
1627*fb1b10abSAndroid Build Coastguard Worker                            const MV *center_mv, MV *best_mv) {
1628*fb1b10abSAndroid Build Coastguard Worker   return bigdia_search(x, ref_mv, VPXMAX(MAX_MVSEARCH_STEPS - 2, search_param),
1629*fb1b10abSAndroid Build Coastguard Worker                        sad_per_bit, do_init_search, cost_list, vfp, use_mvcost,
1630*fb1b10abSAndroid Build Coastguard Worker                        center_mv, best_mv);
1631*fb1b10abSAndroid Build Coastguard Worker }
1632*fb1b10abSAndroid Build Coastguard Worker 
1633*fb1b10abSAndroid Build Coastguard Worker #undef CHECK_BETTER
1634*fb1b10abSAndroid Build Coastguard Worker 
1635*fb1b10abSAndroid Build Coastguard Worker // Exhuastive motion search around a given centre position with a given
1636*fb1b10abSAndroid Build Coastguard Worker // step size.
exhaustive_mesh_search(const MACROBLOCK * x,MV * ref_mv,MV * best_mv,int range,int step,int sad_per_bit,const vp9_variance_fn_ptr_t * fn_ptr,const MV * center_mv)1637*fb1b10abSAndroid Build Coastguard Worker static int exhaustive_mesh_search(const MACROBLOCK *x, MV *ref_mv, MV *best_mv,
1638*fb1b10abSAndroid Build Coastguard Worker                                   int range, int step, int sad_per_bit,
1639*fb1b10abSAndroid Build Coastguard Worker                                   const vp9_variance_fn_ptr_t *fn_ptr,
1640*fb1b10abSAndroid Build Coastguard Worker                                   const MV *center_mv) {
1641*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1642*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
1643*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
1644*fb1b10abSAndroid Build Coastguard Worker   MV fcenter_mv = { center_mv->row, center_mv->col };
1645*fb1b10abSAndroid Build Coastguard Worker   unsigned int best_sad = INT_MAX;
1646*fb1b10abSAndroid Build Coastguard Worker   int r, c, i;
1647*fb1b10abSAndroid Build Coastguard Worker   int start_col, end_col, start_row, end_row;
1648*fb1b10abSAndroid Build Coastguard Worker   int col_step = (step > 1) ? step : 4;
1649*fb1b10abSAndroid Build Coastguard Worker 
1650*fb1b10abSAndroid Build Coastguard Worker   assert(step >= 1);
1651*fb1b10abSAndroid Build Coastguard Worker 
1652*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(&fcenter_mv, x->mv_limits.col_min, x->mv_limits.col_max,
1653*fb1b10abSAndroid Build Coastguard Worker            x->mv_limits.row_min, x->mv_limits.row_max);
1654*fb1b10abSAndroid Build Coastguard Worker   *best_mv = fcenter_mv;
1655*fb1b10abSAndroid Build Coastguard Worker   best_sad =
1656*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->sdf(what->buf, what->stride,
1657*fb1b10abSAndroid Build Coastguard Worker                   get_buf_from_mv(in_what, &fcenter_mv), in_what->stride) +
1658*fb1b10abSAndroid Build Coastguard Worker       mvsad_err_cost(x, &fcenter_mv, ref_mv, sad_per_bit);
1659*fb1b10abSAndroid Build Coastguard Worker   start_row = VPXMAX(-range, x->mv_limits.row_min - fcenter_mv.row);
1660*fb1b10abSAndroid Build Coastguard Worker   start_col = VPXMAX(-range, x->mv_limits.col_min - fcenter_mv.col);
1661*fb1b10abSAndroid Build Coastguard Worker   end_row = VPXMIN(range, x->mv_limits.row_max - fcenter_mv.row);
1662*fb1b10abSAndroid Build Coastguard Worker   end_col = VPXMIN(range, x->mv_limits.col_max - fcenter_mv.col);
1663*fb1b10abSAndroid Build Coastguard Worker 
1664*fb1b10abSAndroid Build Coastguard Worker   for (r = start_row; r <= end_row; r += step) {
1665*fb1b10abSAndroid Build Coastguard Worker     for (c = start_col; c <= end_col; c += col_step) {
1666*fb1b10abSAndroid Build Coastguard Worker       // Step > 1 means we are not checking every location in this pass.
1667*fb1b10abSAndroid Build Coastguard Worker       if (step > 1) {
1668*fb1b10abSAndroid Build Coastguard Worker         const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c };
1669*fb1b10abSAndroid Build Coastguard Worker         unsigned int sad =
1670*fb1b10abSAndroid Build Coastguard Worker             fn_ptr->sdf(what->buf, what->stride, get_buf_from_mv(in_what, &mv),
1671*fb1b10abSAndroid Build Coastguard Worker                         in_what->stride);
1672*fb1b10abSAndroid Build Coastguard Worker         if (sad < best_sad) {
1673*fb1b10abSAndroid Build Coastguard Worker           sad += mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
1674*fb1b10abSAndroid Build Coastguard Worker           if (sad < best_sad) {
1675*fb1b10abSAndroid Build Coastguard Worker             best_sad = sad;
1676*fb1b10abSAndroid Build Coastguard Worker             *best_mv = mv;
1677*fb1b10abSAndroid Build Coastguard Worker           }
1678*fb1b10abSAndroid Build Coastguard Worker         }
1679*fb1b10abSAndroid Build Coastguard Worker       } else {
1680*fb1b10abSAndroid Build Coastguard Worker         // 4 sads in a single call if we are checking every location
1681*fb1b10abSAndroid Build Coastguard Worker         if (c + 3 <= end_col) {
1682*fb1b10abSAndroid Build Coastguard Worker           unsigned int sads[4];
1683*fb1b10abSAndroid Build Coastguard Worker           const uint8_t *addrs[4];
1684*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < 4; ++i) {
1685*fb1b10abSAndroid Build Coastguard Worker             const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
1686*fb1b10abSAndroid Build Coastguard Worker             addrs[i] = get_buf_from_mv(in_what, &mv);
1687*fb1b10abSAndroid Build Coastguard Worker           }
1688*fb1b10abSAndroid Build Coastguard Worker           fn_ptr->sdx4df(what->buf, what->stride, addrs, in_what->stride, sads);
1689*fb1b10abSAndroid Build Coastguard Worker 
1690*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < 4; ++i) {
1691*fb1b10abSAndroid Build Coastguard Worker             if (sads[i] < best_sad) {
1692*fb1b10abSAndroid Build Coastguard Worker               const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
1693*fb1b10abSAndroid Build Coastguard Worker               const unsigned int sad =
1694*fb1b10abSAndroid Build Coastguard Worker                   sads[i] + mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
1695*fb1b10abSAndroid Build Coastguard Worker               if (sad < best_sad) {
1696*fb1b10abSAndroid Build Coastguard Worker                 best_sad = sad;
1697*fb1b10abSAndroid Build Coastguard Worker                 *best_mv = mv;
1698*fb1b10abSAndroid Build Coastguard Worker               }
1699*fb1b10abSAndroid Build Coastguard Worker             }
1700*fb1b10abSAndroid Build Coastguard Worker           }
1701*fb1b10abSAndroid Build Coastguard Worker         } else {
1702*fb1b10abSAndroid Build Coastguard Worker           for (i = 0; i < end_col - c; ++i) {
1703*fb1b10abSAndroid Build Coastguard Worker             const MV mv = { fcenter_mv.row + r, fcenter_mv.col + c + i };
1704*fb1b10abSAndroid Build Coastguard Worker             unsigned int sad =
1705*fb1b10abSAndroid Build Coastguard Worker                 fn_ptr->sdf(what->buf, what->stride,
1706*fb1b10abSAndroid Build Coastguard Worker                             get_buf_from_mv(in_what, &mv), in_what->stride);
1707*fb1b10abSAndroid Build Coastguard Worker             if (sad < best_sad) {
1708*fb1b10abSAndroid Build Coastguard Worker               sad += mvsad_err_cost(x, &mv, ref_mv, sad_per_bit);
1709*fb1b10abSAndroid Build Coastguard Worker               if (sad < best_sad) {
1710*fb1b10abSAndroid Build Coastguard Worker                 best_sad = sad;
1711*fb1b10abSAndroid Build Coastguard Worker                 *best_mv = mv;
1712*fb1b10abSAndroid Build Coastguard Worker               }
1713*fb1b10abSAndroid Build Coastguard Worker             }
1714*fb1b10abSAndroid Build Coastguard Worker           }
1715*fb1b10abSAndroid Build Coastguard Worker         }
1716*fb1b10abSAndroid Build Coastguard Worker       }
1717*fb1b10abSAndroid Build Coastguard Worker     }
1718*fb1b10abSAndroid Build Coastguard Worker   }
1719*fb1b10abSAndroid Build Coastguard Worker 
1720*fb1b10abSAndroid Build Coastguard Worker   return best_sad;
1721*fb1b10abSAndroid Build Coastguard Worker }
1722*fb1b10abSAndroid Build Coastguard Worker 
1723*fb1b10abSAndroid Build Coastguard Worker #define MIN_RANGE 7
1724*fb1b10abSAndroid Build Coastguard Worker #define MAX_RANGE 256
1725*fb1b10abSAndroid Build Coastguard Worker #define MIN_INTERVAL 1
1726*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
exhaustive_mesh_search_multi_step(MV * best_mv,const MV * center_mv,int range,int step,const struct buf_2d * src,const struct buf_2d * pre,int lambda,const int_mv * nb_full_mvs,int full_mv_num,const MvLimits * mv_limits,const vp9_variance_fn_ptr_t * fn_ptr)1727*fb1b10abSAndroid Build Coastguard Worker static int64_t exhaustive_mesh_search_multi_step(
1728*fb1b10abSAndroid Build Coastguard Worker     MV *best_mv, const MV *center_mv, int range, int step,
1729*fb1b10abSAndroid Build Coastguard Worker     const struct buf_2d *src, const struct buf_2d *pre, int lambda,
1730*fb1b10abSAndroid Build Coastguard Worker     const int_mv *nb_full_mvs, int full_mv_num, const MvLimits *mv_limits,
1731*fb1b10abSAndroid Build Coastguard Worker     const vp9_variance_fn_ptr_t *fn_ptr) {
1732*fb1b10abSAndroid Build Coastguard Worker   int64_t best_sad;
1733*fb1b10abSAndroid Build Coastguard Worker   int r, c;
1734*fb1b10abSAndroid Build Coastguard Worker   int start_col, end_col, start_row, end_row;
1735*fb1b10abSAndroid Build Coastguard Worker   *best_mv = *center_mv;
1736*fb1b10abSAndroid Build Coastguard Worker   best_sad =
1737*fb1b10abSAndroid Build Coastguard Worker       ((int64_t)fn_ptr->sdf(src->buf, src->stride,
1738*fb1b10abSAndroid Build Coastguard Worker                             get_buf_from_mv(pre, center_mv), pre->stride)
1739*fb1b10abSAndroid Build Coastguard Worker        << LOG2_PRECISION) +
1740*fb1b10abSAndroid Build Coastguard Worker       lambda * vp9_nb_mvs_inconsistency(best_mv, nb_full_mvs, full_mv_num);
1741*fb1b10abSAndroid Build Coastguard Worker   start_row = VPXMAX(center_mv->row - range, mv_limits->row_min);
1742*fb1b10abSAndroid Build Coastguard Worker   start_col = VPXMAX(center_mv->col - range, mv_limits->col_min);
1743*fb1b10abSAndroid Build Coastguard Worker   end_row = VPXMIN(center_mv->row + range, mv_limits->row_max);
1744*fb1b10abSAndroid Build Coastguard Worker   end_col = VPXMIN(center_mv->col + range, mv_limits->col_max);
1745*fb1b10abSAndroid Build Coastguard Worker   for (r = start_row; r <= end_row; r += step) {
1746*fb1b10abSAndroid Build Coastguard Worker     for (c = start_col; c <= end_col; c += step) {
1747*fb1b10abSAndroid Build Coastguard Worker       const MV mv = { r, c };
1748*fb1b10abSAndroid Build Coastguard Worker       int64_t sad = (int64_t)fn_ptr->sdf(src->buf, src->stride,
1749*fb1b10abSAndroid Build Coastguard Worker                                          get_buf_from_mv(pre, &mv), pre->stride)
1750*fb1b10abSAndroid Build Coastguard Worker                     << LOG2_PRECISION;
1751*fb1b10abSAndroid Build Coastguard Worker       if (sad < best_sad) {
1752*fb1b10abSAndroid Build Coastguard Worker         sad += lambda * vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
1753*fb1b10abSAndroid Build Coastguard Worker         if (sad < best_sad) {
1754*fb1b10abSAndroid Build Coastguard Worker           best_sad = sad;
1755*fb1b10abSAndroid Build Coastguard Worker           *best_mv = mv;
1756*fb1b10abSAndroid Build Coastguard Worker         }
1757*fb1b10abSAndroid Build Coastguard Worker       }
1758*fb1b10abSAndroid Build Coastguard Worker     }
1759*fb1b10abSAndroid Build Coastguard Worker   }
1760*fb1b10abSAndroid Build Coastguard Worker   return best_sad;
1761*fb1b10abSAndroid Build Coastguard Worker }
1762*fb1b10abSAndroid Build Coastguard Worker 
exhaustive_mesh_search_single_step(MV * best_mv,const MV * center_mv,int range,const struct buf_2d * src,const struct buf_2d * pre,int lambda,const int_mv * nb_full_mvs,int full_mv_num,const MvLimits * mv_limits,const vp9_variance_fn_ptr_t * fn_ptr)1763*fb1b10abSAndroid Build Coastguard Worker static int64_t exhaustive_mesh_search_single_step(
1764*fb1b10abSAndroid Build Coastguard Worker     MV *best_mv, const MV *center_mv, int range, const struct buf_2d *src,
1765*fb1b10abSAndroid Build Coastguard Worker     const struct buf_2d *pre, int lambda, const int_mv *nb_full_mvs,
1766*fb1b10abSAndroid Build Coastguard Worker     int full_mv_num, const MvLimits *mv_limits,
1767*fb1b10abSAndroid Build Coastguard Worker     const vp9_variance_fn_ptr_t *fn_ptr) {
1768*fb1b10abSAndroid Build Coastguard Worker   int64_t best_sad;
1769*fb1b10abSAndroid Build Coastguard Worker   int r, c, i;
1770*fb1b10abSAndroid Build Coastguard Worker   int start_col, end_col, start_row, end_row;
1771*fb1b10abSAndroid Build Coastguard Worker 
1772*fb1b10abSAndroid Build Coastguard Worker   *best_mv = *center_mv;
1773*fb1b10abSAndroid Build Coastguard Worker   best_sad =
1774*fb1b10abSAndroid Build Coastguard Worker       ((int64_t)fn_ptr->sdf(src->buf, src->stride,
1775*fb1b10abSAndroid Build Coastguard Worker                             get_buf_from_mv(pre, center_mv), pre->stride)
1776*fb1b10abSAndroid Build Coastguard Worker        << LOG2_PRECISION) +
1777*fb1b10abSAndroid Build Coastguard Worker       lambda * vp9_nb_mvs_inconsistency(best_mv, nb_full_mvs, full_mv_num);
1778*fb1b10abSAndroid Build Coastguard Worker   start_row = VPXMAX(center_mv->row - range, mv_limits->row_min);
1779*fb1b10abSAndroid Build Coastguard Worker   start_col = VPXMAX(center_mv->col - range, mv_limits->col_min);
1780*fb1b10abSAndroid Build Coastguard Worker   end_row = VPXMIN(center_mv->row + range, mv_limits->row_max);
1781*fb1b10abSAndroid Build Coastguard Worker   end_col = VPXMIN(center_mv->col + range, mv_limits->col_max);
1782*fb1b10abSAndroid Build Coastguard Worker   for (r = start_row; r <= end_row; r += 1) {
1783*fb1b10abSAndroid Build Coastguard Worker     c = start_col;
1784*fb1b10abSAndroid Build Coastguard Worker     while (c + 3 <= end_col) {
1785*fb1b10abSAndroid Build Coastguard Worker       unsigned int sads[4];
1786*fb1b10abSAndroid Build Coastguard Worker       const uint8_t *addrs[4];
1787*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 4; ++i) {
1788*fb1b10abSAndroid Build Coastguard Worker         const MV mv = { r, c + i };
1789*fb1b10abSAndroid Build Coastguard Worker         addrs[i] = get_buf_from_mv(pre, &mv);
1790*fb1b10abSAndroid Build Coastguard Worker       }
1791*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->sdx4df(src->buf, src->stride, addrs, pre->stride, sads);
1792*fb1b10abSAndroid Build Coastguard Worker 
1793*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 4; ++i) {
1794*fb1b10abSAndroid Build Coastguard Worker         int64_t sad = (int64_t)sads[i] << LOG2_PRECISION;
1795*fb1b10abSAndroid Build Coastguard Worker         if (sad < best_sad) {
1796*fb1b10abSAndroid Build Coastguard Worker           const MV mv = { r, c + i };
1797*fb1b10abSAndroid Build Coastguard Worker           sad +=
1798*fb1b10abSAndroid Build Coastguard Worker               lambda * vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
1799*fb1b10abSAndroid Build Coastguard Worker           if (sad < best_sad) {
1800*fb1b10abSAndroid Build Coastguard Worker             best_sad = sad;
1801*fb1b10abSAndroid Build Coastguard Worker             *best_mv = mv;
1802*fb1b10abSAndroid Build Coastguard Worker           }
1803*fb1b10abSAndroid Build Coastguard Worker         }
1804*fb1b10abSAndroid Build Coastguard Worker       }
1805*fb1b10abSAndroid Build Coastguard Worker       c += 4;
1806*fb1b10abSAndroid Build Coastguard Worker     }
1807*fb1b10abSAndroid Build Coastguard Worker     while (c <= end_col) {
1808*fb1b10abSAndroid Build Coastguard Worker       const MV mv = { r, c };
1809*fb1b10abSAndroid Build Coastguard Worker       int64_t sad = (int64_t)fn_ptr->sdf(src->buf, src->stride,
1810*fb1b10abSAndroid Build Coastguard Worker                                          get_buf_from_mv(pre, &mv), pre->stride)
1811*fb1b10abSAndroid Build Coastguard Worker                     << LOG2_PRECISION;
1812*fb1b10abSAndroid Build Coastguard Worker       if (sad < best_sad) {
1813*fb1b10abSAndroid Build Coastguard Worker         sad += lambda * vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
1814*fb1b10abSAndroid Build Coastguard Worker         if (sad < best_sad) {
1815*fb1b10abSAndroid Build Coastguard Worker           best_sad = sad;
1816*fb1b10abSAndroid Build Coastguard Worker           *best_mv = mv;
1817*fb1b10abSAndroid Build Coastguard Worker         }
1818*fb1b10abSAndroid Build Coastguard Worker       }
1819*fb1b10abSAndroid Build Coastguard Worker       c += 1;
1820*fb1b10abSAndroid Build Coastguard Worker     }
1821*fb1b10abSAndroid Build Coastguard Worker   }
1822*fb1b10abSAndroid Build Coastguard Worker   return best_sad;
1823*fb1b10abSAndroid Build Coastguard Worker }
1824*fb1b10abSAndroid Build Coastguard Worker 
exhaustive_mesh_search_new(const MACROBLOCK * x,MV * best_mv,int range,int step,const vp9_variance_fn_ptr_t * fn_ptr,const MV * center_mv,int lambda,const int_mv * nb_full_mvs,int full_mv_num)1825*fb1b10abSAndroid Build Coastguard Worker static int64_t exhaustive_mesh_search_new(const MACROBLOCK *x, MV *best_mv,
1826*fb1b10abSAndroid Build Coastguard Worker                                           int range, int step,
1827*fb1b10abSAndroid Build Coastguard Worker                                           const vp9_variance_fn_ptr_t *fn_ptr,
1828*fb1b10abSAndroid Build Coastguard Worker                                           const MV *center_mv, int lambda,
1829*fb1b10abSAndroid Build Coastguard Worker                                           const int_mv *nb_full_mvs,
1830*fb1b10abSAndroid Build Coastguard Worker                                           int full_mv_num) {
1831*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1832*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *src = &x->plane[0].src;
1833*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *pre = &xd->plane[0].pre[0];
1834*fb1b10abSAndroid Build Coastguard Worker   assert(step >= 1);
1835*fb1b10abSAndroid Build Coastguard Worker   assert(is_mv_in(&x->mv_limits, center_mv));
1836*fb1b10abSAndroid Build Coastguard Worker   if (step == 1) {
1837*fb1b10abSAndroid Build Coastguard Worker     return exhaustive_mesh_search_single_step(
1838*fb1b10abSAndroid Build Coastguard Worker         best_mv, center_mv, range, src, pre, lambda, nb_full_mvs, full_mv_num,
1839*fb1b10abSAndroid Build Coastguard Worker         &x->mv_limits, fn_ptr);
1840*fb1b10abSAndroid Build Coastguard Worker   }
1841*fb1b10abSAndroid Build Coastguard Worker   return exhaustive_mesh_search_multi_step(best_mv, center_mv, range, step, src,
1842*fb1b10abSAndroid Build Coastguard Worker                                            pre, lambda, nb_full_mvs,
1843*fb1b10abSAndroid Build Coastguard Worker                                            full_mv_num, &x->mv_limits, fn_ptr);
1844*fb1b10abSAndroid Build Coastguard Worker }
1845*fb1b10abSAndroid Build Coastguard Worker 
full_pixel_exhaustive_new(const VP9_COMP * cpi,MACROBLOCK * x,MV * centre_mv_full,const vp9_variance_fn_ptr_t * fn_ptr,MV * dst_mv,int lambda,const int_mv * nb_full_mvs,int full_mv_num)1846*fb1b10abSAndroid Build Coastguard Worker static int64_t full_pixel_exhaustive_new(const VP9_COMP *cpi, MACROBLOCK *x,
1847*fb1b10abSAndroid Build Coastguard Worker                                          MV *centre_mv_full,
1848*fb1b10abSAndroid Build Coastguard Worker                                          const vp9_variance_fn_ptr_t *fn_ptr,
1849*fb1b10abSAndroid Build Coastguard Worker                                          MV *dst_mv, int lambda,
1850*fb1b10abSAndroid Build Coastguard Worker                                          const int_mv *nb_full_mvs,
1851*fb1b10abSAndroid Build Coastguard Worker                                          int full_mv_num) {
1852*fb1b10abSAndroid Build Coastguard Worker   const SPEED_FEATURES *const sf = &cpi->sf;
1853*fb1b10abSAndroid Build Coastguard Worker   MV temp_mv = { centre_mv_full->row, centre_mv_full->col };
1854*fb1b10abSAndroid Build Coastguard Worker   int64_t bestsme;
1855*fb1b10abSAndroid Build Coastguard Worker   int i;
1856*fb1b10abSAndroid Build Coastguard Worker   int interval = sf->mesh_patterns[0].interval;
1857*fb1b10abSAndroid Build Coastguard Worker   int range = sf->mesh_patterns[0].range;
1858*fb1b10abSAndroid Build Coastguard Worker   int baseline_interval_divisor;
1859*fb1b10abSAndroid Build Coastguard Worker 
1860*fb1b10abSAndroid Build Coastguard Worker   // Trap illegal values for interval and range for this function.
1861*fb1b10abSAndroid Build Coastguard Worker   if ((range < MIN_RANGE) || (range > MAX_RANGE) || (interval < MIN_INTERVAL) ||
1862*fb1b10abSAndroid Build Coastguard Worker       (interval > range)) {
1863*fb1b10abSAndroid Build Coastguard Worker     printf("ERROR: invalid range\n");
1864*fb1b10abSAndroid Build Coastguard Worker     assert(0);
1865*fb1b10abSAndroid Build Coastguard Worker   }
1866*fb1b10abSAndroid Build Coastguard Worker 
1867*fb1b10abSAndroid Build Coastguard Worker   baseline_interval_divisor = range / interval;
1868*fb1b10abSAndroid Build Coastguard Worker 
1869*fb1b10abSAndroid Build Coastguard Worker   // Check size of proposed first range against magnitude of the centre
1870*fb1b10abSAndroid Build Coastguard Worker   // value used as a starting point.
1871*fb1b10abSAndroid Build Coastguard Worker   range = VPXMAX(range, (5 * VPXMAX(abs(temp_mv.row), abs(temp_mv.col))) / 4);
1872*fb1b10abSAndroid Build Coastguard Worker   range = VPXMIN(range, MAX_RANGE);
1873*fb1b10abSAndroid Build Coastguard Worker   interval = VPXMAX(interval, range / baseline_interval_divisor);
1874*fb1b10abSAndroid Build Coastguard Worker 
1875*fb1b10abSAndroid Build Coastguard Worker   // initial search
1876*fb1b10abSAndroid Build Coastguard Worker   bestsme =
1877*fb1b10abSAndroid Build Coastguard Worker       exhaustive_mesh_search_new(x, &temp_mv, range, interval, fn_ptr, &temp_mv,
1878*fb1b10abSAndroid Build Coastguard Worker                                  lambda, nb_full_mvs, full_mv_num);
1879*fb1b10abSAndroid Build Coastguard Worker 
1880*fb1b10abSAndroid Build Coastguard Worker   if ((interval > MIN_INTERVAL) && (range > MIN_RANGE)) {
1881*fb1b10abSAndroid Build Coastguard Worker     // Progressive searches with range and step size decreasing each time
1882*fb1b10abSAndroid Build Coastguard Worker     // till we reach a step size of 1. Then break out.
1883*fb1b10abSAndroid Build Coastguard Worker     for (i = 1; i < MAX_MESH_STEP; ++i) {
1884*fb1b10abSAndroid Build Coastguard Worker       // First pass with coarser step and longer range
1885*fb1b10abSAndroid Build Coastguard Worker       bestsme = exhaustive_mesh_search_new(
1886*fb1b10abSAndroid Build Coastguard Worker           x, &temp_mv, sf->mesh_patterns[i].range,
1887*fb1b10abSAndroid Build Coastguard Worker           sf->mesh_patterns[i].interval, fn_ptr, &temp_mv, lambda, nb_full_mvs,
1888*fb1b10abSAndroid Build Coastguard Worker           full_mv_num);
1889*fb1b10abSAndroid Build Coastguard Worker 
1890*fb1b10abSAndroid Build Coastguard Worker       if (sf->mesh_patterns[i].interval == 1) break;
1891*fb1b10abSAndroid Build Coastguard Worker     }
1892*fb1b10abSAndroid Build Coastguard Worker   }
1893*fb1b10abSAndroid Build Coastguard Worker 
1894*fb1b10abSAndroid Build Coastguard Worker   *dst_mv = temp_mv;
1895*fb1b10abSAndroid Build Coastguard Worker 
1896*fb1b10abSAndroid Build Coastguard Worker   return bestsme;
1897*fb1b10abSAndroid Build Coastguard Worker }
1898*fb1b10abSAndroid Build Coastguard Worker 
diamond_search_sad_new(const MACROBLOCK * x,const search_site_config * cfg,const MV * init_full_mv,MV * best_full_mv,int search_param,int lambda,int * num00,const vp9_variance_fn_ptr_t * fn_ptr,const int_mv * nb_full_mvs,int full_mv_num)1899*fb1b10abSAndroid Build Coastguard Worker static int64_t diamond_search_sad_new(const MACROBLOCK *x,
1900*fb1b10abSAndroid Build Coastguard Worker                                       const search_site_config *cfg,
1901*fb1b10abSAndroid Build Coastguard Worker                                       const MV *init_full_mv, MV *best_full_mv,
1902*fb1b10abSAndroid Build Coastguard Worker                                       int search_param, int lambda, int *num00,
1903*fb1b10abSAndroid Build Coastguard Worker                                       const vp9_variance_fn_ptr_t *fn_ptr,
1904*fb1b10abSAndroid Build Coastguard Worker                                       const int_mv *nb_full_mvs,
1905*fb1b10abSAndroid Build Coastguard Worker                                       int full_mv_num) {
1906*fb1b10abSAndroid Build Coastguard Worker   int i, j, step;
1907*fb1b10abSAndroid Build Coastguard Worker 
1908*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
1909*fb1b10abSAndroid Build Coastguard Worker   uint8_t *what = x->plane[0].src.buf;
1910*fb1b10abSAndroid Build Coastguard Worker   const int what_stride = x->plane[0].src.stride;
1911*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *in_what;
1912*fb1b10abSAndroid Build Coastguard Worker   const int in_what_stride = xd->plane[0].pre[0].stride;
1913*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *best_address;
1914*fb1b10abSAndroid Build Coastguard Worker 
1915*fb1b10abSAndroid Build Coastguard Worker   int64_t bestsad;
1916*fb1b10abSAndroid Build Coastguard Worker   int best_site = -1;
1917*fb1b10abSAndroid Build Coastguard Worker   int last_site = -1;
1918*fb1b10abSAndroid Build Coastguard Worker 
1919*fb1b10abSAndroid Build Coastguard Worker   // search_param determines the length of the initial step and hence the number
1920*fb1b10abSAndroid Build Coastguard Worker   // of iterations.
1921*fb1b10abSAndroid Build Coastguard Worker   // 0 = initial step (MAX_FIRST_STEP) pel
1922*fb1b10abSAndroid Build Coastguard Worker   // 1 = (MAX_FIRST_STEP/2) pel,
1923*fb1b10abSAndroid Build Coastguard Worker   // 2 = (MAX_FIRST_STEP/4) pel...
1924*fb1b10abSAndroid Build Coastguard Worker   //  const search_site *ss = &cfg->ss[search_param * cfg->searches_per_step];
1925*fb1b10abSAndroid Build Coastguard Worker   const MV *ss_mv = &cfg->ss_mv[search_param * cfg->searches_per_step];
1926*fb1b10abSAndroid Build Coastguard Worker   const intptr_t *ss_os = &cfg->ss_os[search_param * cfg->searches_per_step];
1927*fb1b10abSAndroid Build Coastguard Worker   const int tot_steps = cfg->total_steps - search_param;
1928*fb1b10abSAndroid Build Coastguard Worker   vpx_clear_system_state();
1929*fb1b10abSAndroid Build Coastguard Worker 
1930*fb1b10abSAndroid Build Coastguard Worker   *best_full_mv = *init_full_mv;
1931*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(best_full_mv, x->mv_limits.col_min, x->mv_limits.col_max,
1932*fb1b10abSAndroid Build Coastguard Worker            x->mv_limits.row_min, x->mv_limits.row_max);
1933*fb1b10abSAndroid Build Coastguard Worker   *num00 = 0;
1934*fb1b10abSAndroid Build Coastguard Worker 
1935*fb1b10abSAndroid Build Coastguard Worker   // Work out the start point for the search
1936*fb1b10abSAndroid Build Coastguard Worker   in_what = xd->plane[0].pre[0].buf + best_full_mv->row * in_what_stride +
1937*fb1b10abSAndroid Build Coastguard Worker             best_full_mv->col;
1938*fb1b10abSAndroid Build Coastguard Worker   best_address = in_what;
1939*fb1b10abSAndroid Build Coastguard Worker 
1940*fb1b10abSAndroid Build Coastguard Worker   // Check the starting position
1941*fb1b10abSAndroid Build Coastguard Worker   {
1942*fb1b10abSAndroid Build Coastguard Worker     const int64_t mv_dist =
1943*fb1b10abSAndroid Build Coastguard Worker         (int64_t)fn_ptr->sdf(what, what_stride, in_what, in_what_stride)
1944*fb1b10abSAndroid Build Coastguard Worker         << LOG2_PRECISION;
1945*fb1b10abSAndroid Build Coastguard Worker     const int64_t mv_cost =
1946*fb1b10abSAndroid Build Coastguard Worker         vp9_nb_mvs_inconsistency(best_full_mv, nb_full_mvs, full_mv_num);
1947*fb1b10abSAndroid Build Coastguard Worker     bestsad = mv_dist + lambda * mv_cost;
1948*fb1b10abSAndroid Build Coastguard Worker   }
1949*fb1b10abSAndroid Build Coastguard Worker 
1950*fb1b10abSAndroid Build Coastguard Worker   i = 0;
1951*fb1b10abSAndroid Build Coastguard Worker 
1952*fb1b10abSAndroid Build Coastguard Worker   for (step = 0; step < tot_steps; step++) {
1953*fb1b10abSAndroid Build Coastguard Worker     int all_in = 1, t;
1954*fb1b10abSAndroid Build Coastguard Worker 
1955*fb1b10abSAndroid Build Coastguard Worker     // All_in is true if every one of the points we are checking are within
1956*fb1b10abSAndroid Build Coastguard Worker     // the bounds of the image.
1957*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_full_mv->row + ss_mv[i].row) > x->mv_limits.row_min);
1958*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_full_mv->row + ss_mv[i + 1].row) < x->mv_limits.row_max);
1959*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_full_mv->col + ss_mv[i + 2].col) > x->mv_limits.col_min);
1960*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_full_mv->col + ss_mv[i + 3].col) < x->mv_limits.col_max);
1961*fb1b10abSAndroid Build Coastguard Worker 
1962*fb1b10abSAndroid Build Coastguard Worker     // If all the pixels are within the bounds we don't check whether the
1963*fb1b10abSAndroid Build Coastguard Worker     // search point is valid in this loop,  otherwise we check each point
1964*fb1b10abSAndroid Build Coastguard Worker     // for validity..
1965*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
1966*fb1b10abSAndroid Build Coastguard Worker       unsigned int sad_array[4];
1967*fb1b10abSAndroid Build Coastguard Worker 
1968*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < cfg->searches_per_step; j += 4) {
1969*fb1b10abSAndroid Build Coastguard Worker         unsigned char const *block_offset[4];
1970*fb1b10abSAndroid Build Coastguard Worker 
1971*fb1b10abSAndroid Build Coastguard Worker         for (t = 0; t < 4; t++) block_offset[t] = ss_os[i + t] + best_address;
1972*fb1b10abSAndroid Build Coastguard Worker 
1973*fb1b10abSAndroid Build Coastguard Worker         fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride,
1974*fb1b10abSAndroid Build Coastguard Worker                        sad_array);
1975*fb1b10abSAndroid Build Coastguard Worker 
1976*fb1b10abSAndroid Build Coastguard Worker         for (t = 0; t < 4; t++, i++) {
1977*fb1b10abSAndroid Build Coastguard Worker           const int64_t mv_dist = (int64_t)sad_array[t] << LOG2_PRECISION;
1978*fb1b10abSAndroid Build Coastguard Worker           if (mv_dist < bestsad) {
1979*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { best_full_mv->row + ss_mv[i].row,
1980*fb1b10abSAndroid Build Coastguard Worker                                  best_full_mv->col + ss_mv[i].col };
1981*fb1b10abSAndroid Build Coastguard Worker             const int64_t mv_cost =
1982*fb1b10abSAndroid Build Coastguard Worker                 vp9_nb_mvs_inconsistency(&this_mv, nb_full_mvs, full_mv_num);
1983*fb1b10abSAndroid Build Coastguard Worker             const int64_t thissad = mv_dist + lambda * mv_cost;
1984*fb1b10abSAndroid Build Coastguard Worker             if (thissad < bestsad) {
1985*fb1b10abSAndroid Build Coastguard Worker               bestsad = thissad;
1986*fb1b10abSAndroid Build Coastguard Worker               best_site = i;
1987*fb1b10abSAndroid Build Coastguard Worker             }
1988*fb1b10abSAndroid Build Coastguard Worker           }
1989*fb1b10abSAndroid Build Coastguard Worker         }
1990*fb1b10abSAndroid Build Coastguard Worker       }
1991*fb1b10abSAndroid Build Coastguard Worker     } else {
1992*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < cfg->searches_per_step; j++) {
1993*fb1b10abSAndroid Build Coastguard Worker         // Trap illegal vectors
1994*fb1b10abSAndroid Build Coastguard Worker         const MV this_mv = { best_full_mv->row + ss_mv[i].row,
1995*fb1b10abSAndroid Build Coastguard Worker                              best_full_mv->col + ss_mv[i].col };
1996*fb1b10abSAndroid Build Coastguard Worker 
1997*fb1b10abSAndroid Build Coastguard Worker         if (is_mv_in(&x->mv_limits, &this_mv)) {
1998*fb1b10abSAndroid Build Coastguard Worker           const uint8_t *const check_here = ss_os[i] + best_address;
1999*fb1b10abSAndroid Build Coastguard Worker           const int64_t mv_dist =
2000*fb1b10abSAndroid Build Coastguard Worker               (int64_t)fn_ptr->sdf(what, what_stride, check_here,
2001*fb1b10abSAndroid Build Coastguard Worker                                    in_what_stride)
2002*fb1b10abSAndroid Build Coastguard Worker               << LOG2_PRECISION;
2003*fb1b10abSAndroid Build Coastguard Worker           if (mv_dist < bestsad) {
2004*fb1b10abSAndroid Build Coastguard Worker             const int64_t mv_cost =
2005*fb1b10abSAndroid Build Coastguard Worker                 vp9_nb_mvs_inconsistency(&this_mv, nb_full_mvs, full_mv_num);
2006*fb1b10abSAndroid Build Coastguard Worker             const int64_t thissad = mv_dist + lambda * mv_cost;
2007*fb1b10abSAndroid Build Coastguard Worker             if (thissad < bestsad) {
2008*fb1b10abSAndroid Build Coastguard Worker               bestsad = thissad;
2009*fb1b10abSAndroid Build Coastguard Worker               best_site = i;
2010*fb1b10abSAndroid Build Coastguard Worker             }
2011*fb1b10abSAndroid Build Coastguard Worker           }
2012*fb1b10abSAndroid Build Coastguard Worker         }
2013*fb1b10abSAndroid Build Coastguard Worker         i++;
2014*fb1b10abSAndroid Build Coastguard Worker       }
2015*fb1b10abSAndroid Build Coastguard Worker     }
2016*fb1b10abSAndroid Build Coastguard Worker     if (best_site != last_site) {
2017*fb1b10abSAndroid Build Coastguard Worker       best_full_mv->row += ss_mv[best_site].row;
2018*fb1b10abSAndroid Build Coastguard Worker       best_full_mv->col += ss_mv[best_site].col;
2019*fb1b10abSAndroid Build Coastguard Worker       best_address += ss_os[best_site];
2020*fb1b10abSAndroid Build Coastguard Worker       last_site = best_site;
2021*fb1b10abSAndroid Build Coastguard Worker     } else if (best_address == in_what) {
2022*fb1b10abSAndroid Build Coastguard Worker       (*num00)++;
2023*fb1b10abSAndroid Build Coastguard Worker     }
2024*fb1b10abSAndroid Build Coastguard Worker   }
2025*fb1b10abSAndroid Build Coastguard Worker   return bestsad;
2026*fb1b10abSAndroid Build Coastguard Worker }
2027*fb1b10abSAndroid Build Coastguard Worker 
vp9_prepare_nb_full_mvs(const MotionField * motion_field,int mi_row,int mi_col,int_mv * nb_full_mvs)2028*fb1b10abSAndroid Build Coastguard Worker int vp9_prepare_nb_full_mvs(const MotionField *motion_field, int mi_row,
2029*fb1b10abSAndroid Build Coastguard Worker                             int mi_col, int_mv *nb_full_mvs) {
2030*fb1b10abSAndroid Build Coastguard Worker   const int mi_width = num_8x8_blocks_wide_lookup[motion_field->bsize];
2031*fb1b10abSAndroid Build Coastguard Worker   const int mi_height = num_8x8_blocks_high_lookup[motion_field->bsize];
2032*fb1b10abSAndroid Build Coastguard Worker   const int dirs[NB_MVS_NUM][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
2033*fb1b10abSAndroid Build Coastguard Worker   int nb_full_mv_num = 0;
2034*fb1b10abSAndroid Build Coastguard Worker   int i;
2035*fb1b10abSAndroid Build Coastguard Worker   assert(mi_row % mi_height == 0);
2036*fb1b10abSAndroid Build Coastguard Worker   assert(mi_col % mi_width == 0);
2037*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < NB_MVS_NUM; ++i) {
2038*fb1b10abSAndroid Build Coastguard Worker     int r = dirs[i][0];
2039*fb1b10abSAndroid Build Coastguard Worker     int c = dirs[i][1];
2040*fb1b10abSAndroid Build Coastguard Worker     int brow = mi_row / mi_height + r;
2041*fb1b10abSAndroid Build Coastguard Worker     int bcol = mi_col / mi_width + c;
2042*fb1b10abSAndroid Build Coastguard Worker     if (brow >= 0 && brow < motion_field->block_rows && bcol >= 0 &&
2043*fb1b10abSAndroid Build Coastguard Worker         bcol < motion_field->block_cols) {
2044*fb1b10abSAndroid Build Coastguard Worker       if (vp9_motion_field_is_mv_set(motion_field, brow, bcol)) {
2045*fb1b10abSAndroid Build Coastguard Worker         int_mv mv = vp9_motion_field_get_mv(motion_field, brow, bcol);
2046*fb1b10abSAndroid Build Coastguard Worker         nb_full_mvs[nb_full_mv_num].as_mv = get_full_mv(&mv.as_mv);
2047*fb1b10abSAndroid Build Coastguard Worker         ++nb_full_mv_num;
2048*fb1b10abSAndroid Build Coastguard Worker       }
2049*fb1b10abSAndroid Build Coastguard Worker     }
2050*fb1b10abSAndroid Build Coastguard Worker   }
2051*fb1b10abSAndroid Build Coastguard Worker   return nb_full_mv_num;
2052*fb1b10abSAndroid Build Coastguard Worker }
2053*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_NON_GREEDY_MV
2054*fb1b10abSAndroid Build Coastguard Worker 
vp9_diamond_search_sad_c(const MACROBLOCK * x,const search_site_config * cfg,MV * ref_mv,uint32_t start_mv_sad,MV * best_mv,int search_param,int sad_per_bit,int * num00,const vp9_sad_fn_ptr_t * sad_fn_ptr,const MV * center_mv)2055*fb1b10abSAndroid Build Coastguard Worker int vp9_diamond_search_sad_c(const MACROBLOCK *x, const search_site_config *cfg,
2056*fb1b10abSAndroid Build Coastguard Worker                              MV *ref_mv, uint32_t start_mv_sad, MV *best_mv,
2057*fb1b10abSAndroid Build Coastguard Worker                              int search_param, int sad_per_bit, int *num00,
2058*fb1b10abSAndroid Build Coastguard Worker                              const vp9_sad_fn_ptr_t *sad_fn_ptr,
2059*fb1b10abSAndroid Build Coastguard Worker                              const MV *center_mv) {
2060*fb1b10abSAndroid Build Coastguard Worker   int i, j, step;
2061*fb1b10abSAndroid Build Coastguard Worker 
2062*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
2063*fb1b10abSAndroid Build Coastguard Worker   uint8_t *what = x->plane[0].src.buf;
2064*fb1b10abSAndroid Build Coastguard Worker   const int what_stride = x->plane[0].src.stride;
2065*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *in_what;
2066*fb1b10abSAndroid Build Coastguard Worker   const int in_what_stride = xd->plane[0].pre[0].stride;
2067*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *best_address;
2068*fb1b10abSAndroid Build Coastguard Worker 
2069*fb1b10abSAndroid Build Coastguard Worker   unsigned int bestsad = start_mv_sad;
2070*fb1b10abSAndroid Build Coastguard Worker   int best_site = -1;
2071*fb1b10abSAndroid Build Coastguard Worker   int last_site = -1;
2072*fb1b10abSAndroid Build Coastguard Worker 
2073*fb1b10abSAndroid Build Coastguard Worker   int ref_row;
2074*fb1b10abSAndroid Build Coastguard Worker   int ref_col;
2075*fb1b10abSAndroid Build Coastguard Worker 
2076*fb1b10abSAndroid Build Coastguard Worker   // search_param determines the length of the initial step and hence the number
2077*fb1b10abSAndroid Build Coastguard Worker   // of iterations.
2078*fb1b10abSAndroid Build Coastguard Worker   // 0 = initial step (MAX_FIRST_STEP) pel
2079*fb1b10abSAndroid Build Coastguard Worker   // 1 = (MAX_FIRST_STEP/2) pel,
2080*fb1b10abSAndroid Build Coastguard Worker   // 2 = (MAX_FIRST_STEP/4) pel...
2081*fb1b10abSAndroid Build Coastguard Worker   //  const search_site *ss = &cfg->ss[search_param * cfg->searches_per_step];
2082*fb1b10abSAndroid Build Coastguard Worker   const MV *ss_mv = &cfg->ss_mv[search_param * cfg->searches_per_step];
2083*fb1b10abSAndroid Build Coastguard Worker   const intptr_t *ss_os = &cfg->ss_os[search_param * cfg->searches_per_step];
2084*fb1b10abSAndroid Build Coastguard Worker   const int tot_steps = cfg->total_steps - search_param;
2085*fb1b10abSAndroid Build Coastguard Worker 
2086*fb1b10abSAndroid Build Coastguard Worker   const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
2087*fb1b10abSAndroid Build Coastguard Worker   ref_row = ref_mv->row;
2088*fb1b10abSAndroid Build Coastguard Worker   ref_col = ref_mv->col;
2089*fb1b10abSAndroid Build Coastguard Worker   *num00 = 0;
2090*fb1b10abSAndroid Build Coastguard Worker   best_mv->row = ref_row;
2091*fb1b10abSAndroid Build Coastguard Worker   best_mv->col = ref_col;
2092*fb1b10abSAndroid Build Coastguard Worker 
2093*fb1b10abSAndroid Build Coastguard Worker   // Work out the start point for the search
2094*fb1b10abSAndroid Build Coastguard Worker   in_what = xd->plane[0].pre[0].buf + ref_row * in_what_stride + ref_col;
2095*fb1b10abSAndroid Build Coastguard Worker   best_address = in_what;
2096*fb1b10abSAndroid Build Coastguard Worker 
2097*fb1b10abSAndroid Build Coastguard Worker   i = 0;
2098*fb1b10abSAndroid Build Coastguard Worker 
2099*fb1b10abSAndroid Build Coastguard Worker   for (step = 0; step < tot_steps; step++) {
2100*fb1b10abSAndroid Build Coastguard Worker     int all_in = 1, t;
2101*fb1b10abSAndroid Build Coastguard Worker 
2102*fb1b10abSAndroid Build Coastguard Worker     // All_in is true if every one of the points we are checking are within
2103*fb1b10abSAndroid Build Coastguard Worker     // the bounds of the image.
2104*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->row + ss_mv[i].row) > x->mv_limits.row_min);
2105*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->row + ss_mv[i + 1].row) < x->mv_limits.row_max);
2106*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->col + ss_mv[i + 2].col) > x->mv_limits.col_min);
2107*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->col + ss_mv[i + 3].col) < x->mv_limits.col_max);
2108*fb1b10abSAndroid Build Coastguard Worker 
2109*fb1b10abSAndroid Build Coastguard Worker     // If all the pixels are within the bounds we don't check whether the
2110*fb1b10abSAndroid Build Coastguard Worker     // search point is valid in this loop,  otherwise we check each point
2111*fb1b10abSAndroid Build Coastguard Worker     // for validity..
2112*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
2113*fb1b10abSAndroid Build Coastguard Worker       unsigned int sad_array[4];
2114*fb1b10abSAndroid Build Coastguard Worker 
2115*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < cfg->searches_per_step; j += 4) {
2116*fb1b10abSAndroid Build Coastguard Worker         unsigned char const *block_offset[4];
2117*fb1b10abSAndroid Build Coastguard Worker 
2118*fb1b10abSAndroid Build Coastguard Worker         for (t = 0; t < 4; t++) block_offset[t] = ss_os[i + t] + best_address;
2119*fb1b10abSAndroid Build Coastguard Worker 
2120*fb1b10abSAndroid Build Coastguard Worker         sad_fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride,
2121*fb1b10abSAndroid Build Coastguard Worker                            sad_array);
2122*fb1b10abSAndroid Build Coastguard Worker 
2123*fb1b10abSAndroid Build Coastguard Worker         for (t = 0; t < 4; t++, i++) {
2124*fb1b10abSAndroid Build Coastguard Worker           if (sad_array[t] < bestsad) {
2125*fb1b10abSAndroid Build Coastguard Worker             const MV this_mv = { best_mv->row + ss_mv[i].row,
2126*fb1b10abSAndroid Build Coastguard Worker                                  best_mv->col + ss_mv[i].col };
2127*fb1b10abSAndroid Build Coastguard Worker             sad_array[t] +=
2128*fb1b10abSAndroid Build Coastguard Worker                 mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
2129*fb1b10abSAndroid Build Coastguard Worker             if (sad_array[t] < bestsad) {
2130*fb1b10abSAndroid Build Coastguard Worker               bestsad = sad_array[t];
2131*fb1b10abSAndroid Build Coastguard Worker               best_site = i;
2132*fb1b10abSAndroid Build Coastguard Worker             }
2133*fb1b10abSAndroid Build Coastguard Worker           }
2134*fb1b10abSAndroid Build Coastguard Worker         }
2135*fb1b10abSAndroid Build Coastguard Worker       }
2136*fb1b10abSAndroid Build Coastguard Worker     } else {
2137*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < cfg->searches_per_step; j++) {
2138*fb1b10abSAndroid Build Coastguard Worker         // Trap illegal vectors
2139*fb1b10abSAndroid Build Coastguard Worker         const MV this_mv = { best_mv->row + ss_mv[i].row,
2140*fb1b10abSAndroid Build Coastguard Worker                              best_mv->col + ss_mv[i].col };
2141*fb1b10abSAndroid Build Coastguard Worker 
2142*fb1b10abSAndroid Build Coastguard Worker         if (is_mv_in(&x->mv_limits, &this_mv)) {
2143*fb1b10abSAndroid Build Coastguard Worker           const uint8_t *const check_here = ss_os[i] + best_address;
2144*fb1b10abSAndroid Build Coastguard Worker           unsigned int thissad =
2145*fb1b10abSAndroid Build Coastguard Worker               sad_fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
2146*fb1b10abSAndroid Build Coastguard Worker 
2147*fb1b10abSAndroid Build Coastguard Worker           if (thissad < bestsad) {
2148*fb1b10abSAndroid Build Coastguard Worker             thissad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
2149*fb1b10abSAndroid Build Coastguard Worker             if (thissad < bestsad) {
2150*fb1b10abSAndroid Build Coastguard Worker               bestsad = thissad;
2151*fb1b10abSAndroid Build Coastguard Worker               best_site = i;
2152*fb1b10abSAndroid Build Coastguard Worker             }
2153*fb1b10abSAndroid Build Coastguard Worker           }
2154*fb1b10abSAndroid Build Coastguard Worker         }
2155*fb1b10abSAndroid Build Coastguard Worker         i++;
2156*fb1b10abSAndroid Build Coastguard Worker       }
2157*fb1b10abSAndroid Build Coastguard Worker     }
2158*fb1b10abSAndroid Build Coastguard Worker     if (best_site != last_site) {
2159*fb1b10abSAndroid Build Coastguard Worker       best_mv->row += ss_mv[best_site].row;
2160*fb1b10abSAndroid Build Coastguard Worker       best_mv->col += ss_mv[best_site].col;
2161*fb1b10abSAndroid Build Coastguard Worker       best_address += ss_os[best_site];
2162*fb1b10abSAndroid Build Coastguard Worker       last_site = best_site;
2163*fb1b10abSAndroid Build Coastguard Worker #if defined(NEW_DIAMOND_SEARCH)
2164*fb1b10abSAndroid Build Coastguard Worker       while (1) {
2165*fb1b10abSAndroid Build Coastguard Worker         const MV this_mv = { best_mv->row + ss_mv[best_site].row,
2166*fb1b10abSAndroid Build Coastguard Worker                              best_mv->col + ss_mv[best_site].col };
2167*fb1b10abSAndroid Build Coastguard Worker         if (is_mv_in(&x->mv_limits, &this_mv)) {
2168*fb1b10abSAndroid Build Coastguard Worker           const uint8_t *const check_here = ss_os[best_site] + best_address;
2169*fb1b10abSAndroid Build Coastguard Worker           unsigned int thissad =
2170*fb1b10abSAndroid Build Coastguard Worker               fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
2171*fb1b10abSAndroid Build Coastguard Worker           if (thissad < bestsad) {
2172*fb1b10abSAndroid Build Coastguard Worker             thissad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
2173*fb1b10abSAndroid Build Coastguard Worker             if (thissad < bestsad) {
2174*fb1b10abSAndroid Build Coastguard Worker               bestsad = thissad;
2175*fb1b10abSAndroid Build Coastguard Worker               best_mv->row += ss_mv[best_site].row;
2176*fb1b10abSAndroid Build Coastguard Worker               best_mv->col += ss_mv[best_site].col;
2177*fb1b10abSAndroid Build Coastguard Worker               best_address += ss_os[best_site];
2178*fb1b10abSAndroid Build Coastguard Worker               continue;
2179*fb1b10abSAndroid Build Coastguard Worker             }
2180*fb1b10abSAndroid Build Coastguard Worker           }
2181*fb1b10abSAndroid Build Coastguard Worker         }
2182*fb1b10abSAndroid Build Coastguard Worker         break;
2183*fb1b10abSAndroid Build Coastguard Worker       }
2184*fb1b10abSAndroid Build Coastguard Worker #endif
2185*fb1b10abSAndroid Build Coastguard Worker     } else if (best_address == in_what) {
2186*fb1b10abSAndroid Build Coastguard Worker       (*num00)++;
2187*fb1b10abSAndroid Build Coastguard Worker     }
2188*fb1b10abSAndroid Build Coastguard Worker   }
2189*fb1b10abSAndroid Build Coastguard Worker   return bestsad;
2190*fb1b10abSAndroid Build Coastguard Worker }
2191*fb1b10abSAndroid Build Coastguard Worker 
vector_match(int16_t * ref,int16_t * src,int bwl)2192*fb1b10abSAndroid Build Coastguard Worker static int vector_match(int16_t *ref, int16_t *src, int bwl) {
2193*fb1b10abSAndroid Build Coastguard Worker   int best_sad = INT_MAX;
2194*fb1b10abSAndroid Build Coastguard Worker   int this_sad;
2195*fb1b10abSAndroid Build Coastguard Worker   int d;
2196*fb1b10abSAndroid Build Coastguard Worker   int center, offset = 0;
2197*fb1b10abSAndroid Build Coastguard Worker   int bw = 4 << bwl;  // redundant variable, to be changed in the experiments.
2198*fb1b10abSAndroid Build Coastguard Worker   for (d = 0; d <= bw; d += 16) {
2199*fb1b10abSAndroid Build Coastguard Worker     this_sad = vpx_vector_var(&ref[d], src, bwl);
2200*fb1b10abSAndroid Build Coastguard Worker     if (this_sad < best_sad) {
2201*fb1b10abSAndroid Build Coastguard Worker       best_sad = this_sad;
2202*fb1b10abSAndroid Build Coastguard Worker       offset = d;
2203*fb1b10abSAndroid Build Coastguard Worker     }
2204*fb1b10abSAndroid Build Coastguard Worker   }
2205*fb1b10abSAndroid Build Coastguard Worker   center = offset;
2206*fb1b10abSAndroid Build Coastguard Worker 
2207*fb1b10abSAndroid Build Coastguard Worker   for (d = -8; d <= 8; d += 16) {
2208*fb1b10abSAndroid Build Coastguard Worker     int this_pos = offset + d;
2209*fb1b10abSAndroid Build Coastguard Worker     // check limit
2210*fb1b10abSAndroid Build Coastguard Worker     if (this_pos < 0 || this_pos > bw) continue;
2211*fb1b10abSAndroid Build Coastguard Worker     this_sad = vpx_vector_var(&ref[this_pos], src, bwl);
2212*fb1b10abSAndroid Build Coastguard Worker     if (this_sad < best_sad) {
2213*fb1b10abSAndroid Build Coastguard Worker       best_sad = this_sad;
2214*fb1b10abSAndroid Build Coastguard Worker       center = this_pos;
2215*fb1b10abSAndroid Build Coastguard Worker     }
2216*fb1b10abSAndroid Build Coastguard Worker   }
2217*fb1b10abSAndroid Build Coastguard Worker   offset = center;
2218*fb1b10abSAndroid Build Coastguard Worker 
2219*fb1b10abSAndroid Build Coastguard Worker   for (d = -4; d <= 4; d += 8) {
2220*fb1b10abSAndroid Build Coastguard Worker     int this_pos = offset + d;
2221*fb1b10abSAndroid Build Coastguard Worker     // check limit
2222*fb1b10abSAndroid Build Coastguard Worker     if (this_pos < 0 || this_pos > bw) continue;
2223*fb1b10abSAndroid Build Coastguard Worker     this_sad = vpx_vector_var(&ref[this_pos], src, bwl);
2224*fb1b10abSAndroid Build Coastguard Worker     if (this_sad < best_sad) {
2225*fb1b10abSAndroid Build Coastguard Worker       best_sad = this_sad;
2226*fb1b10abSAndroid Build Coastguard Worker       center = this_pos;
2227*fb1b10abSAndroid Build Coastguard Worker     }
2228*fb1b10abSAndroid Build Coastguard Worker   }
2229*fb1b10abSAndroid Build Coastguard Worker   offset = center;
2230*fb1b10abSAndroid Build Coastguard Worker 
2231*fb1b10abSAndroid Build Coastguard Worker   for (d = -2; d <= 2; d += 4) {
2232*fb1b10abSAndroid Build Coastguard Worker     int this_pos = offset + d;
2233*fb1b10abSAndroid Build Coastguard Worker     // check limit
2234*fb1b10abSAndroid Build Coastguard Worker     if (this_pos < 0 || this_pos > bw) continue;
2235*fb1b10abSAndroid Build Coastguard Worker     this_sad = vpx_vector_var(&ref[this_pos], src, bwl);
2236*fb1b10abSAndroid Build Coastguard Worker     if (this_sad < best_sad) {
2237*fb1b10abSAndroid Build Coastguard Worker       best_sad = this_sad;
2238*fb1b10abSAndroid Build Coastguard Worker       center = this_pos;
2239*fb1b10abSAndroid Build Coastguard Worker     }
2240*fb1b10abSAndroid Build Coastguard Worker   }
2241*fb1b10abSAndroid Build Coastguard Worker   offset = center;
2242*fb1b10abSAndroid Build Coastguard Worker 
2243*fb1b10abSAndroid Build Coastguard Worker   for (d = -1; d <= 1; d += 2) {
2244*fb1b10abSAndroid Build Coastguard Worker     int this_pos = offset + d;
2245*fb1b10abSAndroid Build Coastguard Worker     // check limit
2246*fb1b10abSAndroid Build Coastguard Worker     if (this_pos < 0 || this_pos > bw) continue;
2247*fb1b10abSAndroid Build Coastguard Worker     this_sad = vpx_vector_var(&ref[this_pos], src, bwl);
2248*fb1b10abSAndroid Build Coastguard Worker     if (this_sad < best_sad) {
2249*fb1b10abSAndroid Build Coastguard Worker       best_sad = this_sad;
2250*fb1b10abSAndroid Build Coastguard Worker       center = this_pos;
2251*fb1b10abSAndroid Build Coastguard Worker     }
2252*fb1b10abSAndroid Build Coastguard Worker   }
2253*fb1b10abSAndroid Build Coastguard Worker 
2254*fb1b10abSAndroid Build Coastguard Worker   return (center - (bw >> 1));
2255*fb1b10abSAndroid Build Coastguard Worker }
2256*fb1b10abSAndroid Build Coastguard Worker 
2257*fb1b10abSAndroid Build Coastguard Worker static const MV search_pos[4] = {
2258*fb1b10abSAndroid Build Coastguard Worker   { -1, 0 },
2259*fb1b10abSAndroid Build Coastguard Worker   { 0, -1 },
2260*fb1b10abSAndroid Build Coastguard Worker   { 0, 1 },
2261*fb1b10abSAndroid Build Coastguard Worker   { 1, 0 },
2262*fb1b10abSAndroid Build Coastguard Worker };
2263*fb1b10abSAndroid Build Coastguard Worker 
vp9_int_pro_motion_estimation(const VP9_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,int mi_row,int mi_col,const MV * ref_mv)2264*fb1b10abSAndroid Build Coastguard Worker unsigned int vp9_int_pro_motion_estimation(const VP9_COMP *cpi, MACROBLOCK *x,
2265*fb1b10abSAndroid Build Coastguard Worker                                            BLOCK_SIZE bsize, int mi_row,
2266*fb1b10abSAndroid Build Coastguard Worker                                            int mi_col, const MV *ref_mv) {
2267*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
2268*fb1b10abSAndroid Build Coastguard Worker   MODE_INFO *mi = xd->mi[0];
2269*fb1b10abSAndroid Build Coastguard Worker   struct buf_2d backup_yv12[MAX_MB_PLANE] = { { 0, 0 } };
2270*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, int16_t, hbuf[128]);
2271*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, int16_t, vbuf[128]);
2272*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, int16_t, src_hbuf[64]);
2273*fb1b10abSAndroid Build Coastguard Worker   DECLARE_ALIGNED(16, int16_t, src_vbuf[64]);
2274*fb1b10abSAndroid Build Coastguard Worker   int idx;
2275*fb1b10abSAndroid Build Coastguard Worker   const int bw = 4 << b_width_log2_lookup[bsize];
2276*fb1b10abSAndroid Build Coastguard Worker   const int bh = 4 << b_height_log2_lookup[bsize];
2277*fb1b10abSAndroid Build Coastguard Worker   const int search_width = bw << 1;
2278*fb1b10abSAndroid Build Coastguard Worker   const int search_height = bh << 1;
2279*fb1b10abSAndroid Build Coastguard Worker   const int src_stride = x->plane[0].src.stride;
2280*fb1b10abSAndroid Build Coastguard Worker   const int ref_stride = xd->plane[0].pre[0].stride;
2281*fb1b10abSAndroid Build Coastguard Worker   uint8_t const *ref_buf, *src_buf;
2282*fb1b10abSAndroid Build Coastguard Worker   MV *tmp_mv = &xd->mi[0]->mv[0].as_mv;
2283*fb1b10abSAndroid Build Coastguard Worker   unsigned int best_sad, tmp_sad, this_sad[4];
2284*fb1b10abSAndroid Build Coastguard Worker   MV this_mv;
2285*fb1b10abSAndroid Build Coastguard Worker   const int norm_factor = 3 + (bw >> 5);
2286*fb1b10abSAndroid Build Coastguard Worker   const YV12_BUFFER_CONFIG *scaled_ref_frame =
2287*fb1b10abSAndroid Build Coastguard Worker       vp9_get_scaled_ref_frame(cpi, mi->ref_frame[0]);
2288*fb1b10abSAndroid Build Coastguard Worker   MvLimits subpel_mv_limits;
2289*fb1b10abSAndroid Build Coastguard Worker 
2290*fb1b10abSAndroid Build Coastguard Worker   if (scaled_ref_frame) {
2291*fb1b10abSAndroid Build Coastguard Worker     int i;
2292*fb1b10abSAndroid Build Coastguard Worker     // Swap out the reference frame for a version that's been scaled to
2293*fb1b10abSAndroid Build Coastguard Worker     // match the resolution of the current frame, allowing the existing
2294*fb1b10abSAndroid Build Coastguard Worker     // motion search code to be used without additional modifications.
2295*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < MAX_MB_PLANE; i++) backup_yv12[i] = xd->plane[i].pre[0];
2296*fb1b10abSAndroid Build Coastguard Worker     vp9_setup_pre_planes(xd, 0, scaled_ref_frame, mi_row, mi_col, NULL);
2297*fb1b10abSAndroid Build Coastguard Worker   }
2298*fb1b10abSAndroid Build Coastguard Worker 
2299*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
2300*fb1b10abSAndroid Build Coastguard Worker   // TODO(jingning): Implement integral projection functions for high bit-depth
2301*fb1b10abSAndroid Build Coastguard Worker   // setting and remove this part of code.
2302*fb1b10abSAndroid Build Coastguard Worker   if (xd->bd != 8) {
2303*fb1b10abSAndroid Build Coastguard Worker     const unsigned int sad = cpi->fn_ptr[bsize].sdf(
2304*fb1b10abSAndroid Build Coastguard Worker         x->plane[0].src.buf, src_stride, xd->plane[0].pre[0].buf, ref_stride);
2305*fb1b10abSAndroid Build Coastguard Worker     tmp_mv->row = 0;
2306*fb1b10abSAndroid Build Coastguard Worker     tmp_mv->col = 0;
2307*fb1b10abSAndroid Build Coastguard Worker 
2308*fb1b10abSAndroid Build Coastguard Worker     if (scaled_ref_frame) {
2309*fb1b10abSAndroid Build Coastguard Worker       int i;
2310*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < MAX_MB_PLANE; i++) xd->plane[i].pre[0] = backup_yv12[i];
2311*fb1b10abSAndroid Build Coastguard Worker     }
2312*fb1b10abSAndroid Build Coastguard Worker     return sad;
2313*fb1b10abSAndroid Build Coastguard Worker   }
2314*fb1b10abSAndroid Build Coastguard Worker #endif
2315*fb1b10abSAndroid Build Coastguard Worker 
2316*fb1b10abSAndroid Build Coastguard Worker   // Set up prediction 1-D reference set
2317*fb1b10abSAndroid Build Coastguard Worker   ref_buf = xd->plane[0].pre[0].buf - (bw >> 1);
2318*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < search_width; idx += 16) {
2319*fb1b10abSAndroid Build Coastguard Worker     vpx_int_pro_row(&hbuf[idx], ref_buf, ref_stride, bh);
2320*fb1b10abSAndroid Build Coastguard Worker     ref_buf += 16;
2321*fb1b10abSAndroid Build Coastguard Worker   }
2322*fb1b10abSAndroid Build Coastguard Worker 
2323*fb1b10abSAndroid Build Coastguard Worker   ref_buf = xd->plane[0].pre[0].buf - (bh >> 1) * ref_stride;
2324*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < search_height; ++idx) {
2325*fb1b10abSAndroid Build Coastguard Worker     vbuf[idx] = vpx_int_pro_col(ref_buf, bw) >> norm_factor;
2326*fb1b10abSAndroid Build Coastguard Worker     ref_buf += ref_stride;
2327*fb1b10abSAndroid Build Coastguard Worker   }
2328*fb1b10abSAndroid Build Coastguard Worker 
2329*fb1b10abSAndroid Build Coastguard Worker   // Set up src 1-D reference set
2330*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < bw; idx += 16) {
2331*fb1b10abSAndroid Build Coastguard Worker     src_buf = x->plane[0].src.buf + idx;
2332*fb1b10abSAndroid Build Coastguard Worker     vpx_int_pro_row(&src_hbuf[idx], src_buf, src_stride, bh);
2333*fb1b10abSAndroid Build Coastguard Worker   }
2334*fb1b10abSAndroid Build Coastguard Worker 
2335*fb1b10abSAndroid Build Coastguard Worker   src_buf = x->plane[0].src.buf;
2336*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < bh; ++idx) {
2337*fb1b10abSAndroid Build Coastguard Worker     src_vbuf[idx] = vpx_int_pro_col(src_buf, bw) >> norm_factor;
2338*fb1b10abSAndroid Build Coastguard Worker     src_buf += src_stride;
2339*fb1b10abSAndroid Build Coastguard Worker   }
2340*fb1b10abSAndroid Build Coastguard Worker 
2341*fb1b10abSAndroid Build Coastguard Worker   // Find the best match per 1-D search
2342*fb1b10abSAndroid Build Coastguard Worker   tmp_mv->col = vector_match(hbuf, src_hbuf, b_width_log2_lookup[bsize]);
2343*fb1b10abSAndroid Build Coastguard Worker   tmp_mv->row = vector_match(vbuf, src_vbuf, b_height_log2_lookup[bsize]);
2344*fb1b10abSAndroid Build Coastguard Worker 
2345*fb1b10abSAndroid Build Coastguard Worker   this_mv = *tmp_mv;
2346*fb1b10abSAndroid Build Coastguard Worker   src_buf = x->plane[0].src.buf;
2347*fb1b10abSAndroid Build Coastguard Worker   ref_buf = xd->plane[0].pre[0].buf + this_mv.row * ref_stride + this_mv.col;
2348*fb1b10abSAndroid Build Coastguard Worker   best_sad = cpi->fn_ptr[bsize].sdf(src_buf, src_stride, ref_buf, ref_stride);
2349*fb1b10abSAndroid Build Coastguard Worker 
2350*fb1b10abSAndroid Build Coastguard Worker   {
2351*fb1b10abSAndroid Build Coastguard Worker     const uint8_t *const pos[4] = {
2352*fb1b10abSAndroid Build Coastguard Worker       ref_buf - ref_stride,
2353*fb1b10abSAndroid Build Coastguard Worker       ref_buf - 1,
2354*fb1b10abSAndroid Build Coastguard Worker       ref_buf + 1,
2355*fb1b10abSAndroid Build Coastguard Worker       ref_buf + ref_stride,
2356*fb1b10abSAndroid Build Coastguard Worker     };
2357*fb1b10abSAndroid Build Coastguard Worker 
2358*fb1b10abSAndroid Build Coastguard Worker     cpi->fn_ptr[bsize].sdx4df(src_buf, src_stride, pos, ref_stride, this_sad);
2359*fb1b10abSAndroid Build Coastguard Worker   }
2360*fb1b10abSAndroid Build Coastguard Worker 
2361*fb1b10abSAndroid Build Coastguard Worker   for (idx = 0; idx < 4; ++idx) {
2362*fb1b10abSAndroid Build Coastguard Worker     if (this_sad[idx] < best_sad) {
2363*fb1b10abSAndroid Build Coastguard Worker       best_sad = this_sad[idx];
2364*fb1b10abSAndroid Build Coastguard Worker       tmp_mv->row = search_pos[idx].row + this_mv.row;
2365*fb1b10abSAndroid Build Coastguard Worker       tmp_mv->col = search_pos[idx].col + this_mv.col;
2366*fb1b10abSAndroid Build Coastguard Worker     }
2367*fb1b10abSAndroid Build Coastguard Worker   }
2368*fb1b10abSAndroid Build Coastguard Worker 
2369*fb1b10abSAndroid Build Coastguard Worker   if (this_sad[0] < this_sad[3])
2370*fb1b10abSAndroid Build Coastguard Worker     this_mv.row -= 1;
2371*fb1b10abSAndroid Build Coastguard Worker   else
2372*fb1b10abSAndroid Build Coastguard Worker     this_mv.row += 1;
2373*fb1b10abSAndroid Build Coastguard Worker 
2374*fb1b10abSAndroid Build Coastguard Worker   if (this_sad[1] < this_sad[2])
2375*fb1b10abSAndroid Build Coastguard Worker     this_mv.col -= 1;
2376*fb1b10abSAndroid Build Coastguard Worker   else
2377*fb1b10abSAndroid Build Coastguard Worker     this_mv.col += 1;
2378*fb1b10abSAndroid Build Coastguard Worker 
2379*fb1b10abSAndroid Build Coastguard Worker   ref_buf = xd->plane[0].pre[0].buf + this_mv.row * ref_stride + this_mv.col;
2380*fb1b10abSAndroid Build Coastguard Worker 
2381*fb1b10abSAndroid Build Coastguard Worker   tmp_sad = cpi->fn_ptr[bsize].sdf(src_buf, src_stride, ref_buf, ref_stride);
2382*fb1b10abSAndroid Build Coastguard Worker   if (best_sad > tmp_sad) {
2383*fb1b10abSAndroid Build Coastguard Worker     *tmp_mv = this_mv;
2384*fb1b10abSAndroid Build Coastguard Worker     best_sad = tmp_sad;
2385*fb1b10abSAndroid Build Coastguard Worker   }
2386*fb1b10abSAndroid Build Coastguard Worker 
2387*fb1b10abSAndroid Build Coastguard Worker   tmp_mv->row *= 8;
2388*fb1b10abSAndroid Build Coastguard Worker   tmp_mv->col *= 8;
2389*fb1b10abSAndroid Build Coastguard Worker 
2390*fb1b10abSAndroid Build Coastguard Worker   vp9_set_subpel_mv_search_range(&subpel_mv_limits, &x->mv_limits, ref_mv);
2391*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(tmp_mv, subpel_mv_limits.col_min, subpel_mv_limits.col_max,
2392*fb1b10abSAndroid Build Coastguard Worker            subpel_mv_limits.row_min, subpel_mv_limits.row_max);
2393*fb1b10abSAndroid Build Coastguard Worker 
2394*fb1b10abSAndroid Build Coastguard Worker   if (scaled_ref_frame) {
2395*fb1b10abSAndroid Build Coastguard Worker     int i;
2396*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < MAX_MB_PLANE; i++) xd->plane[i].pre[0] = backup_yv12[i];
2397*fb1b10abSAndroid Build Coastguard Worker   }
2398*fb1b10abSAndroid Build Coastguard Worker 
2399*fb1b10abSAndroid Build Coastguard Worker   return best_sad;
2400*fb1b10abSAndroid Build Coastguard Worker }
2401*fb1b10abSAndroid Build Coastguard Worker 
get_exhaustive_threshold(int exhaustive_searches_thresh,BLOCK_SIZE bsize)2402*fb1b10abSAndroid Build Coastguard Worker static int get_exhaustive_threshold(int exhaustive_searches_thresh,
2403*fb1b10abSAndroid Build Coastguard Worker                                     BLOCK_SIZE bsize) {
2404*fb1b10abSAndroid Build Coastguard Worker   return exhaustive_searches_thresh >>
2405*fb1b10abSAndroid Build Coastguard Worker          (8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]));
2406*fb1b10abSAndroid Build Coastguard Worker }
2407*fb1b10abSAndroid Build Coastguard Worker 
2408*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
2409*fb1b10abSAndroid Build Coastguard Worker // Runs sequence of diamond searches in smaller steps for RD.
2410*fb1b10abSAndroid Build Coastguard Worker /* do_refine: If last step (1-away) of n-step search doesn't pick the center
2411*fb1b10abSAndroid Build Coastguard Worker               point as the best match, we will do a final 1-away diamond
2412*fb1b10abSAndroid Build Coastguard Worker               refining search  */
vp9_full_pixel_diamond_new(const VP9_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,MV * mvp_full,int step_param,int lambda,int do_refine,const int_mv * nb_full_mvs,int full_mv_num,MV * best_mv)2413*fb1b10abSAndroid Build Coastguard Worker int vp9_full_pixel_diamond_new(const VP9_COMP *cpi, MACROBLOCK *x,
2414*fb1b10abSAndroid Build Coastguard Worker                                BLOCK_SIZE bsize, MV *mvp_full, int step_param,
2415*fb1b10abSAndroid Build Coastguard Worker                                int lambda, int do_refine,
2416*fb1b10abSAndroid Build Coastguard Worker                                const int_mv *nb_full_mvs, int full_mv_num,
2417*fb1b10abSAndroid Build Coastguard Worker                                MV *best_mv) {
2418*fb1b10abSAndroid Build Coastguard Worker   const vp9_variance_fn_ptr_t *fn_ptr = &cpi->fn_ptr[bsize];
2419*fb1b10abSAndroid Build Coastguard Worker   const SPEED_FEATURES *const sf = &cpi->sf;
2420*fb1b10abSAndroid Build Coastguard Worker   int n, num00 = 0;
2421*fb1b10abSAndroid Build Coastguard Worker   int thissme;
2422*fb1b10abSAndroid Build Coastguard Worker   int bestsme;
2423*fb1b10abSAndroid Build Coastguard Worker   const int further_steps = MAX_MVSEARCH_STEPS - 1 - step_param;
2424*fb1b10abSAndroid Build Coastguard Worker   const MV center_mv = { 0, 0 };
2425*fb1b10abSAndroid Build Coastguard Worker   vpx_clear_system_state();
2426*fb1b10abSAndroid Build Coastguard Worker   diamond_search_sad_new(x, &cpi->ss_cfg, mvp_full, best_mv, step_param, lambda,
2427*fb1b10abSAndroid Build Coastguard Worker                          &n, fn_ptr, nb_full_mvs, full_mv_num);
2428*fb1b10abSAndroid Build Coastguard Worker 
2429*fb1b10abSAndroid Build Coastguard Worker   bestsme = vp9_get_mvpred_var(x, best_mv, &center_mv, fn_ptr, 0);
2430*fb1b10abSAndroid Build Coastguard Worker 
2431*fb1b10abSAndroid Build Coastguard Worker   // If there won't be more n-step search, check to see if refining search is
2432*fb1b10abSAndroid Build Coastguard Worker   // needed.
2433*fb1b10abSAndroid Build Coastguard Worker   if (n > further_steps) do_refine = 0;
2434*fb1b10abSAndroid Build Coastguard Worker 
2435*fb1b10abSAndroid Build Coastguard Worker   while (n < further_steps) {
2436*fb1b10abSAndroid Build Coastguard Worker     ++n;
2437*fb1b10abSAndroid Build Coastguard Worker     if (num00) {
2438*fb1b10abSAndroid Build Coastguard Worker       num00--;
2439*fb1b10abSAndroid Build Coastguard Worker     } else {
2440*fb1b10abSAndroid Build Coastguard Worker       MV temp_mv;
2441*fb1b10abSAndroid Build Coastguard Worker       diamond_search_sad_new(x, &cpi->ss_cfg, mvp_full, &temp_mv,
2442*fb1b10abSAndroid Build Coastguard Worker                              step_param + n, lambda, &num00, fn_ptr,
2443*fb1b10abSAndroid Build Coastguard Worker                              nb_full_mvs, full_mv_num);
2444*fb1b10abSAndroid Build Coastguard Worker       thissme = vp9_get_mvpred_var(x, &temp_mv, &center_mv, fn_ptr, 0);
2445*fb1b10abSAndroid Build Coastguard Worker       // check to see if refining search is needed.
2446*fb1b10abSAndroid Build Coastguard Worker       if (num00 > further_steps - n) do_refine = 0;
2447*fb1b10abSAndroid Build Coastguard Worker 
2448*fb1b10abSAndroid Build Coastguard Worker       if (thissme < bestsme) {
2449*fb1b10abSAndroid Build Coastguard Worker         bestsme = thissme;
2450*fb1b10abSAndroid Build Coastguard Worker         *best_mv = temp_mv;
2451*fb1b10abSAndroid Build Coastguard Worker       }
2452*fb1b10abSAndroid Build Coastguard Worker     }
2453*fb1b10abSAndroid Build Coastguard Worker   }
2454*fb1b10abSAndroid Build Coastguard Worker 
2455*fb1b10abSAndroid Build Coastguard Worker   // final 1-away diamond refining search
2456*fb1b10abSAndroid Build Coastguard Worker   if (do_refine) {
2457*fb1b10abSAndroid Build Coastguard Worker     const int search_range = 8;
2458*fb1b10abSAndroid Build Coastguard Worker     MV temp_mv = *best_mv;
2459*fb1b10abSAndroid Build Coastguard Worker     vp9_refining_search_sad_new(x, &temp_mv, lambda, search_range, fn_ptr,
2460*fb1b10abSAndroid Build Coastguard Worker                                 nb_full_mvs, full_mv_num);
2461*fb1b10abSAndroid Build Coastguard Worker     thissme = vp9_get_mvpred_var(x, &temp_mv, &center_mv, fn_ptr, 0);
2462*fb1b10abSAndroid Build Coastguard Worker     if (thissme < bestsme) {
2463*fb1b10abSAndroid Build Coastguard Worker       bestsme = thissme;
2464*fb1b10abSAndroid Build Coastguard Worker       *best_mv = temp_mv;
2465*fb1b10abSAndroid Build Coastguard Worker     }
2466*fb1b10abSAndroid Build Coastguard Worker   }
2467*fb1b10abSAndroid Build Coastguard Worker 
2468*fb1b10abSAndroid Build Coastguard Worker   if (sf->exhaustive_searches_thresh < INT_MAX &&
2469*fb1b10abSAndroid Build Coastguard Worker       !cpi->rc.is_src_frame_alt_ref) {
2470*fb1b10abSAndroid Build Coastguard Worker     const int64_t exhaustive_thr =
2471*fb1b10abSAndroid Build Coastguard Worker         get_exhaustive_threshold(sf->exhaustive_searches_thresh, bsize);
2472*fb1b10abSAndroid Build Coastguard Worker     if (bestsme > exhaustive_thr) {
2473*fb1b10abSAndroid Build Coastguard Worker       full_pixel_exhaustive_new(cpi, x, best_mv, fn_ptr, best_mv, lambda,
2474*fb1b10abSAndroid Build Coastguard Worker                                 nb_full_mvs, full_mv_num);
2475*fb1b10abSAndroid Build Coastguard Worker       bestsme = vp9_get_mvpred_var(x, best_mv, &center_mv, fn_ptr, 0);
2476*fb1b10abSAndroid Build Coastguard Worker     }
2477*fb1b10abSAndroid Build Coastguard Worker   }
2478*fb1b10abSAndroid Build Coastguard Worker   return bestsme;
2479*fb1b10abSAndroid Build Coastguard Worker }
2480*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_NON_GREEDY_MV
2481*fb1b10abSAndroid Build Coastguard Worker 
2482*fb1b10abSAndroid Build Coastguard Worker // Runs sequence of diamond searches in smaller steps for RD.
2483*fb1b10abSAndroid Build Coastguard Worker /* do_refine: If last step (1-away) of n-step search doesn't pick the center
2484*fb1b10abSAndroid Build Coastguard Worker               point as the best match, we will do a final 1-away diamond
2485*fb1b10abSAndroid Build Coastguard Worker               refining search  */
full_pixel_diamond(const VP9_COMP * const cpi,const MACROBLOCK * const x,BLOCK_SIZE bsize,MV * mvp_full,int step_param,int sadpb,int further_steps,int do_refine,int use_downsampled_sad,int * cost_list,const vp9_variance_fn_ptr_t * fn_ptr,const MV * ref_mv,MV * dst_mv)2486*fb1b10abSAndroid Build Coastguard Worker static int full_pixel_diamond(const VP9_COMP *const cpi,
2487*fb1b10abSAndroid Build Coastguard Worker                               const MACROBLOCK *const x, BLOCK_SIZE bsize,
2488*fb1b10abSAndroid Build Coastguard Worker                               MV *mvp_full, int step_param, int sadpb,
2489*fb1b10abSAndroid Build Coastguard Worker                               int further_steps, int do_refine,
2490*fb1b10abSAndroid Build Coastguard Worker                               int use_downsampled_sad, int *cost_list,
2491*fb1b10abSAndroid Build Coastguard Worker                               const vp9_variance_fn_ptr_t *fn_ptr,
2492*fb1b10abSAndroid Build Coastguard Worker                               const MV *ref_mv, MV *dst_mv) {
2493*fb1b10abSAndroid Build Coastguard Worker   MV temp_mv;
2494*fb1b10abSAndroid Build Coastguard Worker   int thissme, n, num00 = 0;
2495*fb1b10abSAndroid Build Coastguard Worker   int bestsme;
2496*fb1b10abSAndroid Build Coastguard Worker   const int src_buf_stride = x->plane[0].src.stride;
2497*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *const src_buf = x->plane[0].src.buf;
2498*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
2499*fb1b10abSAndroid Build Coastguard Worker   const int pred_buf_stride = xd->plane[0].pre[0].stride;
2500*fb1b10abSAndroid Build Coastguard Worker   uint8_t *pred_buf;
2501*fb1b10abSAndroid Build Coastguard Worker   vp9_sad_fn_ptr_t sad_fn_ptr;
2502*fb1b10abSAndroid Build Coastguard Worker   unsigned int start_mv_sad, start_mv_sad_even_rows, start_mv_sad_odd_rows;
2503*fb1b10abSAndroid Build Coastguard Worker   const MV ref_mv_full = { ref_mv->row >> 3, ref_mv->col >> 3 };
2504*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(mvp_full, x->mv_limits.col_min, x->mv_limits.col_max,
2505*fb1b10abSAndroid Build Coastguard Worker            x->mv_limits.row_min, x->mv_limits.row_max);
2506*fb1b10abSAndroid Build Coastguard Worker 
2507*fb1b10abSAndroid Build Coastguard Worker   pred_buf =
2508*fb1b10abSAndroid Build Coastguard Worker       xd->plane[0].pre[0].buf + mvp_full->row * pred_buf_stride + mvp_full->col;
2509*fb1b10abSAndroid Build Coastguard Worker   start_mv_sad_even_rows =
2510*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->sdsf(src_buf, src_buf_stride, pred_buf, pred_buf_stride);
2511*fb1b10abSAndroid Build Coastguard Worker   start_mv_sad_odd_rows =
2512*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->sdsf(src_buf + src_buf_stride, src_buf_stride,
2513*fb1b10abSAndroid Build Coastguard Worker                    pred_buf + pred_buf_stride, pred_buf_stride);
2514*fb1b10abSAndroid Build Coastguard Worker   start_mv_sad = (start_mv_sad_even_rows + start_mv_sad_odd_rows) >> 1;
2515*fb1b10abSAndroid Build Coastguard Worker   start_mv_sad += mvsad_err_cost(x, mvp_full, &ref_mv_full, sadpb);
2516*fb1b10abSAndroid Build Coastguard Worker 
2517*fb1b10abSAndroid Build Coastguard Worker   sad_fn_ptr.sdf = fn_ptr->sdf;
2518*fb1b10abSAndroid Build Coastguard Worker   sad_fn_ptr.sdx4df = fn_ptr->sdx4df;
2519*fb1b10abSAndroid Build Coastguard Worker   if (use_downsampled_sad && num_4x4_blocks_high_lookup[bsize] >= 2) {
2520*fb1b10abSAndroid Build Coastguard Worker     // If the absolute difference between the pred-to-src SAD of even rows and
2521*fb1b10abSAndroid Build Coastguard Worker     // the pred-to-src SAD of odd rows is small, skip every other row in sad
2522*fb1b10abSAndroid Build Coastguard Worker     // computation.
2523*fb1b10abSAndroid Build Coastguard Worker     const int odd_to_even_diff_sad =
2524*fb1b10abSAndroid Build Coastguard Worker         abs((int)start_mv_sad_even_rows - (int)start_mv_sad_odd_rows);
2525*fb1b10abSAndroid Build Coastguard Worker     const int mult_thresh = 10;
2526*fb1b10abSAndroid Build Coastguard Worker     if (odd_to_even_diff_sad * mult_thresh < (int)start_mv_sad_even_rows) {
2527*fb1b10abSAndroid Build Coastguard Worker       sad_fn_ptr.sdf = fn_ptr->sdsf;
2528*fb1b10abSAndroid Build Coastguard Worker       sad_fn_ptr.sdx4df = fn_ptr->sdsx4df;
2529*fb1b10abSAndroid Build Coastguard Worker     }
2530*fb1b10abSAndroid Build Coastguard Worker   }
2531*fb1b10abSAndroid Build Coastguard Worker 
2532*fb1b10abSAndroid Build Coastguard Worker   bestsme =
2533*fb1b10abSAndroid Build Coastguard Worker       cpi->diamond_search_sad(x, &cpi->ss_cfg, mvp_full, start_mv_sad, &temp_mv,
2534*fb1b10abSAndroid Build Coastguard Worker                               step_param, sadpb, &n, &sad_fn_ptr, ref_mv);
2535*fb1b10abSAndroid Build Coastguard Worker   if (bestsme < INT_MAX)
2536*fb1b10abSAndroid Build Coastguard Worker     bestsme = vp9_get_mvpred_var(x, &temp_mv, ref_mv, fn_ptr, 1);
2537*fb1b10abSAndroid Build Coastguard Worker   *dst_mv = temp_mv;
2538*fb1b10abSAndroid Build Coastguard Worker 
2539*fb1b10abSAndroid Build Coastguard Worker   // If there won't be more n-step search, check to see if refining search is
2540*fb1b10abSAndroid Build Coastguard Worker   // needed.
2541*fb1b10abSAndroid Build Coastguard Worker   if (n > further_steps) do_refine = 0;
2542*fb1b10abSAndroid Build Coastguard Worker 
2543*fb1b10abSAndroid Build Coastguard Worker   while (n < further_steps) {
2544*fb1b10abSAndroid Build Coastguard Worker     ++n;
2545*fb1b10abSAndroid Build Coastguard Worker 
2546*fb1b10abSAndroid Build Coastguard Worker     if (num00) {
2547*fb1b10abSAndroid Build Coastguard Worker       num00--;
2548*fb1b10abSAndroid Build Coastguard Worker     } else {
2549*fb1b10abSAndroid Build Coastguard Worker       thissme = cpi->diamond_search_sad(x, &cpi->ss_cfg, mvp_full, start_mv_sad,
2550*fb1b10abSAndroid Build Coastguard Worker                                         &temp_mv, step_param + n, sadpb, &num00,
2551*fb1b10abSAndroid Build Coastguard Worker                                         &sad_fn_ptr, ref_mv);
2552*fb1b10abSAndroid Build Coastguard Worker       if (thissme < INT_MAX)
2553*fb1b10abSAndroid Build Coastguard Worker         thissme = vp9_get_mvpred_var(x, &temp_mv, ref_mv, fn_ptr, 1);
2554*fb1b10abSAndroid Build Coastguard Worker 
2555*fb1b10abSAndroid Build Coastguard Worker       // check to see if refining search is needed.
2556*fb1b10abSAndroid Build Coastguard Worker       if (num00 > further_steps - n) do_refine = 0;
2557*fb1b10abSAndroid Build Coastguard Worker 
2558*fb1b10abSAndroid Build Coastguard Worker       if (thissme < bestsme) {
2559*fb1b10abSAndroid Build Coastguard Worker         bestsme = thissme;
2560*fb1b10abSAndroid Build Coastguard Worker         *dst_mv = temp_mv;
2561*fb1b10abSAndroid Build Coastguard Worker       }
2562*fb1b10abSAndroid Build Coastguard Worker     }
2563*fb1b10abSAndroid Build Coastguard Worker   }
2564*fb1b10abSAndroid Build Coastguard Worker 
2565*fb1b10abSAndroid Build Coastguard Worker   // final 1-away diamond refining search
2566*fb1b10abSAndroid Build Coastguard Worker   if (do_refine) {
2567*fb1b10abSAndroid Build Coastguard Worker     const int search_range = 8;
2568*fb1b10abSAndroid Build Coastguard Worker     MV best_mv = *dst_mv;
2569*fb1b10abSAndroid Build Coastguard Worker     thissme = vp9_refining_search_sad(x, &best_mv, sadpb, search_range,
2570*fb1b10abSAndroid Build Coastguard Worker                                       &sad_fn_ptr, ref_mv);
2571*fb1b10abSAndroid Build Coastguard Worker     if (thissme < INT_MAX)
2572*fb1b10abSAndroid Build Coastguard Worker       thissme = vp9_get_mvpred_var(x, &best_mv, ref_mv, fn_ptr, 1);
2573*fb1b10abSAndroid Build Coastguard Worker     if (thissme < bestsme) {
2574*fb1b10abSAndroid Build Coastguard Worker       bestsme = thissme;
2575*fb1b10abSAndroid Build Coastguard Worker       *dst_mv = best_mv;
2576*fb1b10abSAndroid Build Coastguard Worker     }
2577*fb1b10abSAndroid Build Coastguard Worker   }
2578*fb1b10abSAndroid Build Coastguard Worker 
2579*fb1b10abSAndroid Build Coastguard Worker   if (sad_fn_ptr.sdf != fn_ptr->sdf) {
2580*fb1b10abSAndroid Build Coastguard Worker     // If we are skipping rows when we perform the motion search, we need to
2581*fb1b10abSAndroid Build Coastguard Worker     // check the quality of skipping. If it's bad, then we run search with
2582*fb1b10abSAndroid Build Coastguard Worker     // skip row features off.
2583*fb1b10abSAndroid Build Coastguard Worker     const uint8_t *best_address = get_buf_from_mv(&xd->plane[0].pre[0], dst_mv);
2584*fb1b10abSAndroid Build Coastguard Worker     const int sad =
2585*fb1b10abSAndroid Build Coastguard Worker         fn_ptr->sdf(src_buf, src_buf_stride, best_address, pred_buf_stride);
2586*fb1b10abSAndroid Build Coastguard Worker     const int skip_sad =
2587*fb1b10abSAndroid Build Coastguard Worker         fn_ptr->sdsf(src_buf, src_buf_stride, best_address, pred_buf_stride);
2588*fb1b10abSAndroid Build Coastguard Worker     // We will keep the result of skipping rows if it's good enough.
2589*fb1b10abSAndroid Build Coastguard Worker     const int kSADThresh =
2590*fb1b10abSAndroid Build Coastguard Worker         1 << (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
2591*fb1b10abSAndroid Build Coastguard Worker     if (sad > kSADThresh && abs(skip_sad - sad) * 10 >= VPXMAX(sad, 1) * 9) {
2592*fb1b10abSAndroid Build Coastguard Worker       // There is a large discrepancy between skipping and not skipping, so we
2593*fb1b10abSAndroid Build Coastguard Worker       // need to redo the motion search.
2594*fb1b10abSAndroid Build Coastguard Worker       return full_pixel_diamond(cpi, x, bsize, mvp_full, step_param, sadpb,
2595*fb1b10abSAndroid Build Coastguard Worker                                 further_steps, do_refine, 0, cost_list, fn_ptr,
2596*fb1b10abSAndroid Build Coastguard Worker                                 ref_mv, dst_mv);
2597*fb1b10abSAndroid Build Coastguard Worker     }
2598*fb1b10abSAndroid Build Coastguard Worker   }
2599*fb1b10abSAndroid Build Coastguard Worker 
2600*fb1b10abSAndroid Build Coastguard Worker   // Return cost list.
2601*fb1b10abSAndroid Build Coastguard Worker   if (cost_list) {
2602*fb1b10abSAndroid Build Coastguard Worker     calc_int_cost_list(x, ref_mv, sadpb, fn_ptr, dst_mv, cost_list);
2603*fb1b10abSAndroid Build Coastguard Worker   }
2604*fb1b10abSAndroid Build Coastguard Worker   return bestsme;
2605*fb1b10abSAndroid Build Coastguard Worker }
2606*fb1b10abSAndroid Build Coastguard Worker 
2607*fb1b10abSAndroid Build Coastguard Worker // Runs an limited range exhaustive mesh search using a pattern set
2608*fb1b10abSAndroid Build Coastguard Worker // according to the encode speed profile.
full_pixel_exhaustive(const VP9_COMP * const cpi,const MACROBLOCK * const x,MV * centre_mv_full,int sadpb,int * cost_list,const vp9_variance_fn_ptr_t * fn_ptr,const MV * ref_mv,MV * dst_mv)2609*fb1b10abSAndroid Build Coastguard Worker static int full_pixel_exhaustive(const VP9_COMP *const cpi,
2610*fb1b10abSAndroid Build Coastguard Worker                                  const MACROBLOCK *const x, MV *centre_mv_full,
2611*fb1b10abSAndroid Build Coastguard Worker                                  int sadpb, int *cost_list,
2612*fb1b10abSAndroid Build Coastguard Worker                                  const vp9_variance_fn_ptr_t *fn_ptr,
2613*fb1b10abSAndroid Build Coastguard Worker                                  const MV *ref_mv, MV *dst_mv) {
2614*fb1b10abSAndroid Build Coastguard Worker   const SPEED_FEATURES *const sf = &cpi->sf;
2615*fb1b10abSAndroid Build Coastguard Worker   MV temp_mv = { centre_mv_full->row, centre_mv_full->col };
2616*fb1b10abSAndroid Build Coastguard Worker   MV f_ref_mv = { ref_mv->row >> 3, ref_mv->col >> 3 };
2617*fb1b10abSAndroid Build Coastguard Worker   int bestsme;
2618*fb1b10abSAndroid Build Coastguard Worker   int i;
2619*fb1b10abSAndroid Build Coastguard Worker   int interval = sf->mesh_patterns[0].interval;
2620*fb1b10abSAndroid Build Coastguard Worker   int range = sf->mesh_patterns[0].range;
2621*fb1b10abSAndroid Build Coastguard Worker   int baseline_interval_divisor;
2622*fb1b10abSAndroid Build Coastguard Worker 
2623*fb1b10abSAndroid Build Coastguard Worker   // Trap illegal values for interval and range for this function.
2624*fb1b10abSAndroid Build Coastguard Worker   if ((range < MIN_RANGE) || (range > MAX_RANGE) || (interval < MIN_INTERVAL) ||
2625*fb1b10abSAndroid Build Coastguard Worker       (interval > range))
2626*fb1b10abSAndroid Build Coastguard Worker     return INT_MAX;
2627*fb1b10abSAndroid Build Coastguard Worker 
2628*fb1b10abSAndroid Build Coastguard Worker   baseline_interval_divisor = range / interval;
2629*fb1b10abSAndroid Build Coastguard Worker 
2630*fb1b10abSAndroid Build Coastguard Worker   // Check size of proposed first range against magnitude of the centre
2631*fb1b10abSAndroid Build Coastguard Worker   // value used as a starting point.
2632*fb1b10abSAndroid Build Coastguard Worker   range = VPXMAX(range, (5 * VPXMAX(abs(temp_mv.row), abs(temp_mv.col))) / 4);
2633*fb1b10abSAndroid Build Coastguard Worker   range = VPXMIN(range, MAX_RANGE);
2634*fb1b10abSAndroid Build Coastguard Worker   interval = VPXMAX(interval, range / baseline_interval_divisor);
2635*fb1b10abSAndroid Build Coastguard Worker 
2636*fb1b10abSAndroid Build Coastguard Worker   // initial search
2637*fb1b10abSAndroid Build Coastguard Worker   bestsme = exhaustive_mesh_search(x, &f_ref_mv, &temp_mv, range, interval,
2638*fb1b10abSAndroid Build Coastguard Worker                                    sadpb, fn_ptr, &temp_mv);
2639*fb1b10abSAndroid Build Coastguard Worker 
2640*fb1b10abSAndroid Build Coastguard Worker   if ((interval > MIN_INTERVAL) && (range > MIN_RANGE)) {
2641*fb1b10abSAndroid Build Coastguard Worker     // Progressive searches with range and step size decreasing each time
2642*fb1b10abSAndroid Build Coastguard Worker     // till we reach a step size of 1. Then break out.
2643*fb1b10abSAndroid Build Coastguard Worker     for (i = 1; i < MAX_MESH_STEP; ++i) {
2644*fb1b10abSAndroid Build Coastguard Worker       // First pass with coarser step and longer range
2645*fb1b10abSAndroid Build Coastguard Worker       bestsme = exhaustive_mesh_search(
2646*fb1b10abSAndroid Build Coastguard Worker           x, &f_ref_mv, &temp_mv, sf->mesh_patterns[i].range,
2647*fb1b10abSAndroid Build Coastguard Worker           sf->mesh_patterns[i].interval, sadpb, fn_ptr, &temp_mv);
2648*fb1b10abSAndroid Build Coastguard Worker 
2649*fb1b10abSAndroid Build Coastguard Worker       if (sf->mesh_patterns[i].interval == 1) break;
2650*fb1b10abSAndroid Build Coastguard Worker     }
2651*fb1b10abSAndroid Build Coastguard Worker   }
2652*fb1b10abSAndroid Build Coastguard Worker 
2653*fb1b10abSAndroid Build Coastguard Worker   if (bestsme < INT_MAX)
2654*fb1b10abSAndroid Build Coastguard Worker     bestsme = vp9_get_mvpred_var(x, &temp_mv, ref_mv, fn_ptr, 1);
2655*fb1b10abSAndroid Build Coastguard Worker   *dst_mv = temp_mv;
2656*fb1b10abSAndroid Build Coastguard Worker 
2657*fb1b10abSAndroid Build Coastguard Worker   // Return cost list.
2658*fb1b10abSAndroid Build Coastguard Worker   if (cost_list) {
2659*fb1b10abSAndroid Build Coastguard Worker     calc_int_cost_list(x, ref_mv, sadpb, fn_ptr, dst_mv, cost_list);
2660*fb1b10abSAndroid Build Coastguard Worker   }
2661*fb1b10abSAndroid Build Coastguard Worker   return bestsme;
2662*fb1b10abSAndroid Build Coastguard Worker }
2663*fb1b10abSAndroid Build Coastguard Worker 
2664*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_NON_GREEDY_MV
vp9_refining_search_sad_new(const MACROBLOCK * x,MV * best_full_mv,int lambda,int search_range,const vp9_variance_fn_ptr_t * fn_ptr,const int_mv * nb_full_mvs,int full_mv_num)2665*fb1b10abSAndroid Build Coastguard Worker int64_t vp9_refining_search_sad_new(const MACROBLOCK *x, MV *best_full_mv,
2666*fb1b10abSAndroid Build Coastguard Worker                                     int lambda, int search_range,
2667*fb1b10abSAndroid Build Coastguard Worker                                     const vp9_variance_fn_ptr_t *fn_ptr,
2668*fb1b10abSAndroid Build Coastguard Worker                                     const int_mv *nb_full_mvs,
2669*fb1b10abSAndroid Build Coastguard Worker                                     int full_mv_num) {
2670*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
2671*fb1b10abSAndroid Build Coastguard Worker   const MV neighbors[4] = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
2672*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
2673*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
2674*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *best_address = get_buf_from_mv(in_what, best_full_mv);
2675*fb1b10abSAndroid Build Coastguard Worker   int64_t best_sad;
2676*fb1b10abSAndroid Build Coastguard Worker   int i, j;
2677*fb1b10abSAndroid Build Coastguard Worker   vpx_clear_system_state();
2678*fb1b10abSAndroid Build Coastguard Worker   {
2679*fb1b10abSAndroid Build Coastguard Worker     const int64_t mv_dist = (int64_t)fn_ptr->sdf(what->buf, what->stride,
2680*fb1b10abSAndroid Build Coastguard Worker                                                  best_address, in_what->stride)
2681*fb1b10abSAndroid Build Coastguard Worker                             << LOG2_PRECISION;
2682*fb1b10abSAndroid Build Coastguard Worker     const int64_t mv_cost =
2683*fb1b10abSAndroid Build Coastguard Worker         vp9_nb_mvs_inconsistency(best_full_mv, nb_full_mvs, full_mv_num);
2684*fb1b10abSAndroid Build Coastguard Worker     best_sad = mv_dist + lambda * mv_cost;
2685*fb1b10abSAndroid Build Coastguard Worker   }
2686*fb1b10abSAndroid Build Coastguard Worker 
2687*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < search_range; i++) {
2688*fb1b10abSAndroid Build Coastguard Worker     int best_site = -1;
2689*fb1b10abSAndroid Build Coastguard Worker     const int all_in = ((best_full_mv->row - 1) > x->mv_limits.row_min) &
2690*fb1b10abSAndroid Build Coastguard Worker                        ((best_full_mv->row + 1) < x->mv_limits.row_max) &
2691*fb1b10abSAndroid Build Coastguard Worker                        ((best_full_mv->col - 1) > x->mv_limits.col_min) &
2692*fb1b10abSAndroid Build Coastguard Worker                        ((best_full_mv->col + 1) < x->mv_limits.col_max);
2693*fb1b10abSAndroid Build Coastguard Worker 
2694*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
2695*fb1b10abSAndroid Build Coastguard Worker       unsigned int sads[4];
2696*fb1b10abSAndroid Build Coastguard Worker       const uint8_t *const positions[4] = { best_address - in_what->stride,
2697*fb1b10abSAndroid Build Coastguard Worker                                             best_address - 1, best_address + 1,
2698*fb1b10abSAndroid Build Coastguard Worker                                             best_address + in_what->stride };
2699*fb1b10abSAndroid Build Coastguard Worker 
2700*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->sdx4df(what->buf, what->stride, positions, in_what->stride, sads);
2701*fb1b10abSAndroid Build Coastguard Worker 
2702*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < 4; ++j) {
2703*fb1b10abSAndroid Build Coastguard Worker         const MV mv = { best_full_mv->row + neighbors[j].row,
2704*fb1b10abSAndroid Build Coastguard Worker                         best_full_mv->col + neighbors[j].col };
2705*fb1b10abSAndroid Build Coastguard Worker         const int64_t mv_dist = (int64_t)sads[j] << LOG2_PRECISION;
2706*fb1b10abSAndroid Build Coastguard Worker         const int64_t mv_cost =
2707*fb1b10abSAndroid Build Coastguard Worker             vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
2708*fb1b10abSAndroid Build Coastguard Worker         const int64_t thissad = mv_dist + lambda * mv_cost;
2709*fb1b10abSAndroid Build Coastguard Worker         if (thissad < best_sad) {
2710*fb1b10abSAndroid Build Coastguard Worker           best_sad = thissad;
2711*fb1b10abSAndroid Build Coastguard Worker           best_site = j;
2712*fb1b10abSAndroid Build Coastguard Worker         }
2713*fb1b10abSAndroid Build Coastguard Worker       }
2714*fb1b10abSAndroid Build Coastguard Worker     } else {
2715*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < 4; ++j) {
2716*fb1b10abSAndroid Build Coastguard Worker         const MV mv = { best_full_mv->row + neighbors[j].row,
2717*fb1b10abSAndroid Build Coastguard Worker                         best_full_mv->col + neighbors[j].col };
2718*fb1b10abSAndroid Build Coastguard Worker 
2719*fb1b10abSAndroid Build Coastguard Worker         if (is_mv_in(&x->mv_limits, &mv)) {
2720*fb1b10abSAndroid Build Coastguard Worker           const int64_t mv_dist =
2721*fb1b10abSAndroid Build Coastguard Worker               (int64_t)fn_ptr->sdf(what->buf, what->stride,
2722*fb1b10abSAndroid Build Coastguard Worker                                    get_buf_from_mv(in_what, &mv),
2723*fb1b10abSAndroid Build Coastguard Worker                                    in_what->stride)
2724*fb1b10abSAndroid Build Coastguard Worker               << LOG2_PRECISION;
2725*fb1b10abSAndroid Build Coastguard Worker           const int64_t mv_cost =
2726*fb1b10abSAndroid Build Coastguard Worker               vp9_nb_mvs_inconsistency(&mv, nb_full_mvs, full_mv_num);
2727*fb1b10abSAndroid Build Coastguard Worker           const int64_t thissad = mv_dist + lambda * mv_cost;
2728*fb1b10abSAndroid Build Coastguard Worker           if (thissad < best_sad) {
2729*fb1b10abSAndroid Build Coastguard Worker             best_sad = thissad;
2730*fb1b10abSAndroid Build Coastguard Worker             best_site = j;
2731*fb1b10abSAndroid Build Coastguard Worker           }
2732*fb1b10abSAndroid Build Coastguard Worker         }
2733*fb1b10abSAndroid Build Coastguard Worker       }
2734*fb1b10abSAndroid Build Coastguard Worker     }
2735*fb1b10abSAndroid Build Coastguard Worker 
2736*fb1b10abSAndroid Build Coastguard Worker     if (best_site == -1) {
2737*fb1b10abSAndroid Build Coastguard Worker       break;
2738*fb1b10abSAndroid Build Coastguard Worker     } else {
2739*fb1b10abSAndroid Build Coastguard Worker       best_full_mv->row += neighbors[best_site].row;
2740*fb1b10abSAndroid Build Coastguard Worker       best_full_mv->col += neighbors[best_site].col;
2741*fb1b10abSAndroid Build Coastguard Worker       best_address = get_buf_from_mv(in_what, best_full_mv);
2742*fb1b10abSAndroid Build Coastguard Worker     }
2743*fb1b10abSAndroid Build Coastguard Worker   }
2744*fb1b10abSAndroid Build Coastguard Worker 
2745*fb1b10abSAndroid Build Coastguard Worker   return best_sad;
2746*fb1b10abSAndroid Build Coastguard Worker }
2747*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_NON_GREEDY_MV
2748*fb1b10abSAndroid Build Coastguard Worker 
vp9_refining_search_sad(const MACROBLOCK * x,MV * ref_mv,int error_per_bit,int search_range,const vp9_sad_fn_ptr_t * sad_fn_ptr,const MV * center_mv)2749*fb1b10abSAndroid Build Coastguard Worker int vp9_refining_search_sad(const MACROBLOCK *x, MV *ref_mv, int error_per_bit,
2750*fb1b10abSAndroid Build Coastguard Worker                             int search_range,
2751*fb1b10abSAndroid Build Coastguard Worker                             const vp9_sad_fn_ptr_t *sad_fn_ptr,
2752*fb1b10abSAndroid Build Coastguard Worker                             const MV *center_mv) {
2753*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
2754*fb1b10abSAndroid Build Coastguard Worker   const MV neighbors[4] = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
2755*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
2756*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
2757*fb1b10abSAndroid Build Coastguard Worker   const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
2758*fb1b10abSAndroid Build Coastguard Worker   const uint8_t *best_address = get_buf_from_mv(in_what, ref_mv);
2759*fb1b10abSAndroid Build Coastguard Worker   unsigned int best_sad =
2760*fb1b10abSAndroid Build Coastguard Worker       sad_fn_ptr->sdf(what->buf, what->stride, best_address, in_what->stride) +
2761*fb1b10abSAndroid Build Coastguard Worker       mvsad_err_cost(x, ref_mv, &fcenter_mv, error_per_bit);
2762*fb1b10abSAndroid Build Coastguard Worker   int i, j;
2763*fb1b10abSAndroid Build Coastguard Worker 
2764*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < search_range; i++) {
2765*fb1b10abSAndroid Build Coastguard Worker     int best_site = -1;
2766*fb1b10abSAndroid Build Coastguard Worker     const int all_in = ((ref_mv->row - 1) > x->mv_limits.row_min) &
2767*fb1b10abSAndroid Build Coastguard Worker                        ((ref_mv->row + 1) < x->mv_limits.row_max) &
2768*fb1b10abSAndroid Build Coastguard Worker                        ((ref_mv->col - 1) > x->mv_limits.col_min) &
2769*fb1b10abSAndroid Build Coastguard Worker                        ((ref_mv->col + 1) < x->mv_limits.col_max);
2770*fb1b10abSAndroid Build Coastguard Worker 
2771*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
2772*fb1b10abSAndroid Build Coastguard Worker       unsigned int sads[4];
2773*fb1b10abSAndroid Build Coastguard Worker       const uint8_t *const positions[4] = { best_address - in_what->stride,
2774*fb1b10abSAndroid Build Coastguard Worker                                             best_address - 1, best_address + 1,
2775*fb1b10abSAndroid Build Coastguard Worker                                             best_address + in_what->stride };
2776*fb1b10abSAndroid Build Coastguard Worker 
2777*fb1b10abSAndroid Build Coastguard Worker       sad_fn_ptr->sdx4df(what->buf, what->stride, positions, in_what->stride,
2778*fb1b10abSAndroid Build Coastguard Worker                          sads);
2779*fb1b10abSAndroid Build Coastguard Worker 
2780*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < 4; ++j) {
2781*fb1b10abSAndroid Build Coastguard Worker         if (sads[j] < best_sad) {
2782*fb1b10abSAndroid Build Coastguard Worker           const MV mv = { ref_mv->row + neighbors[j].row,
2783*fb1b10abSAndroid Build Coastguard Worker                           ref_mv->col + neighbors[j].col };
2784*fb1b10abSAndroid Build Coastguard Worker           sads[j] += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
2785*fb1b10abSAndroid Build Coastguard Worker           if (sads[j] < best_sad) {
2786*fb1b10abSAndroid Build Coastguard Worker             best_sad = sads[j];
2787*fb1b10abSAndroid Build Coastguard Worker             best_site = j;
2788*fb1b10abSAndroid Build Coastguard Worker           }
2789*fb1b10abSAndroid Build Coastguard Worker         }
2790*fb1b10abSAndroid Build Coastguard Worker       }
2791*fb1b10abSAndroid Build Coastguard Worker     } else {
2792*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < 4; ++j) {
2793*fb1b10abSAndroid Build Coastguard Worker         const MV mv = { ref_mv->row + neighbors[j].row,
2794*fb1b10abSAndroid Build Coastguard Worker                         ref_mv->col + neighbors[j].col };
2795*fb1b10abSAndroid Build Coastguard Worker 
2796*fb1b10abSAndroid Build Coastguard Worker         if (is_mv_in(&x->mv_limits, &mv)) {
2797*fb1b10abSAndroid Build Coastguard Worker           unsigned int sad =
2798*fb1b10abSAndroid Build Coastguard Worker               sad_fn_ptr->sdf(what->buf, what->stride,
2799*fb1b10abSAndroid Build Coastguard Worker                               get_buf_from_mv(in_what, &mv), in_what->stride);
2800*fb1b10abSAndroid Build Coastguard Worker           if (sad < best_sad) {
2801*fb1b10abSAndroid Build Coastguard Worker             sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
2802*fb1b10abSAndroid Build Coastguard Worker             if (sad < best_sad) {
2803*fb1b10abSAndroid Build Coastguard Worker               best_sad = sad;
2804*fb1b10abSAndroid Build Coastguard Worker               best_site = j;
2805*fb1b10abSAndroid Build Coastguard Worker             }
2806*fb1b10abSAndroid Build Coastguard Worker           }
2807*fb1b10abSAndroid Build Coastguard Worker         }
2808*fb1b10abSAndroid Build Coastguard Worker       }
2809*fb1b10abSAndroid Build Coastguard Worker     }
2810*fb1b10abSAndroid Build Coastguard Worker 
2811*fb1b10abSAndroid Build Coastguard Worker     if (best_site == -1) {
2812*fb1b10abSAndroid Build Coastguard Worker       break;
2813*fb1b10abSAndroid Build Coastguard Worker     } else {
2814*fb1b10abSAndroid Build Coastguard Worker       ref_mv->row += neighbors[best_site].row;
2815*fb1b10abSAndroid Build Coastguard Worker       ref_mv->col += neighbors[best_site].col;
2816*fb1b10abSAndroid Build Coastguard Worker       best_address = get_buf_from_mv(in_what, ref_mv);
2817*fb1b10abSAndroid Build Coastguard Worker     }
2818*fb1b10abSAndroid Build Coastguard Worker   }
2819*fb1b10abSAndroid Build Coastguard Worker 
2820*fb1b10abSAndroid Build Coastguard Worker   return best_sad;
2821*fb1b10abSAndroid Build Coastguard Worker }
2822*fb1b10abSAndroid Build Coastguard Worker 
2823*fb1b10abSAndroid Build Coastguard Worker // This function is called when we do joint motion search in comp_inter_inter
2824*fb1b10abSAndroid Build Coastguard Worker // mode.
vp9_refining_search_8p_c(const MACROBLOCK * x,MV * ref_mv,int error_per_bit,int search_range,const vp9_variance_fn_ptr_t * fn_ptr,const MV * center_mv,const uint8_t * second_pred)2825*fb1b10abSAndroid Build Coastguard Worker int vp9_refining_search_8p_c(const MACROBLOCK *x, MV *ref_mv, int error_per_bit,
2826*fb1b10abSAndroid Build Coastguard Worker                              int search_range,
2827*fb1b10abSAndroid Build Coastguard Worker                              const vp9_variance_fn_ptr_t *fn_ptr,
2828*fb1b10abSAndroid Build Coastguard Worker                              const MV *center_mv, const uint8_t *second_pred) {
2829*fb1b10abSAndroid Build Coastguard Worker   const MV neighbors[8] = { { -1, 0 },  { 0, -1 }, { 0, 1 },  { 1, 0 },
2830*fb1b10abSAndroid Build Coastguard Worker                             { -1, -1 }, { 1, -1 }, { -1, 1 }, { 1, 1 } };
2831*fb1b10abSAndroid Build Coastguard Worker   const MACROBLOCKD *const xd = &x->e_mbd;
2832*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const what = &x->plane[0].src;
2833*fb1b10abSAndroid Build Coastguard Worker   const struct buf_2d *const in_what = &xd->plane[0].pre[0];
2834*fb1b10abSAndroid Build Coastguard Worker   const MV fcenter_mv = { center_mv->row >> 3, center_mv->col >> 3 };
2835*fb1b10abSAndroid Build Coastguard Worker   unsigned int best_sad = INT_MAX;
2836*fb1b10abSAndroid Build Coastguard Worker   int i, j;
2837*fb1b10abSAndroid Build Coastguard Worker   clamp_mv(ref_mv, x->mv_limits.col_min, x->mv_limits.col_max,
2838*fb1b10abSAndroid Build Coastguard Worker            x->mv_limits.row_min, x->mv_limits.row_max);
2839*fb1b10abSAndroid Build Coastguard Worker   best_sad =
2840*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->sdaf(what->buf, what->stride, get_buf_from_mv(in_what, ref_mv),
2841*fb1b10abSAndroid Build Coastguard Worker                    in_what->stride, second_pred) +
2842*fb1b10abSAndroid Build Coastguard Worker       mvsad_err_cost(x, ref_mv, &fcenter_mv, error_per_bit);
2843*fb1b10abSAndroid Build Coastguard Worker 
2844*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < search_range; ++i) {
2845*fb1b10abSAndroid Build Coastguard Worker     int best_site = -1;
2846*fb1b10abSAndroid Build Coastguard Worker 
2847*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 8; ++j) {
2848*fb1b10abSAndroid Build Coastguard Worker       const MV mv = { ref_mv->row + neighbors[j].row,
2849*fb1b10abSAndroid Build Coastguard Worker                       ref_mv->col + neighbors[j].col };
2850*fb1b10abSAndroid Build Coastguard Worker 
2851*fb1b10abSAndroid Build Coastguard Worker       if (is_mv_in(&x->mv_limits, &mv)) {
2852*fb1b10abSAndroid Build Coastguard Worker         unsigned int sad =
2853*fb1b10abSAndroid Build Coastguard Worker             fn_ptr->sdaf(what->buf, what->stride, get_buf_from_mv(in_what, &mv),
2854*fb1b10abSAndroid Build Coastguard Worker                          in_what->stride, second_pred);
2855*fb1b10abSAndroid Build Coastguard Worker         if (sad < best_sad) {
2856*fb1b10abSAndroid Build Coastguard Worker           sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
2857*fb1b10abSAndroid Build Coastguard Worker           if (sad < best_sad) {
2858*fb1b10abSAndroid Build Coastguard Worker             best_sad = sad;
2859*fb1b10abSAndroid Build Coastguard Worker             best_site = j;
2860*fb1b10abSAndroid Build Coastguard Worker           }
2861*fb1b10abSAndroid Build Coastguard Worker         }
2862*fb1b10abSAndroid Build Coastguard Worker       }
2863*fb1b10abSAndroid Build Coastguard Worker     }
2864*fb1b10abSAndroid Build Coastguard Worker 
2865*fb1b10abSAndroid Build Coastguard Worker     if (best_site == -1) {
2866*fb1b10abSAndroid Build Coastguard Worker       break;
2867*fb1b10abSAndroid Build Coastguard Worker     } else {
2868*fb1b10abSAndroid Build Coastguard Worker       ref_mv->row += neighbors[best_site].row;
2869*fb1b10abSAndroid Build Coastguard Worker       ref_mv->col += neighbors[best_site].col;
2870*fb1b10abSAndroid Build Coastguard Worker     }
2871*fb1b10abSAndroid Build Coastguard Worker   }
2872*fb1b10abSAndroid Build Coastguard Worker   return best_sad;
2873*fb1b10abSAndroid Build Coastguard Worker }
2874*fb1b10abSAndroid Build Coastguard Worker 
vp9_full_pixel_search(const VP9_COMP * const cpi,const MACROBLOCK * const x,BLOCK_SIZE bsize,MV * mvp_full,int step_param,int search_method,int error_per_bit,int * cost_list,const MV * ref_mv,MV * tmp_mv,int var_max,int rd)2875*fb1b10abSAndroid Build Coastguard Worker int vp9_full_pixel_search(const VP9_COMP *const cpi, const MACROBLOCK *const x,
2876*fb1b10abSAndroid Build Coastguard Worker                           BLOCK_SIZE bsize, MV *mvp_full, int step_param,
2877*fb1b10abSAndroid Build Coastguard Worker                           int search_method, int error_per_bit, int *cost_list,
2878*fb1b10abSAndroid Build Coastguard Worker                           const MV *ref_mv, MV *tmp_mv, int var_max, int rd) {
2879*fb1b10abSAndroid Build Coastguard Worker   const SPEED_FEATURES *const sf = &cpi->sf;
2880*fb1b10abSAndroid Build Coastguard Worker   const SEARCH_METHODS method = (SEARCH_METHODS)search_method;
2881*fb1b10abSAndroid Build Coastguard Worker   const vp9_variance_fn_ptr_t *fn_ptr = &cpi->fn_ptr[bsize];
2882*fb1b10abSAndroid Build Coastguard Worker   int var = 0;
2883*fb1b10abSAndroid Build Coastguard Worker   int run_exhaustive_search = 0;
2884*fb1b10abSAndroid Build Coastguard Worker 
2885*fb1b10abSAndroid Build Coastguard Worker   if (cost_list) {
2886*fb1b10abSAndroid Build Coastguard Worker     cost_list[0] = INT_MAX;
2887*fb1b10abSAndroid Build Coastguard Worker     cost_list[1] = INT_MAX;
2888*fb1b10abSAndroid Build Coastguard Worker     cost_list[2] = INT_MAX;
2889*fb1b10abSAndroid Build Coastguard Worker     cost_list[3] = INT_MAX;
2890*fb1b10abSAndroid Build Coastguard Worker     cost_list[4] = INT_MAX;
2891*fb1b10abSAndroid Build Coastguard Worker   }
2892*fb1b10abSAndroid Build Coastguard Worker 
2893*fb1b10abSAndroid Build Coastguard Worker   switch (method) {
2894*fb1b10abSAndroid Build Coastguard Worker     case FAST_DIAMOND:
2895*fb1b10abSAndroid Build Coastguard Worker       var = fast_dia_search(x, mvp_full, step_param, error_per_bit, 0,
2896*fb1b10abSAndroid Build Coastguard Worker                             cost_list, fn_ptr, 1, ref_mv, tmp_mv);
2897*fb1b10abSAndroid Build Coastguard Worker       break;
2898*fb1b10abSAndroid Build Coastguard Worker     case FAST_HEX:
2899*fb1b10abSAndroid Build Coastguard Worker       var = fast_hex_search(x, mvp_full, step_param, error_per_bit, 0,
2900*fb1b10abSAndroid Build Coastguard Worker                             cost_list, fn_ptr, 1, ref_mv, tmp_mv);
2901*fb1b10abSAndroid Build Coastguard Worker       break;
2902*fb1b10abSAndroid Build Coastguard Worker     case HEX:
2903*fb1b10abSAndroid Build Coastguard Worker       var = hex_search(x, mvp_full, step_param, error_per_bit, 1, cost_list,
2904*fb1b10abSAndroid Build Coastguard Worker                        fn_ptr, 1, ref_mv, tmp_mv);
2905*fb1b10abSAndroid Build Coastguard Worker       break;
2906*fb1b10abSAndroid Build Coastguard Worker     case SQUARE:
2907*fb1b10abSAndroid Build Coastguard Worker       var = square_search(x, mvp_full, step_param, error_per_bit, 1, cost_list,
2908*fb1b10abSAndroid Build Coastguard Worker                           fn_ptr, 1, ref_mv, tmp_mv);
2909*fb1b10abSAndroid Build Coastguard Worker       break;
2910*fb1b10abSAndroid Build Coastguard Worker     case BIGDIA:
2911*fb1b10abSAndroid Build Coastguard Worker       var = bigdia_search(x, mvp_full, step_param, error_per_bit, 1, cost_list,
2912*fb1b10abSAndroid Build Coastguard Worker                           fn_ptr, 1, ref_mv, tmp_mv);
2913*fb1b10abSAndroid Build Coastguard Worker       break;
2914*fb1b10abSAndroid Build Coastguard Worker     case NSTEP:
2915*fb1b10abSAndroid Build Coastguard Worker     case MESH:
2916*fb1b10abSAndroid Build Coastguard Worker       var = full_pixel_diamond(
2917*fb1b10abSAndroid Build Coastguard Worker           cpi, x, bsize, mvp_full, step_param, error_per_bit,
2918*fb1b10abSAndroid Build Coastguard Worker           MAX_MVSEARCH_STEPS - 1 - step_param, 1,
2919*fb1b10abSAndroid Build Coastguard Worker           cpi->sf.mv.use_downsampled_sad, cost_list, fn_ptr, ref_mv, tmp_mv);
2920*fb1b10abSAndroid Build Coastguard Worker       break;
2921*fb1b10abSAndroid Build Coastguard Worker     default: assert(0 && "Unknown search method");
2922*fb1b10abSAndroid Build Coastguard Worker   }
2923*fb1b10abSAndroid Build Coastguard Worker 
2924*fb1b10abSAndroid Build Coastguard Worker   if (method == NSTEP) {
2925*fb1b10abSAndroid Build Coastguard Worker     if (sf->exhaustive_searches_thresh < INT_MAX &&
2926*fb1b10abSAndroid Build Coastguard Worker         !cpi->rc.is_src_frame_alt_ref) {
2927*fb1b10abSAndroid Build Coastguard Worker       const int64_t exhaustive_thr =
2928*fb1b10abSAndroid Build Coastguard Worker           get_exhaustive_threshold(sf->exhaustive_searches_thresh, bsize);
2929*fb1b10abSAndroid Build Coastguard Worker       if (var > exhaustive_thr) {
2930*fb1b10abSAndroid Build Coastguard Worker         run_exhaustive_search = 1;
2931*fb1b10abSAndroid Build Coastguard Worker       }
2932*fb1b10abSAndroid Build Coastguard Worker     }
2933*fb1b10abSAndroid Build Coastguard Worker   } else if (method == MESH) {
2934*fb1b10abSAndroid Build Coastguard Worker     run_exhaustive_search = 1;
2935*fb1b10abSAndroid Build Coastguard Worker   }
2936*fb1b10abSAndroid Build Coastguard Worker 
2937*fb1b10abSAndroid Build Coastguard Worker   if (run_exhaustive_search) {
2938*fb1b10abSAndroid Build Coastguard Worker     int var_ex;
2939*fb1b10abSAndroid Build Coastguard Worker     MV tmp_mv_ex;
2940*fb1b10abSAndroid Build Coastguard Worker     var_ex = full_pixel_exhaustive(cpi, x, tmp_mv, error_per_bit, cost_list,
2941*fb1b10abSAndroid Build Coastguard Worker                                    fn_ptr, ref_mv, &tmp_mv_ex);
2942*fb1b10abSAndroid Build Coastguard Worker     if (var_ex < var) {
2943*fb1b10abSAndroid Build Coastguard Worker       var = var_ex;
2944*fb1b10abSAndroid Build Coastguard Worker       *tmp_mv = tmp_mv_ex;
2945*fb1b10abSAndroid Build Coastguard Worker     }
2946*fb1b10abSAndroid Build Coastguard Worker   }
2947*fb1b10abSAndroid Build Coastguard Worker 
2948*fb1b10abSAndroid Build Coastguard Worker   if (method != NSTEP && method != MESH && rd && var < var_max)
2949*fb1b10abSAndroid Build Coastguard Worker     var = vp9_get_mvpred_var(x, tmp_mv, ref_mv, fn_ptr, 1);
2950*fb1b10abSAndroid Build Coastguard Worker 
2951*fb1b10abSAndroid Build Coastguard Worker   return var;
2952*fb1b10abSAndroid Build Coastguard Worker }
2953*fb1b10abSAndroid Build Coastguard Worker 
2954*fb1b10abSAndroid Build Coastguard Worker // Note(yunqingwang): The following 2 functions are only used in the motion
2955*fb1b10abSAndroid Build Coastguard Worker // vector unit test, which return extreme motion vectors allowed by the MV
2956*fb1b10abSAndroid Build Coastguard Worker // limits.
2957*fb1b10abSAndroid Build Coastguard Worker #define COMMON_MV_TEST \
2958*fb1b10abSAndroid Build Coastguard Worker   SETUP_SUBPEL_SEARCH; \
2959*fb1b10abSAndroid Build Coastguard Worker                        \
2960*fb1b10abSAndroid Build Coastguard Worker   (void)error_per_bit; \
2961*fb1b10abSAndroid Build Coastguard Worker   (void)vfp;           \
2962*fb1b10abSAndroid Build Coastguard Worker   (void)z;             \
2963*fb1b10abSAndroid Build Coastguard Worker   (void)src_stride;    \
2964*fb1b10abSAndroid Build Coastguard Worker   (void)y;             \
2965*fb1b10abSAndroid Build Coastguard Worker   (void)y_stride;      \
2966*fb1b10abSAndroid Build Coastguard Worker   (void)second_pred;   \
2967*fb1b10abSAndroid Build Coastguard Worker   (void)w;             \
2968*fb1b10abSAndroid Build Coastguard Worker   (void)h;             \
2969*fb1b10abSAndroid Build Coastguard Worker   (void)offset;        \
2970*fb1b10abSAndroid Build Coastguard Worker   (void)mvjcost;       \
2971*fb1b10abSAndroid Build Coastguard Worker   (void)mvcost;        \
2972*fb1b10abSAndroid Build Coastguard Worker   (void)sse1;          \
2973*fb1b10abSAndroid Build Coastguard Worker   (void)distortion;    \
2974*fb1b10abSAndroid Build Coastguard Worker                        \
2975*fb1b10abSAndroid Build Coastguard Worker   (void)halfiters;     \
2976*fb1b10abSAndroid Build Coastguard Worker   (void)quarteriters;  \
2977*fb1b10abSAndroid Build Coastguard Worker   (void)eighthiters;   \
2978*fb1b10abSAndroid Build Coastguard Worker   (void)whichdir;      \
2979*fb1b10abSAndroid Build Coastguard Worker   (void)allow_hp;      \
2980*fb1b10abSAndroid Build Coastguard Worker   (void)forced_stop;   \
2981*fb1b10abSAndroid Build Coastguard Worker   (void)hstep;         \
2982*fb1b10abSAndroid Build Coastguard Worker   (void)rr;            \
2983*fb1b10abSAndroid Build Coastguard Worker   (void)rc;            \
2984*fb1b10abSAndroid Build Coastguard Worker                        \
2985*fb1b10abSAndroid Build Coastguard Worker   (void)tr;            \
2986*fb1b10abSAndroid Build Coastguard Worker   (void)tc;            \
2987*fb1b10abSAndroid Build Coastguard Worker   (void)sse;           \
2988*fb1b10abSAndroid Build Coastguard Worker   (void)thismse;       \
2989*fb1b10abSAndroid Build Coastguard Worker   (void)cost_list;     \
2990*fb1b10abSAndroid Build Coastguard Worker   (void)use_accurate_subpel_search
2991*fb1b10abSAndroid Build Coastguard Worker 
2992*fb1b10abSAndroid Build Coastguard Worker // Return the maximum MV.
vp9_return_max_sub_pixel_mv(const MACROBLOCK * x,MV * bestmv,const MV * ref_mv,int allow_hp,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,int forced_stop,int iters_per_step,int * cost_list,int * mvjcost,int * mvcost[2],uint32_t * distortion,uint32_t * sse1,const uint8_t * second_pred,int w,int h,int use_accurate_subpel_search)2993*fb1b10abSAndroid Build Coastguard Worker uint32_t vp9_return_max_sub_pixel_mv(
2994*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
2995*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
2996*fb1b10abSAndroid Build Coastguard Worker     int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
2997*fb1b10abSAndroid Build Coastguard Worker     uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
2998*fb1b10abSAndroid Build Coastguard Worker     int h, int use_accurate_subpel_search) {
2999*fb1b10abSAndroid Build Coastguard Worker   COMMON_MV_TEST;
3000*fb1b10abSAndroid Build Coastguard Worker 
3001*fb1b10abSAndroid Build Coastguard Worker   (void)minr;
3002*fb1b10abSAndroid Build Coastguard Worker   (void)minc;
3003*fb1b10abSAndroid Build Coastguard Worker 
3004*fb1b10abSAndroid Build Coastguard Worker   bestmv->row = maxr;
3005*fb1b10abSAndroid Build Coastguard Worker   bestmv->col = maxc;
3006*fb1b10abSAndroid Build Coastguard Worker   besterr = 0;
3007*fb1b10abSAndroid Build Coastguard Worker 
3008*fb1b10abSAndroid Build Coastguard Worker   // In the sub-pel motion search, if hp is not used, then the last bit of mv
3009*fb1b10abSAndroid Build Coastguard Worker   // has to be 0.
3010*fb1b10abSAndroid Build Coastguard Worker   lower_mv_precision(bestmv, allow_hp && use_mv_hp(ref_mv));
3011*fb1b10abSAndroid Build Coastguard Worker 
3012*fb1b10abSAndroid Build Coastguard Worker   return besterr;
3013*fb1b10abSAndroid Build Coastguard Worker }
3014*fb1b10abSAndroid Build Coastguard Worker // Return the minimum MV.
vp9_return_min_sub_pixel_mv(const MACROBLOCK * x,MV * bestmv,const MV * ref_mv,int allow_hp,int error_per_bit,const vp9_variance_fn_ptr_t * vfp,int forced_stop,int iters_per_step,int * cost_list,int * mvjcost,int * mvcost[2],uint32_t * distortion,uint32_t * sse1,const uint8_t * second_pred,int w,int h,int use_accurate_subpel_search)3015*fb1b10abSAndroid Build Coastguard Worker uint32_t vp9_return_min_sub_pixel_mv(
3016*fb1b10abSAndroid Build Coastguard Worker     const MACROBLOCK *x, MV *bestmv, const MV *ref_mv, int allow_hp,
3017*fb1b10abSAndroid Build Coastguard Worker     int error_per_bit, const vp9_variance_fn_ptr_t *vfp, int forced_stop,
3018*fb1b10abSAndroid Build Coastguard Worker     int iters_per_step, int *cost_list, int *mvjcost, int *mvcost[2],
3019*fb1b10abSAndroid Build Coastguard Worker     uint32_t *distortion, uint32_t *sse1, const uint8_t *second_pred, int w,
3020*fb1b10abSAndroid Build Coastguard Worker     int h, int use_accurate_subpel_search) {
3021*fb1b10abSAndroid Build Coastguard Worker   COMMON_MV_TEST;
3022*fb1b10abSAndroid Build Coastguard Worker 
3023*fb1b10abSAndroid Build Coastguard Worker   (void)maxr;
3024*fb1b10abSAndroid Build Coastguard Worker   (void)maxc;
3025*fb1b10abSAndroid Build Coastguard Worker 
3026*fb1b10abSAndroid Build Coastguard Worker   bestmv->row = minr;
3027*fb1b10abSAndroid Build Coastguard Worker   bestmv->col = minc;
3028*fb1b10abSAndroid Build Coastguard Worker   besterr = 0;
3029*fb1b10abSAndroid Build Coastguard Worker 
3030*fb1b10abSAndroid Build Coastguard Worker   // In the sub-pel motion search, if hp is not used, then the last bit of mv
3031*fb1b10abSAndroid Build Coastguard Worker   // has to be 0.
3032*fb1b10abSAndroid Build Coastguard Worker   lower_mv_precision(bestmv, allow_hp && use_mv_hp(ref_mv));
3033*fb1b10abSAndroid Build Coastguard Worker 
3034*fb1b10abSAndroid Build Coastguard Worker   return besterr;
3035*fb1b10abSAndroid Build Coastguard Worker }
3036