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