• 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 "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