1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker *
4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker */
11*77c1e3ccSAndroid Build Coastguard Worker
12*77c1e3ccSAndroid Build Coastguard Worker #include <stdio.h>
13*77c1e3ccSAndroid Build Coastguard Worker #include <stdlib.h>
14*77c1e3ccSAndroid Build Coastguard Worker #include <stdbool.h>
15*77c1e3ccSAndroid Build Coastguard Worker #include <memory.h>
16*77c1e3ccSAndroid Build Coastguard Worker #include <math.h>
17*77c1e3ccSAndroid Build Coastguard Worker #include <assert.h>
18*77c1e3ccSAndroid Build Coastguard Worker
19*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
20*77c1e3ccSAndroid Build Coastguard Worker
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/global_motion.h"
22*77c1e3ccSAndroid Build Coastguard Worker
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/convolve.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/warped_motion.h"
25*77c1e3ccSAndroid Build Coastguard Worker
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/segmentation.h"
27*77c1e3ccSAndroid Build Coastguard Worker
28*77c1e3ccSAndroid Build Coastguard Worker #define MIN_TRANS_THRESH (1 * GM_TRANS_DECODE_FACTOR)
29*77c1e3ccSAndroid Build Coastguard Worker
30*77c1e3ccSAndroid Build Coastguard Worker // Border over which to compute the global motion
31*77c1e3ccSAndroid Build Coastguard Worker #define ERRORADV_BORDER 0
32*77c1e3ccSAndroid Build Coastguard Worker
av1_is_enough_erroradvantage(double best_erroradvantage,int params_cost)33*77c1e3ccSAndroid Build Coastguard Worker int av1_is_enough_erroradvantage(double best_erroradvantage, int params_cost) {
34*77c1e3ccSAndroid Build Coastguard Worker return best_erroradvantage < erroradv_tr &&
35*77c1e3ccSAndroid Build Coastguard Worker best_erroradvantage * params_cost < erroradv_prod_tr;
36*77c1e3ccSAndroid Build Coastguard Worker }
37*77c1e3ccSAndroid Build Coastguard Worker
convert_to_params(const double * params,int32_t * model)38*77c1e3ccSAndroid Build Coastguard Worker static void convert_to_params(const double *params, int32_t *model) {
39*77c1e3ccSAndroid Build Coastguard Worker int i;
40*77c1e3ccSAndroid Build Coastguard Worker model[0] = (int32_t)floor(params[0] * (1 << GM_TRANS_PREC_BITS) + 0.5);
41*77c1e3ccSAndroid Build Coastguard Worker model[1] = (int32_t)floor(params[1] * (1 << GM_TRANS_PREC_BITS) + 0.5);
42*77c1e3ccSAndroid Build Coastguard Worker model[0] = (int32_t)clamp(model[0], GM_TRANS_MIN, GM_TRANS_MAX) *
43*77c1e3ccSAndroid Build Coastguard Worker GM_TRANS_DECODE_FACTOR;
44*77c1e3ccSAndroid Build Coastguard Worker model[1] = (int32_t)clamp(model[1], GM_TRANS_MIN, GM_TRANS_MAX) *
45*77c1e3ccSAndroid Build Coastguard Worker GM_TRANS_DECODE_FACTOR;
46*77c1e3ccSAndroid Build Coastguard Worker
47*77c1e3ccSAndroid Build Coastguard Worker for (i = 2; i < 6; ++i) {
48*77c1e3ccSAndroid Build Coastguard Worker const int diag_value = ((i == 2 || i == 5) ? (1 << GM_ALPHA_PREC_BITS) : 0);
49*77c1e3ccSAndroid Build Coastguard Worker model[i] = (int32_t)floor(params[i] * (1 << GM_ALPHA_PREC_BITS) + 0.5);
50*77c1e3ccSAndroid Build Coastguard Worker model[i] =
51*77c1e3ccSAndroid Build Coastguard Worker (int32_t)clamp(model[i] - diag_value, GM_ALPHA_MIN, GM_ALPHA_MAX);
52*77c1e3ccSAndroid Build Coastguard Worker model[i] = (model[i] + diag_value) * GM_ALPHA_DECODE_FACTOR;
53*77c1e3ccSAndroid Build Coastguard Worker }
54*77c1e3ccSAndroid Build Coastguard Worker }
55*77c1e3ccSAndroid Build Coastguard Worker
av1_convert_model_to_params(const double * params,WarpedMotionParams * model)56*77c1e3ccSAndroid Build Coastguard Worker void av1_convert_model_to_params(const double *params,
57*77c1e3ccSAndroid Build Coastguard Worker WarpedMotionParams *model) {
58*77c1e3ccSAndroid Build Coastguard Worker convert_to_params(params, model->wmmat);
59*77c1e3ccSAndroid Build Coastguard Worker model->wmtype = get_wmtype(model);
60*77c1e3ccSAndroid Build Coastguard Worker model->invalid = 0;
61*77c1e3ccSAndroid Build Coastguard Worker }
62*77c1e3ccSAndroid Build Coastguard Worker
63*77c1e3ccSAndroid Build Coastguard Worker // Adds some offset to a global motion parameter and handles
64*77c1e3ccSAndroid Build Coastguard Worker // all of the necessary precision shifts, clamping, and
65*77c1e3ccSAndroid Build Coastguard Worker // zero-centering.
add_param_offset(int param_index,int32_t param_value,int32_t offset)66*77c1e3ccSAndroid Build Coastguard Worker static int32_t add_param_offset(int param_index, int32_t param_value,
67*77c1e3ccSAndroid Build Coastguard Worker int32_t offset) {
68*77c1e3ccSAndroid Build Coastguard Worker const int scale_vals[2] = { GM_TRANS_PREC_DIFF, GM_ALPHA_PREC_DIFF };
69*77c1e3ccSAndroid Build Coastguard Worker const int clamp_vals[2] = { GM_TRANS_MAX, GM_ALPHA_MAX };
70*77c1e3ccSAndroid Build Coastguard Worker // type of param: 0 - translation, 1 - affine
71*77c1e3ccSAndroid Build Coastguard Worker const int param_type = (param_index < 2 ? 0 : 1);
72*77c1e3ccSAndroid Build Coastguard Worker const int is_one_centered = (param_index == 2 || param_index == 5);
73*77c1e3ccSAndroid Build Coastguard Worker
74*77c1e3ccSAndroid Build Coastguard Worker // Make parameter zero-centered and offset the shift that was done to make
75*77c1e3ccSAndroid Build Coastguard Worker // it compatible with the warped model
76*77c1e3ccSAndroid Build Coastguard Worker param_value = (param_value - (is_one_centered << WARPEDMODEL_PREC_BITS)) >>
77*77c1e3ccSAndroid Build Coastguard Worker scale_vals[param_type];
78*77c1e3ccSAndroid Build Coastguard Worker // Add desired offset to the rescaled/zero-centered parameter
79*77c1e3ccSAndroid Build Coastguard Worker param_value += offset;
80*77c1e3ccSAndroid Build Coastguard Worker // Clamp the parameter so it does not overflow the number of bits allotted
81*77c1e3ccSAndroid Build Coastguard Worker // to it in the bitstream
82*77c1e3ccSAndroid Build Coastguard Worker param_value = (int32_t)clamp(param_value, -clamp_vals[param_type],
83*77c1e3ccSAndroid Build Coastguard Worker clamp_vals[param_type]);
84*77c1e3ccSAndroid Build Coastguard Worker // Rescale the parameter to WARPEDMODEL_PRECISION_BITS so it is compatible
85*77c1e3ccSAndroid Build Coastguard Worker // with the warped motion library
86*77c1e3ccSAndroid Build Coastguard Worker param_value *= (1 << scale_vals[param_type]);
87*77c1e3ccSAndroid Build Coastguard Worker
88*77c1e3ccSAndroid Build Coastguard Worker // Undo the zero-centering step if necessary
89*77c1e3ccSAndroid Build Coastguard Worker return param_value + (is_one_centered << WARPEDMODEL_PREC_BITS);
90*77c1e3ccSAndroid Build Coastguard Worker }
91*77c1e3ccSAndroid Build Coastguard Worker
force_wmtype(WarpedMotionParams * wm,TransformationType wmtype)92*77c1e3ccSAndroid Build Coastguard Worker static void force_wmtype(WarpedMotionParams *wm, TransformationType wmtype) {
93*77c1e3ccSAndroid Build Coastguard Worker switch (wmtype) {
94*77c1e3ccSAndroid Build Coastguard Worker case IDENTITY:
95*77c1e3ccSAndroid Build Coastguard Worker wm->wmmat[0] = 0;
96*77c1e3ccSAndroid Build Coastguard Worker wm->wmmat[1] = 0;
97*77c1e3ccSAndroid Build Coastguard Worker AOM_FALLTHROUGH_INTENDED;
98*77c1e3ccSAndroid Build Coastguard Worker case TRANSLATION:
99*77c1e3ccSAndroid Build Coastguard Worker wm->wmmat[2] = 1 << WARPEDMODEL_PREC_BITS;
100*77c1e3ccSAndroid Build Coastguard Worker wm->wmmat[3] = 0;
101*77c1e3ccSAndroid Build Coastguard Worker AOM_FALLTHROUGH_INTENDED;
102*77c1e3ccSAndroid Build Coastguard Worker case ROTZOOM:
103*77c1e3ccSAndroid Build Coastguard Worker wm->wmmat[4] = -wm->wmmat[3];
104*77c1e3ccSAndroid Build Coastguard Worker wm->wmmat[5] = wm->wmmat[2];
105*77c1e3ccSAndroid Build Coastguard Worker AOM_FALLTHROUGH_INTENDED;
106*77c1e3ccSAndroid Build Coastguard Worker case AFFINE: break;
107*77c1e3ccSAndroid Build Coastguard Worker default: assert(0);
108*77c1e3ccSAndroid Build Coastguard Worker }
109*77c1e3ccSAndroid Build Coastguard Worker wm->wmtype = wmtype;
110*77c1e3ccSAndroid Build Coastguard Worker }
111*77c1e3ccSAndroid Build Coastguard Worker
112*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
generic_sad_highbd(const uint16_t * const ref,int ref_stride,const uint16_t * const dst,int dst_stride,int p_width,int p_height)113*77c1e3ccSAndroid Build Coastguard Worker static inline int generic_sad_highbd(const uint16_t *const ref, int ref_stride,
114*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *const dst, int dst_stride,
115*77c1e3ccSAndroid Build Coastguard Worker int p_width, int p_height) {
116*77c1e3ccSAndroid Build Coastguard Worker // This function should only be called for patches smaller than
117*77c1e3ccSAndroid Build Coastguard Worker // WARP_ERROR_BLOCK x WARP_ERROR_BLOCK. This keeps the number of pixels
118*77c1e3ccSAndroid Build Coastguard Worker // small enough that we don't need a 64-bit accumulator
119*77c1e3ccSAndroid Build Coastguard Worker assert(p_width <= WARP_ERROR_BLOCK && p_height <= WARP_ERROR_BLOCK);
120*77c1e3ccSAndroid Build Coastguard Worker
121*77c1e3ccSAndroid Build Coastguard Worker int sad = 0;
122*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < p_height; ++i) {
123*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < p_width; ++j) {
124*77c1e3ccSAndroid Build Coastguard Worker sad += abs(dst[j + i * dst_stride] - ref[j + i * ref_stride]);
125*77c1e3ccSAndroid Build Coastguard Worker }
126*77c1e3ccSAndroid Build Coastguard Worker }
127*77c1e3ccSAndroid Build Coastguard Worker return sad;
128*77c1e3ccSAndroid Build Coastguard Worker }
129*77c1e3ccSAndroid Build Coastguard Worker
130*77c1e3ccSAndroid Build Coastguard Worker #if WARP_ERROR_BLOCK != 32
131*77c1e3ccSAndroid Build Coastguard Worker #error "Need to change SAD call size in highbd_segmented_frame_error"
132*77c1e3ccSAndroid Build Coastguard Worker #endif // WARP_ERROR_BLOCK != 32
highbd_segmented_frame_error(const uint16_t * const ref,int ref_stride,const uint16_t * const dst,int dst_stride,int p_width,int p_height,int bd,uint8_t * segment_map,int segment_map_stride)133*77c1e3ccSAndroid Build Coastguard Worker static int64_t highbd_segmented_frame_error(
134*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *const ref, int ref_stride, const uint16_t *const dst,
135*77c1e3ccSAndroid Build Coastguard Worker int dst_stride, int p_width, int p_height, int bd, uint8_t *segment_map,
136*77c1e3ccSAndroid Build Coastguard Worker int segment_map_stride) {
137*77c1e3ccSAndroid Build Coastguard Worker (void)bd;
138*77c1e3ccSAndroid Build Coastguard Worker int patch_w, patch_h;
139*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK);
140*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK);
141*77c1e3ccSAndroid Build Coastguard Worker int64_t sum_error = 0;
142*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < p_height; i += WARP_ERROR_BLOCK) {
143*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < p_width; j += WARP_ERROR_BLOCK) {
144*77c1e3ccSAndroid Build Coastguard Worker int seg_x = j >> WARP_ERROR_BLOCK_LOG;
145*77c1e3ccSAndroid Build Coastguard Worker int seg_y = i >> WARP_ERROR_BLOCK_LOG;
146*77c1e3ccSAndroid Build Coastguard Worker // Only compute the error if this block contains inliers from the motion
147*77c1e3ccSAndroid Build Coastguard Worker // model
148*77c1e3ccSAndroid Build Coastguard Worker if (!segment_map[seg_y * segment_map_stride + seg_x]) continue;
149*77c1e3ccSAndroid Build Coastguard Worker
150*77c1e3ccSAndroid Build Coastguard Worker // avoid computing error into the frame padding
151*77c1e3ccSAndroid Build Coastguard Worker patch_w = AOMMIN(error_bsize_w, p_width - j);
152*77c1e3ccSAndroid Build Coastguard Worker patch_h = AOMMIN(error_bsize_h, p_height - i);
153*77c1e3ccSAndroid Build Coastguard Worker
154*77c1e3ccSAndroid Build Coastguard Worker if (patch_w == WARP_ERROR_BLOCK && patch_h == WARP_ERROR_BLOCK) {
155*77c1e3ccSAndroid Build Coastguard Worker sum_error += aom_highbd_sad32x32(
156*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_BYTEPTR(ref + j + i * ref_stride), ref_stride,
157*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_BYTEPTR(dst + j + i * dst_stride), dst_stride);
158*77c1e3ccSAndroid Build Coastguard Worker } else {
159*77c1e3ccSAndroid Build Coastguard Worker sum_error += generic_sad_highbd(ref + j + i * ref_stride, ref_stride,
160*77c1e3ccSAndroid Build Coastguard Worker dst + j + i * dst_stride, dst_stride,
161*77c1e3ccSAndroid Build Coastguard Worker patch_w, patch_h);
162*77c1e3ccSAndroid Build Coastguard Worker }
163*77c1e3ccSAndroid Build Coastguard Worker }
164*77c1e3ccSAndroid Build Coastguard Worker }
165*77c1e3ccSAndroid Build Coastguard Worker return sum_error;
166*77c1e3ccSAndroid Build Coastguard Worker }
167*77c1e3ccSAndroid Build Coastguard Worker
168*77c1e3ccSAndroid Build Coastguard Worker #if WARP_ERROR_BLOCK != 32
169*77c1e3ccSAndroid Build Coastguard Worker #error "Need to change SAD call size in highbd_warp_error"
170*77c1e3ccSAndroid Build Coastguard Worker #endif // WARP_ERROR_BLOCK != 32
highbd_warp_error(WarpedMotionParams * wm,const uint16_t * const ref,int ref_width,int ref_height,int ref_stride,const uint16_t * const dst,int dst_stride,int p_col,int p_row,int p_width,int p_height,int subsampling_x,int subsampling_y,int bd,int64_t best_error,uint8_t * segment_map,int segment_map_stride)171*77c1e3ccSAndroid Build Coastguard Worker static int64_t highbd_warp_error(WarpedMotionParams *wm,
172*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *const ref, int ref_width,
173*77c1e3ccSAndroid Build Coastguard Worker int ref_height, int ref_stride,
174*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *const dst, int dst_stride,
175*77c1e3ccSAndroid Build Coastguard Worker int p_col, int p_row, int p_width,
176*77c1e3ccSAndroid Build Coastguard Worker int p_height, int subsampling_x,
177*77c1e3ccSAndroid Build Coastguard Worker int subsampling_y, int bd, int64_t best_error,
178*77c1e3ccSAndroid Build Coastguard Worker uint8_t *segment_map, int segment_map_stride) {
179*77c1e3ccSAndroid Build Coastguard Worker int64_t gm_sumerr = 0;
180*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK);
181*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK);
182*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, uint16_t, tmp[WARP_ERROR_BLOCK * WARP_ERROR_BLOCK]);
183*77c1e3ccSAndroid Build Coastguard Worker
184*77c1e3ccSAndroid Build Coastguard Worker ConvolveParams conv_params = get_conv_params(0, 0, bd);
185*77c1e3ccSAndroid Build Coastguard Worker conv_params.use_dist_wtd_comp_avg = 0;
186*77c1e3ccSAndroid Build Coastguard Worker for (int i = p_row; i < p_row + p_height; i += WARP_ERROR_BLOCK) {
187*77c1e3ccSAndroid Build Coastguard Worker for (int j = p_col; j < p_col + p_width; j += WARP_ERROR_BLOCK) {
188*77c1e3ccSAndroid Build Coastguard Worker int seg_x = j >> WARP_ERROR_BLOCK_LOG;
189*77c1e3ccSAndroid Build Coastguard Worker int seg_y = i >> WARP_ERROR_BLOCK_LOG;
190*77c1e3ccSAndroid Build Coastguard Worker // Only compute the error if this block contains inliers from the motion
191*77c1e3ccSAndroid Build Coastguard Worker // model
192*77c1e3ccSAndroid Build Coastguard Worker if (!segment_map[seg_y * segment_map_stride + seg_x]) continue;
193*77c1e3ccSAndroid Build Coastguard Worker // avoid warping extra 8x8 blocks in the padded region of the frame
194*77c1e3ccSAndroid Build Coastguard Worker // when p_width and p_height are not multiples of WARP_ERROR_BLOCK
195*77c1e3ccSAndroid Build Coastguard Worker const int warp_w = AOMMIN(error_bsize_w, p_col + ref_width - j);
196*77c1e3ccSAndroid Build Coastguard Worker const int warp_h = AOMMIN(error_bsize_h, p_row + ref_height - i);
197*77c1e3ccSAndroid Build Coastguard Worker highbd_warp_plane(wm, ref, ref_width, ref_height, ref_stride, tmp, j, i,
198*77c1e3ccSAndroid Build Coastguard Worker warp_w, warp_h, WARP_ERROR_BLOCK, subsampling_x,
199*77c1e3ccSAndroid Build Coastguard Worker subsampling_y, bd, &conv_params);
200*77c1e3ccSAndroid Build Coastguard Worker
201*77c1e3ccSAndroid Build Coastguard Worker if (warp_w == WARP_ERROR_BLOCK && warp_h == WARP_ERROR_BLOCK) {
202*77c1e3ccSAndroid Build Coastguard Worker gm_sumerr += aom_highbd_sad32x32(
203*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_BYTEPTR(tmp), WARP_ERROR_BLOCK,
204*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_BYTEPTR(dst + j + i * dst_stride), dst_stride);
205*77c1e3ccSAndroid Build Coastguard Worker } else {
206*77c1e3ccSAndroid Build Coastguard Worker gm_sumerr +=
207*77c1e3ccSAndroid Build Coastguard Worker generic_sad_highbd(tmp, WARP_ERROR_BLOCK, dst + j + i * dst_stride,
208*77c1e3ccSAndroid Build Coastguard Worker dst_stride, warp_w, warp_h);
209*77c1e3ccSAndroid Build Coastguard Worker }
210*77c1e3ccSAndroid Build Coastguard Worker
211*77c1e3ccSAndroid Build Coastguard Worker if (gm_sumerr > best_error) return INT64_MAX;
212*77c1e3ccSAndroid Build Coastguard Worker }
213*77c1e3ccSAndroid Build Coastguard Worker }
214*77c1e3ccSAndroid Build Coastguard Worker return gm_sumerr;
215*77c1e3ccSAndroid Build Coastguard Worker }
216*77c1e3ccSAndroid Build Coastguard Worker #endif
217*77c1e3ccSAndroid Build Coastguard Worker
generic_sad(const uint8_t * const ref,int ref_stride,const uint8_t * const dst,int dst_stride,int p_width,int p_height)218*77c1e3ccSAndroid Build Coastguard Worker static inline int generic_sad(const uint8_t *const ref, int ref_stride,
219*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *const dst, int dst_stride,
220*77c1e3ccSAndroid Build Coastguard Worker int p_width, int p_height) {
221*77c1e3ccSAndroid Build Coastguard Worker // This function should only be called for patches smaller than
222*77c1e3ccSAndroid Build Coastguard Worker // WARP_ERROR_BLOCK x WARP_ERROR_BLOCK. This keeps the number of pixels
223*77c1e3ccSAndroid Build Coastguard Worker // small enough that we don't need a 64-bit accumulator
224*77c1e3ccSAndroid Build Coastguard Worker assert(p_width <= WARP_ERROR_BLOCK && p_height <= WARP_ERROR_BLOCK);
225*77c1e3ccSAndroid Build Coastguard Worker
226*77c1e3ccSAndroid Build Coastguard Worker int sad = 0;
227*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < p_height; ++i) {
228*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < p_width; ++j) {
229*77c1e3ccSAndroid Build Coastguard Worker sad += abs(dst[j + i * dst_stride] - ref[j + i * ref_stride]);
230*77c1e3ccSAndroid Build Coastguard Worker }
231*77c1e3ccSAndroid Build Coastguard Worker }
232*77c1e3ccSAndroid Build Coastguard Worker return sad;
233*77c1e3ccSAndroid Build Coastguard Worker }
234*77c1e3ccSAndroid Build Coastguard Worker
235*77c1e3ccSAndroid Build Coastguard Worker #if WARP_ERROR_BLOCK != 32
236*77c1e3ccSAndroid Build Coastguard Worker #error "Need to change SAD call size in segmented_warp_error"
237*77c1e3ccSAndroid Build Coastguard Worker #endif // WARP_ERROR_BLOCK != 32
segmented_frame_error(const uint8_t * const ref,int ref_stride,const uint8_t * const dst,int dst_stride,int p_width,int p_height,uint8_t * segment_map,int segment_map_stride)238*77c1e3ccSAndroid Build Coastguard Worker static int64_t segmented_frame_error(const uint8_t *const ref, int ref_stride,
239*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *const dst, int dst_stride,
240*77c1e3ccSAndroid Build Coastguard Worker int p_width, int p_height,
241*77c1e3ccSAndroid Build Coastguard Worker uint8_t *segment_map,
242*77c1e3ccSAndroid Build Coastguard Worker int segment_map_stride) {
243*77c1e3ccSAndroid Build Coastguard Worker int patch_w, patch_h;
244*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK);
245*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK);
246*77c1e3ccSAndroid Build Coastguard Worker int64_t sum_error = 0;
247*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < p_height; i += WARP_ERROR_BLOCK) {
248*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < p_width; j += WARP_ERROR_BLOCK) {
249*77c1e3ccSAndroid Build Coastguard Worker int seg_x = j >> WARP_ERROR_BLOCK_LOG;
250*77c1e3ccSAndroid Build Coastguard Worker int seg_y = i >> WARP_ERROR_BLOCK_LOG;
251*77c1e3ccSAndroid Build Coastguard Worker // Only compute the error if this block contains inliers from the motion
252*77c1e3ccSAndroid Build Coastguard Worker // model
253*77c1e3ccSAndroid Build Coastguard Worker if (!segment_map[seg_y * segment_map_stride + seg_x]) continue;
254*77c1e3ccSAndroid Build Coastguard Worker
255*77c1e3ccSAndroid Build Coastguard Worker // avoid computing error into the frame padding
256*77c1e3ccSAndroid Build Coastguard Worker patch_w = AOMMIN(error_bsize_w, p_width - j);
257*77c1e3ccSAndroid Build Coastguard Worker patch_h = AOMMIN(error_bsize_h, p_height - i);
258*77c1e3ccSAndroid Build Coastguard Worker
259*77c1e3ccSAndroid Build Coastguard Worker if (patch_w == WARP_ERROR_BLOCK && patch_h == WARP_ERROR_BLOCK) {
260*77c1e3ccSAndroid Build Coastguard Worker sum_error += aom_sad32x32(ref + j + i * ref_stride, ref_stride,
261*77c1e3ccSAndroid Build Coastguard Worker dst + j + i * dst_stride, dst_stride);
262*77c1e3ccSAndroid Build Coastguard Worker } else {
263*77c1e3ccSAndroid Build Coastguard Worker sum_error +=
264*77c1e3ccSAndroid Build Coastguard Worker generic_sad(ref + j + i * ref_stride, ref_stride,
265*77c1e3ccSAndroid Build Coastguard Worker dst + j + i * dst_stride, dst_stride, patch_w, patch_h);
266*77c1e3ccSAndroid Build Coastguard Worker }
267*77c1e3ccSAndroid Build Coastguard Worker }
268*77c1e3ccSAndroid Build Coastguard Worker }
269*77c1e3ccSAndroid Build Coastguard Worker return sum_error;
270*77c1e3ccSAndroid Build Coastguard Worker }
271*77c1e3ccSAndroid Build Coastguard Worker
272*77c1e3ccSAndroid Build Coastguard Worker #if WARP_ERROR_BLOCK != 32
273*77c1e3ccSAndroid Build Coastguard Worker #error "Need to change SAD call size in warp_error"
274*77c1e3ccSAndroid Build Coastguard Worker #endif // WARP_ERROR_BLOCK != 32
warp_error(WarpedMotionParams * wm,const uint8_t * const ref,int ref_width,int ref_height,int ref_stride,const uint8_t * const dst,int dst_stride,int p_col,int p_row,int p_width,int p_height,int subsampling_x,int subsampling_y,int64_t best_error,uint8_t * segment_map,int segment_map_stride)275*77c1e3ccSAndroid Build Coastguard Worker static int64_t warp_error(WarpedMotionParams *wm, const uint8_t *const ref,
276*77c1e3ccSAndroid Build Coastguard Worker int ref_width, int ref_height, int ref_stride,
277*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *const dst, int dst_stride, int p_col,
278*77c1e3ccSAndroid Build Coastguard Worker int p_row, int p_width, int p_height,
279*77c1e3ccSAndroid Build Coastguard Worker int subsampling_x, int subsampling_y,
280*77c1e3ccSAndroid Build Coastguard Worker int64_t best_error, uint8_t *segment_map,
281*77c1e3ccSAndroid Build Coastguard Worker int segment_map_stride) {
282*77c1e3ccSAndroid Build Coastguard Worker int64_t gm_sumerr = 0;
283*77c1e3ccSAndroid Build Coastguard Worker int warp_w, warp_h;
284*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK);
285*77c1e3ccSAndroid Build Coastguard Worker const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK);
286*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, uint8_t, tmp[WARP_ERROR_BLOCK * WARP_ERROR_BLOCK]);
287*77c1e3ccSAndroid Build Coastguard Worker ConvolveParams conv_params = get_conv_params(0, 0, 8);
288*77c1e3ccSAndroid Build Coastguard Worker conv_params.use_dist_wtd_comp_avg = 0;
289*77c1e3ccSAndroid Build Coastguard Worker
290*77c1e3ccSAndroid Build Coastguard Worker for (int i = p_row; i < p_row + p_height; i += WARP_ERROR_BLOCK) {
291*77c1e3ccSAndroid Build Coastguard Worker for (int j = p_col; j < p_col + p_width; j += WARP_ERROR_BLOCK) {
292*77c1e3ccSAndroid Build Coastguard Worker int seg_x = j >> WARP_ERROR_BLOCK_LOG;
293*77c1e3ccSAndroid Build Coastguard Worker int seg_y = i >> WARP_ERROR_BLOCK_LOG;
294*77c1e3ccSAndroid Build Coastguard Worker // Only compute the error if this block contains inliers from the motion
295*77c1e3ccSAndroid Build Coastguard Worker // model
296*77c1e3ccSAndroid Build Coastguard Worker if (!segment_map[seg_y * segment_map_stride + seg_x]) continue;
297*77c1e3ccSAndroid Build Coastguard Worker // avoid warping extra 8x8 blocks in the padded region of the frame
298*77c1e3ccSAndroid Build Coastguard Worker // when p_width and p_height are not multiples of WARP_ERROR_BLOCK
299*77c1e3ccSAndroid Build Coastguard Worker warp_w = AOMMIN(error_bsize_w, p_col + ref_width - j);
300*77c1e3ccSAndroid Build Coastguard Worker warp_h = AOMMIN(error_bsize_h, p_row + ref_height - i);
301*77c1e3ccSAndroid Build Coastguard Worker warp_plane(wm, ref, ref_width, ref_height, ref_stride, tmp, j, i, warp_w,
302*77c1e3ccSAndroid Build Coastguard Worker warp_h, WARP_ERROR_BLOCK, subsampling_x, subsampling_y,
303*77c1e3ccSAndroid Build Coastguard Worker &conv_params);
304*77c1e3ccSAndroid Build Coastguard Worker
305*77c1e3ccSAndroid Build Coastguard Worker if (warp_w == WARP_ERROR_BLOCK && warp_h == WARP_ERROR_BLOCK) {
306*77c1e3ccSAndroid Build Coastguard Worker gm_sumerr += aom_sad32x32(tmp, WARP_ERROR_BLOCK,
307*77c1e3ccSAndroid Build Coastguard Worker dst + j + i * dst_stride, dst_stride);
308*77c1e3ccSAndroid Build Coastguard Worker } else {
309*77c1e3ccSAndroid Build Coastguard Worker gm_sumerr +=
310*77c1e3ccSAndroid Build Coastguard Worker generic_sad(tmp, WARP_ERROR_BLOCK, dst + j + i * dst_stride,
311*77c1e3ccSAndroid Build Coastguard Worker dst_stride, warp_w, warp_h);
312*77c1e3ccSAndroid Build Coastguard Worker }
313*77c1e3ccSAndroid Build Coastguard Worker
314*77c1e3ccSAndroid Build Coastguard Worker if (gm_sumerr > best_error) return INT64_MAX;
315*77c1e3ccSAndroid Build Coastguard Worker }
316*77c1e3ccSAndroid Build Coastguard Worker }
317*77c1e3ccSAndroid Build Coastguard Worker return gm_sumerr;
318*77c1e3ccSAndroid Build Coastguard Worker }
319*77c1e3ccSAndroid Build Coastguard Worker
av1_segmented_frame_error(int use_hbd,int bd,const uint8_t * ref,int ref_stride,uint8_t * dst,int dst_stride,int p_width,int p_height,uint8_t * segment_map,int segment_map_stride)320*77c1e3ccSAndroid Build Coastguard Worker int64_t av1_segmented_frame_error(int use_hbd, int bd, const uint8_t *ref,
321*77c1e3ccSAndroid Build Coastguard Worker int ref_stride, uint8_t *dst, int dst_stride,
322*77c1e3ccSAndroid Build Coastguard Worker int p_width, int p_height,
323*77c1e3ccSAndroid Build Coastguard Worker uint8_t *segment_map,
324*77c1e3ccSAndroid Build Coastguard Worker int segment_map_stride) {
325*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
326*77c1e3ccSAndroid Build Coastguard Worker if (use_hbd) {
327*77c1e3ccSAndroid Build Coastguard Worker return highbd_segmented_frame_error(
328*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_SHORTPTR(ref), ref_stride, CONVERT_TO_SHORTPTR(dst),
329*77c1e3ccSAndroid Build Coastguard Worker dst_stride, p_width, p_height, bd, segment_map, segment_map_stride);
330*77c1e3ccSAndroid Build Coastguard Worker }
331*77c1e3ccSAndroid Build Coastguard Worker #endif
332*77c1e3ccSAndroid Build Coastguard Worker (void)use_hbd;
333*77c1e3ccSAndroid Build Coastguard Worker (void)bd;
334*77c1e3ccSAndroid Build Coastguard Worker return segmented_frame_error(ref, ref_stride, dst, dst_stride, p_width,
335*77c1e3ccSAndroid Build Coastguard Worker p_height, segment_map, segment_map_stride);
336*77c1e3ccSAndroid Build Coastguard Worker }
337*77c1e3ccSAndroid Build Coastguard Worker
338*77c1e3ccSAndroid Build Coastguard Worker // Returns the error between the result of applying motion 'wm' to the frame
339*77c1e3ccSAndroid Build Coastguard Worker // described by 'ref' and the frame described by 'dst'.
get_warp_error(WarpedMotionParams * wm,int use_hbd,int bd,const uint8_t * ref,int ref_width,int ref_height,int ref_stride,uint8_t * dst,int dst_stride,int p_col,int p_row,int p_width,int p_height,int subsampling_x,int subsampling_y,int64_t best_error,uint8_t * segment_map,int segment_map_stride)340*77c1e3ccSAndroid Build Coastguard Worker static int64_t get_warp_error(WarpedMotionParams *wm, int use_hbd, int bd,
341*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *ref, int ref_width, int ref_height,
342*77c1e3ccSAndroid Build Coastguard Worker int ref_stride, uint8_t *dst, int dst_stride,
343*77c1e3ccSAndroid Build Coastguard Worker int p_col, int p_row, int p_width, int p_height,
344*77c1e3ccSAndroid Build Coastguard Worker int subsampling_x, int subsampling_y,
345*77c1e3ccSAndroid Build Coastguard Worker int64_t best_error, uint8_t *segment_map,
346*77c1e3ccSAndroid Build Coastguard Worker int segment_map_stride) {
347*77c1e3ccSAndroid Build Coastguard Worker if (!av1_get_shear_params(wm)) return INT64_MAX;
348*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
349*77c1e3ccSAndroid Build Coastguard Worker if (use_hbd)
350*77c1e3ccSAndroid Build Coastguard Worker return highbd_warp_error(wm, CONVERT_TO_SHORTPTR(ref), ref_width,
351*77c1e3ccSAndroid Build Coastguard Worker ref_height, ref_stride, CONVERT_TO_SHORTPTR(dst),
352*77c1e3ccSAndroid Build Coastguard Worker dst_stride, p_col, p_row, p_width, p_height,
353*77c1e3ccSAndroid Build Coastguard Worker subsampling_x, subsampling_y, bd, best_error,
354*77c1e3ccSAndroid Build Coastguard Worker segment_map, segment_map_stride);
355*77c1e3ccSAndroid Build Coastguard Worker #endif
356*77c1e3ccSAndroid Build Coastguard Worker (void)use_hbd;
357*77c1e3ccSAndroid Build Coastguard Worker (void)bd;
358*77c1e3ccSAndroid Build Coastguard Worker return warp_error(wm, ref, ref_width, ref_height, ref_stride, dst, dst_stride,
359*77c1e3ccSAndroid Build Coastguard Worker p_col, p_row, p_width, p_height, subsampling_x,
360*77c1e3ccSAndroid Build Coastguard Worker subsampling_y, best_error, segment_map, segment_map_stride);
361*77c1e3ccSAndroid Build Coastguard Worker }
362*77c1e3ccSAndroid Build Coastguard Worker
av1_refine_integerized_param(WarpedMotionParams * wm,TransformationType wmtype,int use_hbd,int bd,uint8_t * ref,int r_width,int r_height,int r_stride,uint8_t * dst,int d_width,int d_height,int d_stride,int n_refinements,int64_t ref_frame_error,uint8_t * segment_map,int segment_map_stride)363*77c1e3ccSAndroid Build Coastguard Worker int64_t av1_refine_integerized_param(
364*77c1e3ccSAndroid Build Coastguard Worker WarpedMotionParams *wm, TransformationType wmtype, int use_hbd, int bd,
365*77c1e3ccSAndroid Build Coastguard Worker uint8_t *ref, int r_width, int r_height, int r_stride, uint8_t *dst,
366*77c1e3ccSAndroid Build Coastguard Worker int d_width, int d_height, int d_stride, int n_refinements,
367*77c1e3ccSAndroid Build Coastguard Worker int64_t ref_frame_error, uint8_t *segment_map, int segment_map_stride) {
368*77c1e3ccSAndroid Build Coastguard Worker static const int max_trans_model_params[TRANS_TYPES] = { 0, 2, 4, 6 };
369*77c1e3ccSAndroid Build Coastguard Worker const int border = ERRORADV_BORDER;
370*77c1e3ccSAndroid Build Coastguard Worker int i = 0, p;
371*77c1e3ccSAndroid Build Coastguard Worker int n_params = max_trans_model_params[wmtype];
372*77c1e3ccSAndroid Build Coastguard Worker int32_t *param_mat = wm->wmmat;
373*77c1e3ccSAndroid Build Coastguard Worker int64_t step_error, best_error;
374*77c1e3ccSAndroid Build Coastguard Worker int32_t step;
375*77c1e3ccSAndroid Build Coastguard Worker int32_t *param;
376*77c1e3ccSAndroid Build Coastguard Worker int32_t curr_param;
377*77c1e3ccSAndroid Build Coastguard Worker int32_t best_param;
378*77c1e3ccSAndroid Build Coastguard Worker
379*77c1e3ccSAndroid Build Coastguard Worker force_wmtype(wm, wmtype);
380*77c1e3ccSAndroid Build Coastguard Worker wm->wmtype = get_wmtype(wm);
381*77c1e3ccSAndroid Build Coastguard Worker
382*77c1e3ccSAndroid Build Coastguard Worker if (n_refinements == 0) {
383*77c1e3ccSAndroid Build Coastguard Worker // Compute the maximum error value that will be accepted, so that
384*77c1e3ccSAndroid Build Coastguard Worker // get_warp_error can terminate early if it proves the model will not
385*77c1e3ccSAndroid Build Coastguard Worker // be accepted.
386*77c1e3ccSAndroid Build Coastguard Worker int64_t selection_threshold = (int64_t)lrint(ref_frame_error * erroradv_tr);
387*77c1e3ccSAndroid Build Coastguard Worker return get_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
388*77c1e3ccSAndroid Build Coastguard Worker dst + border * d_stride + border, d_stride, border,
389*77c1e3ccSAndroid Build Coastguard Worker border, d_width - 2 * border, d_height - 2 * border,
390*77c1e3ccSAndroid Build Coastguard Worker 0, 0, selection_threshold, segment_map,
391*77c1e3ccSAndroid Build Coastguard Worker segment_map_stride);
392*77c1e3ccSAndroid Build Coastguard Worker }
393*77c1e3ccSAndroid Build Coastguard Worker
394*77c1e3ccSAndroid Build Coastguard Worker // When refining, use a slightly higher threshold for the initial error
395*77c1e3ccSAndroid Build Coastguard Worker // calculation - see comment above erroradv_early_tr for why.
396*77c1e3ccSAndroid Build Coastguard Worker int64_t selection_threshold =
397*77c1e3ccSAndroid Build Coastguard Worker (int64_t)lrint(ref_frame_error * erroradv_early_tr);
398*77c1e3ccSAndroid Build Coastguard Worker best_error =
399*77c1e3ccSAndroid Build Coastguard Worker get_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
400*77c1e3ccSAndroid Build Coastguard Worker dst + border * d_stride + border, d_stride, border, border,
401*77c1e3ccSAndroid Build Coastguard Worker d_width - 2 * border, d_height - 2 * border, 0, 0,
402*77c1e3ccSAndroid Build Coastguard Worker selection_threshold, segment_map, segment_map_stride);
403*77c1e3ccSAndroid Build Coastguard Worker
404*77c1e3ccSAndroid Build Coastguard Worker if (best_error > selection_threshold) {
405*77c1e3ccSAndroid Build Coastguard Worker return INT64_MAX;
406*77c1e3ccSAndroid Build Coastguard Worker }
407*77c1e3ccSAndroid Build Coastguard Worker
408*77c1e3ccSAndroid Build Coastguard Worker step = 1 << (n_refinements - 1);
409*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < n_refinements; i++, step >>= 1) {
410*77c1e3ccSAndroid Build Coastguard Worker for (p = 0; p < n_params; ++p) {
411*77c1e3ccSAndroid Build Coastguard Worker int step_dir = 0;
412*77c1e3ccSAndroid Build Coastguard Worker param = param_mat + p;
413*77c1e3ccSAndroid Build Coastguard Worker curr_param = *param;
414*77c1e3ccSAndroid Build Coastguard Worker best_param = curr_param;
415*77c1e3ccSAndroid Build Coastguard Worker // look to the left
416*77c1e3ccSAndroid Build Coastguard Worker // Note: We have to use force_wmtype() to keep the proper symmetry for
417*77c1e3ccSAndroid Build Coastguard Worker // ROTZOOM type models
418*77c1e3ccSAndroid Build Coastguard Worker *param = add_param_offset(p, curr_param, -step);
419*77c1e3ccSAndroid Build Coastguard Worker force_wmtype(wm, wmtype);
420*77c1e3ccSAndroid Build Coastguard Worker step_error =
421*77c1e3ccSAndroid Build Coastguard Worker get_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
422*77c1e3ccSAndroid Build Coastguard Worker dst + border * d_stride + border, d_stride, border,
423*77c1e3ccSAndroid Build Coastguard Worker border, d_width - 2 * border, d_height - 2 * border, 0,
424*77c1e3ccSAndroid Build Coastguard Worker 0, best_error, segment_map, segment_map_stride);
425*77c1e3ccSAndroid Build Coastguard Worker if (step_error < best_error) {
426*77c1e3ccSAndroid Build Coastguard Worker best_error = step_error;
427*77c1e3ccSAndroid Build Coastguard Worker best_param = *param;
428*77c1e3ccSAndroid Build Coastguard Worker step_dir = -1;
429*77c1e3ccSAndroid Build Coastguard Worker }
430*77c1e3ccSAndroid Build Coastguard Worker
431*77c1e3ccSAndroid Build Coastguard Worker // look to the right
432*77c1e3ccSAndroid Build Coastguard Worker *param = add_param_offset(p, curr_param, step);
433*77c1e3ccSAndroid Build Coastguard Worker force_wmtype(wm, wmtype);
434*77c1e3ccSAndroid Build Coastguard Worker step_error =
435*77c1e3ccSAndroid Build Coastguard Worker get_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
436*77c1e3ccSAndroid Build Coastguard Worker dst + border * d_stride + border, d_stride, border,
437*77c1e3ccSAndroid Build Coastguard Worker border, d_width - 2 * border, d_height - 2 * border, 0,
438*77c1e3ccSAndroid Build Coastguard Worker 0, best_error, segment_map, segment_map_stride);
439*77c1e3ccSAndroid Build Coastguard Worker if (step_error < best_error) {
440*77c1e3ccSAndroid Build Coastguard Worker best_error = step_error;
441*77c1e3ccSAndroid Build Coastguard Worker best_param = *param;
442*77c1e3ccSAndroid Build Coastguard Worker step_dir = 1;
443*77c1e3ccSAndroid Build Coastguard Worker }
444*77c1e3ccSAndroid Build Coastguard Worker
445*77c1e3ccSAndroid Build Coastguard Worker // look to the direction chosen above repeatedly until error increases
446*77c1e3ccSAndroid Build Coastguard Worker // for the biggest step size
447*77c1e3ccSAndroid Build Coastguard Worker while (step_dir) {
448*77c1e3ccSAndroid Build Coastguard Worker *param = add_param_offset(p, best_param, step * step_dir);
449*77c1e3ccSAndroid Build Coastguard Worker force_wmtype(wm, wmtype);
450*77c1e3ccSAndroid Build Coastguard Worker step_error =
451*77c1e3ccSAndroid Build Coastguard Worker get_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride,
452*77c1e3ccSAndroid Build Coastguard Worker dst + border * d_stride + border, d_stride, border,
453*77c1e3ccSAndroid Build Coastguard Worker border, d_width - 2 * border, d_height - 2 * border,
454*77c1e3ccSAndroid Build Coastguard Worker 0, 0, best_error, segment_map, segment_map_stride);
455*77c1e3ccSAndroid Build Coastguard Worker if (step_error < best_error) {
456*77c1e3ccSAndroid Build Coastguard Worker best_error = step_error;
457*77c1e3ccSAndroid Build Coastguard Worker best_param = *param;
458*77c1e3ccSAndroid Build Coastguard Worker } else {
459*77c1e3ccSAndroid Build Coastguard Worker step_dir = 0;
460*77c1e3ccSAndroid Build Coastguard Worker }
461*77c1e3ccSAndroid Build Coastguard Worker }
462*77c1e3ccSAndroid Build Coastguard Worker
463*77c1e3ccSAndroid Build Coastguard Worker // Restore best parameter value so far
464*77c1e3ccSAndroid Build Coastguard Worker *param = best_param;
465*77c1e3ccSAndroid Build Coastguard Worker force_wmtype(wm, wmtype);
466*77c1e3ccSAndroid Build Coastguard Worker }
467*77c1e3ccSAndroid Build Coastguard Worker }
468*77c1e3ccSAndroid Build Coastguard Worker
469*77c1e3ccSAndroid Build Coastguard Worker wm->wmtype = get_wmtype(wm);
470*77c1e3ccSAndroid Build Coastguard Worker // Recompute shear params for the refined model
471*77c1e3ccSAndroid Build Coastguard Worker // This should never fail, because we only ever consider warp-able models
472*77c1e3ccSAndroid Build Coastguard Worker if (!av1_get_shear_params(wm)) {
473*77c1e3ccSAndroid Build Coastguard Worker assert(0);
474*77c1e3ccSAndroid Build Coastguard Worker }
475*77c1e3ccSAndroid Build Coastguard Worker return best_error;
476*77c1e3ccSAndroid Build Coastguard Worker }
477*77c1e3ccSAndroid Build Coastguard Worker
478*77c1e3ccSAndroid Build Coastguard Worker #define FEAT_COUNT_TR 3
479*77c1e3ccSAndroid Build Coastguard Worker #define SEG_COUNT_TR 48
av1_compute_feature_segmentation_map(uint8_t * segment_map,int width,int height,int * inliers,int num_inliers)480*77c1e3ccSAndroid Build Coastguard Worker void av1_compute_feature_segmentation_map(uint8_t *segment_map, int width,
481*77c1e3ccSAndroid Build Coastguard Worker int height, int *inliers,
482*77c1e3ccSAndroid Build Coastguard Worker int num_inliers) {
483*77c1e3ccSAndroid Build Coastguard Worker int seg_count = 0;
484*77c1e3ccSAndroid Build Coastguard Worker memset(segment_map, 0, sizeof(*segment_map) * width * height);
485*77c1e3ccSAndroid Build Coastguard Worker
486*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < num_inliers; i++) {
487*77c1e3ccSAndroid Build Coastguard Worker int x = inliers[i * 2];
488*77c1e3ccSAndroid Build Coastguard Worker int y = inliers[i * 2 + 1];
489*77c1e3ccSAndroid Build Coastguard Worker int seg_x = x >> WARP_ERROR_BLOCK_LOG;
490*77c1e3ccSAndroid Build Coastguard Worker int seg_y = y >> WARP_ERROR_BLOCK_LOG;
491*77c1e3ccSAndroid Build Coastguard Worker segment_map[seg_y * width + seg_x] += 1;
492*77c1e3ccSAndroid Build Coastguard Worker }
493*77c1e3ccSAndroid Build Coastguard Worker
494*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < height; i++) {
495*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < width; j++) {
496*77c1e3ccSAndroid Build Coastguard Worker uint8_t feat_count = segment_map[i * width + j];
497*77c1e3ccSAndroid Build Coastguard Worker segment_map[i * width + j] = (feat_count >= FEAT_COUNT_TR);
498*77c1e3ccSAndroid Build Coastguard Worker seg_count += (segment_map[i * width + j]);
499*77c1e3ccSAndroid Build Coastguard Worker }
500*77c1e3ccSAndroid Build Coastguard Worker }
501*77c1e3ccSAndroid Build Coastguard Worker
502*77c1e3ccSAndroid Build Coastguard Worker // If this motion does not make up a large enough portion of the frame,
503*77c1e3ccSAndroid Build Coastguard Worker // use the unsegmented version of the error metric
504*77c1e3ccSAndroid Build Coastguard Worker if (seg_count < SEG_COUNT_TR)
505*77c1e3ccSAndroid Build Coastguard Worker memset(segment_map, 1, width * height * sizeof(*segment_map));
506*77c1e3ccSAndroid Build Coastguard Worker }
507