Coverage Report

Created: 2026-05-16 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/svt-av1/Source/Lib/Codec/global_me.c
Line
Count
Source
1
/*
2
* Copyright(c) 2019 Intel Corporation
3
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
4
*
5
* This source code is subject to the terms of the BSD 2 Clause License and
6
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
7
* was not distributed with this source code in the LICENSE file, you can
8
* obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open
9
* Media Patent License 1.0 was not distributed with this source code in the
10
* PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license.
11
*/
12
13
#include <stdlib.h>
14
15
#include "global_me.h"
16
#include "global_me_cost.h"
17
#include "reference_object.h"
18
#include "me_process.h"
19
#include "warped_motion.h"
20
#include "utility.h"
21
#include "global_motion.h"
22
#include "corner_detect.h"
23
#include "aom_dsp_rtcd.h"
24
// Normalized distortion-based thresholds
25
0
#define GMV_ME_SAD_TH_0 1
26
0
#define GMV_ME_SAD_TH_1 5
27
0
#define GMV_ME_SAD_TH_2 10
28
#define GMV_PIC_VAR_TH 750
29
30
static void compute_global_motion(PictureParentControlSet* pcs, int* frm_corners, int num_frm_corners,
31
                                  EbPictureBufferDesc* det_input_pic, //src frame for detection
32
                                  EbPictureBufferDesc* det_ref_pic, //ref frame for detection
33
                                  EbPictureBufferDesc* input_pic, //src frame for refinement
34
                                  EbPictureBufferDesc* ref_pic, //ref frame for refinement
35
                                  uint8_t              sf, //downsacle factor between det and refinement
36
                                  uint8_t chess_refn, WarpedMotionParams* best_wm, int allow_high_precision_mv,
37
                                  uint8_t list_idx, uint8_t ref_idx);
