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