• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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