aboutsummaryrefslogtreecommitdiff
path: root/av1/encoder/mcomp.h
blob: 3917d84358be07f053eb513d2ca9acf4c80578cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#ifndef AOM_AV1_ENCODER_MCOMP_H_
#define AOM_AV1_ENCODER_MCOMP_H_

#include "av1/common/mv.h"
#include "av1/encoder/block.h"
#include "av1/encoder/rd.h"

#include "aom_dsp/variance.h"

#ifdef __cplusplus
extern "C" {
#endif

struct AV1_COMP;
struct SPEED_FEATURES;

// =============================================================================
//  Cost functions
// =============================================================================

enum {
  MV_COST_ENTROPY,    // Use the entropy rate of the mv as the cost
  MV_COST_L1_LOWRES,  // Use the l1 norm of the mv as the cost (<480p)
  MV_COST_L1_MIDRES,  // Use the l1 norm of the mv as the cost (>=480p)
  MV_COST_L1_HDRES,   // Use the l1 norm of the mv as the cost (>=720p)
  MV_COST_NONE        // Use 0 as as cost irrespective of the current mv
} UENUM1BYTE(MV_COST_TYPE);

typedef struct {
  // The reference mv used to compute the mv cost
  const MV *ref_mv;
  FULLPEL_MV full_ref_mv;
  MV_COST_TYPE mv_cost_type;
  const int *mvjcost;
  const int *mvcost[2];
  int error_per_bit;
  // A multiplier used to convert rate to sad cost
  int sad_per_bit;
} MV_COST_PARAMS;

int av1_mv_bit_cost(const MV *mv, const MV *ref_mv, const int *mvjcost,
                    int *const mvcost[2], int weight);

int av1_get_mvpred_sse(const MV_COST_PARAMS *mv_cost_params,
                       const FULLPEL_MV best_mv,
                       const aom_variance_fn_ptr_t *vfp,
                       const struct buf_2d *src, const struct buf_2d *pre);
int av1_get_mvpred_compound_var(const MV_COST_PARAMS *ms_params,
                                const FULLPEL_MV best_mv,
                                const uint8_t *second_pred, const uint8_t *mask,
                                int mask_stride, int invert_mask,
                                const aom_variance_fn_ptr_t *vfp,
                                const struct buf_2d *src,
                                const struct buf_2d *pre);

// =============================================================================
//  Motion Search
// =============================================================================
typedef struct {
  // The reference buffer
  const struct buf_2d *ref;

  // The source and predictors/mask used by translational search
  const struct buf_2d *src;
  const uint8_t *second_pred;
  const uint8_t *mask;
  int mask_stride;
  int inv_mask;

  // The weighted source and mask used by OBMC
  const int32_t *wsrc;
  const int32_t *obmc_mask;
} MSBuffers;

static INLINE void av1_set_ms_compound_refs(MSBuffers *ms_buffers,
                                            const uint8_t *second_pred,
                                            const uint8_t *mask,
                                            int mask_stride, int invert_mask) {
  ms_buffers->second_pred = second_pred;
  ms_buffers->mask = mask;
  ms_buffers->mask_stride = mask_stride;
  ms_buffers->inv_mask = invert_mask;
}

// =============================================================================
//  Fullpixel Motion Search
// =============================================================================
// This struct holds fullpixel motion search parameters that should be constant
// during the search
typedef struct {
  BLOCK_SIZE bsize;
  // A function pointer to the simd function for fast computation
  const aom_variance_fn_ptr_t *vfp;

  MSBuffers ms_buffers;

  // WARNING: search_method should be regarded as a private variable and should
  // not be modified directly so it is in sync with search_sites. To modify it,
  // use av1_set_mv_search_method.
  SEARCH_METHODS search_method;
  const search_site_config *search_sites;
  FullMvLimits mv_limits;

  int run_mesh_search;    // Sets mesh search unless it got pruned by
                          // prune_mesh_search.
  int prune_mesh_search;  // Disables mesh search if the best_mv after a normal
                          // search if close to the start_mv.
  int mesh_search_mv_diff_threshold;  // mv diff threshold to enable
                                      // prune_mesh_search
  int force_mesh_thresh;  // Forces mesh search if the residue variance is
                          // higher than the threshold.
  const struct MESH_PATTERN *mesh_patterns[2];

  // Use maximum search interval of 4 if true. This helps motion search to find
  // the best motion vector for screen content types.
  int fine_search_interval;

  int is_intra_mode;

  int fast_obmc_search;

  // For calculating mv cost
  MV_COST_PARAMS mv_cost_params;

  // Stores the function used to compute the sad. This can be different from the
  // sdf in vfp (e.g. downsampled sad and not sad) to allow speed up.
  aom_sad_fn_t sdf;
  aom_sad_multi_d_fn_t sdx4df;
} FULLPEL_MOTION_SEARCH_PARAMS;

void av1_init_obmc_buffer(OBMCBuffer *obmc_buffer);

void av1_make_default_fullpel_ms_params(
    FULLPEL_MOTION_SEARCH_PARAMS *ms_params, const struct AV1_COMP *cpi,
    const MACROBLOCK *x, BLOCK_SIZE bsize, const MV *ref_mv,
    const search_site_config search_sites[NUM_DISTINCT_SEARCH_METHODS],
    int fine_search_interval);

/*! Sets the \ref FULLPEL_MOTION_SEARCH_PARAMS to intra mode. */
void av1_set_ms_to_intra_mode(FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
                              const IntraBCMVCosts *dv_costs);

// Sets up configs for fullpixel DIAMOND / CLAMPED_DIAMOND search method.
void av1_init_dsmotion_compensation(search_site_config *cfg, int stride,
                                    int level);
// Sets up configs for firstpass motion search.
void av1_init_motion_fpf(search_site_config *cfg, int stride);
// Sets up configs for NSTEP / NSTEP_8PT motion search method.
void av1_init_motion_compensation_nstep(search_site_config *cfg, int stride,
                                        int level);
// Sets up configs for BIGDIA / FAST_DIAMOND / FAST_BIGDIA
// motion search method.
void av1_init_motion_compensation_bigdia(search_site_config *cfg, int stride,
                                         int level);
// Sets up configs for HEX or FAST_HEX motion search method.
void av1_init_motion_compensation_hex(search_site_config *cfg, int stride,
                                      int level);
// Sets up configs for SQUARE motion search method.
void av1_init_motion_compensation_square(search_site_config *cfg, int stride,
                                         int level);

/*! Function pointer to search site config initialization of different search
 * method functions. */
typedef void (*av1_init_search_site_config)(search_site_config *cfg, int stride,
                                            int level);

/*! Array of function pointer used to set the motion search config. */
static const av1_init_search_site_config
    av1_init_motion_compensation[NUM_DISTINCT_SEARCH_METHODS] = {
      av1_init_dsmotion_compensation,     av1_init_motion_compensation_nstep,
      av1_init_motion_compensation_nstep, av1_init_dsmotion_compensation,
      av1_init_motion_compensation_hex,   av1_init_motion_compensation_bigdia,
      av1_init_motion_compensation_square
    };

// Array to inform which all search methods are having
// same candidates and different in number of search steps.
static const SEARCH_METHODS search_method_lookup[NUM_SEARCH_METHODS] = {
  DIAMOND,          // DIAMOND
  NSTEP,            // NSTEP
  NSTEP_8PT,        // NSTEP_8PT
  CLAMPED_DIAMOND,  // CLAMPED_DIAMOND
  HEX,              // HEX
  BIGDIA,           // BIGDIA
  SQUARE,           // SQUARE
  HEX,              // FAST_HEX
  BIGDIA,           // FAST_DIAMOND
  BIGDIA            // FAST_BIGDIA
};

// Mv beyond the range do not produce new/different prediction block.
static INLINE void 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) {
  ms_params->search_method = search_method;
  ms_params->search_sites =
      &search_sites[search_method_lookup[ms_params->search_method]];
}