38
39
//gm pre-processing pass, is an analysis pass done at the same time TF to detect any GM activity in
40
//the clip. in case of detection in this pre-processing phase, a second GM detection pass is invoked.
41
0
void svt_aom_gm_pre_processor(PictureParentControlSet* pcs, PictureParentControlSet** pcs_list) {
42
0
    uint8_t              detect_refn_scale_factor;
43
0
    EbPictureBufferDesc *input_detection, *ref_detection, *input_refinement, *ref_refinement;
44
0
    WarpedMotionParams   wm_tmp[MAX_NUM_OF_REF_PIC_LIST];
45
46
    //fill gm controls to be used locally for the preprocessor gm pass.
47
    //final gm controls will be set later for the final gm detection pass.
48
0
    pcs->gm_ctrls.enabled                 = 1;
49
0
    pcs->gm_ctrls.identiy_exit            = 1;
50
0
    pcs->gm_ctrls.search_start_model      = TRANSLATION;
51
0
    pcs->gm_ctrls.search_end_model        = ROTZOOM;
52
0
    pcs->gm_ctrls.bypass_based_on_me      = 1;
53
0
    pcs->gm_ctrls.params_refinement_steps = 2;
54
0
    pcs->gm_ctrls.downsample_level        = GM_FULL;
55
0
    pcs->gm_ctrls.corners                 = 2;
56
0
    pcs->gm_ctrls.chess_rfn               = 1;
57
0
    pcs->gm_ctrls.match_sz                = 7;
58
0
    pcs->gm_ctrls.inj_psq_glb             = true;
59
0
    pcs->gm_ctrls.rfn_early_exit          = 1;
60
0
    pcs->gm_ctrls.correspondence_method   = CORNERS;
61
62
0
    PictureParentControlSet* ref_pcs_list[2];
63
0
    PictureParentControlSet* cur_pcs   = pcs_list[0];
64
0
    uint8_t                  list_size = pcs->past_altref_nframes + pcs->future_altref_nframes + 1;
65
0
    ref_pcs_list[0]                    = list_size > 0 ? pcs_list[1] : NULL;
66
0
    ref_pcs_list[1]                    = list_size > 5 ? pcs_list[5] : list_size > 2 ? pcs_list[list_size - 1] : NULL;
67
68
0
    EbPaReferenceObject* src_object = (EbPaReferenceObject*)cur_pcs->pa_ref_pic_wrapper->object_ptr;
69
0
    EbPictureBufferDesc* input_pic  = src_object->input_padded_pic;
70
0
    EbPictureBufferDesc* quart_pic  = src_object->quarter_downsampled_picture_ptr;
71
0
    EbPictureBufferDesc* sixt_pic   = src_object->sixteenth_downsampled_picture_ptr;
72
73
0
    if (pcs->gm_ctrls.downsample_level == GM_DOWN16) {
74
0
        input_detection  = sixt_pic;
75
0
        input_refinement = sixt_pic;
76
0
    } else if (pcs->gm_ctrls.downsample_level == GM_DOWN) {
77
0
        input_detection  = quart_pic;
78
0
        input_refinement = quart_pic;
79
0
    } else {
80
0
        input_detection  = input_pic;
81
0
        input_refinement = input_pic;
82
0
    }
83
84
0
    int frm_corners[2 * MAX_CORNERS];
85
0
    int num_frm_corners = svt_av1_fast_corner_detect(input_detection->y_buffer,
86
0
                                                     input_detection->width,
87
0
                                                     input_detection->height,
88
0
                                                     input_detection->y_stride,
89
0
                                                     frm_corners,
90
0
                                                     MAX_CORNERS);
91
92
0
    for (uint32_t ref_idx = 0; ref_idx < 2; ++ref_idx) {
93
0
        if (ref_pcs_list[ref_idx] == NULL || ref_pcs_list[ref_idx] == pcs /*as curr might have TF underway*/) {
94
0
            continue;
95
0
        }
96
0
        EbPaReferenceObject* ref_obj       = ref_pcs_list[ref_idx]->pa_ref_pic_wrapper->object_ptr;
97
0
        EbPictureBufferDesc* ref_pic       = ref_obj->input_padded_pic;
98
0
        EbPictureBufferDesc* quart_ref_pic = ref_obj->quarter_downsampled_picture_ptr;
99
0
        EbPictureBufferDesc* sixt_ref_pic  = ref_obj->sixteenth_downsampled_picture_ptr;
100
101
0
        if (pcs->gm_ctrls.downsample_level == GM_DOWN16) {
102
0
            ref_detection            = sixt_ref_pic;
103
0
            ref_refinement           = sixt_ref_pic;
104
0
            detect_refn_scale_factor = 1;
105
0
        } else if (pcs->gm_ctrls.downsample_level == GM_DOWN) {
106
0
            ref_detection            = quart_ref_pic;
107
0
            ref_refinement           = quart_ref_pic;
108
0
            detect_refn_scale_factor = 1;
109
0
        } else {
110
0
            ref_detection            = ref_pic;
111
0
            ref_refinement           = ref_pic;
112
0
            detect_refn_scale_factor = 1;
113
0
        }
114
115
0
        compute_global_motion(
116
0
            pcs,
117
0
            frm_corners,
118
0
            num_frm_corners,
119
0
            input_detection,
120
0
            ref_detection,
121
0
            input_refinement,
122
0
            ref_refinement,
123
0
            detect_refn_scale_factor,
124
0
            pcs->gm_ctrls.chess_rfn,
125
0
            &wm_tmp[0],
126
0
            pcs->frm_hdr.allow_high_precision_mv,
127
0
            0, //list_idx/ref_idx used for generating correspondences when correspondence_method is MV-based. That is incompatable with pp, so just send 0; it won't be used
128
0
            0);
129
130
0
        if (wm_tmp[0].wmtype != IDENTITY) {
131
0
            pcs->gm_pp_detected = true;
132
0
            break;
133
0
        }
134
0
    }
135
0
}
136
137
0
void svt_aom_global_motion_estimation(PictureParentControlSet* pcs, EbPictureBufferDesc* input_pic) {
138
    // Get downsampled pictures with a downsampling factor of 2 in each dimension
139
0
    EbPaReferenceObject* pa_reference_object   = (EbPaReferenceObject*)pcs->pa_ref_pic_wrapper->object_ptr;
140
0
    EbPictureBufferDesc* quarter_picture_ptr   = pa_reference_object->quarter_downsampled_picture_ptr;
141
0
    EbPictureBufferDesc* sixteenth_picture_ptr = pa_reference_object->sixteenth_downsampled_picture_ptr;
142
    // Initilize global motion to be OFF for all references frames.
143
0
    memset(pcs->is_global_motion, false, MAX_NUM_OF_REF_PIC_LIST * REF_LIST_MAX_DEPTH);
144
    // Initilize wmtype to be IDENTITY for all references frames
145
0
    for (uint32_t list_index = REF_LIST_0; list_index < MAX_NUM_OF_REF_PIC_LIST; ++list_index) {
146
0
        for (uint32_t ref_pic_index = 0; ref_pic_index < REF_LIST_MAX_DEPTH; ++ref_pic_index) {
147
0
            pcs->global_motion_estimation[list_index][ref_pic_index].wmtype = IDENTITY;
148
0
        }
149
0
    }
150
    // Derive total_me_sad
151
0
    uint32_t total_me_sad = 0;
152
0
    uint32_t total_gm_sbs = 0;
153
0
    for (uint16_t b64_index = 0; b64_index < pcs->b64_total_count; ++b64_index) {
154
0
        total_me_sad += pcs->rc_me_distortion[b64_index];
155
0
        total_gm_sbs += pcs->rc_me_allow_gm[b64_index];
156
0
    }
157
0
    uint32_t average_me_sad = total_me_sad / (input_pic->width * input_pic->height);
158
    // Derive global_motion_estimation level
159
160
0
    uint8_t global_motion_estimation_level;
161
    // 0: skip GMV params derivation
162
    // 1: use up to 1 ref per list @ the GMV params derivation
163
    // 2: use up to 2 ref per list @ the GMV params derivation
164
    // 3: all refs @ the GMV params derivation
165
0
    if (average_me_sad < (GMV_ME_SAD_TH_0)) {
166
0
        global_motion_estimation_level = 0;
167
0
    } else if (average_me_sad < (GMV_ME_SAD_TH_1)) {
168
0
        global_motion_estimation_level = 1;
169
0
    } else if (average_me_sad < (GMV_ME_SAD_TH_2)) {
170
0
        global_motion_estimation_level = 2;
171
0
    } else {
172
0
        global_motion_estimation_level = 3;
173
0
    }
174
175
0
    if (pcs->gm_ctrls.downsample_level == GM_ADAPT_0) {
176
0
        pcs->gm_downsample_level = (average_me_sad < GMV_ME_SAD_TH_1) ? GM_DOWN : GM_FULL;
177
0
    } else if (pcs->gm_ctrls.downsample_level == GM_ADAPT_1) {
178
0
        pcs->gm_downsample_level = (average_me_sad < GMV_ME_SAD_TH_2) ? GM_DOWN16 : GM_DOWN;
179
0
    } else {
180
0
        pcs->gm_downsample_level = pcs->gm_ctrls.downsample_level;
181
0
    }
182
183
0
    if (pcs->gm_ctrls.bypass_based_on_me) {
184
0
        if ((total_gm_sbs < (uint32_t)(pcs->b64_total_count >> 1))) {
185
0
            global_motion_estimation_level = 0;
186
0
        }
187
0
    }
188
0
    if (global_motion_estimation_level) {
189
0
        EbPictureBufferDesc* input_detection;
190
0
        if (pcs->gm_downsample_level == GM_DOWN16) {
191
0
            input_detection = sixteenth_picture_ptr;
192
0
        } else if (pcs->gm_downsample_level == GM_DOWN) {
193
0
            input_detection = quarter_picture_ptr;
194
0
        } else {
195
0
            input_detection = input_pic;
196
0
        }
197
198
0
        int frm_corners[2 * MAX_CORNERS];
199
0
        int num_frm_corners = 0;
200
        // If generating the correspondences from corners, search for the current frame's corners outside the loop over all ref pics
201
0
        if (pcs->gm_ctrls.correspondence_method == CORNERS) {
202
0
            num_frm_corners = svt_av1_fast_corner_detect(input_detection->y_buffer,
203
0
                                                         input_detection->width,
204
0
                                                         input_detection->height,
205
0
                                                         input_detection->y_stride,
206
0
                                                         frm_corners,
207
0
                                                         MAX_CORNERS);
208
0
        }
209
0
        for (uint32_t list_index = REF_LIST_0; list_index < MAX_NUM_OF_REF_PIC_LIST; ++list_index) {
210
0
            uint32_t num_of_ref_pic_to_search = list_index == REF_LIST_0 ? pcs->ref_list0_count_try
211
0
                                                                         : pcs->ref_list1_count_try;
212
0
            if (global_motion_estimation_level == 1) {
213
0
                num_of_ref_pic_to_search = MIN(num_of_ref_pic_to_search, 1);
214
0
            } else if (global_motion_estimation_level == 2) {
215
0
                num_of_ref_pic_to_search = MIN(num_of_ref_pic_to_search, 2);
216
0
            }
217
218
0
            if (pcs->temporal_layer_index > 0 && pcs->gm_ctrls.ref_idx0_only) {
219
0
                num_of_ref_pic_to_search = MIN(num_of_ref_pic_to_search, 1);
220
0
            }
221
222
            // Ref Picture Loop
223
0
            for (uint32_t ref_pic_index = 0; ref_pic_index < num_of_ref_pic_to_search; ++ref_pic_index) {
224
0
                EbPaReferenceObject* ref_object =
225
0
                    (EbPaReferenceObject*)pcs->ref_pa_pic_ptr_array[list_index][ref_pic_index]->object_ptr;
226
227
0
                uint8_t              detect_refine_scale_factor;
228
0
                EbPictureBufferDesc *ref_detection, *ref_refinement;
229
0
                uint8_t              chess_refn;
230
0
                EbPictureBufferDesc* ref_picture_ptr       = ref_object->input_padded_pic;
231
0
                EbPictureBufferDesc* quarter_ref_pic_ptr   = ref_object->quarter_downsampled_picture_ptr;
232
0
                EbPictureBufferDesc* sixteenth_ref_pic_ptr = ref_object->sixteenth_downsampled_picture_ptr;
233
234
0
                EbPictureBufferDesc* input_refinement;
235
236
0
                if (pcs->gm_downsample_level == GM_DOWN16) {
237
0
                    input_detection = sixteenth_picture_ptr;
238
0
                    ref_detection   = sixteenth_ref_pic_ptr;
239
240
0
                    input_refinement = sixteenth_picture_ptr;
241
0
                    ref_refinement   = sixteenth_ref_pic_ptr;
242
243
0
                    detect_refine_scale_factor = 1;
244
0
                    chess_refn                 = 0;
245
0
                } else if (pcs->gm_downsample_level == GM_DOWN) {
246
0
                    input_detection = quarter_picture_ptr;
247
0
                    ref_detection   = quarter_ref_pic_ptr;
248
249
0
                    input_refinement = quarter_picture_ptr;
250
0
                    ref_refinement   = quarter_ref_pic_ptr;
251
252
0
                    detect_refine_scale_factor = 1;
253
0
                    chess_refn                 = GM_ADAPT_1 ? pcs->gm_ctrls.chess_rfn : 0;
254
0
                } else {
255
0
                    input_detection = input_pic;
256
0
                    ref_detection   = ref_picture_ptr;
257
258
0
                    input_refinement = input_pic;
259
0
                    ref_refinement   = ref_picture_ptr;
260
261
0
                    detect_refine_scale_factor = 1;
262
0
                    chess_refn                 = pcs->gm_ctrls.chess_rfn;
263
0
                }
264
0
                compute_global_motion(pcs,
265
0
                                      frm_corners,
266
0
                                      num_frm_corners,
267
0
                                      input_detection,
268
0
                                      ref_detection,
269
0
                                      input_refinement,
270
0
                                      ref_refinement,
271
0
                                      detect_refine_scale_factor,
272
0
                                      chess_refn,
273
0
                                      &pcs->global_motion_estimation[list_index][ref_pic_index],
274
0
                                      pcs->frm_hdr.allow_high_precision_mv,
275
0
                                      list_index,
276
0
                                      ref_pic_index);
277
0
            }
278
279
0
            if (pcs->gm_ctrls.identiy_exit) {
280
0
                if (list_index == 0) {
281
0
                    if (pcs->global_motion_estimation[0][0].wmtype == IDENTITY) {
282
0
                        break;
283
0
                    }
284
0
                }
285
0
            }
286
0
        }
287
0
    }
288
289
0
    pcs->is_gm_on = 0;
290
0
    for (uint32_t list_index = REF_LIST_0; list_index < MAX_NUM_OF_REF_PIC_LIST; ++list_index) {
291
0
        const uint32_t num_of_ref_pic_to_search = list_index == REF_LIST_0 ? pcs->ref_list0_count
292
0
                                                                           : pcs->ref_list1_count;
293
        // Ref Picture Loop
294
0
        for (uint32_t ref_pic_index = 0; ref_pic_index < num_of_ref_pic_to_search; ++ref_pic_index) {
295
0
            pcs->is_global_motion[list_index][ref_pic_index] = false;
296
0
            if (pcs->global_motion_estimation[list_index][ref_pic_index].wmtype != IDENTITY) {
297
0
                pcs->is_global_motion[list_index][ref_pic_index] = true;
298
299
0
                pcs->is_gm_on = 1;
300
0
            }
301
0
        }
302
0
    }
303
0
}
304
305
0
void svt_aom_upscale_wm_params(WarpedMotionParams* wm_params, uint8_t scale_factor) {
306
    // Upscale the translation parameters by 2 or 4,
307
    // because the search is done on a down-sampled
308
    // version of the source picture
309
0
    if (scale_factor > 1) {
310
0
        wm_params->wmmat[0] = (int32_t)clamp(wm_params->wmmat[0] * scale_factor,
311
0
                                             GM_TRANS_MIN * GM_TRANS_DECODE_FACTOR,
312
0
                                             GM_TRANS_MAX * GM_TRANS_DECODE_FACTOR);
313
314
0
        wm_params->wmmat[1] = (int32_t)clamp(wm_params->wmmat[1] * scale_factor,
315
0
                                             GM_TRANS_MIN * GM_TRANS_DECODE_FACTOR,
316
0
                                             GM_TRANS_MAX * GM_TRANS_DECODE_FACTOR);
317
0
    }
318
0
}
319
320
static void compute_global_motion(PictureParentControlSet* pcs, int* frm_corners, int num_frm_corners,
321
                                  EbPictureBufferDesc* det_input_pic, //src frame for detection
322
                                  EbPictureBufferDesc* det_ref_pic, //ref frame for detection
323
                                  EbPictureBufferDesc* input_pic, //src frame for refinement
324
                                  EbPictureBufferDesc* ref_pic, //ref frame for refinement
325
                                  uint8_t              sf, //downsacle factor between det and refinement
326
                                  uint8_t chess_refn, WarpedMotionParams* best_wm, int allow_high_precision_mv,
327
0
                                  uint8_t list_idx, uint8_t ref_idx) {
328
0
    WarpedMotionParams        global_motion = default_warp_params;
329
0
    const WarpedMotionParams* ref_params    = &default_warp_params;
330
0
    unsigned char*            frm_buffer    = input_pic->y_buffer;
331
0
    unsigned char*            ref_buffer    = ref_pic->y_buffer;
332
333
0
    const uint32_t ref_sad_error = svt_nxm_sad_kernel(
334
0
        ref_buffer, ref_pic->y_stride, frm_buffer, input_pic->y_stride, input_pic->height, input_pic->width);
335
336
0
    if (ref_sad_error == 0) {
337
0
        *best_wm = global_motion;
338
0
        return;
339
0
    }
340
341
0
    unsigned char* det_frm_buffer = det_input_pic->y_buffer;
342
0
    unsigned char* det_ref_buffer = det_ref_pic->y_buffer;
343
344
0
    int size_correspondence = num_frm_corners;
345
0
    if (pcs->gm_ctrls.correspondence_method < CORNERS) {
346
0
        const int mv_search_lvl     = pcs->gm_ctrls.correspondence_method;
347
0
        const int blocks_per_line   = 1 << mv_search_lvl;
348
0
        const int num_blocks_per_sb = blocks_per_line * blocks_per_line;
349
0
        size_correspondence         = num_blocks_per_sb * pcs->b64_total_count;
350
0
    }
351
0
    int             num_correspondences = 0;
352
0
    Correspondence* correspondences;
353
0
    EB_MALLOC_ARRAY_NO_CHECK(correspondences, size_correspondence);
354
0
    gm_compute_correspondence(pcs,
355
0
                              det_frm_buffer,
356
0
                              det_input_pic->width,
357
0
                              det_input_pic->height,
358
0
                              det_input_pic->y_stride,
359
0
                              frm_corners,
360
0
                              num_frm_corners,
361
0
                              det_ref_buffer,
362
0
                              det_ref_pic->y_stride,
363
0
                              correspondences,
364
0
                              &num_correspondences,
365
0
                              list_idx,
366
0
                              ref_idx);
367
368
0
    MotionModel params_by_motion[RANSAC_NUM_MOTIONS];
369
0
    for (int m = 0; m < RANSAC_NUM_MOTIONS; m++) {
370
0
        memset(&params_by_motion[m], 0, sizeof(params_by_motion[m]));
371
0
        EB_MALLOC_ARRAY_NO_CHECK(params_by_motion[m].inliers, 2 * size_correspondence);
372
0
    }
373
374
0
    assert(pcs->gm_ctrls.search_start_model > IDENTITY);
375
0
    assert(pcs->gm_ctrls.search_end_model <= AFFINE);
376
0
    assert(pcs->gm_ctrls.search_start_model <= pcs->gm_ctrls.search_end_model);
377
0
    for (TransformationType model = pcs->gm_ctrls.search_start_model; model <= pcs->gm_ctrls.search_end_model;
378
0
         ++model) {
379
0
        int64_t best_warp_error = INT64_MAX;
380
381
        // Take the pre-computed correspondences (between cur frame/ref frame) and
382
        // determine the parameters for the current GM model
383
0
        determine_gm_params(model, params_by_motion, RANSAC_NUM_MOTIONS, correspondences, num_correspondences);
384
385
0
        for (unsigned i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
386
0
            if (params_by_motion[i].num_inliers == 0) {
387
0
                continue;
388
0
            }
389
0
            WarpedMotionParams tmp_wm_params;
390
0
            svt_av1_convert_model_to_params(params_by_motion[i].params, &tmp_wm_params);
391
392
            //upscale the param before doing refinement
393
0
            svt_aom_upscale_wm_params(&tmp_wm_params, sf);
394
0
            if (tmp_wm_params.wmtype != IDENTITY) {
395
0
                const int params_cost = svt_aom_gm_get_params_cost(&tmp_wm_params, ref_params, allow_high_precision_mv);
396
397
0
                const int64_t warp_error = svt_av1_refine_integerized_param(&pcs->gm_ctrls,
398
0
                                                                            &tmp_wm_params,
399
0
                                                                            tmp_wm_params.wmtype,
400
0
                                                                            ref_buffer,
401
0
                                                                            ref_pic->width,
402
0
                                                                            ref_pic->height,
403
0
                                                                            ref_pic->y_stride,
404
0
                                                                            frm_buffer,
405
0
                                                                            input_pic->width,
406
0
                                                                            input_pic->height,
407
0
                                                                            input_pic->y_stride,
408
0
                                                                            pcs->gm_ctrls.params_refinement_steps,
409
0
                                                                            chess_refn,
410
0
                                                                            best_warp_error,
411
0
                                                                            ref_sad_error,
412
0
                                                                            params_cost);
413
0
                if (warp_error < best_warp_error) {
414
0
                    best_warp_error = warp_error;
415
                    // Save the wm_params modified by
416
                    // svt_av1_refine_integerized_param() rather than motion index to
417
                    // avoid rerunning refine() below.
418
0
                    svt_memcpy(&global_motion, &tmp_wm_params, sizeof(WarpedMotionParams));
419
0
                }
420
0
            }
421
0
        }
422
423
0
        if (!svt_get_shear_params(&global_motion) || global_motion.wmtype != model) {
424
0
            global_motion = default_warp_params;
425
0
        }
426
427
0
        if (global_motion.wmtype == IDENTITY) {
428
0
            continue;
429
0
        }
430
431
        // If the best error advantage found doesn't meet the threshold for
432
        // this motion type, revert to IDENTITY.
433
0
        if (!svt_av1_is_enough_erroradvantage(
434
0
                (double)best_warp_error / ref_sad_error,
435
0
                svt_aom_gm_get_params_cost(&global_motion, ref_params, allow_high_precision_mv),
436
0
                GM_ERRORADV_TR_0)) {
437
0
            global_motion = default_warp_params;
438
0
        }
439
0
        if (global_motion.wmtype != IDENTITY) {
440
0
            break;
441
0
        }
442
0
    }
443
444
0
    *best_wm = global_motion;
445
446
0
    for (int m = 0; m < RANSAC_NUM_MOTIONS; m++) {
447
0
        EB_FREE(params_by_motion[m].inliers);
448
0
    }
449
    EB_FREE(correspondences);
450
0
}