1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12 #ifndef AOM_AV1_COMMON_MV_H_
13 #define AOM_AV1_COMMON_MV_H_
14
15 #include <stdlib.h>
16
17 #include "av1/common/common.h"
18 #include "av1/common/common_data.h"
19 #include "aom_dsp/aom_filter.h"
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 #define INVALID_MV 0x80008000
26 #define GET_MV_RAWPEL(x) (((x) + 3 + ((x) >= 0)) >> 3)
27 #define GET_MV_SUBPEL(x) ((x)*8)
28
29 #define MARK_MV_INVALID(mv) \
30 do { \
31 ((int_mv *)(mv))->as_int = INVALID_MV; \
32 } while (0);
33 #define CHECK_MV_EQUAL(x, y) (((x).row == (y).row) && ((x).col == (y).col))
34
35 // The motion vector in units of full pixel
36 typedef struct fullpel_mv {
37 int16_t row;
38 int16_t col;
39 } FULLPEL_MV;
40
41 // The motion vector in units of 1/8-pel
42 typedef struct mv {
43 int16_t row;
44 int16_t col;
45 } MV;
46
47 static const MV kZeroMv = { 0, 0 };
48 static const FULLPEL_MV kZeroFullMv = { 0, 0 };
49
50 typedef union int_mv {
51 uint32_t as_int;
52 MV as_mv;
53 FULLPEL_MV as_fullmv;
54 } int_mv; /* facilitates faster equality tests and copies */
55
56 typedef struct mv32 {
57 int32_t row;
58 int32_t col;
59 } MV32;
60
61 // The mv limit for fullpel mvs
62 typedef struct {
63 int col_min;
64 int col_max;
65 int row_min;
66 int row_max;
67 } FullMvLimits;
68
69 // The mv limit for subpel mvs
70 typedef struct {
71 int col_min;
72 int col_max;
73 int row_min;
74 int row_max;
75 } SubpelMvLimits;
76
get_fullmv_from_mv(const MV * subpel_mv)77 static AOM_INLINE FULLPEL_MV get_fullmv_from_mv(const MV *subpel_mv) {
78 const FULLPEL_MV full_mv = { (int16_t)GET_MV_RAWPEL(subpel_mv->row),
79 (int16_t)GET_MV_RAWPEL(subpel_mv->col) };
80 return full_mv;
81 }
82
get_mv_from_fullmv(const FULLPEL_MV * full_mv)83 static AOM_INLINE MV get_mv_from_fullmv(const FULLPEL_MV *full_mv) {
84 const MV subpel_mv = { (int16_t)GET_MV_SUBPEL(full_mv->row),
85 (int16_t)GET_MV_SUBPEL(full_mv->col) };
86 return subpel_mv;
87 }
88
convert_fullmv_to_mv(int_mv * mv)89 static AOM_INLINE void convert_fullmv_to_mv(int_mv *mv) {
90 mv->as_mv = get_mv_from_fullmv(&mv->as_fullmv);
91 }
92
93 // Bits of precision used for the model
94 #define WARPEDMODEL_PREC_BITS 16
95 #define WARPEDMODEL_ROW3HOMO_PREC_BITS 16
96
97 #define WARPEDMODEL_TRANS_CLAMP (128 << WARPEDMODEL_PREC_BITS)
98 #define WARPEDMODEL_NONDIAGAFFINE_CLAMP (1 << (WARPEDMODEL_PREC_BITS - 3))
99 #define WARPEDMODEL_ROW3HOMO_CLAMP (1 << (WARPEDMODEL_PREC_BITS - 2))
100
101 // Bits of subpel precision for warped interpolation
102 #define WARPEDPIXEL_PREC_BITS 6
103 #define WARPEDPIXEL_PREC_SHIFTS (1 << WARPEDPIXEL_PREC_BITS)
104
105 #define WARP_PARAM_REDUCE_BITS 6
106
107 #define WARPEDDIFF_PREC_BITS (WARPEDMODEL_PREC_BITS - WARPEDPIXEL_PREC_BITS)
108
109 /* clang-format off */
110 enum {
111 IDENTITY = 0, // identity transformation, 0-parameter
112 TRANSLATION = 1, // translational motion 2-parameter
113 ROTZOOM = 2, // simplified affine with rotation + zoom only, 4-parameter
114 AFFINE = 3, // affine, 6-parameter
115 TRANS_TYPES,
116 } UENUM1BYTE(TransformationType);
117 /* clang-format on */
118
119 // Number of types used for global motion (must be >= 3 and <= TRANS_TYPES)
120 // The following can be useful:
121 // GLOBAL_TRANS_TYPES 3 - up to rotation-zoom
122 // GLOBAL_TRANS_TYPES 4 - up to affine
123 // GLOBAL_TRANS_TYPES 6 - up to hor/ver trapezoids
124 // GLOBAL_TRANS_TYPES 7 - up to full homography
125 #define GLOBAL_TRANS_TYPES 4
126
127 typedef struct {
128 int global_warp_allowed;
129 int local_warp_allowed;
130 } WarpTypesAllowed;
131
132 // number of parameters used by each transformation in TransformationTypes
133 static const int trans_model_params[TRANS_TYPES] = { 0, 2, 4, 6 };
134
135 // The order of values in the wmmat matrix below is best described
136 // by the homography:
137 // [x' (m2 m3 m0 [x
138 // z . y' = m4 m5 m1 * y
139 // 1] m6 m7 1) 1]
140 typedef struct {
141 int32_t wmmat[8];
142 int16_t alpha, beta, gamma, delta;
143 TransformationType wmtype;
144 int8_t invalid;
145 } WarpedMotionParams;
146
147 /* clang-format off */
148 static const WarpedMotionParams default_warp_params = {
149 { 0, 0, (1 << WARPEDMODEL_PREC_BITS), 0, 0, (1 << WARPEDMODEL_PREC_BITS), 0,
150 0 },
151 0, 0, 0, 0,
152 IDENTITY,
153 0,
154 };
155 /* clang-format on */
156
157 // The following constants describe the various precisions
158 // of different parameters in the global motion experiment.
159 //
160 // Given the general homography:
161 // [x' (a b c [x
162 // z . y' = d e f * y
163 // 1] g h i) 1]
164 //
165 // Constants using the name ALPHA here are related to parameters
166 // a, b, d, e. Constants using the name TRANS are related
167 // to parameters c and f.
168 //
169 // Anything ending in PREC_BITS is the number of bits of precision
170 // to maintain when converting from double to integer.
171 //
172 // The ABS parameters are used to create an upper and lower bound
173 // for each parameter. In other words, after a parameter is integerized
174 // it is clamped between -(1 << ABS_XXX_BITS) and (1 << ABS_XXX_BITS).
175 //
176 // XXX_PREC_DIFF and XXX_DECODE_FACTOR
177 // are computed once here to prevent repetitive
178 // computation on the decoder side. These are
179 // to allow the global motion parameters to be encoded in a lower
180 // precision than the warped model precision. This means that they
181 // need to be changed to warped precision when they are decoded.
182 //
183 // XX_MIN, XX_MAX are also computed to avoid repeated computation
184
185 #define SUBEXPFIN_K 3
186 #define GM_TRANS_PREC_BITS 6
187 #define GM_ABS_TRANS_BITS 12
188 #define GM_ABS_TRANS_ONLY_BITS (GM_ABS_TRANS_BITS - GM_TRANS_PREC_BITS + 3)
189 #define GM_TRANS_PREC_DIFF (WARPEDMODEL_PREC_BITS - GM_TRANS_PREC_BITS)
190 #define GM_TRANS_ONLY_PREC_DIFF (WARPEDMODEL_PREC_BITS - 3)
191 #define GM_TRANS_DECODE_FACTOR (1 << GM_TRANS_PREC_DIFF)
192 #define GM_TRANS_ONLY_DECODE_FACTOR (1 << GM_TRANS_ONLY_PREC_DIFF)
193
194 #define GM_ALPHA_PREC_BITS 15
195 #define GM_ABS_ALPHA_BITS 12
196 #define GM_ALPHA_PREC_DIFF (WARPEDMODEL_PREC_BITS - GM_ALPHA_PREC_BITS)
197 #define GM_ALPHA_DECODE_FACTOR (1 << GM_ALPHA_PREC_DIFF)
198
199 #define GM_ROW3HOMO_PREC_BITS 16
200 #define GM_ABS_ROW3HOMO_BITS 11
201 #define GM_ROW3HOMO_PREC_DIFF \
202 (WARPEDMODEL_ROW3HOMO_PREC_BITS - GM_ROW3HOMO_PREC_BITS)
203 #define GM_ROW3HOMO_DECODE_FACTOR (1 << GM_ROW3HOMO_PREC_DIFF)
204
205 #define GM_TRANS_MAX (1 << GM_ABS_TRANS_BITS)
206 #define GM_ALPHA_MAX (1 << GM_ABS_ALPHA_BITS)
207 #define GM_ROW3HOMO_MAX (1 << GM_ABS_ROW3HOMO_BITS)
208
209 #define GM_TRANS_MIN -GM_TRANS_MAX
210 #define GM_ALPHA_MIN -GM_ALPHA_MAX
211 #define GM_ROW3HOMO_MIN -GM_ROW3HOMO_MAX
212
block_center_x(int mi_col,BLOCK_SIZE bs)213 static INLINE int block_center_x(int mi_col, BLOCK_SIZE bs) {
214 const int bw = block_size_wide[bs];
215 return mi_col * MI_SIZE + bw / 2 - 1;
216 }
217
block_center_y(int mi_row,BLOCK_SIZE bs)218 static INLINE int block_center_y(int mi_row, BLOCK_SIZE bs) {
219 const int bh = block_size_high[bs];
220 return mi_row * MI_SIZE + bh / 2 - 1;
221 }
222
convert_to_trans_prec(int allow_hp,int coor)223 static INLINE int convert_to_trans_prec(int allow_hp, int coor) {
224 if (allow_hp)
225 return ROUND_POWER_OF_TWO_SIGNED(coor, WARPEDMODEL_PREC_BITS - 3);
226 else
227 return ROUND_POWER_OF_TWO_SIGNED(coor, WARPEDMODEL_PREC_BITS - 2) * 2;
228 }
integer_mv_precision(MV * mv)229 static INLINE void integer_mv_precision(MV *mv) {
230 int mod = (mv->row % 8);
231 if (mod != 0) {
232 mv->row -= mod;
233 if (abs(mod) > 4) {
234 if (mod > 0) {
235 mv->row += 8;
236 } else {
237 mv->row -= 8;
238 }
239 }
240 }
241
242 mod = (mv->col % 8);
243 if (mod != 0) {
244 mv->col -= mod;
245 if (abs(mod) > 4) {
246 if (mod > 0) {
247 mv->col += 8;
248 } else {
249 mv->col -= 8;
250 }
251 }
252 }
253 }
254 // Convert a global motion vector into a motion vector at the centre of the
255 // given block.
256 //
257 // The resulting motion vector will have three fractional bits of precision. If
258 // allow_hp is zero, the bottom bit will always be zero. If CONFIG_AMVR and
259 // is_integer is true, the bottom three bits will be zero (so the motion vector
260 // represents an integer)
gm_get_motion_vector(const WarpedMotionParams * gm,int allow_hp,BLOCK_SIZE bsize,int mi_col,int mi_row,int is_integer)261 static INLINE int_mv gm_get_motion_vector(const WarpedMotionParams *gm,
262 int allow_hp, BLOCK_SIZE bsize,
263 int mi_col, int mi_row,
264 int is_integer) {
265 int_mv res;
266
267 if (gm->wmtype == IDENTITY) {
268 res.as_int = 0;
269 return res;
270 }
271
272 const int32_t *mat = gm->wmmat;
273 int x, y, tx, ty;
274
275 if (gm->wmtype == TRANSLATION) {
276 // All global motion vectors are stored with WARPEDMODEL_PREC_BITS (16)
277 // bits of fractional precision. The offset for a translation is stored in
278 // entries 0 and 1. For translations, all but the top three (two if
279 // cm->features.allow_high_precision_mv is false) fractional bits are always
280 // zero.
281 //
282 // After the right shifts, there are 3 fractional bits of precision. If
283 // allow_hp is false, the bottom bit is always zero (so we don't need a
284 // call to convert_to_trans_prec here)
285 res.as_mv.row = gm->wmmat[0] >> GM_TRANS_ONLY_PREC_DIFF;
286 res.as_mv.col = gm->wmmat[1] >> GM_TRANS_ONLY_PREC_DIFF;
287 assert(IMPLIES(1 & (res.as_mv.row | res.as_mv.col), allow_hp));
288 if (is_integer) {
289 integer_mv_precision(&res.as_mv);
290 }
291 return res;
292 }
293
294 x = block_center_x(mi_col, bsize);
295 y = block_center_y(mi_row, bsize);
296
297 if (gm->wmtype == ROTZOOM) {
298 assert(gm->wmmat[5] == gm->wmmat[2]);
299 assert(gm->wmmat[4] == -gm->wmmat[3]);
300 }
301
302 const int xc =
303 (mat[2] - (1 << WARPEDMODEL_PREC_BITS)) * x + mat[3] * y + mat[0];
304 const int yc =
305 mat[4] * x + (mat[5] - (1 << WARPEDMODEL_PREC_BITS)) * y + mat[1];
306 tx = convert_to_trans_prec(allow_hp, xc);
307 ty = convert_to_trans_prec(allow_hp, yc);
308
309 res.as_mv.row = ty;
310 res.as_mv.col = tx;
311
312 if (is_integer) {
313 integer_mv_precision(&res.as_mv);
314 }
315 return res;
316 }
317
get_wmtype(const WarpedMotionParams * gm)318 static INLINE TransformationType get_wmtype(const WarpedMotionParams *gm) {
319 if (gm->wmmat[5] == (1 << WARPEDMODEL_PREC_BITS) && !gm->wmmat[4] &&
320 gm->wmmat[2] == (1 << WARPEDMODEL_PREC_BITS) && !gm->wmmat[3]) {
321 return ((!gm->wmmat[1] && !gm->wmmat[0]) ? IDENTITY : TRANSLATION);
322 }
323 if (gm->wmmat[2] == gm->wmmat[5] && gm->wmmat[3] == -gm->wmmat[4])
324 return ROTZOOM;
325 else
326 return AFFINE;
327 }
328
329 typedef struct candidate_mv {
330 int_mv this_mv;
331 int_mv comp_mv;
332 } CANDIDATE_MV;
333
is_zero_mv(const MV * mv)334 static INLINE int is_zero_mv(const MV *mv) {
335 return *((const uint32_t *)mv) == 0;
336 }
337
is_equal_mv(const MV * a,const MV * b)338 static INLINE int is_equal_mv(const MV *a, const MV *b) {
339 return *((const uint32_t *)a) == *((const uint32_t *)b);
340 }
341
clamp_mv(MV * mv,const SubpelMvLimits * mv_limits)342 static INLINE void clamp_mv(MV *mv, const SubpelMvLimits *mv_limits) {
343 mv->col = clamp(mv->col, mv_limits->col_min, mv_limits->col_max);
344 mv->row = clamp(mv->row, mv_limits->row_min, mv_limits->row_max);
345 }
346
clamp_fullmv(FULLPEL_MV * mv,const FullMvLimits * mv_limits)347 static INLINE void clamp_fullmv(FULLPEL_MV *mv, const FullMvLimits *mv_limits) {
348 mv->col = clamp(mv->col, mv_limits->col_min, mv_limits->col_max);
349 mv->row = clamp(mv->row, mv_limits->row_min, mv_limits->row_max);
350 }
351
352 #ifdef __cplusplus
353 } // extern "C"
354 #endif
355
356 #endif // AOM_AV1_COMMON_MV_H_
357