• 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_ENCODER_MCOMP_H_
13 #define AOM_AV1_ENCODER_MCOMP_H_
14 
15 #include "av1/common/mv.h"
16 #include "av1/encoder/block.h"
17 #include "av1/encoder/rd.h"
18 
19 #include "aom_dsp/variance.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 struct AV1_COMP;
26 struct SPEED_FEATURES;
27 
28 // =============================================================================
29 //  Cost functions
30 // =============================================================================
31 
32 enum {
33   MV_COST_ENTROPY,    // Use the entropy rate of the mv as the cost
34   MV_COST_L1_LOWRES,  // Use the l1 norm of the mv as the cost (<480p)
35   MV_COST_L1_MIDRES,  // Use the l1 norm of the mv as the cost (>=480p)
36   MV_COST_L1_HDRES,   // Use the l1 norm of the mv as the cost (>=720p)
37   MV_COST_NONE        // Use 0 as as cost irrespective of the current mv
38 } UENUM1BYTE(MV_COST_TYPE);
39 
40 typedef struct {
41   // The reference mv used to compute the mv cost
42   const MV *ref_mv;
43   FULLPEL_MV full_ref_mv;
44   MV_COST_TYPE mv_cost_type;
45   const int *mvjcost;
46   const int *mvcost[2];
47   int error_per_bit;
48   // A multiplier used to convert rate to sad cost
49   int sad_per_bit;
50 } MV_COST_PARAMS;
51 
52 int av1_mv_bit_cost(const MV *mv, const MV *ref_mv, const int *mvjcost,
53                     int *const mvcost[2], int weight);
54 
55 int av1_get_mvpred_sse(const MV_COST_PARAMS *mv_cost_params,
56                        const FULLPEL_MV best_mv,
57                        const aom_variance_fn_ptr_t *vfp,
58                        const struct buf_2d *src, const struct buf_2d *pre);
59 int av1_get_mvpred_compound_var(const MV_COST_PARAMS *ms_params,
60                                 const FULLPEL_MV best_mv,
61                                 const uint8_t *second_pred, const uint8_t *mask,
62                                 int mask_stride, int invert_mask,
63                                 const aom_variance_fn_ptr_t *vfp,
64                                 const struct buf_2d *src,
65                                 const struct buf_2d *pre);
66 
67 // =============================================================================
68 //  Motion Search
69 // =============================================================================
70 typedef struct {
71   // The reference buffer
72   const struct buf_2d *ref;
73 
74   // The source and predictors/mask used by translational search
75   const struct buf_2d *src;
76   const uint8_t *second_pred;
77   const uint8_t *mask;
78   int mask_stride;
79   int inv_mask;
80 
81   // The weighted source and mask used by OBMC
82   const int32_t *wsrc;
83   const int32_t *obmc_mask;
84 } MSBuffers;
85 
av1_set_ms_compound_refs(MSBuffers * ms_buffers,const uint8_t * second_pred,const uint8_t * mask,int mask_stride,int invert_mask)86 static INLINE void av1_set_ms_compound_refs(MSBuffers *ms_buffers,
87                                             const uint8_t *second_pred,
88                                             const uint8_t *mask,
89                                             int mask_stride, int invert_mask) {
90   ms_buffers->second_pred = second_pred;
91   ms_buffers->mask = mask;
92   ms_buffers->mask_stride = mask_stride;
93   ms_buffers->inv_mask = invert_mask;
94 }
95 
96 // =============================================================================
97 //  Fullpixel Motion Search
98 // =============================================================================
99 // This struct holds fullpixel motion search parameters that should be constant
100 // during the search
101 typedef struct {
102   BLOCK_SIZE bsize;
103   // A function pointer to the simd function for fast computation
104   const aom_variance_fn_ptr_t *vfp;
105 
106   MSBuffers ms_buffers;
107 
108   // WARNING: search_method should be regarded as a private variable and should
109   // not be modified directly so it is in sync with search_sites. To modify it,
110   // use av1_set_mv_search_method.
111   SEARCH_METHODS search_method;
112   const search_site_config *search_sites;
113   FullMvLimits mv_limits;
114 
115   int run_mesh_search;    // Sets mesh search unless it got pruned by
116                           // prune_mesh_search.
117   int prune_mesh_search;  // Disables mesh search if the best_mv after a normal
118                           // search if close to the start_mv.
119   int mesh_search_mv_diff_threshold;  // mv diff threshold to enable
120                                       // prune_mesh_search
121   int force_mesh_thresh;  // Forces mesh search if the residue variance is
122                           // higher than the threshold.
123   const struct MESH_PATTERN *mesh_patterns[2];
124 
125   // Use maximum search interval of 4 if true. This helps motion search to find
126   // the best motion vector for screen content types.
127   int fine_search_interval;
128 
129   int is_intra_mode;
130 
131   int fast_obmc_search;
132 
133   // For calculating mv cost
134   MV_COST_PARAMS mv_cost_params;
135 
136   // Stores the function used to compute the sad. This can be different from the
137   // sdf in vfp (e.g. downsampled sad and not sad) to allow speed up.
138   aom_sad_fn_t sdf;
139   aom_sad_multi_d_fn_t sdx4df;
140   aom_sad_multi_d_fn_t sdx3df;
141 } FULLPEL_MOTION_SEARCH_PARAMS;
142 
143 typedef struct {
144   int err_cost;
145   unsigned int distortion;
146   unsigned int sse;
147 } FULLPEL_MV_STATS;
148 
149 void av1_init_obmc_buffer(OBMCBuffer *obmc_buffer);
150 
151 void av1_make_default_fullpel_ms_params(
152     FULLPEL_MOTION_SEARCH_PARAMS *ms_params, const struct AV1_COMP *cpi,
153     MACROBLOCK *x, BLOCK_SIZE bsize, const MV *ref_mv, FULLPEL_MV start_mv,
154     const search_site_config search_sites[NUM_DISTINCT_SEARCH_METHODS],
155     SEARCH_METHODS search_method, int fine_search_interval);
156 
157 /*! Sets the \ref FULLPEL_MOTION_SEARCH_PARAMS to intra mode. */
158 void av1_set_ms_to_intra_mode(FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
159                               const IntraBCMVCosts *dv_costs);
160 
161 // Sets up configs for fullpixel DIAMOND / CLAMPED_DIAMOND search method.
162 void av1_init_dsmotion_compensation(search_site_config *cfg, int stride,
163                                     int level);
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 NSTEP / NSTEP_8PT motion search method.
167 void av1_init_motion_compensation_nstep(search_site_config *cfg, int stride,
168                                         int level);
169 // Sets up configs for BIGDIA / FAST_DIAMOND / FAST_BIGDIA
170 // motion search method.
171 void av1_init_motion_compensation_bigdia(search_site_config *cfg, int stride,
172                                          int level);
173 // Sets up configs for HEX or FAST_HEX motion search method.
174 void av1_init_motion_compensation_hex(search_site_config *cfg, int stride,
175                                       int level);
176 // Sets up configs for SQUARE motion search method.
177 void av1_init_motion_compensation_square(search_site_config *cfg, int stride,
178                                          int level);
179 
180 /*! Function pointer to search site config initialization of different search
181  * method functions. */
182 typedef void (*av1_init_search_site_config)(search_site_config *cfg, int stride,
183                                             int level);
184 
185 /*! Array of function pointers used to set the motion search config. */
186 extern const av1_init_search_site_config
187     av1_init_motion_compensation[NUM_DISTINCT_SEARCH_METHODS];
188 
189 // Array to inform which all search methods are having
190 // same candidates and different in number of search steps.
191 static const SEARCH_METHODS search_method_lookup[NUM_SEARCH_METHODS] = {
192   DIAMOND,          // DIAMOND
193   NSTEP,            // NSTEP
194   NSTEP_8PT,        // NSTEP_8PT
195   CLAMPED_DIAMOND,  // CLAMPED_DIAMOND
196   HEX,              // HEX
197   BIGDIA,           // BIGDIA
198   SQUARE,           // SQUARE
199   HEX,              // FAST_HEX
200   BIGDIA,           // FAST_DIAMOND
201   BIGDIA,           // FAST_BIGDIA
202   BIGDIA            // VFAST_DIAMOND
203 };
204 
205 // Reinitialize the search site config.
av1_refresh_search_site_config(search_site_config * ss_cfg_buf,SEARCH_METHODS search_method,const int ref_stride)206 static AOM_INLINE void av1_refresh_search_site_config(
207     search_site_config *ss_cfg_buf, SEARCH_METHODS search_method,
208     const int ref_stride) {
209   const int level =
210       search_method == NSTEP_8PT || search_method == CLAMPED_DIAMOND;
211   search_method = search_method_lookup[search_method];
212   av1_init_motion_compensation[search_method](&ss_cfg_buf[search_method],
213                                               ref_stride, level);
214 }
215 
216 // Mv beyond the range do not produce new/different prediction block.
av1_set_mv_search_method(FULLPEL_MOTION_SEARCH_PARAMS * ms_params,const search_site_config search_sites[NUM_DISTINCT_SEARCH_METHODS],SEARCH_METHODS search_method)217 static INLINE void av1_set_mv_search_method(
218     FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
219     const search_site_config search_sites[NUM_DISTINCT_SEARCH_METHODS],
220     SEARCH_METHODS search_method) {
221   ms_params->search_method = search_method;
222   ms_params->search_sites =
223       &search_sites[search_method_lookup[ms_params->search_method]];
224 }
225 
226 // Set up limit values for MV components.
227 // 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)228 static INLINE void av1_set_mv_row_limits(
229     const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
230     int mi_row, int mi_height, int border) {
231   const int min1 = -(mi_row * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
232   const int min2 = -(((mi_row + mi_height) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
233   mv_limits->row_min = AOMMAX(min1, min2);
234   const int max1 = (mi_params->mi_rows - mi_row - mi_height) * MI_SIZE +
235                    border - 2 * AOM_INTERP_EXTEND;
236   const int max2 =
237       (mi_params->mi_rows - mi_row) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
238   mv_limits->row_max = AOMMIN(max1, max2);
239 }
240 
av1_set_mv_col_limits(const CommonModeInfoParams * const mi_params,FullMvLimits * mv_limits,int mi_col,int mi_width,int border)241 static INLINE void av1_set_mv_col_limits(
242     const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
243     int mi_col, int mi_width, int border) {
244   const int min1 = -(mi_col * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
245   const int min2 = -(((mi_col + mi_width) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
246   mv_limits->col_min = AOMMAX(min1, min2);
247   const int max1 = (mi_params->mi_cols - mi_col - mi_width) * MI_SIZE + border -
248                    2 * AOM_INTERP_EXTEND;
249   const int max2 =
250       (mi_params->mi_cols - mi_col) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
251   mv_limits->col_max = AOMMIN(max1, max2);
252 }
253 
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)254 static INLINE void av1_set_mv_limits(
255     const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
256     int mi_row, int mi_col, int mi_height, int mi_width, int border) {
257   av1_set_mv_row_limits(mi_params, mv_limits, mi_row, mi_height, border);
258   av1_set_mv_col_limits(mi_params, mv_limits, mi_col, mi_width, border);
259 }
260 
261 void av1_set_mv_search_range(FullMvLimits *mv_limits, const MV *mv);
262 
263 int av1_init_search_range(int size);
264 
265 unsigned int av1_int_pro_motion_estimation(
266     const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int mi_row,
267     int mi_col, const MV *ref_mv, unsigned int *y_sad_zero,
268     int me_search_size_col, int me_search_size_row);
269 
270 int av1_refining_search_8p_c(const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
271                              const FULLPEL_MV start_mv, FULLPEL_MV *best_mv);
272 
273 int av1_full_pixel_search(const FULLPEL_MV start_mv,
274                           const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
275                           const int step_param, int *cost_list,
276                           FULLPEL_MV *best_mv, FULLPEL_MV_STATS *best_mv_stats,
277                           FULLPEL_MV *second_best_mv);
278 
279 int av1_intrabc_hash_search(const struct AV1_COMP *cpi, const MACROBLOCKD *xd,
280                             const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
281                             IntraBCHashInfo *intrabc_hash_info,
282                             FULLPEL_MV *best_mv);
283 
284 int av1_obmc_full_pixel_search(const FULLPEL_MV start_mv,
285                                const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
286                                const int step_param, FULLPEL_MV *best_mv);
287 
av1_is_fullmv_in_range(const FullMvLimits * mv_limits,FULLPEL_MV mv)288 static INLINE int av1_is_fullmv_in_range(const FullMvLimits *mv_limits,
289                                          FULLPEL_MV mv) {
290   return (mv.col >= mv_limits->col_min) && (mv.col <= mv_limits->col_max) &&
291          (mv.row >= mv_limits->row_min) && (mv.row <= mv_limits->row_max);
292 }
293 // =============================================================================
294 //  Subpixel Motion Search
295 // =============================================================================
296 enum {
297   EIGHTH_PEL,
298   QUARTER_PEL,
299   HALF_PEL,
300   FULL_PEL
301 } UENUM1BYTE(SUBPEL_FORCE_STOP);
302 
303 typedef struct {
304   const aom_variance_fn_ptr_t *vfp;
305   SUBPEL_SEARCH_TYPE subpel_search_type;
306   // Source and reference buffers
307   MSBuffers ms_buffers;
308   int w, h;
309 } SUBPEL_SEARCH_VAR_PARAMS;
310 
311 // This struct holds subpixel motion search parameters that should be constant
312 // during the search
313 typedef struct {
314   // High level motion search settings
315   int allow_hp;
316   const int *cost_list;
317   SUBPEL_FORCE_STOP forced_stop;
318   int iters_per_step;
319   SubpelMvLimits mv_limits;
320 
321   // For calculating mv cost
322   MV_COST_PARAMS mv_cost_params;
323 
324   // Distortion calculation params
325   SUBPEL_SEARCH_VAR_PARAMS var_params;
326 } SUBPEL_MOTION_SEARCH_PARAMS;
327 
328 void av1_make_default_subpel_ms_params(SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
329                                        const struct AV1_COMP *cpi,
330                                        const MACROBLOCK *x, BLOCK_SIZE bsize,
331                                        const MV *ref_mv, const int *cost_list);
332 
333 typedef int(fractional_mv_step_fp)(MACROBLOCKD *xd, const AV1_COMMON *const cm,
334                                    const SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
335                                    MV start_mv,
336                                    const FULLPEL_MV_STATS *start_mv_stats,
337                                    MV *bestmv, int *distortion,
338                                    unsigned int *sse1,
339                                    int_mv *last_mv_search_list);
340 
341 extern fractional_mv_step_fp av1_find_best_sub_pixel_tree;
342 extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned;
343 extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned_more;
344 extern fractional_mv_step_fp av1_return_max_sub_pixel_mv;
345 extern fractional_mv_step_fp av1_return_min_sub_pixel_mv;
346 extern fractional_mv_step_fp av1_find_best_obmc_sub_pixel_tree_up;
347 
348 unsigned int av1_refine_warped_mv(MACROBLOCKD *xd, const AV1_COMMON *const cm,
349                                   const SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
350                                   BLOCK_SIZE bsize, const int *pts0,
351                                   const int *pts_inref0, int total_samples,
352                                   WARP_SEARCH_METHOD search_method,
353                                   int num_iterations);
354 
av1_set_fractional_mv(int_mv * fractional_best_mv)355 static INLINE void av1_set_fractional_mv(int_mv *fractional_best_mv) {
356   for (int z = 0; z < 3; z++) {
357     fractional_best_mv[z].as_int = INVALID_MV;
358   }
359 }
360 
av1_set_subpel_mv_search_range(SubpelMvLimits * subpel_limits,const FullMvLimits * mv_limits,const MV * ref_mv)361 static INLINE void av1_set_subpel_mv_search_range(SubpelMvLimits *subpel_limits,
362                                                   const FullMvLimits *mv_limits,
363                                                   const MV *ref_mv) {
364   const int max_mv = GET_MV_SUBPEL(MAX_FULL_PEL_VAL);
365   int minc = AOMMAX(GET_MV_SUBPEL(mv_limits->col_min), ref_mv->col - max_mv);
366   int maxc = AOMMIN(GET_MV_SUBPEL(mv_limits->col_max), ref_mv->col + max_mv);
367   int minr = AOMMAX(GET_MV_SUBPEL(mv_limits->row_min), ref_mv->row - max_mv);
368   int maxr = AOMMIN(GET_MV_SUBPEL(mv_limits->row_max), ref_mv->row + max_mv);
369 
370   maxc = AOMMAX(minc, maxc);
371   maxr = AOMMAX(minr, maxr);
372 
373   subpel_limits->col_min = AOMMAX(MV_LOW + 1, minc);
374   subpel_limits->col_max = AOMMIN(MV_UPP - 1, maxc);
375   subpel_limits->row_min = AOMMAX(MV_LOW + 1, minr);
376   subpel_limits->row_max = AOMMIN(MV_UPP - 1, maxr);
377 }
378 
av1_is_subpelmv_in_range(const SubpelMvLimits * mv_limits,MV mv)379 static INLINE int av1_is_subpelmv_in_range(const SubpelMvLimits *mv_limits,
380                                            MV mv) {
381   return (mv.col >= mv_limits->col_min) && (mv.col <= mv_limits->col_max) &&
382          (mv.row >= mv_limits->row_min) && (mv.row <= mv_limits->row_max);
383 }
384 
get_offset_from_fullmv(const FULLPEL_MV * mv,int stride)385 static INLINE int get_offset_from_fullmv(const FULLPEL_MV *mv, int stride) {
386   return mv->row * stride + mv->col;
387 }
388 
get_buf_from_fullmv(const struct buf_2d * buf,const FULLPEL_MV * mv)389 static INLINE const uint8_t *get_buf_from_fullmv(const struct buf_2d *buf,
390                                                  const FULLPEL_MV *mv) {
391   return &buf->buf[get_offset_from_fullmv(mv, buf->stride)];
392 }
393 
394 #ifdef __cplusplus
395 }  // extern "C"
396 #endif
397 
398 #endif  // AOM_AV1_ENCODER_MCOMP_H_
399