Line data Source code
1 : /*
2 : * Copyright(c) 2019 Intel Corporation
3 : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 : */
5 :
6 : /*
7 : * Copyright (c) 2016, Alliance for Open Media. All rights reserved
8 : *
9 : * This source code is subject to the terms of the BSD 2 Clause License and
10 : * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
11 : * was not distributed with this source code in the LICENSE file, you can
12 : * obtain it at www.aomedia.org/license/software. If the Alliance for Open
13 : * Media Patent License 1.0 was not distributed with this source code in the
14 : * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
15 : */
16 :
17 : #include <stdlib.h>
18 :
19 : #include "EbGlobalMotionEstimation.h"
20 : #include "EbGlobalMotionEstimationCost.h"
21 : #include "EbReferenceObject.h"
22 :
23 : #include "global_motion.h"
24 : #include "corner_detect.h"
25 :
26 :
27 :
28 60 : void global_motion_estimation(PictureParentControlSet *picture_control_set_ptr,
29 : MeContext *context_ptr,
30 : EbPictureBufferDesc *input_picture_ptr)
31 : {
32 60 : uint32_t numOfListToSearch = (picture_control_set_ptr->slice_type == P_SLICE)
33 60 : ? (uint32_t)REF_LIST_0 : (uint32_t)REF_LIST_1;
34 :
35 177 : for (uint32_t listIndex = REF_LIST_0; listIndex <= numOfListToSearch; ++listIndex) {
36 :
37 : uint32_t num_of_ref_pic_to_search;
38 117 : if (context_ptr->me_alt_ref == EB_TRUE)
39 0 : num_of_ref_pic_to_search = 1;
40 : else
41 117 : num_of_ref_pic_to_search = picture_control_set_ptr->slice_type == P_SLICE
42 3 : ? picture_control_set_ptr->ref_list0_count
43 231 : : listIndex == REF_LIST_0
44 57 : ? picture_control_set_ptr->ref_list0_count
45 57 : : picture_control_set_ptr->ref_list1_count;
46 :
47 : // Limit the global motion search to the first frame types of ref lists
48 117 : num_of_ref_pic_to_search = MIN(num_of_ref_pic_to_search, 1);
49 :
50 : // Ref Picture Loop
51 230 : for (uint32_t ref_pic_index = 0; ref_pic_index < num_of_ref_pic_to_search;
52 113 : ++ref_pic_index)
53 : {
54 : EbPaReferenceObject *referenceObject;
55 :
56 113 : if (context_ptr->me_alt_ref == EB_TRUE)
57 0 : referenceObject = (EbPaReferenceObject *)context_ptr->alt_ref_reference_ptr;
58 : else
59 113 : referenceObject = (EbPaReferenceObject *)picture_control_set_ptr
60 113 : ->ref_pa_pic_ptr_array[listIndex][ref_pic_index]->object_ptr;
61 :
62 :
63 113 : EbPictureBufferDesc *ref_picture_ptr = (EbPictureBufferDesc*)referenceObject->input_padded_picture_ptr;
64 :
65 113 : compute_global_motion(input_picture_ptr, ref_picture_ptr,
66 : &picture_control_set_ptr->global_motion_estimation[listIndex][ref_pic_index],
67 113 : picture_control_set_ptr->frm_hdr.allow_high_precision_mv);
68 : }
69 : }
70 60 : }
71 :
72 :
73 0 : static INLINE int convert_to_trans_prec(int allow_hp, int coor) {
74 0 : if (allow_hp)
75 0 : return ROUND_POWER_OF_TWO_SIGNED(coor, WARPEDMODEL_PREC_BITS - 3);
76 : else
77 0 : return ROUND_POWER_OF_TWO_SIGNED(coor, WARPEDMODEL_PREC_BITS - 2) * 2;
78 : }
79 :
80 :
81 113 : void compute_global_motion(EbPictureBufferDesc *input_pic, EbPictureBufferDesc *ref_pic,
82 : EbWarpedMotionParams *bestWarpedMotion, int allow_high_precision_mv)
83 : {
84 : MotionModel params_by_motion[RANSAC_NUM_MOTIONS];
85 11413 : for (int m = 0; m < RANSAC_NUM_MOTIONS; m++) {
86 11300 : memset(¶ms_by_motion[m], 0, sizeof(params_by_motion[m]));
87 11300 : params_by_motion[m].inliers =
88 11300 : malloc(sizeof(*(params_by_motion[m].inliers)) * 2 * MAX_CORNERS);
89 : }
90 :
91 : const double *params_this_motion;
92 : int inliers_by_motion[RANSAC_NUM_MOTIONS];
93 : EbWarpedMotionParams tmp_wm_params;
94 : // clang-format off
95 : static const double kIdentityParams[MAX_PARAMDIM - 1] = {
96 : 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0
97 : };
98 : // clang-format on
99 :
100 : int frm_corners[2 * MAX_CORNERS];
101 113 : unsigned char *frm_buffer = input_pic->buffer_y + input_pic->origin_x + input_pic->origin_y * input_pic->stride_y;
102 113 : unsigned char *ref_buffer = ref_pic->buffer_y + ref_pic->origin_x + ref_pic->origin_y * ref_pic->stride_y;
103 :
104 113 : EbWarpedMotionParams global_motion = default_warp_params;
105 :
106 : // TODO: check ref_params
107 113 : const EbWarpedMotionParams *ref_params = &default_warp_params;
108 :
109 : {
110 : // compute interest points using FAST features
111 113 : int num_frm_corners = av1_fast_corner_detect(
112 113 : frm_buffer, input_pic->width, input_pic->height,
113 113 : input_pic->stride_y, frm_corners, MAX_CORNERS);
114 :
115 : TransformationType model;
116 : #define GLOBAL_TRANS_TYPES_ENC 3
117 :
118 113 : const GlobalMotionEstimationType gm_estimation_type = GLOBAL_MOTION_FEATURE_BASED;
119 113 : for (model = ROTZOOM; model <= GLOBAL_TRANS_TYPES_ENC; ++model) {
120 113 : int64_t best_warp_error = INT64_MAX;
121 : // Initially set all params to identity.
122 11413 : for (unsigned i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
123 11300 : memcpy(params_by_motion[i].params, kIdentityParams,
124 : (MAX_PARAMDIM - 1) * sizeof(*(params_by_motion[i].params)));
125 : }
126 :
127 113 : av1_compute_global_motion(
128 113 : model, frm_buffer, input_pic->width, input_pic->height,
129 113 : input_pic->stride_y, frm_corners, num_frm_corners,
130 113 : ref_buffer, ref_pic->stride_y, EB_8BIT,
131 : gm_estimation_type, inliers_by_motion, params_by_motion,
132 : RANSAC_NUM_MOTIONS);
133 :
134 11413 : for (unsigned i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
135 11300 : if (inliers_by_motion[i] == 0) continue;
136 :
137 2173 : params_this_motion = params_by_motion[i].params;
138 2173 : av1_convert_model_to_params(params_this_motion, &tmp_wm_params);
139 :
140 2173 : if (tmp_wm_params.wmtype != IDENTITY) {
141 2173 : const int64_t warp_error = av1_refine_integerized_param(
142 : &tmp_wm_params, tmp_wm_params.wmtype, EB_FALSE, EB_8BIT,
143 2173 : ref_buffer, ref_pic->width, ref_pic->height, ref_pic->stride_y,
144 2173 : frm_buffer, input_pic->width, input_pic->height, input_pic->stride_y, 5,
145 : best_warp_error);
146 2173 : if (warp_error < best_warp_error) {
147 255 : best_warp_error = warp_error;
148 : // Save the wm_params modified by
149 : // av1_refine_integerized_param() rather than motion index to
150 : // avoid rerunning refine() below.
151 255 : memcpy(&global_motion, &tmp_wm_params,
152 : sizeof(EbWarpedMotionParams));
153 : }
154 : }
155 : }
156 113 : if (global_motion.wmtype <= AFFINE)
157 113 : if (!eb_get_shear_params(&global_motion))
158 0 : global_motion = default_warp_params;
159 :
160 113 : if (global_motion.wmtype == TRANSLATION) {
161 0 : global_motion.wmmat[0] =
162 0 : convert_to_trans_prec(allow_high_precision_mv,
163 0 : global_motion.wmmat[0]) *
164 : GM_TRANS_ONLY_DECODE_FACTOR;
165 0 : global_motion.wmmat[1] =
166 0 : convert_to_trans_prec(allow_high_precision_mv,
167 0 : global_motion.wmmat[1]) *
168 : GM_TRANS_ONLY_DECODE_FACTOR;
169 : }
170 :
171 113 : if (global_motion.wmtype == IDENTITY)
172 0 : continue;
173 :
174 113 : const int64_t ref_frame_error = eb_av1_frame_error(
175 113 : EB_FALSE, EB_8BIT, ref_buffer, ref_pic->stride_y, frm_buffer,
176 113 : input_pic->width, input_pic->height, input_pic->stride_y);
177 :
178 113 : if (ref_frame_error == 0)
179 0 : continue;
180 :
181 : // If the best error advantage found doesn't meet the threshold for
182 : // this motion type, revert to IDENTITY.
183 226 : if (!av1_is_enough_erroradvantage(
184 113 : (double)best_warp_error / ref_frame_error,
185 : gm_get_params_cost(&global_motion, ref_params,
186 : allow_high_precision_mv),
187 : GM_ERRORADV_TR_0 /* TODO: check error advantage */)) {
188 0 : global_motion = default_warp_params;
189 : }
190 113 : if (global_motion.wmtype != IDENTITY) {
191 113 : break;
192 : }
193 : }
194 : }
195 :
196 113 : *bestWarpedMotion = global_motion;
197 :
198 11413 : for (int m = 0; m < RANSAC_NUM_MOTIONS; m++) {
199 11300 : free(params_by_motion[m].inliers);
200 : }
201 113 : }
|