/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(¶ms_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 | } |