xref: /aosp_15_r20/external/libvpx/vp8/encoder/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 "./vp8_rtcd.h"
12*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "onyx_int.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "mcomp.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vpx_config.h"
17*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
18*fb1b10abSAndroid Build Coastguard Worker #include <limits.h>
19*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
20*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/findnearmv.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/common.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
23*fb1b10abSAndroid Build Coastguard Worker 
vp8_mv_bit_cost(int_mv * mv,int_mv * ref,int * mvcost[2],int Weight)24*fb1b10abSAndroid Build Coastguard Worker int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight) {
25*fb1b10abSAndroid Build Coastguard Worker   /* MV costing is based on the distribution of vectors in the previous
26*fb1b10abSAndroid Build Coastguard Worker    * frame and as such will tend to over state the cost of vectors. In
27*fb1b10abSAndroid Build Coastguard Worker    * addition coding a new vector can have a knock on effect on the cost
28*fb1b10abSAndroid Build Coastguard Worker    * of subsequent vectors and the quality of prediction from NEAR and
29*fb1b10abSAndroid Build Coastguard Worker    * NEAREST for subsequent blocks. The "Weight" parameter allows, to a
30*fb1b10abSAndroid Build Coastguard Worker    * limited extent, for some account to be taken of these factors.
31*fb1b10abSAndroid Build Coastguard Worker    */
32*fb1b10abSAndroid Build Coastguard Worker   const int mv_idx_row =
33*fb1b10abSAndroid Build Coastguard Worker       clamp((mv->as_mv.row - ref->as_mv.row) >> 1, 0, MVvals);
34*fb1b10abSAndroid Build Coastguard Worker   const int mv_idx_col =
35*fb1b10abSAndroid Build Coastguard Worker       clamp((mv->as_mv.col - ref->as_mv.col) >> 1, 0, MVvals);
36*fb1b10abSAndroid Build Coastguard Worker   return ((mvcost[0][mv_idx_row] + mvcost[1][mv_idx_col]) * Weight) >> 7;
37*fb1b10abSAndroid Build Coastguard Worker }
38*fb1b10abSAndroid Build Coastguard Worker 
mv_err_cost(int_mv * mv,int_mv * ref,int * mvcost[2],int error_per_bit)39*fb1b10abSAndroid Build Coastguard Worker static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2],
40*fb1b10abSAndroid Build Coastguard Worker                        int error_per_bit) {
41*fb1b10abSAndroid Build Coastguard Worker   /* Ignore mv costing if mvcost is NULL */
42*fb1b10abSAndroid Build Coastguard Worker   if (mvcost) {
43*fb1b10abSAndroid Build Coastguard Worker     const int mv_idx_row =
44*fb1b10abSAndroid Build Coastguard Worker         clamp((mv->as_mv.row - ref->as_mv.row) >> 1, 0, MVvals);
45*fb1b10abSAndroid Build Coastguard Worker     const int mv_idx_col =
46*fb1b10abSAndroid Build Coastguard Worker         clamp((mv->as_mv.col - ref->as_mv.col) >> 1, 0, MVvals);
47*fb1b10abSAndroid Build Coastguard Worker     return ((mvcost[0][mv_idx_row] + mvcost[1][mv_idx_col]) * error_per_bit +
48*fb1b10abSAndroid Build Coastguard Worker             128) >>
49*fb1b10abSAndroid Build Coastguard Worker            8;
50*fb1b10abSAndroid Build Coastguard Worker   }
51*fb1b10abSAndroid Build Coastguard Worker   return 0;
52*fb1b10abSAndroid Build Coastguard Worker }
53*fb1b10abSAndroid Build Coastguard Worker 
mvsad_err_cost(int_mv * mv,int_mv * ref,int * mvsadcost[2],int error_per_bit)54*fb1b10abSAndroid Build Coastguard Worker static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2],
55*fb1b10abSAndroid Build Coastguard Worker                           int error_per_bit) {
56*fb1b10abSAndroid Build Coastguard Worker   /* Calculate sad error cost on full pixel basis. */
57*fb1b10abSAndroid Build Coastguard Worker   /* Ignore mv costing if mvsadcost is NULL */
58*fb1b10abSAndroid Build Coastguard Worker   if (mvsadcost) {
59*fb1b10abSAndroid Build Coastguard Worker     return ((mvsadcost[0][(mv->as_mv.row - ref->as_mv.row)] +
60*fb1b10abSAndroid Build Coastguard Worker              mvsadcost[1][(mv->as_mv.col - ref->as_mv.col)]) *
61*fb1b10abSAndroid Build Coastguard Worker                 error_per_bit +
62*fb1b10abSAndroid Build Coastguard Worker             128) >>
63*fb1b10abSAndroid Build Coastguard Worker            8;
64*fb1b10abSAndroid Build Coastguard Worker   }
65*fb1b10abSAndroid Build Coastguard Worker   return 0;
66*fb1b10abSAndroid Build Coastguard Worker }
67*fb1b10abSAndroid Build Coastguard Worker 
vp8_init_dsmotion_compensation(MACROBLOCK * x,int stride)68*fb1b10abSAndroid Build Coastguard Worker void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride) {
69*fb1b10abSAndroid Build Coastguard Worker   int Len;
70*fb1b10abSAndroid Build Coastguard Worker   int search_site_count = 0;
71*fb1b10abSAndroid Build Coastguard Worker 
72*fb1b10abSAndroid Build Coastguard Worker   /* Generate offsets for 4 search sites per step. */
73*fb1b10abSAndroid Build Coastguard Worker   Len = MAX_FIRST_STEP;
74*fb1b10abSAndroid Build Coastguard Worker   x->ss[search_site_count].mv.col = 0;
75*fb1b10abSAndroid Build Coastguard Worker   x->ss[search_site_count].mv.row = 0;
76*fb1b10abSAndroid Build Coastguard Worker   x->ss[search_site_count].offset = 0;
77*fb1b10abSAndroid Build Coastguard Worker   search_site_count++;
78*fb1b10abSAndroid Build Coastguard Worker 
79*fb1b10abSAndroid Build Coastguard Worker   while (Len > 0) {
80*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
81*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = 0;
82*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = -Len;
83*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = -Len * stride;
84*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
85*fb1b10abSAndroid Build Coastguard Worker 
86*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
87*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = 0;
88*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = Len;
89*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = Len * stride;
90*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
91*fb1b10abSAndroid Build Coastguard Worker 
92*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
93*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = -Len;
94*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = 0;
95*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = -Len;
96*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
97*fb1b10abSAndroid Build Coastguard Worker 
98*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
99*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = Len;
100*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = 0;
101*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = Len;
102*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
103*fb1b10abSAndroid Build Coastguard Worker 
104*fb1b10abSAndroid Build Coastguard Worker     /* Contract. */
105*fb1b10abSAndroid Build Coastguard Worker     Len /= 2;
106*fb1b10abSAndroid Build Coastguard Worker   }
107*fb1b10abSAndroid Build Coastguard Worker 
108*fb1b10abSAndroid Build Coastguard Worker   x->ss_count = search_site_count;
109*fb1b10abSAndroid Build Coastguard Worker   x->searches_per_step = 4;
110*fb1b10abSAndroid Build Coastguard Worker }
111*fb1b10abSAndroid Build Coastguard Worker 
vp8_init3smotion_compensation(MACROBLOCK * x,int stride)112*fb1b10abSAndroid Build Coastguard Worker void vp8_init3smotion_compensation(MACROBLOCK *x, int stride) {
113*fb1b10abSAndroid Build Coastguard Worker   int Len;
114*fb1b10abSAndroid Build Coastguard Worker   int search_site_count = 0;
115*fb1b10abSAndroid Build Coastguard Worker 
116*fb1b10abSAndroid Build Coastguard Worker   /* Generate offsets for 8 search sites per step. */
117*fb1b10abSAndroid Build Coastguard Worker   Len = MAX_FIRST_STEP;
118*fb1b10abSAndroid Build Coastguard Worker   x->ss[search_site_count].mv.col = 0;
119*fb1b10abSAndroid Build Coastguard Worker   x->ss[search_site_count].mv.row = 0;
120*fb1b10abSAndroid Build Coastguard Worker   x->ss[search_site_count].offset = 0;
121*fb1b10abSAndroid Build Coastguard Worker   search_site_count++;
122*fb1b10abSAndroid Build Coastguard Worker 
123*fb1b10abSAndroid Build Coastguard Worker   while (Len > 0) {
124*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
125*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = 0;
126*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = -Len;
127*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = -Len * stride;
128*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
129*fb1b10abSAndroid Build Coastguard Worker 
130*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
131*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = 0;
132*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = Len;
133*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = Len * stride;
134*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
135*fb1b10abSAndroid Build Coastguard Worker 
136*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
137*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = -Len;
138*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = 0;
139*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = -Len;
140*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
141*fb1b10abSAndroid Build Coastguard Worker 
142*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
143*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = Len;
144*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = 0;
145*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = Len;
146*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
147*fb1b10abSAndroid Build Coastguard Worker 
148*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
149*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = -Len;
150*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = -Len;
151*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = -Len * stride - Len;
152*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
153*fb1b10abSAndroid Build Coastguard Worker 
154*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
155*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = Len;
156*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = -Len;
157*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = -Len * stride + Len;
158*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
159*fb1b10abSAndroid Build Coastguard Worker 
160*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
161*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = -Len;
162*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = Len;
163*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = Len * stride - Len;
164*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
165*fb1b10abSAndroid Build Coastguard Worker 
166*fb1b10abSAndroid Build Coastguard Worker     /* Compute offsets for search sites. */
167*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.col = Len;
168*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].mv.row = Len;
169*fb1b10abSAndroid Build Coastguard Worker     x->ss[search_site_count].offset = Len * stride + Len;
170*fb1b10abSAndroid Build Coastguard Worker     search_site_count++;
171*fb1b10abSAndroid Build Coastguard Worker 
172*fb1b10abSAndroid Build Coastguard Worker     /* Contract. */
173*fb1b10abSAndroid Build Coastguard Worker     Len /= 2;
174*fb1b10abSAndroid Build Coastguard Worker   }
175*fb1b10abSAndroid Build Coastguard Worker 
176*fb1b10abSAndroid Build Coastguard Worker   x->ss_count = search_site_count;
177*fb1b10abSAndroid Build Coastguard Worker   x->searches_per_step = 8;
178*fb1b10abSAndroid Build Coastguard Worker }
179*fb1b10abSAndroid Build Coastguard Worker 
180*fb1b10abSAndroid Build Coastguard Worker /*
181*fb1b10abSAndroid Build Coastguard Worker  * To avoid the penalty for crossing cache-line read, preload the reference
182*fb1b10abSAndroid Build Coastguard Worker  * area in a small buffer, which is aligned to make sure there won't be crossing
183*fb1b10abSAndroid Build Coastguard Worker  * cache-line read while reading from this buffer. This reduced the cpu
184*fb1b10abSAndroid Build Coastguard Worker  * cycles spent on reading ref data in sub-pixel filter functions.
185*fb1b10abSAndroid Build Coastguard Worker  * TODO: Currently, since sub-pixel search range here is -3 ~ 3, copy 22 rows x
186*fb1b10abSAndroid Build Coastguard Worker  * 32 cols area that is enough for 16x16 macroblock. Later, for SPLITMV, we
187*fb1b10abSAndroid Build Coastguard Worker  * could reduce the area.
188*fb1b10abSAndroid Build Coastguard Worker  */
189*fb1b10abSAndroid Build Coastguard Worker 
190*fb1b10abSAndroid Build Coastguard Worker /* estimated cost of a motion vector (r,c) */
191*fb1b10abSAndroid Build Coastguard Worker #define MVC(r, c)                                                             \
192*fb1b10abSAndroid Build Coastguard Worker   (mvcost                                                                     \
193*fb1b10abSAndroid Build Coastguard Worker        ? ((mvcost[0][(r)-rr] + mvcost[1][(c)-rc]) * error_per_bit + 128) >> 8 \
194*fb1b10abSAndroid Build Coastguard Worker        : 0)
195*fb1b10abSAndroid Build Coastguard Worker /* pointer to predictor base of a motionvector */
196*fb1b10abSAndroid Build Coastguard Worker #define PRE(r, c) (y + (((r) >> 2) * y_stride + ((c) >> 2) - (offset)))
197*fb1b10abSAndroid Build Coastguard Worker /* convert motion vector component to offset for svf calc */
198*fb1b10abSAndroid Build Coastguard Worker #define SP(x) (((x)&3) << 1)
199*fb1b10abSAndroid Build Coastguard Worker /* returns subpixel variance error function. */
200*fb1b10abSAndroid Build Coastguard Worker #define DIST(r, c) \
201*fb1b10abSAndroid Build Coastguard Worker   vfp->svf(PRE(r, c), y_stride, SP(c), SP(r), z, b->src_stride, &sse)
202*fb1b10abSAndroid Build Coastguard Worker #define IFMVCV(r, c, s, e) \
203*fb1b10abSAndroid Build Coastguard Worker   if (c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;
204*fb1b10abSAndroid Build Coastguard Worker /* returns distortion + motion vector cost */
205*fb1b10abSAndroid Build Coastguard Worker #define ERR(r, c) (MVC(r, c) + DIST(r, c))
206*fb1b10abSAndroid Build Coastguard Worker /* checks if (r,c) has better score than previous best */
207*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BETTER(v, r, c)                          \
208*fb1b10abSAndroid Build Coastguard Worker   do {                                                 \
209*fb1b10abSAndroid Build Coastguard Worker     IFMVCV(                                            \
210*fb1b10abSAndroid Build Coastguard Worker         r, c,                                          \
211*fb1b10abSAndroid Build Coastguard Worker         {                                              \
212*fb1b10abSAndroid Build Coastguard Worker           thismse = DIST(r, c);                        \
213*fb1b10abSAndroid Build Coastguard Worker           if ((v = (MVC(r, c) + thismse)) < besterr) { \
214*fb1b10abSAndroid Build Coastguard Worker             besterr = v;                               \
215*fb1b10abSAndroid Build Coastguard Worker             br = r;                                    \
216*fb1b10abSAndroid Build Coastguard Worker             bc = c;                                    \
217*fb1b10abSAndroid Build Coastguard Worker             *distortion = thismse;                     \
218*fb1b10abSAndroid Build Coastguard Worker             *sse1 = sse;                               \
219*fb1b10abSAndroid Build Coastguard Worker           }                                            \
220*fb1b10abSAndroid Build Coastguard Worker         },                                             \
221*fb1b10abSAndroid Build Coastguard Worker         v = UINT_MAX;)                                 \
222*fb1b10abSAndroid Build Coastguard Worker   } while (0)
223*fb1b10abSAndroid Build Coastguard Worker 
vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * bestmv,int_mv * ref_mv,int error_per_bit,const vp8_variance_fn_ptr_t * vfp,int * mvcost[2],int * distortion,unsigned int * sse1)224*fb1b10abSAndroid Build Coastguard Worker int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
225*fb1b10abSAndroid Build Coastguard Worker                                              int_mv *bestmv, int_mv *ref_mv,
226*fb1b10abSAndroid Build Coastguard Worker                                              int error_per_bit,
227*fb1b10abSAndroid Build Coastguard Worker                                              const vp8_variance_fn_ptr_t *vfp,
228*fb1b10abSAndroid Build Coastguard Worker                                              int *mvcost[2], int *distortion,
229*fb1b10abSAndroid Build Coastguard Worker                                              unsigned int *sse1) {
230*fb1b10abSAndroid Build Coastguard Worker   unsigned char *z = (*(b->base_src) + b->src);
231*fb1b10abSAndroid Build Coastguard Worker 
232*fb1b10abSAndroid Build Coastguard Worker   int rr = ref_mv->as_mv.row >> 1, rc = ref_mv->as_mv.col >> 1;
233*fb1b10abSAndroid Build Coastguard Worker   int br = bestmv->as_mv.row * 4, bc = bestmv->as_mv.col * 4;
234*fb1b10abSAndroid Build Coastguard Worker   int tr = br, tc = bc;
235*fb1b10abSAndroid Build Coastguard Worker   unsigned int besterr;
236*fb1b10abSAndroid Build Coastguard Worker   unsigned int left, right, up, down, diag;
237*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;
238*fb1b10abSAndroid Build Coastguard Worker   unsigned int whichdir;
239*fb1b10abSAndroid Build Coastguard Worker   unsigned int halfiters = 4;
240*fb1b10abSAndroid Build Coastguard Worker   unsigned int quarteriters = 4;
241*fb1b10abSAndroid Build Coastguard Worker   int thismse;
242*fb1b10abSAndroid Build Coastguard Worker 
243*fb1b10abSAndroid Build Coastguard Worker   int minc = VPXMAX(x->mv_col_min * 4,
244*fb1b10abSAndroid Build Coastguard Worker                     (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1));
245*fb1b10abSAndroid Build Coastguard Worker   int maxc = VPXMIN(x->mv_col_max * 4,
246*fb1b10abSAndroid Build Coastguard Worker                     (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1));
247*fb1b10abSAndroid Build Coastguard Worker   int minr = VPXMAX(x->mv_row_min * 4,
248*fb1b10abSAndroid Build Coastguard Worker                     (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1));
249*fb1b10abSAndroid Build Coastguard Worker   int maxr = VPXMIN(x->mv_row_max * 4,
250*fb1b10abSAndroid Build Coastguard Worker                     (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1));
251*fb1b10abSAndroid Build Coastguard Worker 
252*fb1b10abSAndroid Build Coastguard Worker   int y_stride;
253*fb1b10abSAndroid Build Coastguard Worker   int offset;
254*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
255*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
256*fb1b10abSAndroid Build Coastguard Worker 
257*fb1b10abSAndroid Build Coastguard Worker #if VPX_ARCH_X86 || VPX_ARCH_X86_64
258*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
259*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y_0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +
260*fb1b10abSAndroid Build Coastguard Worker                        bestmv->as_mv.col;
261*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y;
262*fb1b10abSAndroid Build Coastguard Worker   int buf_r1, buf_r2, buf_c1;
263*fb1b10abSAndroid Build Coastguard Worker 
264*fb1b10abSAndroid Build Coastguard Worker   /* Clamping to avoid out-of-range data access */
265*fb1b10abSAndroid Build Coastguard Worker   buf_r1 = ((bestmv->as_mv.row - 3) < x->mv_row_min)
266*fb1b10abSAndroid Build Coastguard Worker                ? (bestmv->as_mv.row - x->mv_row_min)
267*fb1b10abSAndroid Build Coastguard Worker                : 3;
268*fb1b10abSAndroid Build Coastguard Worker   buf_r2 = ((bestmv->as_mv.row + 3) > x->mv_row_max)
269*fb1b10abSAndroid Build Coastguard Worker                ? (x->mv_row_max - bestmv->as_mv.row)
270*fb1b10abSAndroid Build Coastguard Worker                : 3;
271*fb1b10abSAndroid Build Coastguard Worker   buf_c1 = ((bestmv->as_mv.col - 3) < x->mv_col_min)
272*fb1b10abSAndroid Build Coastguard Worker                ? (bestmv->as_mv.col - x->mv_col_min)
273*fb1b10abSAndroid Build Coastguard Worker                : 3;
274*fb1b10abSAndroid Build Coastguard Worker   y_stride = 32;
275*fb1b10abSAndroid Build Coastguard Worker 
276*fb1b10abSAndroid Build Coastguard Worker   /* Copy to intermediate buffer before searching. */
277*fb1b10abSAndroid Build Coastguard Worker   vfp->copymem(y_0 - buf_c1 - pre_stride * buf_r1, pre_stride, xd->y_buf,
278*fb1b10abSAndroid Build Coastguard Worker                y_stride, 16 + buf_r1 + buf_r2);
279*fb1b10abSAndroid Build Coastguard Worker   y = xd->y_buf + y_stride * buf_r1 + buf_c1;
280*fb1b10abSAndroid Build Coastguard Worker #else
281*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +
282*fb1b10abSAndroid Build Coastguard Worker                      bestmv->as_mv.col;
283*fb1b10abSAndroid Build Coastguard Worker   y_stride = pre_stride;
284*fb1b10abSAndroid Build Coastguard Worker #endif
285*fb1b10abSAndroid Build Coastguard Worker 
286*fb1b10abSAndroid Build Coastguard Worker   offset = (bestmv->as_mv.row) * y_stride + bestmv->as_mv.col;
287*fb1b10abSAndroid Build Coastguard Worker 
288*fb1b10abSAndroid Build Coastguard Worker   /* central mv */
289*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.row = clamp(bestmv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
290*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.col = clamp(bestmv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
291*fb1b10abSAndroid Build Coastguard Worker 
292*fb1b10abSAndroid Build Coastguard Worker   /* calculate central point error */
293*fb1b10abSAndroid Build Coastguard Worker   besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1);
294*fb1b10abSAndroid Build Coastguard Worker   *distortion = besterr;
295*fb1b10abSAndroid Build Coastguard Worker   besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
296*fb1b10abSAndroid Build Coastguard Worker 
297*fb1b10abSAndroid Build Coastguard Worker   /* TODO: Each subsequent iteration checks at least one point in common
298*fb1b10abSAndroid Build Coastguard Worker    * with the last iteration could be 2 ( if diag selected)
299*fb1b10abSAndroid Build Coastguard Worker    */
300*fb1b10abSAndroid Build Coastguard Worker   while (--halfiters) {
301*fb1b10abSAndroid Build Coastguard Worker     /* 1/2 pel */
302*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(left, tr, tc - 2);
303*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(right, tr, tc + 2);
304*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(up, tr - 2, tc);
305*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(down, tr + 2, tc);
306*fb1b10abSAndroid Build Coastguard Worker 
307*fb1b10abSAndroid Build Coastguard Worker     whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
308*fb1b10abSAndroid Build Coastguard Worker 
309*fb1b10abSAndroid Build Coastguard Worker     switch (whichdir) {
310*fb1b10abSAndroid Build Coastguard Worker       case 0: CHECK_BETTER(diag, tr - 2, tc - 2); break;
311*fb1b10abSAndroid Build Coastguard Worker       case 1: CHECK_BETTER(diag, tr - 2, tc + 2); break;
312*fb1b10abSAndroid Build Coastguard Worker       case 2: CHECK_BETTER(diag, tr + 2, tc - 2); break;
313*fb1b10abSAndroid Build Coastguard Worker       case 3: CHECK_BETTER(diag, tr + 2, tc + 2); break;
314*fb1b10abSAndroid Build Coastguard Worker     }
315*fb1b10abSAndroid Build Coastguard Worker 
316*fb1b10abSAndroid Build Coastguard Worker     /* no reason to check the same one again. */
317*fb1b10abSAndroid Build Coastguard Worker     if (tr == br && tc == bc) break;
318*fb1b10abSAndroid Build Coastguard Worker 
319*fb1b10abSAndroid Build Coastguard Worker     tr = br;
320*fb1b10abSAndroid Build Coastguard Worker     tc = bc;
321*fb1b10abSAndroid Build Coastguard Worker   }
322*fb1b10abSAndroid Build Coastguard Worker 
323*fb1b10abSAndroid Build Coastguard Worker   /* TODO: Each subsequent iteration checks at least one point in common
324*fb1b10abSAndroid Build Coastguard Worker    * with the last iteration could be 2 ( if diag selected)
325*fb1b10abSAndroid Build Coastguard Worker    */
326*fb1b10abSAndroid Build Coastguard Worker 
327*fb1b10abSAndroid Build Coastguard Worker   /* 1/4 pel */
328*fb1b10abSAndroid Build Coastguard Worker   while (--quarteriters) {
329*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(left, tr, tc - 1);
330*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(right, tr, tc + 1);
331*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(up, tr - 1, tc);
332*fb1b10abSAndroid Build Coastguard Worker     CHECK_BETTER(down, tr + 1, tc);
333*fb1b10abSAndroid Build Coastguard Worker 
334*fb1b10abSAndroid Build Coastguard Worker     whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
335*fb1b10abSAndroid Build Coastguard Worker 
336*fb1b10abSAndroid Build Coastguard Worker     switch (whichdir) {
337*fb1b10abSAndroid Build Coastguard Worker       case 0: CHECK_BETTER(diag, tr - 1, tc - 1); break;
338*fb1b10abSAndroid Build Coastguard Worker       case 1: CHECK_BETTER(diag, tr - 1, tc + 1); break;
339*fb1b10abSAndroid Build Coastguard Worker       case 2: CHECK_BETTER(diag, tr + 1, tc - 1); break;
340*fb1b10abSAndroid Build Coastguard Worker       case 3: CHECK_BETTER(diag, tr + 1, tc + 1); break;
341*fb1b10abSAndroid Build Coastguard Worker     }
342*fb1b10abSAndroid Build Coastguard Worker 
343*fb1b10abSAndroid Build Coastguard Worker     /* no reason to check the same one again. */
344*fb1b10abSAndroid Build Coastguard Worker     if (tr == br && tc == bc) break;
345*fb1b10abSAndroid Build Coastguard Worker 
346*fb1b10abSAndroid Build Coastguard Worker     tr = br;
347*fb1b10abSAndroid Build Coastguard Worker     tc = bc;
348*fb1b10abSAndroid Build Coastguard Worker   }
349*fb1b10abSAndroid Build Coastguard Worker 
350*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.row = clamp(br * 2, SHRT_MIN, SHRT_MAX);
351*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.col = clamp(bc * 2, SHRT_MIN, SHRT_MAX);
352*fb1b10abSAndroid Build Coastguard Worker 
353*fb1b10abSAndroid Build Coastguard Worker   if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > (MAX_FULL_PEL_VAL << 3)) ||
354*fb1b10abSAndroid Build Coastguard Worker       (abs(bestmv->as_mv.row - ref_mv->as_mv.row) > (MAX_FULL_PEL_VAL << 3))) {
355*fb1b10abSAndroid Build Coastguard Worker     return INT_MAX;
356*fb1b10abSAndroid Build Coastguard Worker   }
357*fb1b10abSAndroid Build Coastguard Worker 
358*fb1b10abSAndroid Build Coastguard Worker   return besterr;
359*fb1b10abSAndroid Build Coastguard Worker }
360*fb1b10abSAndroid Build Coastguard Worker #undef MVC
361*fb1b10abSAndroid Build Coastguard Worker #undef PRE
362*fb1b10abSAndroid Build Coastguard Worker #undef SP
363*fb1b10abSAndroid Build Coastguard Worker #undef DIST
364*fb1b10abSAndroid Build Coastguard Worker #undef IFMVCV
365*fb1b10abSAndroid Build Coastguard Worker #undef ERR
366*fb1b10abSAndroid Build Coastguard Worker #undef CHECK_BETTER
367*fb1b10abSAndroid Build Coastguard Worker 
vp8_find_best_sub_pixel_step(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * bestmv,int_mv * ref_mv,int error_per_bit,const vp8_variance_fn_ptr_t * vfp,int * mvcost[2],int * distortion,unsigned int * sse1)368*fb1b10abSAndroid Build Coastguard Worker int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
369*fb1b10abSAndroid Build Coastguard Worker                                  int_mv *bestmv, int_mv *ref_mv,
370*fb1b10abSAndroid Build Coastguard Worker                                  int error_per_bit,
371*fb1b10abSAndroid Build Coastguard Worker                                  const vp8_variance_fn_ptr_t *vfp,
372*fb1b10abSAndroid Build Coastguard Worker                                  int *mvcost[2], int *distortion,
373*fb1b10abSAndroid Build Coastguard Worker                                  unsigned int *sse1) {
374*fb1b10abSAndroid Build Coastguard Worker   int bestmse = INT_MAX;
375*fb1b10abSAndroid Build Coastguard Worker   int_mv startmv;
376*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
377*fb1b10abSAndroid Build Coastguard Worker   unsigned char *z = (*(b->base_src) + b->src);
378*fb1b10abSAndroid Build Coastguard Worker   int left, right, up, down, diag;
379*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;
380*fb1b10abSAndroid Build Coastguard Worker   int whichdir;
381*fb1b10abSAndroid Build Coastguard Worker   int thismse;
382*fb1b10abSAndroid Build Coastguard Worker   int y_stride;
383*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
384*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
385*fb1b10abSAndroid Build Coastguard Worker 
386*fb1b10abSAndroid Build Coastguard Worker #if VPX_ARCH_X86 || VPX_ARCH_X86_64
387*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
388*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y_0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +
389*fb1b10abSAndroid Build Coastguard Worker                        bestmv->as_mv.col;
390*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y;
391*fb1b10abSAndroid Build Coastguard Worker 
392*fb1b10abSAndroid Build Coastguard Worker   y_stride = 32;
393*fb1b10abSAndroid Build Coastguard Worker   /* Copy 18 rows x 32 cols area to intermediate buffer before searching. */
394*fb1b10abSAndroid Build Coastguard Worker   vfp->copymem(y_0 - 1 - pre_stride, pre_stride, xd->y_buf, y_stride, 18);
395*fb1b10abSAndroid Build Coastguard Worker   y = xd->y_buf + y_stride + 1;
396*fb1b10abSAndroid Build Coastguard Worker #else
397*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +
398*fb1b10abSAndroid Build Coastguard Worker                      bestmv->as_mv.col;
399*fb1b10abSAndroid Build Coastguard Worker   y_stride = pre_stride;
400*fb1b10abSAndroid Build Coastguard Worker #endif
401*fb1b10abSAndroid Build Coastguard Worker 
402*fb1b10abSAndroid Build Coastguard Worker   /* central mv */
403*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.row = clamp(bestmv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
404*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.col = clamp(bestmv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
405*fb1b10abSAndroid Build Coastguard Worker   startmv = *bestmv;
406*fb1b10abSAndroid Build Coastguard Worker 
407*fb1b10abSAndroid Build Coastguard Worker   /* calculate central point error */
408*fb1b10abSAndroid Build Coastguard Worker   bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
409*fb1b10abSAndroid Build Coastguard Worker   *distortion = bestmse;
410*fb1b10abSAndroid Build Coastguard Worker   bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
411*fb1b10abSAndroid Build Coastguard Worker 
412*fb1b10abSAndroid Build Coastguard Worker   /* go left then right and check error */
413*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = startmv.as_mv.row;
414*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
415*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" horizontal variance */
416*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y - 1, y_stride, 4, 0, z, b->src_stride, &sse);
417*fb1b10abSAndroid Build Coastguard Worker   left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
418*fb1b10abSAndroid Build Coastguard Worker 
419*fb1b10abSAndroid Build Coastguard Worker   if (left < bestmse) {
420*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
421*fb1b10abSAndroid Build Coastguard Worker     bestmse = left;
422*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
423*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
424*fb1b10abSAndroid Build Coastguard Worker   }
425*fb1b10abSAndroid Build Coastguard Worker 
426*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col += 8;
427*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" horizontal variance */
428*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y, y_stride, 4, 0, z, b->src_stride, &sse);
429*fb1b10abSAndroid Build Coastguard Worker   right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
430*fb1b10abSAndroid Build Coastguard Worker 
431*fb1b10abSAndroid Build Coastguard Worker   if (right < bestmse) {
432*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
433*fb1b10abSAndroid Build Coastguard Worker     bestmse = right;
434*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
435*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
436*fb1b10abSAndroid Build Coastguard Worker   }
437*fb1b10abSAndroid Build Coastguard Worker 
438*fb1b10abSAndroid Build Coastguard Worker   /* go up then down and check error */
439*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = startmv.as_mv.col;
440*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
441*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" vertical variance */
442*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y - y_stride, y_stride, 0, 4, z, b->src_stride, &sse);
443*fb1b10abSAndroid Build Coastguard Worker   up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
444*fb1b10abSAndroid Build Coastguard Worker 
445*fb1b10abSAndroid Build Coastguard Worker   if (up < bestmse) {
446*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
447*fb1b10abSAndroid Build Coastguard Worker     bestmse = up;
448*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
449*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
450*fb1b10abSAndroid Build Coastguard Worker   }
451*fb1b10abSAndroid Build Coastguard Worker 
452*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row += 8;
453*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" vertical variance */
454*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y, y_stride, 0, 4, z, b->src_stride, &sse);
455*fb1b10abSAndroid Build Coastguard Worker   down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
456*fb1b10abSAndroid Build Coastguard Worker 
457*fb1b10abSAndroid Build Coastguard Worker   if (down < bestmse) {
458*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
459*fb1b10abSAndroid Build Coastguard Worker     bestmse = down;
460*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
461*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
462*fb1b10abSAndroid Build Coastguard Worker   }
463*fb1b10abSAndroid Build Coastguard Worker 
464*fb1b10abSAndroid Build Coastguard Worker   /* now check 1 more diagonal */
465*fb1b10abSAndroid Build Coastguard Worker   whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
466*fb1b10abSAndroid Build Coastguard Worker   this_mv = startmv;
467*fb1b10abSAndroid Build Coastguard Worker 
468*fb1b10abSAndroid Build Coastguard Worker   switch (whichdir) {
469*fb1b10abSAndroid Build Coastguard Worker     case 0:
470*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
471*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
472*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
473*fb1b10abSAndroid Build Coastguard Worker       thismse =
474*fb1b10abSAndroid Build Coastguard Worker           vfp->svf(y - 1 - y_stride, y_stride, 4, 4, z, b->src_stride, &sse);
475*fb1b10abSAndroid Build Coastguard Worker       break;
476*fb1b10abSAndroid Build Coastguard Worker     case 1:
477*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col += 4;
478*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
479*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
480*fb1b10abSAndroid Build Coastguard Worker       thismse = vfp->svf(y - y_stride, y_stride, 4, 4, z, b->src_stride, &sse);
481*fb1b10abSAndroid Build Coastguard Worker       break;
482*fb1b10abSAndroid Build Coastguard Worker     case 2:
483*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
484*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row += 4;
485*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
486*fb1b10abSAndroid Build Coastguard Worker       thismse = vfp->svf(y - 1, y_stride, 4, 4, z, b->src_stride, &sse);
487*fb1b10abSAndroid Build Coastguard Worker       break;
488*fb1b10abSAndroid Build Coastguard Worker     case 3:
489*fb1b10abSAndroid Build Coastguard Worker     default:
490*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col += 4;
491*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row += 4;
492*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
493*fb1b10abSAndroid Build Coastguard Worker       thismse = vfp->svf(y, y_stride, 4, 4, z, b->src_stride, &sse);
494*fb1b10abSAndroid Build Coastguard Worker       break;
495*fb1b10abSAndroid Build Coastguard Worker   }
496*fb1b10abSAndroid Build Coastguard Worker 
497*fb1b10abSAndroid Build Coastguard Worker   diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
498*fb1b10abSAndroid Build Coastguard Worker 
499*fb1b10abSAndroid Build Coastguard Worker   if (diag < bestmse) {
500*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
501*fb1b10abSAndroid Build Coastguard Worker     bestmse = diag;
502*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
503*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
504*fb1b10abSAndroid Build Coastguard Worker   }
505*fb1b10abSAndroid Build Coastguard Worker 
506*fb1b10abSAndroid Build Coastguard Worker   /* time to check quarter pels. */
507*fb1b10abSAndroid Build Coastguard Worker   if (bestmv->as_mv.row < startmv.as_mv.row) y -= y_stride;
508*fb1b10abSAndroid Build Coastguard Worker 
509*fb1b10abSAndroid Build Coastguard Worker   if (bestmv->as_mv.col < startmv.as_mv.col) y--;
510*fb1b10abSAndroid Build Coastguard Worker 
511*fb1b10abSAndroid Build Coastguard Worker   startmv = *bestmv;
512*fb1b10abSAndroid Build Coastguard Worker 
513*fb1b10abSAndroid Build Coastguard Worker   /* go left then right and check error */
514*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = startmv.as_mv.row;
515*fb1b10abSAndroid Build Coastguard Worker 
516*fb1b10abSAndroid Build Coastguard Worker   if (startmv.as_mv.col & 7) {
517*fb1b10abSAndroid Build Coastguard Worker     this_mv.as_mv.col = startmv.as_mv.col - 2;
518*fb1b10abSAndroid Build Coastguard Worker     thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7,
519*fb1b10abSAndroid Build Coastguard Worker                        this_mv.as_mv.row & 7, z, b->src_stride, &sse);
520*fb1b10abSAndroid Build Coastguard Worker   } else {
521*fb1b10abSAndroid Build Coastguard Worker     this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
522*fb1b10abSAndroid Build Coastguard Worker     thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z,
523*fb1b10abSAndroid Build Coastguard Worker                        b->src_stride, &sse);
524*fb1b10abSAndroid Build Coastguard Worker   }
525*fb1b10abSAndroid Build Coastguard Worker 
526*fb1b10abSAndroid Build Coastguard Worker   left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
527*fb1b10abSAndroid Build Coastguard Worker 
528*fb1b10abSAndroid Build Coastguard Worker   if (left < bestmse) {
529*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
530*fb1b10abSAndroid Build Coastguard Worker     bestmse = left;
531*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
532*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
533*fb1b10abSAndroid Build Coastguard Worker   }
534*fb1b10abSAndroid Build Coastguard Worker 
535*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col += 4;
536*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7,
537*fb1b10abSAndroid Build Coastguard Worker                      z, b->src_stride, &sse);
538*fb1b10abSAndroid Build Coastguard Worker   right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
539*fb1b10abSAndroid Build Coastguard Worker 
540*fb1b10abSAndroid Build Coastguard Worker   if (right < bestmse) {
541*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
542*fb1b10abSAndroid Build Coastguard Worker     bestmse = right;
543*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
544*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
545*fb1b10abSAndroid Build Coastguard Worker   }
546*fb1b10abSAndroid Build Coastguard Worker 
547*fb1b10abSAndroid Build Coastguard Worker   /* go up then down and check error */
548*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = startmv.as_mv.col;
549*fb1b10abSAndroid Build Coastguard Worker 
550*fb1b10abSAndroid Build Coastguard Worker   if (startmv.as_mv.row & 7) {
551*fb1b10abSAndroid Build Coastguard Worker     this_mv.as_mv.row = startmv.as_mv.row - 2;
552*fb1b10abSAndroid Build Coastguard Worker     thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7,
553*fb1b10abSAndroid Build Coastguard Worker                        this_mv.as_mv.row & 7, z, b->src_stride, &sse);
554*fb1b10abSAndroid Build Coastguard Worker   } else {
555*fb1b10abSAndroid Build Coastguard Worker     this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
556*fb1b10abSAndroid Build Coastguard Worker     thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z,
557*fb1b10abSAndroid Build Coastguard Worker                        b->src_stride, &sse);
558*fb1b10abSAndroid Build Coastguard Worker   }
559*fb1b10abSAndroid Build Coastguard Worker 
560*fb1b10abSAndroid Build Coastguard Worker   up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
561*fb1b10abSAndroid Build Coastguard Worker 
562*fb1b10abSAndroid Build Coastguard Worker   if (up < bestmse) {
563*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
564*fb1b10abSAndroid Build Coastguard Worker     bestmse = up;
565*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
566*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
567*fb1b10abSAndroid Build Coastguard Worker   }
568*fb1b10abSAndroid Build Coastguard Worker 
569*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row += 4;
570*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7, this_mv.as_mv.row & 7,
571*fb1b10abSAndroid Build Coastguard Worker                      z, b->src_stride, &sse);
572*fb1b10abSAndroid Build Coastguard Worker   down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
573*fb1b10abSAndroid Build Coastguard Worker 
574*fb1b10abSAndroid Build Coastguard Worker   if (down < bestmse) {
575*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
576*fb1b10abSAndroid Build Coastguard Worker     bestmse = down;
577*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
578*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
579*fb1b10abSAndroid Build Coastguard Worker   }
580*fb1b10abSAndroid Build Coastguard Worker 
581*fb1b10abSAndroid Build Coastguard Worker   /* now check 1 more diagonal */
582*fb1b10abSAndroid Build Coastguard Worker   whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
583*fb1b10abSAndroid Build Coastguard Worker 
584*fb1b10abSAndroid Build Coastguard Worker   this_mv = startmv;
585*fb1b10abSAndroid Build Coastguard Worker 
586*fb1b10abSAndroid Build Coastguard Worker   switch (whichdir) {
587*fb1b10abSAndroid Build Coastguard Worker     case 0:
588*fb1b10abSAndroid Build Coastguard Worker 
589*fb1b10abSAndroid Build Coastguard Worker       if (startmv.as_mv.row & 7) {
590*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row -= 2;
591*fb1b10abSAndroid Build Coastguard Worker 
592*fb1b10abSAndroid Build Coastguard Worker         if (startmv.as_mv.col & 7) {
593*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.col -= 2;
594*fb1b10abSAndroid Build Coastguard Worker           thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7,
595*fb1b10abSAndroid Build Coastguard Worker                              this_mv.as_mv.row & 7, z, b->src_stride, &sse);
596*fb1b10abSAndroid Build Coastguard Worker         } else {
597*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
598*fb1b10abSAndroid Build Coastguard Worker           thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z,
599*fb1b10abSAndroid Build Coastguard Worker                              b->src_stride, &sse);
600*fb1b10abSAndroid Build Coastguard Worker         }
601*fb1b10abSAndroid Build Coastguard Worker       } else {
602*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
603*fb1b10abSAndroid Build Coastguard Worker 
604*fb1b10abSAndroid Build Coastguard Worker         if (startmv.as_mv.col & 7) {
605*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.col -= 2;
606*fb1b10abSAndroid Build Coastguard Worker           thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6,
607*fb1b10abSAndroid Build Coastguard Worker                              z, b->src_stride, &sse);
608*fb1b10abSAndroid Build Coastguard Worker         } else {
609*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
610*fb1b10abSAndroid Build Coastguard Worker           thismse = vfp->svf(y - y_stride - 1, y_stride, 6, 6, z, b->src_stride,
611*fb1b10abSAndroid Build Coastguard Worker                              &sse);
612*fb1b10abSAndroid Build Coastguard Worker         }
613*fb1b10abSAndroid Build Coastguard Worker       }
614*fb1b10abSAndroid Build Coastguard Worker 
615*fb1b10abSAndroid Build Coastguard Worker       break;
616*fb1b10abSAndroid Build Coastguard Worker     case 1:
617*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col += 2;
618*fb1b10abSAndroid Build Coastguard Worker 
619*fb1b10abSAndroid Build Coastguard Worker       if (startmv.as_mv.row & 7) {
620*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row -= 2;
621*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7,
622*fb1b10abSAndroid Build Coastguard Worker                            this_mv.as_mv.row & 7, z, b->src_stride, &sse);
623*fb1b10abSAndroid Build Coastguard Worker       } else {
624*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row = (startmv.as_mv.row - 8) | 6;
625*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svf(y - y_stride, y_stride, this_mv.as_mv.col & 7, 6, z,
626*fb1b10abSAndroid Build Coastguard Worker                            b->src_stride, &sse);
627*fb1b10abSAndroid Build Coastguard Worker       }
628*fb1b10abSAndroid Build Coastguard Worker 
629*fb1b10abSAndroid Build Coastguard Worker       break;
630*fb1b10abSAndroid Build Coastguard Worker     case 2:
631*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row += 2;
632*fb1b10abSAndroid Build Coastguard Worker 
633*fb1b10abSAndroid Build Coastguard Worker       if (startmv.as_mv.col & 7) {
634*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.col -= 2;
635*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7,
636*fb1b10abSAndroid Build Coastguard Worker                            this_mv.as_mv.row & 7, z, b->src_stride, &sse);
637*fb1b10abSAndroid Build Coastguard Worker       } else {
638*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.col = (startmv.as_mv.col - 8) | 6;
639*fb1b10abSAndroid Build Coastguard Worker         thismse = vfp->svf(y - 1, y_stride, 6, this_mv.as_mv.row & 7, z,
640*fb1b10abSAndroid Build Coastguard Worker                            b->src_stride, &sse);
641*fb1b10abSAndroid Build Coastguard Worker       }
642*fb1b10abSAndroid Build Coastguard Worker 
643*fb1b10abSAndroid Build Coastguard Worker       break;
644*fb1b10abSAndroid Build Coastguard Worker     case 3:
645*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col += 2;
646*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row += 2;
647*fb1b10abSAndroid Build Coastguard Worker       thismse = vfp->svf(y, y_stride, this_mv.as_mv.col & 7,
648*fb1b10abSAndroid Build Coastguard Worker                          this_mv.as_mv.row & 7, z, b->src_stride, &sse);
649*fb1b10abSAndroid Build Coastguard Worker       break;
650*fb1b10abSAndroid Build Coastguard Worker   }
651*fb1b10abSAndroid Build Coastguard Worker 
652*fb1b10abSAndroid Build Coastguard Worker   diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
653*fb1b10abSAndroid Build Coastguard Worker 
654*fb1b10abSAndroid Build Coastguard Worker   if (diag < bestmse) {
655*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
656*fb1b10abSAndroid Build Coastguard Worker     bestmse = diag;
657*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
658*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
659*fb1b10abSAndroid Build Coastguard Worker   }
660*fb1b10abSAndroid Build Coastguard Worker 
661*fb1b10abSAndroid Build Coastguard Worker   return bestmse;
662*fb1b10abSAndroid Build Coastguard Worker }
663*fb1b10abSAndroid Build Coastguard Worker 
vp8_find_best_half_pixel_step(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * bestmv,int_mv * ref_mv,int error_per_bit,const vp8_variance_fn_ptr_t * vfp,int * mvcost[2],int * distortion,unsigned int * sse1)664*fb1b10abSAndroid Build Coastguard Worker int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
665*fb1b10abSAndroid Build Coastguard Worker                                   int_mv *bestmv, int_mv *ref_mv,
666*fb1b10abSAndroid Build Coastguard Worker                                   int error_per_bit,
667*fb1b10abSAndroid Build Coastguard Worker                                   const vp8_variance_fn_ptr_t *vfp,
668*fb1b10abSAndroid Build Coastguard Worker                                   int *mvcost[2], int *distortion,
669*fb1b10abSAndroid Build Coastguard Worker                                   unsigned int *sse1) {
670*fb1b10abSAndroid Build Coastguard Worker   int bestmse = INT_MAX;
671*fb1b10abSAndroid Build Coastguard Worker   int_mv startmv;
672*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
673*fb1b10abSAndroid Build Coastguard Worker   unsigned char *z = (*(b->base_src) + b->src);
674*fb1b10abSAndroid Build Coastguard Worker   int left, right, up, down, diag;
675*fb1b10abSAndroid Build Coastguard Worker   unsigned int sse;
676*fb1b10abSAndroid Build Coastguard Worker   int whichdir;
677*fb1b10abSAndroid Build Coastguard Worker   int thismse;
678*fb1b10abSAndroid Build Coastguard Worker   int y_stride;
679*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
680*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
681*fb1b10abSAndroid Build Coastguard Worker 
682*fb1b10abSAndroid Build Coastguard Worker #if VPX_ARCH_X86 || VPX_ARCH_X86_64
683*fb1b10abSAndroid Build Coastguard Worker   MACROBLOCKD *xd = &x->e_mbd;
684*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y_0 = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +
685*fb1b10abSAndroid Build Coastguard Worker                        bestmv->as_mv.col;
686*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y;
687*fb1b10abSAndroid Build Coastguard Worker 
688*fb1b10abSAndroid Build Coastguard Worker   y_stride = 32;
689*fb1b10abSAndroid Build Coastguard Worker   /* Copy 18 rows x 32 cols area to intermediate buffer before searching. */
690*fb1b10abSAndroid Build Coastguard Worker   vfp->copymem(y_0 - 1 - pre_stride, pre_stride, xd->y_buf, y_stride, 18);
691*fb1b10abSAndroid Build Coastguard Worker   y = xd->y_buf + y_stride + 1;
692*fb1b10abSAndroid Build Coastguard Worker #else
693*fb1b10abSAndroid Build Coastguard Worker   unsigned char *y = base_pre + d->offset + (bestmv->as_mv.row) * pre_stride +
694*fb1b10abSAndroid Build Coastguard Worker                      bestmv->as_mv.col;
695*fb1b10abSAndroid Build Coastguard Worker   y_stride = pre_stride;
696*fb1b10abSAndroid Build Coastguard Worker #endif
697*fb1b10abSAndroid Build Coastguard Worker 
698*fb1b10abSAndroid Build Coastguard Worker   /* central mv */
699*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.row = clamp(bestmv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
700*fb1b10abSAndroid Build Coastguard Worker   bestmv->as_mv.col = clamp(bestmv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
701*fb1b10abSAndroid Build Coastguard Worker   startmv = *bestmv;
702*fb1b10abSAndroid Build Coastguard Worker 
703*fb1b10abSAndroid Build Coastguard Worker   /* calculate central point error */
704*fb1b10abSAndroid Build Coastguard Worker   bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1);
705*fb1b10abSAndroid Build Coastguard Worker   *distortion = bestmse;
706*fb1b10abSAndroid Build Coastguard Worker   bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
707*fb1b10abSAndroid Build Coastguard Worker 
708*fb1b10abSAndroid Build Coastguard Worker   /* go left then right and check error */
709*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = startmv.as_mv.row;
710*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4);
711*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" horizontal variance */
712*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y - 1, y_stride, 4, 0, z, b->src_stride, &sse);
713*fb1b10abSAndroid Build Coastguard Worker   left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
714*fb1b10abSAndroid Build Coastguard Worker 
715*fb1b10abSAndroid Build Coastguard Worker   if (left < bestmse) {
716*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
717*fb1b10abSAndroid Build Coastguard Worker     bestmse = left;
718*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
719*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
720*fb1b10abSAndroid Build Coastguard Worker   }
721*fb1b10abSAndroid Build Coastguard Worker 
722*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col += 8;
723*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" horizontal variance */
724*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y, y_stride, 4, 0, z, b->src_stride, &sse);
725*fb1b10abSAndroid Build Coastguard Worker   right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
726*fb1b10abSAndroid Build Coastguard Worker 
727*fb1b10abSAndroid Build Coastguard Worker   if (right < bestmse) {
728*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
729*fb1b10abSAndroid Build Coastguard Worker     bestmse = right;
730*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
731*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
732*fb1b10abSAndroid Build Coastguard Worker   }
733*fb1b10abSAndroid Build Coastguard Worker 
734*fb1b10abSAndroid Build Coastguard Worker   /* go up then down and check error */
735*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = startmv.as_mv.col;
736*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4);
737*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" vertical variance */
738*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y - y_stride, y_stride, 0, 4, z, b->src_stride, &sse);
739*fb1b10abSAndroid Build Coastguard Worker   up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
740*fb1b10abSAndroid Build Coastguard Worker 
741*fb1b10abSAndroid Build Coastguard Worker   if (up < bestmse) {
742*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
743*fb1b10abSAndroid Build Coastguard Worker     bestmse = up;
744*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
745*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
746*fb1b10abSAndroid Build Coastguard Worker   }
747*fb1b10abSAndroid Build Coastguard Worker 
748*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row += 8;
749*fb1b10abSAndroid Build Coastguard Worker   /* "halfpix" vertical variance */
750*fb1b10abSAndroid Build Coastguard Worker   thismse = vfp->svf(y, y_stride, 0, 4, z, b->src_stride, &sse);
751*fb1b10abSAndroid Build Coastguard Worker   down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
752*fb1b10abSAndroid Build Coastguard Worker 
753*fb1b10abSAndroid Build Coastguard Worker   if (down < bestmse) {
754*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
755*fb1b10abSAndroid Build Coastguard Worker     bestmse = down;
756*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
757*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
758*fb1b10abSAndroid Build Coastguard Worker   }
759*fb1b10abSAndroid Build Coastguard Worker 
760*fb1b10abSAndroid Build Coastguard Worker   /* now check 1 more diagonal - */
761*fb1b10abSAndroid Build Coastguard Worker   whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
762*fb1b10abSAndroid Build Coastguard Worker   this_mv = startmv;
763*fb1b10abSAndroid Build Coastguard Worker 
764*fb1b10abSAndroid Build Coastguard Worker   switch (whichdir) {
765*fb1b10abSAndroid Build Coastguard Worker     case 0:
766*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
767*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
768*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
769*fb1b10abSAndroid Build Coastguard Worker       thismse =
770*fb1b10abSAndroid Build Coastguard Worker           vfp->svf(y - 1 - y_stride, y_stride, 4, 4, z, b->src_stride, &sse);
771*fb1b10abSAndroid Build Coastguard Worker       break;
772*fb1b10abSAndroid Build Coastguard Worker     case 1:
773*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col += 4;
774*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row = (this_mv.as_mv.row - 8) | 4;
775*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
776*fb1b10abSAndroid Build Coastguard Worker       thismse = vfp->svf(y - y_stride, y_stride, 4, 4, z, b->src_stride, &sse);
777*fb1b10abSAndroid Build Coastguard Worker       break;
778*fb1b10abSAndroid Build Coastguard Worker     case 2:
779*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col = (this_mv.as_mv.col - 8) | 4;
780*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row += 4;
781*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
782*fb1b10abSAndroid Build Coastguard Worker       thismse = vfp->svf(y - 1, y_stride, 4, 4, z, b->src_stride, &sse);
783*fb1b10abSAndroid Build Coastguard Worker       break;
784*fb1b10abSAndroid Build Coastguard Worker     case 3:
785*fb1b10abSAndroid Build Coastguard Worker     default:
786*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col += 4;
787*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row += 4;
788*fb1b10abSAndroid Build Coastguard Worker       /* "halfpix" horizontal/vertical variance */
789*fb1b10abSAndroid Build Coastguard Worker       thismse = vfp->svf(y, y_stride, 4, 4, z, b->src_stride, &sse);
790*fb1b10abSAndroid Build Coastguard Worker       break;
791*fb1b10abSAndroid Build Coastguard Worker   }
792*fb1b10abSAndroid Build Coastguard Worker 
793*fb1b10abSAndroid Build Coastguard Worker   diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
794*fb1b10abSAndroid Build Coastguard Worker 
795*fb1b10abSAndroid Build Coastguard Worker   if (diag < bestmse) {
796*fb1b10abSAndroid Build Coastguard Worker     *bestmv = this_mv;
797*fb1b10abSAndroid Build Coastguard Worker     bestmse = diag;
798*fb1b10abSAndroid Build Coastguard Worker     *distortion = thismse;
799*fb1b10abSAndroid Build Coastguard Worker     *sse1 = sse;
800*fb1b10abSAndroid Build Coastguard Worker   }
801*fb1b10abSAndroid Build Coastguard Worker 
802*fb1b10abSAndroid Build Coastguard Worker   return bestmse;
803*fb1b10abSAndroid Build Coastguard Worker }
804*fb1b10abSAndroid Build Coastguard Worker 
805*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BOUNDS(range)                    \
806*fb1b10abSAndroid Build Coastguard Worker   do {                                         \
807*fb1b10abSAndroid Build Coastguard Worker     all_in = 1;                                \
808*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((br - range) >= x->mv_row_min); \
809*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((br + range) <= x->mv_row_max); \
810*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((bc - range) >= x->mv_col_min); \
811*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((bc + range) <= x->mv_col_max); \
812*fb1b10abSAndroid Build Coastguard Worker   } while (0)
813*fb1b10abSAndroid Build Coastguard Worker 
814*fb1b10abSAndroid Build Coastguard Worker #define CHECK_POINT                                  \
815*fb1b10abSAndroid Build Coastguard Worker   {                                                  \
816*fb1b10abSAndroid Build Coastguard Worker     if (this_mv.as_mv.col < x->mv_col_min) continue; \
817*fb1b10abSAndroid Build Coastguard Worker     if (this_mv.as_mv.col > x->mv_col_max) continue; \
818*fb1b10abSAndroid Build Coastguard Worker     if (this_mv.as_mv.row < x->mv_row_min) continue; \
819*fb1b10abSAndroid Build Coastguard Worker     if (this_mv.as_mv.row > x->mv_row_max) continue; \
820*fb1b10abSAndroid Build Coastguard Worker   }
821*fb1b10abSAndroid Build Coastguard Worker 
822*fb1b10abSAndroid Build Coastguard Worker #define CHECK_BETTER                                                     \
823*fb1b10abSAndroid Build Coastguard Worker   do {                                                                   \
824*fb1b10abSAndroid Build Coastguard Worker     if (thissad < bestsad) {                                             \
825*fb1b10abSAndroid Build Coastguard Worker       thissad +=                                                         \
826*fb1b10abSAndroid Build Coastguard Worker           mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit); \
827*fb1b10abSAndroid Build Coastguard Worker       if (thissad < bestsad) {                                           \
828*fb1b10abSAndroid Build Coastguard Worker         bestsad = thissad;                                               \
829*fb1b10abSAndroid Build Coastguard Worker         best_site = i;                                                   \
830*fb1b10abSAndroid Build Coastguard Worker       }                                                                  \
831*fb1b10abSAndroid Build Coastguard Worker     }                                                                    \
832*fb1b10abSAndroid Build Coastguard Worker   } while (0)
833*fb1b10abSAndroid Build Coastguard Worker 
834*fb1b10abSAndroid Build Coastguard Worker static const MV next_chkpts[6][3] = {
835*fb1b10abSAndroid Build Coastguard Worker   { { -2, 0 }, { -1, -2 }, { 1, -2 } }, { { -1, -2 }, { 1, -2 }, { 2, 0 } },
836*fb1b10abSAndroid Build Coastguard Worker   { { 1, -2 }, { 2, 0 }, { 1, 2 } },    { { 2, 0 }, { 1, 2 }, { -1, 2 } },
837*fb1b10abSAndroid Build Coastguard Worker   { { 1, 2 }, { -1, 2 }, { -2, 0 } },   { { -1, 2 }, { -2, 0 }, { -1, -2 } }
838*fb1b10abSAndroid Build Coastguard Worker };
839*fb1b10abSAndroid Build Coastguard Worker 
vp8_hex_search(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * ref_mv,int_mv * best_mv,int search_param,int sad_per_bit,const vp8_variance_fn_ptr_t * vfp,int * mvsadcost[2],int_mv * center_mv)840*fb1b10abSAndroid Build Coastguard Worker int vp8_hex_search(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
841*fb1b10abSAndroid Build Coastguard Worker                    int_mv *best_mv, int search_param, int sad_per_bit,
842*fb1b10abSAndroid Build Coastguard Worker                    const vp8_variance_fn_ptr_t *vfp, int *mvsadcost[2],
843*fb1b10abSAndroid Build Coastguard Worker                    int_mv *center_mv) {
844*fb1b10abSAndroid Build Coastguard Worker   MV hex[6] = {
845*fb1b10abSAndroid Build Coastguard Worker     { -1, -2 }, { 1, -2 }, { 2, 0 }, { 1, 2 }, { -1, 2 }, { -2, 0 }
846*fb1b10abSAndroid Build Coastguard Worker   };
847*fb1b10abSAndroid Build Coastguard Worker   MV neighbors[4] = { { 0, -1 }, { -1, 0 }, { 1, 0 }, { 0, 1 } };
848*fb1b10abSAndroid Build Coastguard Worker   int i, j;
849*fb1b10abSAndroid Build Coastguard Worker 
850*fb1b10abSAndroid Build Coastguard Worker   unsigned char *what = (*(b->base_src) + b->src);
851*fb1b10abSAndroid Build Coastguard Worker   int what_stride = b->src_stride;
852*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
853*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
854*fb1b10abSAndroid Build Coastguard Worker 
855*fb1b10abSAndroid Build Coastguard Worker   int in_what_stride = pre_stride;
856*fb1b10abSAndroid Build Coastguard Worker   int br, bc;
857*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
858*fb1b10abSAndroid Build Coastguard Worker   unsigned int bestsad;
859*fb1b10abSAndroid Build Coastguard Worker   unsigned int thissad;
860*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_offset;
861*fb1b10abSAndroid Build Coastguard Worker   unsigned char *this_offset;
862*fb1b10abSAndroid Build Coastguard Worker   int k = -1;
863*fb1b10abSAndroid Build Coastguard Worker   int all_in;
864*fb1b10abSAndroid Build Coastguard Worker   int best_site = -1;
865*fb1b10abSAndroid Build Coastguard Worker   int hex_range = 127;
866*fb1b10abSAndroid Build Coastguard Worker   int dia_range = 8;
867*fb1b10abSAndroid Build Coastguard Worker 
868*fb1b10abSAndroid Build Coastguard Worker   int_mv fcenter_mv;
869*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
870*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
871*fb1b10abSAndroid Build Coastguard Worker 
872*fb1b10abSAndroid Build Coastguard Worker   /* adjust ref_mv to make sure it is within MV range */
873*fb1b10abSAndroid Build Coastguard Worker   vp8_clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min,
874*fb1b10abSAndroid Build Coastguard Worker                x->mv_row_max);
875*fb1b10abSAndroid Build Coastguard Worker   br = ref_mv->as_mv.row;
876*fb1b10abSAndroid Build Coastguard Worker   bc = ref_mv->as_mv.col;
877*fb1b10abSAndroid Build Coastguard Worker 
878*fb1b10abSAndroid Build Coastguard Worker   /* Work out the start point for the search */
879*fb1b10abSAndroid Build Coastguard Worker   base_offset = (unsigned char *)(base_pre + d->offset);
880*fb1b10abSAndroid Build Coastguard Worker   this_offset = base_offset + (br * (pre_stride)) + bc;
881*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = br;
882*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = bc;
883*fb1b10abSAndroid Build Coastguard Worker   bestsad = vfp->sdf(what, what_stride, this_offset, in_what_stride) +
884*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);
885*fb1b10abSAndroid Build Coastguard Worker 
886*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTI_RES_ENCODING
887*fb1b10abSAndroid Build Coastguard Worker   /* Lower search range based on prediction info */
888*fb1b10abSAndroid Build Coastguard Worker   if (search_param >= 6)
889*fb1b10abSAndroid Build Coastguard Worker     goto cal_neighbors;
890*fb1b10abSAndroid Build Coastguard Worker   else if (search_param >= 5)
891*fb1b10abSAndroid Build Coastguard Worker     hex_range = 4;
892*fb1b10abSAndroid Build Coastguard Worker   else if (search_param >= 4)
893*fb1b10abSAndroid Build Coastguard Worker     hex_range = 6;
894*fb1b10abSAndroid Build Coastguard Worker   else if (search_param >= 3)
895*fb1b10abSAndroid Build Coastguard Worker     hex_range = 15;
896*fb1b10abSAndroid Build Coastguard Worker   else if (search_param >= 2)
897*fb1b10abSAndroid Build Coastguard Worker     hex_range = 31;
898*fb1b10abSAndroid Build Coastguard Worker   else if (search_param >= 1)
899*fb1b10abSAndroid Build Coastguard Worker     hex_range = 63;
900*fb1b10abSAndroid Build Coastguard Worker 
901*fb1b10abSAndroid Build Coastguard Worker   dia_range = 8;
902*fb1b10abSAndroid Build Coastguard Worker #else
903*fb1b10abSAndroid Build Coastguard Worker   (void)search_param;
904*fb1b10abSAndroid Build Coastguard Worker #endif
905*fb1b10abSAndroid Build Coastguard Worker 
906*fb1b10abSAndroid Build Coastguard Worker   /* hex search */
907*fb1b10abSAndroid Build Coastguard Worker   CHECK_BOUNDS(2);
908*fb1b10abSAndroid Build Coastguard Worker 
909*fb1b10abSAndroid Build Coastguard Worker   if (all_in) {
910*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 6; ++i) {
911*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row = br + hex[i].row;
912*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col = bc + hex[i].col;
913*fb1b10abSAndroid Build Coastguard Worker       this_offset = base_offset + (this_mv.as_mv.row * in_what_stride) +
914*fb1b10abSAndroid Build Coastguard Worker                     this_mv.as_mv.col;
915*fb1b10abSAndroid Build Coastguard Worker       thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride);
916*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER;
917*fb1b10abSAndroid Build Coastguard Worker     }
918*fb1b10abSAndroid Build Coastguard Worker   } else {
919*fb1b10abSAndroid Build Coastguard Worker     for (i = 0; i < 6; ++i) {
920*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.row = br + hex[i].row;
921*fb1b10abSAndroid Build Coastguard Worker       this_mv.as_mv.col = bc + hex[i].col;
922*fb1b10abSAndroid Build Coastguard Worker       CHECK_POINT
923*fb1b10abSAndroid Build Coastguard Worker       this_offset = base_offset + (this_mv.as_mv.row * in_what_stride) +
924*fb1b10abSAndroid Build Coastguard Worker                     this_mv.as_mv.col;
925*fb1b10abSAndroid Build Coastguard Worker       thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride);
926*fb1b10abSAndroid Build Coastguard Worker       CHECK_BETTER;
927*fb1b10abSAndroid Build Coastguard Worker     }
928*fb1b10abSAndroid Build Coastguard Worker   }
929*fb1b10abSAndroid Build Coastguard Worker 
930*fb1b10abSAndroid Build Coastguard Worker   if (best_site == -1) {
931*fb1b10abSAndroid Build Coastguard Worker     goto cal_neighbors;
932*fb1b10abSAndroid Build Coastguard Worker   } else {
933*fb1b10abSAndroid Build Coastguard Worker     br += hex[best_site].row;
934*fb1b10abSAndroid Build Coastguard Worker     bc += hex[best_site].col;
935*fb1b10abSAndroid Build Coastguard Worker     k = best_site;
936*fb1b10abSAndroid Build Coastguard Worker   }
937*fb1b10abSAndroid Build Coastguard Worker 
938*fb1b10abSAndroid Build Coastguard Worker   for (j = 1; j < hex_range; ++j) {
939*fb1b10abSAndroid Build Coastguard Worker     best_site = -1;
940*fb1b10abSAndroid Build Coastguard Worker     CHECK_BOUNDS(2);
941*fb1b10abSAndroid Build Coastguard Worker 
942*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
943*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) {
944*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row = br + next_chkpts[k][i].row;
945*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.col = bc + next_chkpts[k][i].col;
946*fb1b10abSAndroid Build Coastguard Worker         this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) +
947*fb1b10abSAndroid Build Coastguard Worker                       this_mv.as_mv.col;
948*fb1b10abSAndroid Build Coastguard Worker         thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride);
949*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER;
950*fb1b10abSAndroid Build Coastguard Worker       }
951*fb1b10abSAndroid Build Coastguard Worker     } else {
952*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 3; ++i) {
953*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row = br + next_chkpts[k][i].row;
954*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.col = bc + next_chkpts[k][i].col;
955*fb1b10abSAndroid Build Coastguard Worker         CHECK_POINT
956*fb1b10abSAndroid Build Coastguard Worker         this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) +
957*fb1b10abSAndroid Build Coastguard Worker                       this_mv.as_mv.col;
958*fb1b10abSAndroid Build Coastguard Worker         thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride);
959*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER;
960*fb1b10abSAndroid Build Coastguard Worker       }
961*fb1b10abSAndroid Build Coastguard Worker     }
962*fb1b10abSAndroid Build Coastguard Worker 
963*fb1b10abSAndroid Build Coastguard Worker     if (best_site == -1) {
964*fb1b10abSAndroid Build Coastguard Worker       break;
965*fb1b10abSAndroid Build Coastguard Worker     } else {
966*fb1b10abSAndroid Build Coastguard Worker       br += next_chkpts[k][best_site].row;
967*fb1b10abSAndroid Build Coastguard Worker       bc += next_chkpts[k][best_site].col;
968*fb1b10abSAndroid Build Coastguard Worker       k += 5 + best_site;
969*fb1b10abSAndroid Build Coastguard Worker       if (k >= 12) {
970*fb1b10abSAndroid Build Coastguard Worker         k -= 12;
971*fb1b10abSAndroid Build Coastguard Worker       } else if (k >= 6) {
972*fb1b10abSAndroid Build Coastguard Worker         k -= 6;
973*fb1b10abSAndroid Build Coastguard Worker       }
974*fb1b10abSAndroid Build Coastguard Worker     }
975*fb1b10abSAndroid Build Coastguard Worker   }
976*fb1b10abSAndroid Build Coastguard Worker 
977*fb1b10abSAndroid Build Coastguard Worker /* check 4 1-away neighbors */
978*fb1b10abSAndroid Build Coastguard Worker cal_neighbors:
979*fb1b10abSAndroid Build Coastguard Worker   for (j = 0; j < dia_range; ++j) {
980*fb1b10abSAndroid Build Coastguard Worker     best_site = -1;
981*fb1b10abSAndroid Build Coastguard Worker     CHECK_BOUNDS(1);
982*fb1b10abSAndroid Build Coastguard Worker 
983*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
984*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 4; ++i) {
985*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row = br + neighbors[i].row;
986*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.col = bc + neighbors[i].col;
987*fb1b10abSAndroid Build Coastguard Worker         this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) +
988*fb1b10abSAndroid Build Coastguard Worker                       this_mv.as_mv.col;
989*fb1b10abSAndroid Build Coastguard Worker         thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride);
990*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER;
991*fb1b10abSAndroid Build Coastguard Worker       }
992*fb1b10abSAndroid Build Coastguard Worker     } else {
993*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < 4; ++i) {
994*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.row = br + neighbors[i].row;
995*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.col = bc + neighbors[i].col;
996*fb1b10abSAndroid Build Coastguard Worker         CHECK_POINT
997*fb1b10abSAndroid Build Coastguard Worker         this_offset = base_offset + (this_mv.as_mv.row * (in_what_stride)) +
998*fb1b10abSAndroid Build Coastguard Worker                       this_mv.as_mv.col;
999*fb1b10abSAndroid Build Coastguard Worker         thissad = vfp->sdf(what, what_stride, this_offset, in_what_stride);
1000*fb1b10abSAndroid Build Coastguard Worker         CHECK_BETTER;
1001*fb1b10abSAndroid Build Coastguard Worker       }
1002*fb1b10abSAndroid Build Coastguard Worker     }
1003*fb1b10abSAndroid Build Coastguard Worker 
1004*fb1b10abSAndroid Build Coastguard Worker     if (best_site == -1) {
1005*fb1b10abSAndroid Build Coastguard Worker       break;
1006*fb1b10abSAndroid Build Coastguard Worker     } else {
1007*fb1b10abSAndroid Build Coastguard Worker       br += neighbors[best_site].row;
1008*fb1b10abSAndroid Build Coastguard Worker       bc += neighbors[best_site].col;
1009*fb1b10abSAndroid Build Coastguard Worker     }
1010*fb1b10abSAndroid Build Coastguard Worker   }
1011*fb1b10abSAndroid Build Coastguard Worker 
1012*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.row = br;
1013*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.col = bc;
1014*fb1b10abSAndroid Build Coastguard Worker 
1015*fb1b10abSAndroid Build Coastguard Worker   return bestsad;
1016*fb1b10abSAndroid Build Coastguard Worker }
1017*fb1b10abSAndroid Build Coastguard Worker #undef CHECK_BOUNDS
1018*fb1b10abSAndroid Build Coastguard Worker #undef CHECK_POINT
1019*fb1b10abSAndroid Build Coastguard Worker #undef CHECK_BETTER
1020*fb1b10abSAndroid Build Coastguard Worker 
vp8_diamond_search_sad_c(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * ref_mv,int_mv * best_mv,int search_param,int sad_per_bit,int * num00,vp8_variance_fn_ptr_t * fn_ptr,int * mvcost[2],int_mv * center_mv)1021*fb1b10abSAndroid Build Coastguard Worker int vp8_diamond_search_sad_c(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
1022*fb1b10abSAndroid Build Coastguard Worker                              int_mv *best_mv, int search_param, int sad_per_bit,
1023*fb1b10abSAndroid Build Coastguard Worker                              int *num00, vp8_variance_fn_ptr_t *fn_ptr,
1024*fb1b10abSAndroid Build Coastguard Worker                              int *mvcost[2], int_mv *center_mv) {
1025*fb1b10abSAndroid Build Coastguard Worker   int i, j, step;
1026*fb1b10abSAndroid Build Coastguard Worker 
1027*fb1b10abSAndroid Build Coastguard Worker   unsigned char *what = (*(b->base_src) + b->src);
1028*fb1b10abSAndroid Build Coastguard Worker   int what_stride = b->src_stride;
1029*fb1b10abSAndroid Build Coastguard Worker   unsigned char *in_what;
1030*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
1031*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
1032*fb1b10abSAndroid Build Coastguard Worker   int in_what_stride = pre_stride;
1033*fb1b10abSAndroid Build Coastguard Worker   unsigned char *best_address;
1034*fb1b10abSAndroid Build Coastguard Worker 
1035*fb1b10abSAndroid Build Coastguard Worker   int tot_steps;
1036*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
1037*fb1b10abSAndroid Build Coastguard Worker 
1038*fb1b10abSAndroid Build Coastguard Worker   unsigned int bestsad;
1039*fb1b10abSAndroid Build Coastguard Worker   unsigned int thissad;
1040*fb1b10abSAndroid Build Coastguard Worker   int best_site = 0;
1041*fb1b10abSAndroid Build Coastguard Worker   int last_site = 0;
1042*fb1b10abSAndroid Build Coastguard Worker 
1043*fb1b10abSAndroid Build Coastguard Worker   int ref_row;
1044*fb1b10abSAndroid Build Coastguard Worker   int ref_col;
1045*fb1b10abSAndroid Build Coastguard Worker   int this_row_offset;
1046*fb1b10abSAndroid Build Coastguard Worker   int this_col_offset;
1047*fb1b10abSAndroid Build Coastguard Worker   search_site *ss;
1048*fb1b10abSAndroid Build Coastguard Worker 
1049*fb1b10abSAndroid Build Coastguard Worker   unsigned char *check_here;
1050*fb1b10abSAndroid Build Coastguard Worker 
1051*fb1b10abSAndroid Build Coastguard Worker   int *mvsadcost[2];
1052*fb1b10abSAndroid Build Coastguard Worker   int_mv fcenter_mv;
1053*fb1b10abSAndroid Build Coastguard Worker 
1054*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[0] = x->mvsadcost[0];
1055*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[1] = x->mvsadcost[1];
1056*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
1057*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
1058*fb1b10abSAndroid Build Coastguard Worker 
1059*fb1b10abSAndroid Build Coastguard Worker   vp8_clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min,
1060*fb1b10abSAndroid Build Coastguard Worker                x->mv_row_max);
1061*fb1b10abSAndroid Build Coastguard Worker   ref_row = ref_mv->as_mv.row;
1062*fb1b10abSAndroid Build Coastguard Worker   ref_col = ref_mv->as_mv.col;
1063*fb1b10abSAndroid Build Coastguard Worker   *num00 = 0;
1064*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.row = ref_row;
1065*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.col = ref_col;
1066*fb1b10abSAndroid Build Coastguard Worker 
1067*fb1b10abSAndroid Build Coastguard Worker   /* Work out the start point for the search */
1068*fb1b10abSAndroid Build Coastguard Worker   in_what = (unsigned char *)(base_pre + d->offset + (ref_row * pre_stride) +
1069*fb1b10abSAndroid Build Coastguard Worker                               ref_col);
1070*fb1b10abSAndroid Build Coastguard Worker   best_address = in_what;
1071*fb1b10abSAndroid Build Coastguard Worker 
1072*fb1b10abSAndroid Build Coastguard Worker   /* Check the starting position */
1073*fb1b10abSAndroid Build Coastguard Worker   bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride) +
1074*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
1075*fb1b10abSAndroid Build Coastguard Worker 
1076*fb1b10abSAndroid Build Coastguard Worker   /* search_param determines the length of the initial step and hence
1077*fb1b10abSAndroid Build Coastguard Worker    * the number of iterations 0 = initial step (MAX_FIRST_STEP) pel :
1078*fb1b10abSAndroid Build Coastguard Worker    * 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
1079*fb1b10abSAndroid Build Coastguard Worker    */
1080*fb1b10abSAndroid Build Coastguard Worker   ss = &x->ss[search_param * x->searches_per_step];
1081*fb1b10abSAndroid Build Coastguard Worker   tot_steps = (x->ss_count / x->searches_per_step) - search_param;
1082*fb1b10abSAndroid Build Coastguard Worker 
1083*fb1b10abSAndroid Build Coastguard Worker   i = 1;
1084*fb1b10abSAndroid Build Coastguard Worker 
1085*fb1b10abSAndroid Build Coastguard Worker   for (step = 0; step < tot_steps; ++step) {
1086*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < x->searches_per_step; ++j) {
1087*fb1b10abSAndroid Build Coastguard Worker       /* Trap illegal vectors */
1088*fb1b10abSAndroid Build Coastguard Worker       this_row_offset = best_mv->as_mv.row + ss[i].mv.row;
1089*fb1b10abSAndroid Build Coastguard Worker       this_col_offset = best_mv->as_mv.col + ss[i].mv.col;
1090*fb1b10abSAndroid Build Coastguard Worker 
1091*fb1b10abSAndroid Build Coastguard Worker       if ((this_col_offset > x->mv_col_min) &&
1092*fb1b10abSAndroid Build Coastguard Worker           (this_col_offset < x->mv_col_max) &&
1093*fb1b10abSAndroid Build Coastguard Worker           (this_row_offset > x->mv_row_min) &&
1094*fb1b10abSAndroid Build Coastguard Worker           (this_row_offset < x->mv_row_max))
1095*fb1b10abSAndroid Build Coastguard Worker 
1096*fb1b10abSAndroid Build Coastguard Worker       {
1097*fb1b10abSAndroid Build Coastguard Worker         check_here = ss[i].offset + best_address;
1098*fb1b10abSAndroid Build Coastguard Worker         thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
1099*fb1b10abSAndroid Build Coastguard Worker 
1100*fb1b10abSAndroid Build Coastguard Worker         if (thissad < bestsad) {
1101*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.row = this_row_offset;
1102*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.col = this_col_offset;
1103*fb1b10abSAndroid Build Coastguard Worker           thissad +=
1104*fb1b10abSAndroid Build Coastguard Worker               mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);
1105*fb1b10abSAndroid Build Coastguard Worker 
1106*fb1b10abSAndroid Build Coastguard Worker           if (thissad < bestsad) {
1107*fb1b10abSAndroid Build Coastguard Worker             bestsad = thissad;
1108*fb1b10abSAndroid Build Coastguard Worker             best_site = i;
1109*fb1b10abSAndroid Build Coastguard Worker           }
1110*fb1b10abSAndroid Build Coastguard Worker         }
1111*fb1b10abSAndroid Build Coastguard Worker       }
1112*fb1b10abSAndroid Build Coastguard Worker 
1113*fb1b10abSAndroid Build Coastguard Worker       i++;
1114*fb1b10abSAndroid Build Coastguard Worker     }
1115*fb1b10abSAndroid Build Coastguard Worker 
1116*fb1b10abSAndroid Build Coastguard Worker     if (best_site != last_site) {
1117*fb1b10abSAndroid Build Coastguard Worker       best_mv->as_mv.row += ss[best_site].mv.row;
1118*fb1b10abSAndroid Build Coastguard Worker       best_mv->as_mv.col += ss[best_site].mv.col;
1119*fb1b10abSAndroid Build Coastguard Worker       best_address += ss[best_site].offset;
1120*fb1b10abSAndroid Build Coastguard Worker       last_site = best_site;
1121*fb1b10abSAndroid Build Coastguard Worker     } else if (best_address == in_what) {
1122*fb1b10abSAndroid Build Coastguard Worker       (*num00)++;
1123*fb1b10abSAndroid Build Coastguard Worker     }
1124*fb1b10abSAndroid Build Coastguard Worker   }
1125*fb1b10abSAndroid Build Coastguard Worker 
1126*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = clamp(best_mv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
1127*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = clamp(best_mv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
1128*fb1b10abSAndroid Build Coastguard Worker 
1129*fb1b10abSAndroid Build Coastguard Worker   return fn_ptr->vf(what, what_stride, best_address, in_what_stride, &thissad) +
1130*fb1b10abSAndroid Build Coastguard Worker          mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
1131*fb1b10abSAndroid Build Coastguard Worker }
1132*fb1b10abSAndroid Build Coastguard Worker 
1133*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SSE2 || HAVE_MSA || HAVE_LSX
vp8_diamond_search_sadx4(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * ref_mv,int_mv * best_mv,int search_param,int sad_per_bit,int * num00,vp8_variance_fn_ptr_t * fn_ptr,int * mvcost[2],int_mv * center_mv)1134*fb1b10abSAndroid Build Coastguard Worker int vp8_diamond_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
1135*fb1b10abSAndroid Build Coastguard Worker                              int_mv *best_mv, int search_param, int sad_per_bit,
1136*fb1b10abSAndroid Build Coastguard Worker                              int *num00, vp8_variance_fn_ptr_t *fn_ptr,
1137*fb1b10abSAndroid Build Coastguard Worker                              int *mvcost[2], int_mv *center_mv) {
1138*fb1b10abSAndroid Build Coastguard Worker   int i, j, step;
1139*fb1b10abSAndroid Build Coastguard Worker 
1140*fb1b10abSAndroid Build Coastguard Worker   unsigned char *what = (*(b->base_src) + b->src);
1141*fb1b10abSAndroid Build Coastguard Worker   int what_stride = b->src_stride;
1142*fb1b10abSAndroid Build Coastguard Worker   unsigned char *in_what;
1143*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
1144*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
1145*fb1b10abSAndroid Build Coastguard Worker   int in_what_stride = pre_stride;
1146*fb1b10abSAndroid Build Coastguard Worker   unsigned char *best_address;
1147*fb1b10abSAndroid Build Coastguard Worker 
1148*fb1b10abSAndroid Build Coastguard Worker   int tot_steps;
1149*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
1150*fb1b10abSAndroid Build Coastguard Worker 
1151*fb1b10abSAndroid Build Coastguard Worker   unsigned int bestsad;
1152*fb1b10abSAndroid Build Coastguard Worker   unsigned int thissad;
1153*fb1b10abSAndroid Build Coastguard Worker   int best_site = 0;
1154*fb1b10abSAndroid Build Coastguard Worker   int last_site = 0;
1155*fb1b10abSAndroid Build Coastguard Worker 
1156*fb1b10abSAndroid Build Coastguard Worker   int ref_row;
1157*fb1b10abSAndroid Build Coastguard Worker   int ref_col;
1158*fb1b10abSAndroid Build Coastguard Worker   int this_row_offset;
1159*fb1b10abSAndroid Build Coastguard Worker   int this_col_offset;
1160*fb1b10abSAndroid Build Coastguard Worker   search_site *ss;
1161*fb1b10abSAndroid Build Coastguard Worker 
1162*fb1b10abSAndroid Build Coastguard Worker   unsigned char *check_here;
1163*fb1b10abSAndroid Build Coastguard Worker 
1164*fb1b10abSAndroid Build Coastguard Worker   int *mvsadcost[2];
1165*fb1b10abSAndroid Build Coastguard Worker   int_mv fcenter_mv;
1166*fb1b10abSAndroid Build Coastguard Worker 
1167*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[0] = x->mvsadcost[0];
1168*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[1] = x->mvsadcost[1];
1169*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
1170*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
1171*fb1b10abSAndroid Build Coastguard Worker 
1172*fb1b10abSAndroid Build Coastguard Worker   vp8_clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min,
1173*fb1b10abSAndroid Build Coastguard Worker                x->mv_row_max);
1174*fb1b10abSAndroid Build Coastguard Worker   ref_row = ref_mv->as_mv.row;
1175*fb1b10abSAndroid Build Coastguard Worker   ref_col = ref_mv->as_mv.col;
1176*fb1b10abSAndroid Build Coastguard Worker   *num00 = 0;
1177*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.row = ref_row;
1178*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.col = ref_col;
1179*fb1b10abSAndroid Build Coastguard Worker 
1180*fb1b10abSAndroid Build Coastguard Worker   /* Work out the start point for the search */
1181*fb1b10abSAndroid Build Coastguard Worker   in_what = (unsigned char *)(base_pre + d->offset + (ref_row * pre_stride) +
1182*fb1b10abSAndroid Build Coastguard Worker                               ref_col);
1183*fb1b10abSAndroid Build Coastguard Worker   best_address = in_what;
1184*fb1b10abSAndroid Build Coastguard Worker 
1185*fb1b10abSAndroid Build Coastguard Worker   /* Check the starting position */
1186*fb1b10abSAndroid Build Coastguard Worker   bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride) +
1187*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
1188*fb1b10abSAndroid Build Coastguard Worker 
1189*fb1b10abSAndroid Build Coastguard Worker   /* search_param determines the length of the initial step and hence the
1190*fb1b10abSAndroid Build Coastguard Worker    * number of iterations 0 = initial step (MAX_FIRST_STEP) pel : 1 =
1191*fb1b10abSAndroid Build Coastguard Worker    * (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
1192*fb1b10abSAndroid Build Coastguard Worker    */
1193*fb1b10abSAndroid Build Coastguard Worker   ss = &x->ss[search_param * x->searches_per_step];
1194*fb1b10abSAndroid Build Coastguard Worker   tot_steps = (x->ss_count / x->searches_per_step) - search_param;
1195*fb1b10abSAndroid Build Coastguard Worker 
1196*fb1b10abSAndroid Build Coastguard Worker   i = 1;
1197*fb1b10abSAndroid Build Coastguard Worker 
1198*fb1b10abSAndroid Build Coastguard Worker   for (step = 0; step < tot_steps; ++step) {
1199*fb1b10abSAndroid Build Coastguard Worker     int all_in = 1, t;
1200*fb1b10abSAndroid Build Coastguard Worker 
1201*fb1b10abSAndroid Build Coastguard Worker     /* To know if all neighbor points are within the bounds, 4 bounds
1202*fb1b10abSAndroid Build Coastguard Worker      * checking are enough instead of checking 4 bounds for each
1203*fb1b10abSAndroid Build Coastguard Worker      * points.
1204*fb1b10abSAndroid Build Coastguard Worker      */
1205*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->as_mv.row + ss[i].mv.row) > x->mv_row_min);
1206*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->as_mv.row + ss[i + 1].mv.row) < x->mv_row_max);
1207*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->as_mv.col + ss[i + 2].mv.col) > x->mv_col_min);
1208*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((best_mv->as_mv.col + ss[i + 3].mv.col) < x->mv_col_max);
1209*fb1b10abSAndroid Build Coastguard Worker 
1210*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
1211*fb1b10abSAndroid Build Coastguard Worker       unsigned int sad_array[4];
1212*fb1b10abSAndroid Build Coastguard Worker 
1213*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < x->searches_per_step; j += 4) {
1214*fb1b10abSAndroid Build Coastguard Worker         const unsigned char *block_offset[4];
1215*fb1b10abSAndroid Build Coastguard Worker 
1216*fb1b10abSAndroid Build Coastguard Worker         for (t = 0; t < 4; ++t) {
1217*fb1b10abSAndroid Build Coastguard Worker           block_offset[t] = ss[i + t].offset + best_address;
1218*fb1b10abSAndroid Build Coastguard Worker         }
1219*fb1b10abSAndroid Build Coastguard Worker 
1220*fb1b10abSAndroid Build Coastguard Worker         fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride,
1221*fb1b10abSAndroid Build Coastguard Worker                        sad_array);
1222*fb1b10abSAndroid Build Coastguard Worker 
1223*fb1b10abSAndroid Build Coastguard Worker         for (t = 0; t < 4; t++, i++) {
1224*fb1b10abSAndroid Build Coastguard Worker           if (sad_array[t] < bestsad) {
1225*fb1b10abSAndroid Build Coastguard Worker             this_mv.as_mv.row = best_mv->as_mv.row + ss[i].mv.row;
1226*fb1b10abSAndroid Build Coastguard Worker             this_mv.as_mv.col = best_mv->as_mv.col + ss[i].mv.col;
1227*fb1b10abSAndroid Build Coastguard Worker             sad_array[t] +=
1228*fb1b10abSAndroid Build Coastguard Worker                 mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);
1229*fb1b10abSAndroid Build Coastguard Worker 
1230*fb1b10abSAndroid Build Coastguard Worker             if (sad_array[t] < bestsad) {
1231*fb1b10abSAndroid Build Coastguard Worker               bestsad = sad_array[t];
1232*fb1b10abSAndroid Build Coastguard Worker               best_site = i;
1233*fb1b10abSAndroid Build Coastguard Worker             }
1234*fb1b10abSAndroid Build Coastguard Worker           }
1235*fb1b10abSAndroid Build Coastguard Worker         }
1236*fb1b10abSAndroid Build Coastguard Worker       }
1237*fb1b10abSAndroid Build Coastguard Worker     } else {
1238*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < x->searches_per_step; ++j) {
1239*fb1b10abSAndroid Build Coastguard Worker         /* Trap illegal vectors */
1240*fb1b10abSAndroid Build Coastguard Worker         this_row_offset = best_mv->as_mv.row + ss[i].mv.row;
1241*fb1b10abSAndroid Build Coastguard Worker         this_col_offset = best_mv->as_mv.col + ss[i].mv.col;
1242*fb1b10abSAndroid Build Coastguard Worker 
1243*fb1b10abSAndroid Build Coastguard Worker         if ((this_col_offset > x->mv_col_min) &&
1244*fb1b10abSAndroid Build Coastguard Worker             (this_col_offset < x->mv_col_max) &&
1245*fb1b10abSAndroid Build Coastguard Worker             (this_row_offset > x->mv_row_min) &&
1246*fb1b10abSAndroid Build Coastguard Worker             (this_row_offset < x->mv_row_max)) {
1247*fb1b10abSAndroid Build Coastguard Worker           check_here = ss[i].offset + best_address;
1248*fb1b10abSAndroid Build Coastguard Worker           thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
1249*fb1b10abSAndroid Build Coastguard Worker 
1250*fb1b10abSAndroid Build Coastguard Worker           if (thissad < bestsad) {
1251*fb1b10abSAndroid Build Coastguard Worker             this_mv.as_mv.row = this_row_offset;
1252*fb1b10abSAndroid Build Coastguard Worker             this_mv.as_mv.col = this_col_offset;
1253*fb1b10abSAndroid Build Coastguard Worker             thissad +=
1254*fb1b10abSAndroid Build Coastguard Worker                 mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);
1255*fb1b10abSAndroid Build Coastguard Worker 
1256*fb1b10abSAndroid Build Coastguard Worker             if (thissad < bestsad) {
1257*fb1b10abSAndroid Build Coastguard Worker               bestsad = thissad;
1258*fb1b10abSAndroid Build Coastguard Worker               best_site = i;
1259*fb1b10abSAndroid Build Coastguard Worker             }
1260*fb1b10abSAndroid Build Coastguard Worker           }
1261*fb1b10abSAndroid Build Coastguard Worker         }
1262*fb1b10abSAndroid Build Coastguard Worker         i++;
1263*fb1b10abSAndroid Build Coastguard Worker       }
1264*fb1b10abSAndroid Build Coastguard Worker     }
1265*fb1b10abSAndroid Build Coastguard Worker 
1266*fb1b10abSAndroid Build Coastguard Worker     if (best_site != last_site) {
1267*fb1b10abSAndroid Build Coastguard Worker       best_mv->as_mv.row += ss[best_site].mv.row;
1268*fb1b10abSAndroid Build Coastguard Worker       best_mv->as_mv.col += ss[best_site].mv.col;
1269*fb1b10abSAndroid Build Coastguard Worker       best_address += ss[best_site].offset;
1270*fb1b10abSAndroid Build Coastguard Worker       last_site = best_site;
1271*fb1b10abSAndroid Build Coastguard Worker     } else if (best_address == in_what) {
1272*fb1b10abSAndroid Build Coastguard Worker       (*num00)++;
1273*fb1b10abSAndroid Build Coastguard Worker     }
1274*fb1b10abSAndroid Build Coastguard Worker   }
1275*fb1b10abSAndroid Build Coastguard Worker 
1276*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = clamp(best_mv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
1277*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = clamp(best_mv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
1278*fb1b10abSAndroid Build Coastguard Worker 
1279*fb1b10abSAndroid Build Coastguard Worker   return fn_ptr->vf(what, what_stride, best_address, in_what_stride, &thissad) +
1280*fb1b10abSAndroid Build Coastguard Worker          mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
1281*fb1b10abSAndroid Build Coastguard Worker }
1282*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SSE2 || HAVE_MSA || HAVE_LSX
1283*fb1b10abSAndroid Build Coastguard Worker 
vp8_full_search_sad(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * ref_mv,int sad_per_bit,int distance,vp8_variance_fn_ptr_t * fn_ptr,int * mvcost[2],int_mv * center_mv)1284*fb1b10abSAndroid Build Coastguard Worker int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv,
1285*fb1b10abSAndroid Build Coastguard Worker                         int sad_per_bit, int distance,
1286*fb1b10abSAndroid Build Coastguard Worker                         vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2],
1287*fb1b10abSAndroid Build Coastguard Worker                         int_mv *center_mv) {
1288*fb1b10abSAndroid Build Coastguard Worker   unsigned char *what = (*(b->base_src) + b->src);
1289*fb1b10abSAndroid Build Coastguard Worker   int what_stride = b->src_stride;
1290*fb1b10abSAndroid Build Coastguard Worker   unsigned char *in_what;
1291*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
1292*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
1293*fb1b10abSAndroid Build Coastguard Worker   int in_what_stride = pre_stride;
1294*fb1b10abSAndroid Build Coastguard Worker   int mv_stride = pre_stride;
1295*fb1b10abSAndroid Build Coastguard Worker   unsigned char *bestaddress;
1296*fb1b10abSAndroid Build Coastguard Worker   int_mv *best_mv = &d->bmi.mv;
1297*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
1298*fb1b10abSAndroid Build Coastguard Worker   unsigned int bestsad;
1299*fb1b10abSAndroid Build Coastguard Worker   unsigned int thissad;
1300*fb1b10abSAndroid Build Coastguard Worker   int r, c;
1301*fb1b10abSAndroid Build Coastguard Worker 
1302*fb1b10abSAndroid Build Coastguard Worker   unsigned char *check_here;
1303*fb1b10abSAndroid Build Coastguard Worker 
1304*fb1b10abSAndroid Build Coastguard Worker   int ref_row = ref_mv->as_mv.row;
1305*fb1b10abSAndroid Build Coastguard Worker   int ref_col = ref_mv->as_mv.col;
1306*fb1b10abSAndroid Build Coastguard Worker 
1307*fb1b10abSAndroid Build Coastguard Worker   int row_min = ref_row - distance;
1308*fb1b10abSAndroid Build Coastguard Worker   int row_max = ref_row + distance;
1309*fb1b10abSAndroid Build Coastguard Worker   int col_min = ref_col - distance;
1310*fb1b10abSAndroid Build Coastguard Worker   int col_max = ref_col + distance;
1311*fb1b10abSAndroid Build Coastguard Worker 
1312*fb1b10abSAndroid Build Coastguard Worker   int *mvsadcost[2];
1313*fb1b10abSAndroid Build Coastguard Worker   int_mv fcenter_mv;
1314*fb1b10abSAndroid Build Coastguard Worker 
1315*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[0] = x->mvsadcost[0];
1316*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[1] = x->mvsadcost[1];
1317*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
1318*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
1319*fb1b10abSAndroid Build Coastguard Worker 
1320*fb1b10abSAndroid Build Coastguard Worker   /* Work out the mid point for the search */
1321*fb1b10abSAndroid Build Coastguard Worker   in_what = base_pre + d->offset;
1322*fb1b10abSAndroid Build Coastguard Worker   bestaddress = in_what + (ref_row * pre_stride) + ref_col;
1323*fb1b10abSAndroid Build Coastguard Worker 
1324*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.row = ref_row;
1325*fb1b10abSAndroid Build Coastguard Worker   best_mv->as_mv.col = ref_col;
1326*fb1b10abSAndroid Build Coastguard Worker 
1327*fb1b10abSAndroid Build Coastguard Worker   /* Baseline value at the centre */
1328*fb1b10abSAndroid Build Coastguard Worker   bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride) +
1329*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(best_mv, &fcenter_mv, mvsadcost, sad_per_bit);
1330*fb1b10abSAndroid Build Coastguard Worker 
1331*fb1b10abSAndroid Build Coastguard Worker   /* Apply further limits to prevent us looking using vectors that stretch
1332*fb1b10abSAndroid Build Coastguard Worker    * beyond the UMV border
1333*fb1b10abSAndroid Build Coastguard Worker    */
1334*fb1b10abSAndroid Build Coastguard Worker   if (col_min < x->mv_col_min) col_min = x->mv_col_min;
1335*fb1b10abSAndroid Build Coastguard Worker 
1336*fb1b10abSAndroid Build Coastguard Worker   if (col_max > x->mv_col_max) col_max = x->mv_col_max;
1337*fb1b10abSAndroid Build Coastguard Worker 
1338*fb1b10abSAndroid Build Coastguard Worker   if (row_min < x->mv_row_min) row_min = x->mv_row_min;
1339*fb1b10abSAndroid Build Coastguard Worker 
1340*fb1b10abSAndroid Build Coastguard Worker   if (row_max > x->mv_row_max) row_max = x->mv_row_max;
1341*fb1b10abSAndroid Build Coastguard Worker 
1342*fb1b10abSAndroid Build Coastguard Worker   for (r = row_min; r < row_max; ++r) {
1343*fb1b10abSAndroid Build Coastguard Worker     this_mv.as_mv.row = r;
1344*fb1b10abSAndroid Build Coastguard Worker     check_here = r * mv_stride + in_what + col_min;
1345*fb1b10abSAndroid Build Coastguard Worker 
1346*fb1b10abSAndroid Build Coastguard Worker     for (c = col_min; c < col_max; ++c) {
1347*fb1b10abSAndroid Build Coastguard Worker       thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
1348*fb1b10abSAndroid Build Coastguard Worker 
1349*fb1b10abSAndroid Build Coastguard Worker       if (thissad < bestsad) {
1350*fb1b10abSAndroid Build Coastguard Worker         this_mv.as_mv.col = c;
1351*fb1b10abSAndroid Build Coastguard Worker         thissad +=
1352*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, sad_per_bit);
1353*fb1b10abSAndroid Build Coastguard Worker 
1354*fb1b10abSAndroid Build Coastguard Worker         if (thissad < bestsad) {
1355*fb1b10abSAndroid Build Coastguard Worker           bestsad = thissad;
1356*fb1b10abSAndroid Build Coastguard Worker           best_mv->as_mv.row = r;
1357*fb1b10abSAndroid Build Coastguard Worker           best_mv->as_mv.col = c;
1358*fb1b10abSAndroid Build Coastguard Worker           bestaddress = check_here;
1359*fb1b10abSAndroid Build Coastguard Worker         }
1360*fb1b10abSAndroid Build Coastguard Worker       }
1361*fb1b10abSAndroid Build Coastguard Worker 
1362*fb1b10abSAndroid Build Coastguard Worker       check_here++;
1363*fb1b10abSAndroid Build Coastguard Worker     }
1364*fb1b10abSAndroid Build Coastguard Worker   }
1365*fb1b10abSAndroid Build Coastguard Worker 
1366*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = clamp(best_mv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
1367*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = clamp(best_mv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
1368*fb1b10abSAndroid Build Coastguard Worker 
1369*fb1b10abSAndroid Build Coastguard Worker   return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, &thissad) +
1370*fb1b10abSAndroid Build Coastguard Worker          mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
1371*fb1b10abSAndroid Build Coastguard Worker }
1372*fb1b10abSAndroid Build Coastguard Worker 
vp8_refining_search_sad_c(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * ref_mv,int error_per_bit,int search_range,vp8_variance_fn_ptr_t * fn_ptr,int * mvcost[2],int_mv * center_mv)1373*fb1b10abSAndroid Build Coastguard Worker int vp8_refining_search_sad_c(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
1374*fb1b10abSAndroid Build Coastguard Worker                               int_mv *ref_mv, int error_per_bit,
1375*fb1b10abSAndroid Build Coastguard Worker                               int search_range, vp8_variance_fn_ptr_t *fn_ptr,
1376*fb1b10abSAndroid Build Coastguard Worker                               int *mvcost[2], int_mv *center_mv) {
1377*fb1b10abSAndroid Build Coastguard Worker   MV neighbors[4] = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
1378*fb1b10abSAndroid Build Coastguard Worker   int i, j;
1379*fb1b10abSAndroid Build Coastguard Worker   short this_row_offset, this_col_offset;
1380*fb1b10abSAndroid Build Coastguard Worker 
1381*fb1b10abSAndroid Build Coastguard Worker   int what_stride = b->src_stride;
1382*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
1383*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
1384*fb1b10abSAndroid Build Coastguard Worker   int in_what_stride = pre_stride;
1385*fb1b10abSAndroid Build Coastguard Worker   unsigned char *what = (*(b->base_src) + b->src);
1386*fb1b10abSAndroid Build Coastguard Worker   unsigned char *best_address =
1387*fb1b10abSAndroid Build Coastguard Worker       (unsigned char *)(base_pre + d->offset +
1388*fb1b10abSAndroid Build Coastguard Worker                         (ref_mv->as_mv.row * pre_stride) + ref_mv->as_mv.col);
1389*fb1b10abSAndroid Build Coastguard Worker   unsigned char *check_here;
1390*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
1391*fb1b10abSAndroid Build Coastguard Worker   unsigned int bestsad;
1392*fb1b10abSAndroid Build Coastguard Worker   unsigned int thissad;
1393*fb1b10abSAndroid Build Coastguard Worker 
1394*fb1b10abSAndroid Build Coastguard Worker   int *mvsadcost[2];
1395*fb1b10abSAndroid Build Coastguard Worker   int_mv fcenter_mv;
1396*fb1b10abSAndroid Build Coastguard Worker 
1397*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[0] = x->mvsadcost[0];
1398*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[1] = x->mvsadcost[1];
1399*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
1400*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
1401*fb1b10abSAndroid Build Coastguard Worker 
1402*fb1b10abSAndroid Build Coastguard Worker   bestsad = fn_ptr->sdf(what, what_stride, best_address, in_what_stride) +
1403*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(ref_mv, &fcenter_mv, mvsadcost, error_per_bit);
1404*fb1b10abSAndroid Build Coastguard Worker 
1405*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < search_range; ++i) {
1406*fb1b10abSAndroid Build Coastguard Worker     int best_site = -1;
1407*fb1b10abSAndroid Build Coastguard Worker 
1408*fb1b10abSAndroid Build Coastguard Worker     for (j = 0; j < 4; ++j) {
1409*fb1b10abSAndroid Build Coastguard Worker       this_row_offset = ref_mv->as_mv.row + neighbors[j].row;
1410*fb1b10abSAndroid Build Coastguard Worker       this_col_offset = ref_mv->as_mv.col + neighbors[j].col;
1411*fb1b10abSAndroid Build Coastguard Worker 
1412*fb1b10abSAndroid Build Coastguard Worker       if ((this_col_offset > x->mv_col_min) &&
1413*fb1b10abSAndroid Build Coastguard Worker           (this_col_offset < x->mv_col_max) &&
1414*fb1b10abSAndroid Build Coastguard Worker           (this_row_offset > x->mv_row_min) &&
1415*fb1b10abSAndroid Build Coastguard Worker           (this_row_offset < x->mv_row_max)) {
1416*fb1b10abSAndroid Build Coastguard Worker         check_here = (neighbors[j].row) * in_what_stride + neighbors[j].col +
1417*fb1b10abSAndroid Build Coastguard Worker                      best_address;
1418*fb1b10abSAndroid Build Coastguard Worker         thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
1419*fb1b10abSAndroid Build Coastguard Worker 
1420*fb1b10abSAndroid Build Coastguard Worker         if (thissad < bestsad) {
1421*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.row = this_row_offset;
1422*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.col = this_col_offset;
1423*fb1b10abSAndroid Build Coastguard Worker           thissad +=
1424*fb1b10abSAndroid Build Coastguard Worker               mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, error_per_bit);
1425*fb1b10abSAndroid Build Coastguard Worker 
1426*fb1b10abSAndroid Build Coastguard Worker           if (thissad < bestsad) {
1427*fb1b10abSAndroid Build Coastguard Worker             bestsad = thissad;
1428*fb1b10abSAndroid Build Coastguard Worker             best_site = j;
1429*fb1b10abSAndroid Build Coastguard Worker           }
1430*fb1b10abSAndroid Build Coastguard Worker         }
1431*fb1b10abSAndroid Build Coastguard Worker       }
1432*fb1b10abSAndroid Build Coastguard Worker     }
1433*fb1b10abSAndroid Build Coastguard Worker 
1434*fb1b10abSAndroid Build Coastguard Worker     if (best_site == -1) {
1435*fb1b10abSAndroid Build Coastguard Worker       break;
1436*fb1b10abSAndroid Build Coastguard Worker     } else {
1437*fb1b10abSAndroid Build Coastguard Worker       ref_mv->as_mv.row += neighbors[best_site].row;
1438*fb1b10abSAndroid Build Coastguard Worker       ref_mv->as_mv.col += neighbors[best_site].col;
1439*fb1b10abSAndroid Build Coastguard Worker       best_address += (neighbors[best_site].row) * in_what_stride +
1440*fb1b10abSAndroid Build Coastguard Worker                       neighbors[best_site].col;
1441*fb1b10abSAndroid Build Coastguard Worker     }
1442*fb1b10abSAndroid Build Coastguard Worker   }
1443*fb1b10abSAndroid Build Coastguard Worker 
1444*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = clamp(ref_mv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
1445*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = clamp(ref_mv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
1446*fb1b10abSAndroid Build Coastguard Worker 
1447*fb1b10abSAndroid Build Coastguard Worker   return fn_ptr->vf(what, what_stride, best_address, in_what_stride, &thissad) +
1448*fb1b10abSAndroid Build Coastguard Worker          mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
1449*fb1b10abSAndroid Build Coastguard Worker }
1450*fb1b10abSAndroid Build Coastguard Worker 
1451*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SSE2 || HAVE_MSA
vp8_refining_search_sadx4(MACROBLOCK * x,BLOCK * b,BLOCKD * d,int_mv * ref_mv,int error_per_bit,int search_range,vp8_variance_fn_ptr_t * fn_ptr,int * mvcost[2],int_mv * center_mv)1452*fb1b10abSAndroid Build Coastguard Worker int vp8_refining_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d,
1453*fb1b10abSAndroid Build Coastguard Worker                               int_mv *ref_mv, int error_per_bit,
1454*fb1b10abSAndroid Build Coastguard Worker                               int search_range, vp8_variance_fn_ptr_t *fn_ptr,
1455*fb1b10abSAndroid Build Coastguard Worker                               int *mvcost[2], int_mv *center_mv) {
1456*fb1b10abSAndroid Build Coastguard Worker   MV neighbors[4] = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
1457*fb1b10abSAndroid Build Coastguard Worker   int i, j;
1458*fb1b10abSAndroid Build Coastguard Worker   short this_row_offset, this_col_offset;
1459*fb1b10abSAndroid Build Coastguard Worker 
1460*fb1b10abSAndroid Build Coastguard Worker   int what_stride = b->src_stride;
1461*fb1b10abSAndroid Build Coastguard Worker   int pre_stride = x->e_mbd.pre.y_stride;
1462*fb1b10abSAndroid Build Coastguard Worker   unsigned char *base_pre = x->e_mbd.pre.y_buffer;
1463*fb1b10abSAndroid Build Coastguard Worker   int in_what_stride = pre_stride;
1464*fb1b10abSAndroid Build Coastguard Worker   unsigned char *what = (*(b->base_src) + b->src);
1465*fb1b10abSAndroid Build Coastguard Worker   unsigned char *best_address =
1466*fb1b10abSAndroid Build Coastguard Worker       (unsigned char *)(base_pre + d->offset +
1467*fb1b10abSAndroid Build Coastguard Worker                         (ref_mv->as_mv.row * pre_stride) + ref_mv->as_mv.col);
1468*fb1b10abSAndroid Build Coastguard Worker   unsigned char *check_here;
1469*fb1b10abSAndroid Build Coastguard Worker   int_mv this_mv;
1470*fb1b10abSAndroid Build Coastguard Worker   unsigned int bestsad;
1471*fb1b10abSAndroid Build Coastguard Worker   unsigned int thissad;
1472*fb1b10abSAndroid Build Coastguard Worker 
1473*fb1b10abSAndroid Build Coastguard Worker   int *mvsadcost[2];
1474*fb1b10abSAndroid Build Coastguard Worker   int_mv fcenter_mv;
1475*fb1b10abSAndroid Build Coastguard Worker 
1476*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[0] = x->mvsadcost[0];
1477*fb1b10abSAndroid Build Coastguard Worker   mvsadcost[1] = x->mvsadcost[1];
1478*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3;
1479*fb1b10abSAndroid Build Coastguard Worker   fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3;
1480*fb1b10abSAndroid Build Coastguard Worker 
1481*fb1b10abSAndroid Build Coastguard Worker   bestsad = fn_ptr->sdf(what, what_stride, best_address, in_what_stride) +
1482*fb1b10abSAndroid Build Coastguard Worker             mvsad_err_cost(ref_mv, &fcenter_mv, mvsadcost, error_per_bit);
1483*fb1b10abSAndroid Build Coastguard Worker 
1484*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < search_range; ++i) {
1485*fb1b10abSAndroid Build Coastguard Worker     int best_site = -1;
1486*fb1b10abSAndroid Build Coastguard Worker     int all_in = 1;
1487*fb1b10abSAndroid Build Coastguard Worker 
1488*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((ref_mv->as_mv.row - 1) > x->mv_row_min);
1489*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((ref_mv->as_mv.row + 1) < x->mv_row_max);
1490*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((ref_mv->as_mv.col - 1) > x->mv_col_min);
1491*fb1b10abSAndroid Build Coastguard Worker     all_in &= ((ref_mv->as_mv.col + 1) < x->mv_col_max);
1492*fb1b10abSAndroid Build Coastguard Worker 
1493*fb1b10abSAndroid Build Coastguard Worker     if (all_in) {
1494*fb1b10abSAndroid Build Coastguard Worker       unsigned int sad_array[4];
1495*fb1b10abSAndroid Build Coastguard Worker       const unsigned char *block_offset[4];
1496*fb1b10abSAndroid Build Coastguard Worker       block_offset[0] = best_address - in_what_stride;
1497*fb1b10abSAndroid Build Coastguard Worker       block_offset[1] = best_address - 1;
1498*fb1b10abSAndroid Build Coastguard Worker       block_offset[2] = best_address + 1;
1499*fb1b10abSAndroid Build Coastguard Worker       block_offset[3] = best_address + in_what_stride;
1500*fb1b10abSAndroid Build Coastguard Worker 
1501*fb1b10abSAndroid Build Coastguard Worker       fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride,
1502*fb1b10abSAndroid Build Coastguard Worker                      sad_array);
1503*fb1b10abSAndroid Build Coastguard Worker 
1504*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < 4; ++j) {
1505*fb1b10abSAndroid Build Coastguard Worker         if (sad_array[j] < bestsad) {
1506*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.row = ref_mv->as_mv.row + neighbors[j].row;
1507*fb1b10abSAndroid Build Coastguard Worker           this_mv.as_mv.col = ref_mv->as_mv.col + neighbors[j].col;
1508*fb1b10abSAndroid Build Coastguard Worker           sad_array[j] +=
1509*fb1b10abSAndroid Build Coastguard Worker               mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, error_per_bit);
1510*fb1b10abSAndroid Build Coastguard Worker 
1511*fb1b10abSAndroid Build Coastguard Worker           if (sad_array[j] < bestsad) {
1512*fb1b10abSAndroid Build Coastguard Worker             bestsad = sad_array[j];
1513*fb1b10abSAndroid Build Coastguard Worker             best_site = j;
1514*fb1b10abSAndroid Build Coastguard Worker           }
1515*fb1b10abSAndroid Build Coastguard Worker         }
1516*fb1b10abSAndroid Build Coastguard Worker       }
1517*fb1b10abSAndroid Build Coastguard Worker     } else {
1518*fb1b10abSAndroid Build Coastguard Worker       for (j = 0; j < 4; ++j) {
1519*fb1b10abSAndroid Build Coastguard Worker         this_row_offset = ref_mv->as_mv.row + neighbors[j].row;
1520*fb1b10abSAndroid Build Coastguard Worker         this_col_offset = ref_mv->as_mv.col + neighbors[j].col;
1521*fb1b10abSAndroid Build Coastguard Worker 
1522*fb1b10abSAndroid Build Coastguard Worker         if ((this_col_offset > x->mv_col_min) &&
1523*fb1b10abSAndroid Build Coastguard Worker             (this_col_offset < x->mv_col_max) &&
1524*fb1b10abSAndroid Build Coastguard Worker             (this_row_offset > x->mv_row_min) &&
1525*fb1b10abSAndroid Build Coastguard Worker             (this_row_offset < x->mv_row_max)) {
1526*fb1b10abSAndroid Build Coastguard Worker           check_here = (neighbors[j].row) * in_what_stride + neighbors[j].col +
1527*fb1b10abSAndroid Build Coastguard Worker                        best_address;
1528*fb1b10abSAndroid Build Coastguard Worker           thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride);
1529*fb1b10abSAndroid Build Coastguard Worker 
1530*fb1b10abSAndroid Build Coastguard Worker           if (thissad < bestsad) {
1531*fb1b10abSAndroid Build Coastguard Worker             this_mv.as_mv.row = this_row_offset;
1532*fb1b10abSAndroid Build Coastguard Worker             this_mv.as_mv.col = this_col_offset;
1533*fb1b10abSAndroid Build Coastguard Worker             thissad +=
1534*fb1b10abSAndroid Build Coastguard Worker                 mvsad_err_cost(&this_mv, &fcenter_mv, mvsadcost, error_per_bit);
1535*fb1b10abSAndroid Build Coastguard Worker 
1536*fb1b10abSAndroid Build Coastguard Worker             if (thissad < bestsad) {
1537*fb1b10abSAndroid Build Coastguard Worker               bestsad = thissad;
1538*fb1b10abSAndroid Build Coastguard Worker               best_site = j;
1539*fb1b10abSAndroid Build Coastguard Worker             }
1540*fb1b10abSAndroid Build Coastguard Worker           }
1541*fb1b10abSAndroid Build Coastguard Worker         }
1542*fb1b10abSAndroid Build Coastguard Worker       }
1543*fb1b10abSAndroid Build Coastguard Worker     }
1544*fb1b10abSAndroid Build Coastguard Worker 
1545*fb1b10abSAndroid Build Coastguard Worker     if (best_site == -1) {
1546*fb1b10abSAndroid Build Coastguard Worker       break;
1547*fb1b10abSAndroid Build Coastguard Worker     } else {
1548*fb1b10abSAndroid Build Coastguard Worker       ref_mv->as_mv.row += neighbors[best_site].row;
1549*fb1b10abSAndroid Build Coastguard Worker       ref_mv->as_mv.col += neighbors[best_site].col;
1550*fb1b10abSAndroid Build Coastguard Worker       best_address += (neighbors[best_site].row) * in_what_stride +
1551*fb1b10abSAndroid Build Coastguard Worker                       neighbors[best_site].col;
1552*fb1b10abSAndroid Build Coastguard Worker     }
1553*fb1b10abSAndroid Build Coastguard Worker   }
1554*fb1b10abSAndroid Build Coastguard Worker 
1555*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.row = clamp(ref_mv->as_mv.row * 8, SHRT_MIN, SHRT_MAX);
1556*fb1b10abSAndroid Build Coastguard Worker   this_mv.as_mv.col = clamp(ref_mv->as_mv.col * 8, SHRT_MIN, SHRT_MAX);
1557*fb1b10abSAndroid Build Coastguard Worker 
1558*fb1b10abSAndroid Build Coastguard Worker   return fn_ptr->vf(what, what_stride, best_address, in_what_stride, &thissad) +
1559*fb1b10abSAndroid Build Coastguard Worker          mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit);
1560*fb1b10abSAndroid Build Coastguard Worker }
1561*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SSE2 || HAVE_MSA
1562