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_ENCODER_MCOMP_H_
13 #define AOM_AV1_ENCODER_MCOMP_H_
14 
15 #include "av1/common/mv.h"
16 #include "av1/encoder/block.h"
17 
18 #include "aom_dsp/variance.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 // The maximum number of steps in a step search given the largest
25 // allowed initial step
26 #define MAX_MVSEARCH_STEPS 11
27 // Max full pel mv specified in the unit of full pixel
28 // Enable the use of motion vector in range [-1023, 1023].
29 #define MAX_FULL_PEL_VAL ((1 << (MAX_MVSEARCH_STEPS - 1)) - 1)
30 // Maximum size of the first step in full pel units
31 #define MAX_FIRST_STEP (1 << (MAX_MVSEARCH_STEPS - 1))
32 
33 #define SEARCH_RANGE_8P 3
34 #define SEARCH_GRID_STRIDE_8P (2 * SEARCH_RANGE_8P + 1)
35 #define SEARCH_GRID_CENTER_8P \
36   (SEARCH_RANGE_8P * SEARCH_GRID_STRIDE_8P + SEARCH_RANGE_8P)
37 
38 // motion search site
39 typedef struct search_site {
40   FULLPEL_MV mv;
41   int offset;
42 } search_site;
43 
44 typedef struct search_site_config {
45   search_site ss[MAX_MVSEARCH_STEPS * 2][16 + 1];
46   int ss_count;
47   int searches_per_step[MAX_MVSEARCH_STEPS * 2];
48   int radius[MAX_MVSEARCH_STEPS * 2];
49   int stride;
50 } search_site_config;
51 
52 typedef struct {
53   FULLPEL_MV coord;
54   int coord_offset;
55 } search_neighbors;
56 
57 struct AV1_COMP;
58 struct SPEED_FEATURES;
59 
60 // =============================================================================
61 //  Cost functions
62 // =============================================================================
63 typedef struct {
64   const MV *ref_mv;
65   FULLPEL_MV full_ref_mv;
66   const int *mvjcost;
67   const int *mvcost[2];
68   int error_per_bit;
69   int sad_per_bit;
70   MV_COST_TYPE mv_cost_type;
71 } MV_COST_PARAMS;
72 
73 int av1_mv_bit_cost(const MV *mv, const MV *ref_mv, const int *mvjcost,
74                     int *mvcost[2], int weight);
75 
76 int av1_get_mvpred_sse(const MACROBLOCK *x, const FULLPEL_MV *best_mv,
77                        const MV *ref_mv, const aom_variance_fn_ptr_t *vfp);
78 int av1_get_mvpred_compound_var(const MV_COST_PARAMS *ms_params,
79                                 const FULLPEL_MV best_mv,
80                                 const uint8_t *second_pred, const uint8_t *mask,
81                                 int mask_stride, int invert_mask,
82                                 const aom_variance_fn_ptr_t *vfp,
83                                 const struct buf_2d *src,
84                                 const struct buf_2d *pre);
85 
86 // =============================================================================
87 //  Motion Search
88 // =============================================================================
89 typedef struct {
90   // The reference buffer
91   const struct buf_2d *ref;
92 
93   // The source and predictors/mask used by translational search
94   const struct buf_2d *src;
95   const uint8_t *second_pred;
96   const uint8_t *mask;
97   int mask_stride;
98   int inv_mask;
99 
100   // The weighted source and mask used by OBMC
101   const int32_t *wsrc;
102   const int32_t *obmc_mask;
103 } MSBuffers;
104 
av1_set_ms_compound_refs(MSBuffers * ms_buffers,const uint8_t * second_pred,const uint8_t * mask,int mask_stride,int invert_mask)105 static INLINE void av1_set_ms_compound_refs(MSBuffers *ms_buffers,
106                                             const uint8_t *second_pred,
107                                             const uint8_t *mask,
108                                             int mask_stride, int invert_mask) {
109   ms_buffers->second_pred = second_pred;
110   ms_buffers->mask = mask;
111   ms_buffers->mask_stride = mask_stride;
112   ms_buffers->inv_mask = invert_mask;
113 }
114 
115 // =============================================================================
116 //  Fullpixel Motion Search
117 // =============================================================================
118 enum {
119   DIAMOND = 0,
120   NSTEP = 1,
121   HEX = 2,
122   BIGDIA = 3,
123   SQUARE = 4,
124   FAST_HEX = 5,
125   FAST_DIAMOND = 6
126 } UENUM1BYTE(SEARCH_METHODS);
127 
128 // This struct holds fullpixel motion search parameters that should be constant
129 // during the search
130 typedef struct {
131   BLOCK_SIZE bsize;
132   const aom_variance_fn_ptr_t *vfp;
133 
134   MSBuffers ms_buffers;
135 
136   SEARCH_METHODS search_method;
137   const search_site_config *search_sites;
138   FullMvLimits mv_limits;
139 
140   int run_mesh_search;    // Sets mesh search unless it got pruned by
141                           // prune_mesh_search.
142   int prune_mesh_search;  // Disables mesh search if the best_mv after a normal
143                           // search if close to the start_mv.
144   int force_mesh_thresh;  // Forces mesh search if the residue variance is
145                           // higher than the threshold.
146   const struct MESH_PATTERN *mesh_patterns[2];
147 
148   int is_intra_mode;
149 
150   int fast_obmc_search;
151 
152   // For calculating mv cost
153   MV_COST_PARAMS mv_cost_params;
154 } FULLPEL_MOTION_SEARCH_PARAMS;
155 
156 void av1_make_default_fullpel_ms_params(FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
157                                         const struct AV1_COMP *cpi,
158                                         const MACROBLOCK *x, BLOCK_SIZE bsize,
159                                         const MV *ref_mv,
160                                         const search_site_config *search_sites);
161 
162 // Sets up configs for fullpixel diamond search
163 void av1_init_dsmotion_compensation(search_site_config *cfg, int stride);
164 // Sets up configs for firstpass motion search
165 void av1_init_motion_fpf(search_site_config *cfg, int stride);
166 // Sets up configs for all other types of motion search
167 void av1_init3smotion_compensation(search_site_config *cfg, int stride);
168 
169 // Set up limit values for MV components.
170 // Mv beyond the range do not produce new/different prediction block.
av1_set_mv_row_limits(const CommonModeInfoParams * const mi_params,FullMvLimits * mv_limits,int mi_row,int mi_height,int border)171 static INLINE void av1_set_mv_row_limits(
172     const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
173     int mi_row, int mi_height, int border) {
174   const int min1 = -(mi_row * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
175   const int min2 = -(((mi_row + mi_height) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
176   mv_limits->row_min = AOMMAX(min1, min2);
177   const int max1 = (mi_params->mi_rows - mi_row - mi_height) * MI_SIZE +
178                    border - 2 * AOM_INTERP_EXTEND;
179   const int max2 =
180       (mi_params->mi_rows - mi_row) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
181   mv_limits->row_max = AOMMIN(max1, max2);
182 }
183 
av1_set_mv_col_limits(const CommonModeInfoParams * const mi_params,FullMvLimits * mv_limits,int mi_col,int mi_width,int border)184 static INLINE void av1_set_mv_col_limits(
185     const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
186     int mi_col, int mi_width, int border) {
187   const int min1 = -(mi_col * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
188   const int min2 = -(((mi_col + mi_width) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
189   mv_limits->col_min = AOMMAX(min1, min2);
190   const int max1 = (mi_params->mi_cols - mi_col - mi_width) * MI_SIZE + border -
191                    2 * AOM_INTERP_EXTEND;
192   const int max2 =
193       (mi_params->mi_cols - mi_col) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
194   mv_limits->col_max = AOMMIN(max1, max2);
195 }
196 
av1_set_mv_limits(const CommonModeInfoParams * const mi_params,FullMvLimits * mv_limits,int mi_row,int mi_col,int mi_height,int mi_width,int border)197 static INLINE void av1_set_mv_limits(
198     const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
199     int mi_row, int mi_col, int mi_height, int mi_width, int border) {
200   av1_set_mv_row_limits(mi_params, mv_limits, mi_row, mi_height, border);
201   av1_set_mv_col_limits(mi_params, mv_limits, mi_col, mi_width, border);
202 }
203 
204 void av1_set_mv_search_range(FullMvLimits *mv_limits, const MV *mv);
205 
206 int av1_init_search_range(int size);
207 
208 unsigned int av1_int_pro_motion_estimation(const struct AV1_COMP *cpi,
209                                            MACROBLOCK *x, BLOCK_SIZE bsize,
210                                            int mi_row, int mi_col,
211                                            const MV *ref_mv);
212 
213 int av1_refining_search_8p_c(const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
214                              const FULLPEL_MV start_mv, FULLPEL_MV *best_mv);
215 
216 int av1_full_pixel_search(const FULLPEL_MV start_mv,
217                           const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
218                           const int step_param, int *cost_list,
219                           FULLPEL_MV *best_mv, FULLPEL_MV *second_best_mv);
220 
221 int av1_intrabc_hash_search(const struct AV1_COMP *cpi, const MACROBLOCKD *xd,
222                             const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
223                             IntraBCHashInfo *intrabc_hash_info,
224                             FULLPEL_MV *best_mv);
225 
226 int av1_obmc_full_pixel_search(const FULLPEL_MV start_mv,
227                                const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
228                                const int step_param, FULLPEL_MV *best_mv);
229 
av1_is_fullmv_in_range(const FullMvLimits * mv_limits,FULLPEL_MV mv)230 static INLINE int av1_is_fullmv_in_range(const FullMvLimits *mv_limits,
231                                          FULLPEL_MV mv) {
232   return (mv.col >= mv_limits->col_min) && (mv.col <= mv_limits->col_max) &&
233          (mv.row >= mv_limits->row_min) && (mv.row <= mv_limits->row_max);
234 }
235 // =============================================================================
236 //  Subpixel Motion Search
237 // =============================================================================
238 enum {
239   EIGHTH_PEL,
240   QUARTER_PEL,
241   HALF_PEL,
242   FULL_PEL
243 } UENUM1BYTE(SUBPEL_FORCE_STOP);
244 
245 typedef struct {
246   const aom_variance_fn_ptr_t *vfp;
247   SUBPEL_SEARCH_TYPE subpel_search_type;
248   // Source and reference buffers
249   MSBuffers ms_buffers;
250   int w, h;
251 } SUBPEL_SEARCH_VAR_PARAMS;
252 
253 // This struct holds subpixel motion search parameters that should be constant
254 // during the search
255 typedef struct {
256   // High level motion search settings
257   int allow_hp;
258   const int *cost_list;
259   SUBPEL_FORCE_STOP forced_stop;
260   int iters_per_step;
261   SubpelMvLimits mv_limits;
262 
263   // For calculating mv cost
264   MV_COST_PARAMS mv_cost_params;
265 
266   // Distortion calculation params
267   SUBPEL_SEARCH_VAR_PARAMS var_params;
268 } SUBPEL_MOTION_SEARCH_PARAMS;
269 
270 void av1_make_default_subpel_ms_params(SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
271                                        const struct AV1_COMP *cpi,
272                                        const MACROBLOCK *x, BLOCK_SIZE bsize,
273                                        const MV *ref_mv, const int *cost_list);
274 
275 typedef int(fractional_mv_step_fp)(MACROBLOCKD *xd, const AV1_COMMON *const cm,
276                                    const SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
277                                    MV start_mv, MV *bestmv, int *distortion,
278                                    unsigned int *sse1,
279                                    int_mv *last_mv_search_list);
280 
281 extern fractional_mv_step_fp av1_find_best_sub_pixel_tree;
282 extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned;
283 extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned_more;
284 extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned_evenmore;
285 extern fractional_mv_step_fp av1_return_max_sub_pixel_mv;
286 extern fractional_mv_step_fp av1_return_min_sub_pixel_mv;
287 extern fractional_mv_step_fp av1_find_best_obmc_sub_pixel_tree_up;
288 
289 unsigned int av1_refine_warped_mv(MACROBLOCKD *xd, const AV1_COMMON *const cm,
290                                   const SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
291                                   BLOCK_SIZE bsize, const int *pts0,
292                                   const int *pts_inref0, int total_samples);
293 
av1_set_fractional_mv(int_mv * fractional_best_mv)294 static INLINE void av1_set_fractional_mv(int_mv *fractional_best_mv) {
295   for (int z = 0; z < 3; z++) {
296     fractional_best_mv[z].as_int = INVALID_MV;
297   }
298 }
299 
av1_set_subpel_mv_search_range(SubpelMvLimits * subpel_limits,const FullMvLimits * mv_limits,const MV * ref_mv)300 static INLINE void av1_set_subpel_mv_search_range(SubpelMvLimits *subpel_limits,
301                                                   const FullMvLimits *mv_limits,
302                                                   const MV *ref_mv) {
303   const int max_mv = GET_MV_SUBPEL(MAX_FULL_PEL_VAL);
304   const int minc =
305       AOMMAX(GET_MV_SUBPEL(mv_limits->col_min), ref_mv->col - max_mv);
306   const int maxc =
307       AOMMIN(GET_MV_SUBPEL(mv_limits->col_max), ref_mv->col + max_mv);
308   const int minr =
309       AOMMAX(GET_MV_SUBPEL(mv_limits->row_min), ref_mv->row - max_mv);
310   const int maxr =
311       AOMMIN(GET_MV_SUBPEL(mv_limits->row_max), ref_mv->row + max_mv);
312 
313   subpel_limits->col_min = AOMMAX(MV_LOW + 1, minc);
314   subpel_limits->col_max = AOMMIN(MV_UPP - 1, maxc);
315   subpel_limits->row_min = AOMMAX(MV_LOW + 1, minr);
316   subpel_limits->row_max = AOMMIN(MV_UPP - 1, maxr);
317 }
318 
av1_is_subpelmv_in_range(const SubpelMvLimits * mv_limits,MV mv)319 static INLINE int av1_is_subpelmv_in_range(const SubpelMvLimits *mv_limits,
320                                            MV mv) {
321   return (mv.col >= mv_limits->col_min) && (mv.col <= mv_limits->col_max) &&
322          (mv.row >= mv_limits->row_min) && (mv.row <= mv_limits->row_max);
323 }
324 
325 #ifdef __cplusplus
326 }  // extern "C"
327 #endif
328 
329 #endif  // AOM_AV1_ENCODER_MCOMP_H_
330