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