Coverage Report

Created: 2022-08-24 06:15

/src/aom/av1/encoder/global_motion_facade.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2020, 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
#include "aom_dsp/binary_codes_writer.h"
13
14
#include "av1/encoder/corner_detect.h"
15
#include "av1/encoder/encoder.h"
16
#include "av1/encoder/ethread.h"
17
#include "av1/encoder/rdopt.h"
18
19
// Highest motion model to search.
20
0
#define GLOBAL_TRANS_TYPES_ENC 3
21
22
// Computes the cost for the warp parameters.
23
static int gm_get_params_cost(const WarpedMotionParams *gm,
24
0
                              const WarpedMotionParams *ref_gm, int allow_hp) {
25
0
  int params_cost = 0;
26
0
  int trans_bits, trans_prec_diff;
27
0
  switch (gm->wmtype) {
28
0
    case AFFINE:
29
0
    case ROTZOOM:
30
0
      params_cost += aom_count_signed_primitive_refsubexpfin(
31
0
          GM_ALPHA_MAX + 1, SUBEXPFIN_K,
32
0
          (ref_gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS),
33
0
          (gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
34
0
      params_cost += aom_count_signed_primitive_refsubexpfin(
35
0
          GM_ALPHA_MAX + 1, SUBEXPFIN_K,
36
0
          (ref_gm->wmmat[3] >> GM_ALPHA_PREC_DIFF),
37
0
          (gm->wmmat[3] >> GM_ALPHA_PREC_DIFF));
38
0
      if (gm->wmtype >= AFFINE) {
39
0
        params_cost += aom_count_signed_primitive_refsubexpfin(
40
0
            GM_ALPHA_MAX + 1, SUBEXPFIN_K,
41
0
            (ref_gm->wmmat[4] >> GM_ALPHA_PREC_DIFF),
42
0
            (gm->wmmat[4] >> GM_ALPHA_PREC_DIFF));
43
0
        params_cost += aom_count_signed_primitive_refsubexpfin(
44
0
            GM_ALPHA_MAX + 1, SUBEXPFIN_K,
45
0
            (ref_gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
46
0
                (1 << GM_ALPHA_PREC_BITS),
47
0
            (gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
48
0
      }
49
0
      AOM_FALLTHROUGH_INTENDED;
50
0
    case TRANSLATION:
51
0
      trans_bits = (gm->wmtype == TRANSLATION)
52
0
                       ? GM_ABS_TRANS_ONLY_BITS - !allow_hp
53
0
                       : GM_ABS_TRANS_BITS;
54
0
      trans_prec_diff = (gm->wmtype == TRANSLATION)
55
0
                            ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
56
0
                            : GM_TRANS_PREC_DIFF;
57
0
      params_cost += aom_count_signed_primitive_refsubexpfin(
58
0
          (1 << trans_bits) + 1, SUBEXPFIN_K,
59
0
          (ref_gm->wmmat[0] >> trans_prec_diff),
60
0
          (gm->wmmat[0] >> trans_prec_diff));
61
0
      params_cost += aom_count_signed_primitive_refsubexpfin(
62
0
          (1 << trans_bits) + 1, SUBEXPFIN_K,
63
0
          (ref_gm->wmmat[1] >> trans_prec_diff),
64
0
          (gm->wmmat[1] >> trans_prec_diff));
65
0
      AOM_FALLTHROUGH_INTENDED;
66
0
    case IDENTITY: break;
67
0
    default: assert(0);
68
0
  }
69
0
  return (params_cost << AV1_PROB_COST_SHIFT);
70
0
}
71
72
// Calculates the threshold to be used for warp error computation.
73
0
static AOM_INLINE int64_t calc_erroradv_threshold(int64_t ref_frame_error) {
74
0
  return (int64_t)(ref_frame_error * erroradv_tr + 0.5);
75
0
}
76
77
// For the given reference frame, computes the global motion parameters for
78
// different motion models and finds the best.
79
static AOM_INLINE void compute_global_motion_for_ref_frame(
80
    AV1_COMP *cpi, YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES], int frame,
81
    int num_src_corners, int *src_corners, unsigned char *src_buffer,
82
    MotionModel *params_by_motion, uint8_t *segment_map,
83
    const int segment_map_w, const int segment_map_h,
84
0
    const WarpedMotionParams *ref_params) {
85
0
  ThreadData *const td = &cpi->td;
86
0
  MACROBLOCK *const x = &td->mb;
87
0
  AV1_COMMON *const cm = &cpi->common;
88
0
  MACROBLOCKD *const xd = &x->e_mbd;
89
0
  int i;
90
0
  int src_width = cpi->source->y_width;
91
0
  int src_height = cpi->source->y_height;
92
0
  int src_stride = cpi->source->y_stride;
93
  // clang-format off
94
0
  static const double kIdentityParams[MAX_PARAMDIM - 1] = {
95
0
     0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0
96
0
  };
97
  // clang-format on
98
0
  WarpedMotionParams tmp_wm_params;
99
0
  const double *params_this_motion;
100
0
  int inliers_by_motion[RANSAC_NUM_MOTIONS];
101
0
  assert(ref_buf[frame] != NULL);
102
0
  TransformationType model;
103
104
  // TODO(sarahparker, debargha): Explore do_adaptive_gm_estimation = 1
105
0
  const int do_adaptive_gm_estimation = 0;
106
107
0
  const int ref_frame_dist = get_relative_dist(
108
0
      &cm->seq_params->order_hint_info, cm->current_frame.order_hint,
109
0
      cm->cur_frame->ref_order_hints[frame - LAST_FRAME]);
110
0
  const GlobalMotionEstimationType gm_estimation_type =
111
0
      cm->seq_params->order_hint_info.enable_order_hint &&
112
0
              abs(ref_frame_dist) <= 2 && do_adaptive_gm_estimation
113
0
          ? GLOBAL_MOTION_DISFLOW_BASED
114
0
          : GLOBAL_MOTION_FEATURE_BASED;
115
0
  for (model = ROTZOOM; model < GLOBAL_TRANS_TYPES_ENC; ++model) {
116
0
    int64_t best_warp_error = INT64_MAX;
117
    // Initially set all params to identity.
118
0
    for (i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
119
0
      memcpy(params_by_motion[i].params, kIdentityParams,
120
0
             (MAX_PARAMDIM - 1) * sizeof(*(params_by_motion[i].params)));
121
0
      params_by_motion[i].num_inliers = 0;
122
0
    }
123
124
0
    av1_compute_global_motion(model, src_buffer, src_width, src_height,
125
0
                              src_stride, src_corners, num_src_corners,
126
0
                              ref_buf[frame], cpi->common.seq_params->bit_depth,
127
0
                              gm_estimation_type, inliers_by_motion,
128
0
                              params_by_motion, RANSAC_NUM_MOTIONS);
129
0
    int64_t ref_frame_error = 0;
130
0
    for (i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
131
0
      if (inliers_by_motion[i] == 0) continue;
132
133
0
      params_this_motion = params_by_motion[i].params;
134
0
      av1_convert_model_to_params(params_this_motion, &tmp_wm_params);
135
136
0
      if (tmp_wm_params.wmtype != IDENTITY) {
137
0
        av1_compute_feature_segmentation_map(
138
0
            segment_map, segment_map_w, segment_map_h,
139
0
            params_by_motion[i].inliers, params_by_motion[i].num_inliers);
140
141
0
        ref_frame_error = av1_segmented_frame_error(
142
0
            is_cur_buf_hbd(xd), xd->bd, ref_buf[frame]->y_buffer,
143
0
            ref_buf[frame]->y_stride, cpi->source->y_buffer, src_width,
144
0
            src_height, src_stride, segment_map, segment_map_w);
145
146
0
        const int64_t erroradv_threshold =
147
0
            calc_erroradv_threshold(ref_frame_error);
148
149
0
        const int64_t warp_error = av1_refine_integerized_param(
150
0
            &tmp_wm_params, tmp_wm_params.wmtype, is_cur_buf_hbd(xd), xd->bd,
151
0
            ref_buf[frame]->y_buffer, ref_buf[frame]->y_width,
152
0
            ref_buf[frame]->y_height, ref_buf[frame]->y_stride,
153
0
            cpi->source->y_buffer, src_width, src_height, src_stride,
154
0
            GM_REFINEMENT_COUNT, best_warp_error, segment_map, segment_map_w,
155
0
            erroradv_threshold);
156
157
0
        if (warp_error < best_warp_error) {
158
0
          best_warp_error = warp_error;
159
          // Save the wm_params modified by
160
          // av1_refine_integerized_param() rather than motion index to
161
          // avoid rerunning refine() below.
162
0
          memcpy(&(cm->global_motion[frame]), &tmp_wm_params,
163
0
                 sizeof(WarpedMotionParams));
164
0
        }
165
0
      }
166
0
    }
167
0
    if (cm->global_motion[frame].wmtype <= AFFINE)
168
0
      if (!av1_get_shear_params(&cm->global_motion[frame]))
169
0
        cm->global_motion[frame] = default_warp_params;
170
171
0
    if (cm->global_motion[frame].wmtype == TRANSLATION) {
172
0
      cm->global_motion[frame].wmmat[0] =
173
0
          convert_to_trans_prec(cm->features.allow_high_precision_mv,
174
0
                                cm->global_motion[frame].wmmat[0]) *
175
0
          GM_TRANS_ONLY_DECODE_FACTOR;
176
0
      cm->global_motion[frame].wmmat[1] =
177
0
          convert_to_trans_prec(cm->features.allow_high_precision_mv,
178
0
                                cm->global_motion[frame].wmmat[1]) *
179
0
          GM_TRANS_ONLY_DECODE_FACTOR;
180
0
    }
181
182
0
    if (cm->global_motion[frame].wmtype == IDENTITY) continue;
183
184
0
    if (ref_frame_error == 0) continue;
185
186
    // If the best error advantage found doesn't meet the threshold for
187
    // this motion type, revert to IDENTITY.
188
0
    if (!av1_is_enough_erroradvantage(
189
0
            (double)best_warp_error / ref_frame_error,
190
0
            gm_get_params_cost(&cm->global_motion[frame], ref_params,
191
0
                               cm->features.allow_high_precision_mv))) {
192
0
      cm->global_motion[frame] = default_warp_params;
193
0
    }
194
195
0
    if (cm->global_motion[frame].wmtype != IDENTITY) break;
196
0
  }
197
0
}
198
199
// Computes global motion for the given reference frame.
200
void av1_compute_gm_for_valid_ref_frames(
201
    AV1_COMP *cpi, YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES], int frame,
202
    int num_src_corners, int *src_corners, unsigned char *src_buffer,
203
    MotionModel *params_by_motion, uint8_t *segment_map, int segment_map_w,
204
0
    int segment_map_h) {
205
0
  AV1_COMMON *const cm = &cpi->common;
206
0
  const WarpedMotionParams *ref_params =
207
0
      cm->prev_frame ? &cm->prev_frame->global_motion[frame]
208
0
                     : &default_warp_params;
209
210
0
  compute_global_motion_for_ref_frame(
211
0
      cpi, ref_buf, frame, num_src_corners, src_corners, src_buffer,
212
0
      params_by_motion, segment_map, segment_map_w, segment_map_h, ref_params);
213
0
}
214
215
// Loops over valid reference frames and computes global motion estimation.
216
static AOM_INLINE void compute_global_motion_for_references(
217
    AV1_COMP *cpi, YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES],
218
    FrameDistPair reference_frame[REF_FRAMES - 1], int num_ref_frames,
219
    int num_src_corners, int *src_corners, unsigned char *src_buffer,
220
    MotionModel *params_by_motion, uint8_t *segment_map,
221
0
    const int segment_map_w, const int segment_map_h) {
222
  // Computation of frame corners for the source frame will be done already.
223
0
  assert(num_src_corners != -1);
224
0
  AV1_COMMON *const cm = &cpi->common;
225
  // Compute global motion w.r.t. reference frames starting from the nearest ref
226
  // frame in a given direction.
227
0
  for (int frame = 0; frame < num_ref_frames; frame++) {
228
0
    int ref_frame = reference_frame[frame].frame;
229
0
    av1_compute_gm_for_valid_ref_frames(
230
0
        cpi, ref_buf, ref_frame, num_src_corners, src_corners, src_buffer,
231
0
        params_by_motion, segment_map, segment_map_w, segment_map_h);
232
    // If global motion w.r.t. current ref frame is
233
    // INVALID/TRANSLATION/IDENTITY, skip the evaluation of global motion w.r.t
234
    // the remaining ref frames in that direction. The below exit is disabled
235
    // when ref frame distance w.r.t. current frame is zero. E.g.:
236
    // source_alt_ref_frame w.r.t. ARF frames.
237
0
    if (cpi->sf.gm_sf.prune_ref_frame_for_gm_search &&
238
0
        reference_frame[frame].distance != 0 &&
239
0
        cm->global_motion[ref_frame].wmtype != ROTZOOM)
240
0
      break;
241
0
  }
242
0
}
243
244
// Compares the distance in 'a' and 'b'. Returns 1 if the frame corresponding to
245
// 'a' is farther, -1 if the frame corresponding to 'b' is farther, 0 otherwise.
246
0
static int compare_distance(const void *a, const void *b) {
247
0
  const int diff =
248
0
      ((FrameDistPair *)a)->distance - ((FrameDistPair *)b)->distance;
249
0
  if (diff > 0)
250
0
    return 1;
251
0
  else if (diff < 0)
252
0
    return -1;
253
0
  return 0;
254
0
}
255
256
0
static int disable_gm_search_based_on_stats(const AV1_COMP *const cpi) {
257
0
  int is_gm_present = 1;
258
259
  // Check number of GM models only in GF groups with ARF frames. GM param
260
  // estimation is always done in the case of GF groups with no ARF frames (flat
261
  // gops)
262
0
  if (cpi->ppi->gf_group.arf_index > -1) {
263
    // valid_gm_model_found is initialized to INT32_MAX in the beginning of
264
    // every GF group.
265
    // Therefore, GM param estimation is always done for all frames until
266
    // atleast 1 frame each of ARF_UPDATE, INTNL_ARF_UPDATE and LF_UPDATE are
267
    // encoded in a GF group For subsequent frames, GM param estimation is
268
    // disabled, if no valid models have been found in all the three update
269
    // types.
270
0
    is_gm_present = (cpi->ppi->valid_gm_model_found[ARF_UPDATE] != 0) ||
271
0
                    (cpi->ppi->valid_gm_model_found[INTNL_ARF_UPDATE] != 0) ||
272
0
                    (cpi->ppi->valid_gm_model_found[LF_UPDATE] != 0);
273
0
  }
274
0
  return !is_gm_present;
275
0
}
276
277
// Prunes reference frames for global motion estimation based on the speed
278
// feature 'gm_search_type'.
279
0
static int do_gm_search_logic(SPEED_FEATURES *const sf, int frame) {
280
0
  (void)frame;
281
0
  switch (sf->gm_sf.gm_search_type) {
282
0
    case GM_FULL_SEARCH: return 1;
283
0
    case GM_REDUCED_REF_SEARCH_SKIP_L2_L3:
284
0
      return !(frame == LAST2_FRAME || frame == LAST3_FRAME);
285
0
    case GM_REDUCED_REF_SEARCH_SKIP_L2_L3_ARF2:
286
0
      return !(frame == LAST2_FRAME || frame == LAST3_FRAME ||
287
0
               (frame == ALTREF2_FRAME));
288
0
    case GM_DISABLE_SEARCH: return 0;
289
0
    default: assert(0);
290
0
  }
291
0
  return 1;
292
0
}
293
294
// Populates valid reference frames in past/future directions in
295
// 'reference_frames' and their count in 'num_ref_frames'.
296
static AOM_INLINE void update_valid_ref_frames_for_gm(
297
    AV1_COMP *cpi, YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES],
298
    FrameDistPair reference_frames[MAX_DIRECTIONS][REF_FRAMES - 1],
299
0
    int *num_ref_frames) {
300
0
  AV1_COMMON *const cm = &cpi->common;
301
0
  int *num_past_ref_frames = &num_ref_frames[0];
302
0
  int *num_future_ref_frames = &num_ref_frames[1];
303
0
  const GF_GROUP *gf_group = &cpi->ppi->gf_group;
304
0
  int ref_pruning_enabled = is_frame_eligible_for_ref_pruning(
305
0
      gf_group, cpi->sf.inter_sf.selective_ref_frame, 1, cpi->gf_frame_index);
306
0
  int cur_frame_gm_disabled = 0;
307
308
0
  if (cpi->sf.gm_sf.disable_gm_search_based_on_stats) {
309
0
    cur_frame_gm_disabled = disable_gm_search_based_on_stats(cpi);
310
0
  }
311
312
0
  for (int frame = ALTREF_FRAME; frame >= LAST_FRAME; --frame) {
313
0
    const MV_REFERENCE_FRAME ref_frame[2] = { frame, NONE_FRAME };
314
0
    RefCntBuffer *buf = get_ref_frame_buf(cm, frame);
315
0
    const int ref_disabled =
316
0
        !(cpi->ref_frame_flags & av1_ref_frame_flag_list[frame]);
317
0
    ref_buf[frame] = NULL;
318
0
    cm->global_motion[frame] = default_warp_params;
319
    // Skip global motion estimation for invalid ref frames
320
0
    if (buf == NULL ||
321
0
        (ref_disabled && cpi->sf.hl_sf.recode_loop != DISALLOW_RECODE)) {
322
0
      continue;
323
0
    } else {
324
0
      ref_buf[frame] = &buf->buf;
325
0
    }
326
327
0
    int prune_ref_frames =
328
0
        ref_pruning_enabled &&
329
0
        prune_ref_by_selective_ref_frame(cpi, NULL, ref_frame,
330
0
                                         cm->cur_frame->ref_display_order_hint);
331
332
0
    if (ref_buf[frame]->y_crop_width == cpi->source->y_crop_width &&
333
0
        ref_buf[frame]->y_crop_height == cpi->source->y_crop_height &&
334
0
        do_gm_search_logic(&cpi->sf, frame) && !prune_ref_frames &&
335
0
        !cur_frame_gm_disabled) {
336
0
      assert(ref_buf[frame] != NULL);
337
0
      const int relative_frame_dist = av1_encoder_get_relative_dist(
338
0
          buf->display_order_hint, cm->cur_frame->display_order_hint);
339
      // Populate past and future ref frames.
340
      // reference_frames[0][] indicates past direction and
341
      // reference_frames[1][] indicates future direction.
342
0
      if (relative_frame_dist <= 0) {
343
0
        reference_frames[0][*num_past_ref_frames].distance =
344
0
            abs(relative_frame_dist);
345
0
        reference_frames[0][*num_past_ref_frames].frame = frame;
346
0
        (*num_past_ref_frames)++;
347
0
      } else {
348
0
        reference_frames[1][*num_future_ref_frames].distance =
349
0
            abs(relative_frame_dist);
350
0
        reference_frames[1][*num_future_ref_frames].frame = frame;
351
0
        (*num_future_ref_frames)++;
352
0
      }
353
0
    }
354
0
  }
355
0
}
356
357
// Allocates and initializes memory for segment_map and MotionModel.
358
static AOM_INLINE void alloc_global_motion_data(MotionModel *params_by_motion,
359
                                                uint8_t **segment_map,
360
                                                const int segment_map_w,
361
0
                                                const int segment_map_h) {
362
0
  for (int m = 0; m < RANSAC_NUM_MOTIONS; m++) {
363
0
    av1_zero(params_by_motion[m]);
364
0
    params_by_motion[m].inliers =
365
0
        aom_malloc(sizeof(*(params_by_motion[m].inliers)) * 2 * MAX_CORNERS);
366
0
  }
367
368
0
  *segment_map = (uint8_t *)aom_malloc(sizeof(*segment_map) * segment_map_w *
369
0
                                       segment_map_h);
370
0
  av1_zero_array(*segment_map, segment_map_w * segment_map_h);
371
0
}
372
373
// Deallocates segment_map and inliers.
374
static AOM_INLINE void dealloc_global_motion_data(MotionModel *params_by_motion,
375
0
                                                  uint8_t *segment_map) {
376
0
  aom_free(segment_map);
377
378
0
  for (int m = 0; m < RANSAC_NUM_MOTIONS; m++) {
379
0
    aom_free(params_by_motion[m].inliers);
380
0
  }
381
0
}
382
383
// Initializes parameters used for computing global motion.
384
0
static AOM_INLINE void setup_global_motion_info_params(AV1_COMP *cpi) {
385
0
  GlobalMotionInfo *const gm_info = &cpi->gm_info;
386
0
  YV12_BUFFER_CONFIG *source = cpi->source;
387
388
0
  gm_info->src_buffer = source->y_buffer;
389
0
  if (source->flags & YV12_FLAG_HIGHBITDEPTH) {
390
    // The source buffer is 16-bit, so we need to convert to 8 bits for the
391
    // following code. We cache the result until the source frame is released.
392
0
    gm_info->src_buffer =
393
0
        av1_downconvert_frame(source, cpi->common.seq_params->bit_depth);
394
0
  }
395
396
0
  gm_info->segment_map_w =
397
0
      (source->y_width + WARP_ERROR_BLOCK) >> WARP_ERROR_BLOCK_LOG;
398
0
  gm_info->segment_map_h =
399
0
      (source->y_height + WARP_ERROR_BLOCK) >> WARP_ERROR_BLOCK_LOG;
400
401
0
  memset(gm_info->reference_frames, -1,
402
0
         sizeof(gm_info->reference_frames[0][0]) * MAX_DIRECTIONS *
403
0
             (REF_FRAMES - 1));
404
0
  av1_zero(gm_info->num_ref_frames);
405
406
  // Populate ref_buf for valid ref frames in global motion
407
0
  update_valid_ref_frames_for_gm(cpi, gm_info->ref_buf,
408
0
                                 gm_info->reference_frames,
409
0
                                 gm_info->num_ref_frames);
410
411
  // Sort the past and future ref frames in the ascending order of their
412
  // distance from the current frame. reference_frames[0] => past direction
413
  // and reference_frames[1] => future direction.
414
0
  qsort(gm_info->reference_frames[0], gm_info->num_ref_frames[0],
415
0
        sizeof(gm_info->reference_frames[0][0]), compare_distance);
416
0
  qsort(gm_info->reference_frames[1], gm_info->num_ref_frames[1],
417
0
        sizeof(gm_info->reference_frames[1][0]), compare_distance);
418
419
0
  gm_info->num_src_corners = -1;
420
  // If atleast one valid reference frame exists in past/future directions,
421
  // compute interest points of source frame using FAST features.
422
0
  if (gm_info->num_ref_frames[0] > 0 || gm_info->num_ref_frames[1] > 0) {
423
0
    gm_info->num_src_corners = av1_fast_corner_detect(
424
0
        gm_info->src_buffer, source->y_width, source->y_height,
425
0
        source->y_stride, gm_info->src_corners, MAX_CORNERS);
426
0
  }
427
0
}
428
429
// Computes global motion w.r.t. valid reference frames.
430
0
static AOM_INLINE void global_motion_estimation(AV1_COMP *cpi) {
431
0
  GlobalMotionInfo *const gm_info = &cpi->gm_info;
432
0
  MotionModel params_by_motion[RANSAC_NUM_MOTIONS];
433
0
  uint8_t *segment_map = NULL;
434
435
0
  alloc_global_motion_data(params_by_motion, &segment_map,
436
0
                           gm_info->segment_map_w, gm_info->segment_map_h);
437
438
  // Compute global motion w.r.t. past reference frames and future reference
439
  // frames
440
0
  for (int dir = 0; dir < MAX_DIRECTIONS; dir++) {
441
0
    if (gm_info->num_ref_frames[dir] > 0)
442
0
      compute_global_motion_for_references(
443
0
          cpi, gm_info->ref_buf, gm_info->reference_frames[dir],
444
0
          gm_info->num_ref_frames[dir], gm_info->num_src_corners,
445
0
          gm_info->src_corners, gm_info->src_buffer, params_by_motion,
446
0
          segment_map, gm_info->segment_map_w, gm_info->segment_map_h);
447
0
  }
448
449
0
  dealloc_global_motion_data(params_by_motion, segment_map);
450
0
}
451
452
// Global motion estimation for the current frame is computed.This computation
453
// happens once per frame and the winner motion model parameters are stored in
454
// cm->cur_frame->global_motion.
455
1.26k
void av1_compute_global_motion_facade(AV1_COMP *cpi) {
456
1.26k
  AV1_COMMON *const cm = &cpi->common;
457
1.26k
  GlobalMotionInfo *const gm_info = &cpi->gm_info;
458
459
1.26k
  if (cpi->oxcf.tool_cfg.enable_global_motion) {
460
1.26k
    if (cpi->gf_frame_index == 0) {
461
10.0k
      for (int i = 0; i < FRAME_UPDATE_TYPES; i++) {
462
8.83k
        cpi->ppi->valid_gm_model_found[i] = INT32_MAX;
463
#if CONFIG_FRAME_PARALLEL_ENCODE && CONFIG_FPMT_TEST
464
        if (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE)
465
          cpi->ppi->temp_valid_gm_model_found[i] = INT32_MAX;
466
#endif
467
8.83k
      }
468
1.26k
    }
469
1.26k
  }
470
471
1.26k
  if (cpi->common.current_frame.frame_type == INTER_FRAME && cpi->source &&
472
1.26k
      cpi->oxcf.tool_cfg.enable_global_motion && !gm_info->search_done) {
473
0
    setup_global_motion_info_params(cpi);
474
0
    if (cpi->mt_info.num_workers > 1)
475
0
      av1_global_motion_estimation_mt(cpi);
476
0
    else
477
0
      global_motion_estimation(cpi);
478
0
    gm_info->search_done = 1;
479
0
  }
480
1.26k
  memcpy(cm->cur_frame->global_motion, cm->global_motion,
481
1.26k
         sizeof(cm->cur_frame->global_motion));
482
1.26k
}