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