// Set up limit values for MV components.
// Mv beyond the range do not produce new/different prediction block.
static INLINE void av1_set_mv_row_limits(
    const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
    int mi_row, int mi_height, int border) {
  const int min1 = -(mi_row * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
  const int min2 = -(((mi_row + mi_height) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
  mv_limits->row_min = AOMMAX(min1, min2);
  const int max1 = (mi_params->mi_rows - mi_row - mi_height) * MI_SIZE +
                   border - 2 * AOM_INTERP_EXTEND;
  const int max2 =
      (mi_params->mi_rows - mi_row) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
  mv_limits->row_max = AOMMIN(max1, max2);
}

static INLINE void av1_set_mv_col_limits(
    const CommonModeInfoParams *const mi_params, FullMvLimits *mv_limits,
    int mi_col, int mi_width, int border) {
  const int min1 = -(mi_col * MI_SIZE + border - 2 * AOM_INTERP_EXTEND);
  const int min2 = -(((mi_col + mi_width) * MI_SIZE) + 2 * AOM_INTERP_EXTEND);
  mv_limits->col_min = AOMMAX(min1, min2);
  const int max1 = (mi_params->mi_cols - mi_col - mi_width) * MI_SIZE + border -
                   2 * AOM_INTERP_EXTEND;
  const int max2 =
      (mi_params->mi_cols - mi_col) * MI_SIZE + 2 * AOM_INTERP_EXTEND;
  mv_limits->col_max = AOMMIN(max1, max2);
}

static INLINE void 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) {
  av1_set_mv_row_limits(mi_params, mv_limits, mi_row, mi_height, border);
  av1_set_mv_col_limits(mi_params, mv_limits, mi_col, mi_width, border);
}

void av1_set_mv_search_range(FullMvLimits *mv_limits, const MV *mv);

int av1_init_search_range(int size);

unsigned int av1_int_pro_motion_estimation(const struct AV1_COMP *cpi,
                                           MACROBLOCK *x, BLOCK_SIZE bsize,
                                           int mi_row, int mi_col,
                                           const MV *ref_mv);

int av1_refining_search_8p_c(const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
                             const FULLPEL_MV start_mv, FULLPEL_MV *best_mv);

int av1_full_pixel_search(const FULLPEL_MV start_mv,
                          const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
                          const int step_param, int *cost_list,
                          FULLPEL_MV *best_mv, FULLPEL_MV *second_best_mv);

int av1_intrabc_hash_search(const struct AV1_COMP *cpi, const MACROBLOCKD *xd,
                            const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
                            IntraBCHashInfo *intrabc_hash_info,
                            FULLPEL_MV *best_mv);

int av1_obmc_full_pixel_search(const FULLPEL_MV start_mv,
                               const FULLPEL_MOTION_SEARCH_PARAMS *ms_params,
                               const int step_param, FULLPEL_MV *best_mv);

static INLINE int av1_is_fullmv_in_range(const FullMvLimits *mv_limits,
                                         FULLPEL_MV mv) {
  return (mv.col >= mv_limits->col_min) && (mv.col <= mv_limits->col_max) &&
         (mv.row >= mv_limits->row_min) && (mv.row <= mv_limits->row_max);
}
// =============================================================================
//  Subpixel Motion Search
// =============================================================================
enum {
  EIGHTH_PEL,
  QUARTER_PEL,
  HALF_PEL,
  FULL_PEL
} UENUM1BYTE(SUBPEL_FORCE_STOP);

typedef struct {
  const aom_variance_fn_ptr_t *vfp;
  SUBPEL_SEARCH_TYPE subpel_search_type;
  // Source and reference buffers
  MSBuffers ms_buffers;
  int w, h;
} SUBPEL_SEARCH_VAR_PARAMS;

// This struct holds subpixel motion search parameters that should be constant
// during the search
typedef struct {
  // High level motion search settings
  int allow_hp;
  const int *cost_list;
  SUBPEL_FORCE_STOP forced_stop;
  int iters_per_step;
  SubpelMvLimits mv_limits;

  // For calculating mv cost
  MV_COST_PARAMS mv_cost_params;

  // Distortion calculation params
  SUBPEL_SEARCH_VAR_PARAMS var_params;
} SUBPEL_MOTION_SEARCH_PARAMS;

void av1_make_default_subpel_ms_params(SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
                                       const struct AV1_COMP *cpi,
                                       const MACROBLOCK *x, BLOCK_SIZE bsize,
                                       const MV *ref_mv, const int *cost_list);

typedef int(fractional_mv_step_fp)(MACROBLOCKD *xd, const AV1_COMMON *const cm,
                                   const SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
                                   MV start_mv, MV *bestmv, int *distortion,
                                   unsigned int *sse1,
                                   int_mv *last_mv_search_list);

extern fractional_mv_step_fp av1_find_best_sub_pixel_tree;
extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned;
extern fractional_mv_step_fp av1_find_best_sub_pixel_tree_pruned_more;
extern fractional_mv_step_fp av1_return_max_sub_pixel_mv;
extern fractional_mv_step_fp av1_return_min_sub_pixel_mv;
extern fractional_mv_step_fp av1_find_best_obmc_sub_pixel_tree_up;

unsigned int av1_refine_warped_mv(MACROBLOCKD *xd, const AV1_COMMON *const cm,
                                  const SUBPEL_MOTION_SEARCH_PARAMS *ms_params,
                                  BLOCK_SIZE bsize, const int *pts0,
                                  const int *pts_inref0, int total_samples);

static INLINE void av1_set_fractional_mv(int_mv *fractional_best_mv) {
  for (int z = 0; z < 3; z++) {
    fractional_best_mv[z].as_int = INVALID_MV;
  }
}

static INLINE void av1_set_subpel_mv_search_range(SubpelMvLimits *subpel_limits,
                                                  const FullMvLimits *mv_limits,
                                                  const MV *ref_mv) {
  const int max_mv = GET_MV_SUBPEL(MAX_FULL_PEL_VAL);
  const int minc =
      AOMMAX(GET_MV_SUBPEL(mv_limits->col_min), ref_mv->col - max_mv);
  const int maxc =
      AOMMIN(GET_MV_SUBPEL(mv_limits->col_max), ref_mv->col + max_mv);
  const int minr =
      AOMMAX(GET_MV_SUBPEL(mv_limits->row_min), ref_mv->row - max_mv);
  const int maxr =
      AOMMIN(GET_MV_SUBPEL(mv_limits->row_max), ref_mv->row + max_mv);

  subpel_limits->col_min = AOMMAX(MV_LOW + 1, minc);
  subpel_limits->col_max = AOMMIN(MV_UPP - 1, maxc);
  subpel_limits->row_min = AOMMAX(MV_LOW + 1, minr);
  subpel_limits->row_max = AOMMIN(MV_UPP - 1, maxr);
}

static INLINE int av1_is_subpelmv_in_range(const SubpelMvLimits *mv_limits,
                                           MV mv) {
  return (mv.col >= mv_limits->col_min) && (mv.col <= mv_limits->col_max) &&
         (mv.row >= mv_limits->row_min) && (mv.row <= mv_limits->row_max);
}

#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // AOM_AV1_ENCODER_MCOMP_H_