1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2020, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker *
4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker */
11*77c1e3ccSAndroid Build Coastguard Worker
12*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/binary_codes_writer.h"
13*77c1e3ccSAndroid Build Coastguard Worker
14*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/flow_estimation/corner_detect.h"
15*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/flow_estimation/flow_estimation.h"
16*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/pyramid.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/warped_motion.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/ethread.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rdopt.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/global_motion_facade.h"
22*77c1e3ccSAndroid Build Coastguard Worker
23*77c1e3ccSAndroid Build Coastguard Worker // Range of model types to search
24*77c1e3ccSAndroid Build Coastguard Worker #define FIRST_GLOBAL_TRANS_TYPE ROTZOOM
25*77c1e3ccSAndroid Build Coastguard Worker #define LAST_GLOBAL_TRANS_TYPE ROTZOOM
26*77c1e3ccSAndroid Build Coastguard Worker
27*77c1e3ccSAndroid Build Coastguard Worker // Computes the cost for the warp parameters.
gm_get_params_cost(const WarpedMotionParams * gm,const WarpedMotionParams * ref_gm,int allow_hp)28*77c1e3ccSAndroid Build Coastguard Worker static int gm_get_params_cost(const WarpedMotionParams *gm,
29*77c1e3ccSAndroid Build Coastguard Worker const WarpedMotionParams *ref_gm, int allow_hp) {
30*77c1e3ccSAndroid Build Coastguard Worker int params_cost = 0;
31*77c1e3ccSAndroid Build Coastguard Worker int trans_bits, trans_prec_diff;
32*77c1e3ccSAndroid Build Coastguard Worker switch (gm->wmtype) {
33*77c1e3ccSAndroid Build Coastguard Worker case AFFINE:
34*77c1e3ccSAndroid Build Coastguard Worker case ROTZOOM:
35*77c1e3ccSAndroid Build Coastguard Worker params_cost += aom_count_signed_primitive_refsubexpfin(
36*77c1e3ccSAndroid Build Coastguard Worker GM_ALPHA_MAX + 1, SUBEXPFIN_K,
37*77c1e3ccSAndroid Build Coastguard Worker (ref_gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS),
38*77c1e3ccSAndroid Build Coastguard Worker (gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
39*77c1e3ccSAndroid Build Coastguard Worker params_cost += aom_count_signed_primitive_refsubexpfin(
40*77c1e3ccSAndroid Build Coastguard Worker GM_ALPHA_MAX + 1, SUBEXPFIN_K,
41*77c1e3ccSAndroid Build Coastguard Worker (ref_gm->wmmat[3] >> GM_ALPHA_PREC_DIFF),
42*77c1e3ccSAndroid Build Coastguard Worker (gm->wmmat[3] >> GM_ALPHA_PREC_DIFF));
43*77c1e3ccSAndroid Build Coastguard Worker if (gm->wmtype >= AFFINE) {
44*77c1e3ccSAndroid Build Coastguard Worker params_cost += aom_count_signed_primitive_refsubexpfin(
45*77c1e3ccSAndroid Build Coastguard Worker GM_ALPHA_MAX + 1, SUBEXPFIN_K,
46*77c1e3ccSAndroid Build Coastguard Worker (ref_gm->wmmat[4] >> GM_ALPHA_PREC_DIFF),
47*77c1e3ccSAndroid Build Coastguard Worker (gm->wmmat[4] >> GM_ALPHA_PREC_DIFF));
48*77c1e3ccSAndroid Build Coastguard Worker params_cost += aom_count_signed_primitive_refsubexpfin(
49*77c1e3ccSAndroid Build Coastguard Worker GM_ALPHA_MAX + 1, SUBEXPFIN_K,
50*77c1e3ccSAndroid Build Coastguard Worker (ref_gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
51*77c1e3ccSAndroid Build Coastguard Worker (1 << GM_ALPHA_PREC_BITS),
52*77c1e3ccSAndroid Build Coastguard Worker (gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
53*77c1e3ccSAndroid Build Coastguard Worker }
54*77c1e3ccSAndroid Build Coastguard Worker AOM_FALLTHROUGH_INTENDED;
55*77c1e3ccSAndroid Build Coastguard Worker case TRANSLATION:
56*77c1e3ccSAndroid Build Coastguard Worker trans_bits = (gm->wmtype == TRANSLATION)
57*77c1e3ccSAndroid Build Coastguard Worker ? GM_ABS_TRANS_ONLY_BITS - !allow_hp
58*77c1e3ccSAndroid Build Coastguard Worker : GM_ABS_TRANS_BITS;
59*77c1e3ccSAndroid Build Coastguard Worker trans_prec_diff = (gm->wmtype == TRANSLATION)
60*77c1e3ccSAndroid Build Coastguard Worker ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
61*77c1e3ccSAndroid Build Coastguard Worker : GM_TRANS_PREC_DIFF;
62*77c1e3ccSAndroid Build Coastguard Worker params_cost += aom_count_signed_primitive_refsubexpfin(
63*77c1e3ccSAndroid Build Coastguard Worker (1 << trans_bits) + 1, SUBEXPFIN_K,
64*77c1e3ccSAndroid Build Coastguard Worker (ref_gm->wmmat[0] >> trans_prec_diff),
65*77c1e3ccSAndroid Build Coastguard Worker (gm->wmmat[0] >> trans_prec_diff));
66*77c1e3ccSAndroid Build Coastguard Worker params_cost += aom_count_signed_primitive_refsubexpfin(
67*77c1e3ccSAndroid Build Coastguard Worker (1 << trans_bits) + 1, SUBEXPFIN_K,
68*77c1e3ccSAndroid Build Coastguard Worker (ref_gm->wmmat[1] >> trans_prec_diff),
69*77c1e3ccSAndroid Build Coastguard Worker (gm->wmmat[1] >> trans_prec_diff));
70*77c1e3ccSAndroid Build Coastguard Worker AOM_FALLTHROUGH_INTENDED;
71*77c1e3ccSAndroid Build Coastguard Worker case IDENTITY: break;
72*77c1e3ccSAndroid Build Coastguard Worker default: assert(0);
73*77c1e3ccSAndroid Build Coastguard Worker }
74*77c1e3ccSAndroid Build Coastguard Worker return (params_cost << AV1_PROB_COST_SHIFT);
75*77c1e3ccSAndroid Build Coastguard Worker }
76*77c1e3ccSAndroid Build Coastguard Worker
77*77c1e3ccSAndroid Build Coastguard Worker // For the given reference frame, computes the global motion parameters for
78*77c1e3ccSAndroid Build Coastguard Worker // different motion models and finds the best.
compute_global_motion_for_ref_frame(AV1_COMP * cpi,struct aom_internal_error_info * error_info,YV12_BUFFER_CONFIG * ref_buf[REF_FRAMES],int frame,MotionModel * motion_models,uint8_t * segment_map,const int segment_map_w,const int segment_map_h,const WarpedMotionParams * ref_params)79*77c1e3ccSAndroid Build Coastguard Worker static inline void compute_global_motion_for_ref_frame(
80*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi, struct aom_internal_error_info *error_info,
81*77c1e3ccSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES], int frame,
82*77c1e3ccSAndroid Build Coastguard Worker MotionModel *motion_models, uint8_t *segment_map, const int segment_map_w,
83*77c1e3ccSAndroid Build Coastguard Worker const int segment_map_h, const WarpedMotionParams *ref_params) {
84*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
85*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
86*77c1e3ccSAndroid Build Coastguard Worker int src_width = cpi->source->y_crop_width;
87*77c1e3ccSAndroid Build Coastguard Worker int src_height = cpi->source->y_crop_height;
88*77c1e3ccSAndroid Build Coastguard Worker int src_stride = cpi->source->y_stride;
89*77c1e3ccSAndroid Build Coastguard Worker assert(ref_buf[frame] != NULL);
90*77c1e3ccSAndroid Build Coastguard Worker int bit_depth = cpi->common.seq_params->bit_depth;
91*77c1e3ccSAndroid Build Coastguard Worker GlobalMotionMethod global_motion_method = default_global_motion_method;
92*77c1e3ccSAndroid Build Coastguard Worker int downsample_level = cpi->sf.gm_sf.downsample_level;
93*77c1e3ccSAndroid Build Coastguard Worker int num_refinements = cpi->sf.gm_sf.num_refinement_steps;
94*77c1e3ccSAndroid Build Coastguard Worker bool mem_alloc_failed = false;
95*77c1e3ccSAndroid Build Coastguard Worker
96*77c1e3ccSAndroid Build Coastguard Worker // Select the best model based on fractional error reduction.
97*77c1e3ccSAndroid Build Coastguard Worker // By initializing this to erroradv_tr, the same logic which is used to
98*77c1e3ccSAndroid Build Coastguard Worker // select the best model will automatically filter out any model which
99*77c1e3ccSAndroid Build Coastguard Worker // doesn't meet the required quality threshold
100*77c1e3ccSAndroid Build Coastguard Worker double best_erroradv = erroradv_tr;
101*77c1e3ccSAndroid Build Coastguard Worker for (TransformationType model = FIRST_GLOBAL_TRANS_TYPE;
102*77c1e3ccSAndroid Build Coastguard Worker model <= LAST_GLOBAL_TRANS_TYPE; ++model) {
103*77c1e3ccSAndroid Build Coastguard Worker if (!aom_compute_global_motion(model, cpi->source, ref_buf[frame],
104*77c1e3ccSAndroid Build Coastguard Worker bit_depth, global_motion_method,
105*77c1e3ccSAndroid Build Coastguard Worker downsample_level, motion_models,
106*77c1e3ccSAndroid Build Coastguard Worker RANSAC_NUM_MOTIONS, &mem_alloc_failed)) {
107*77c1e3ccSAndroid Build Coastguard Worker if (mem_alloc_failed) {
108*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_MEM_ERROR,
109*77c1e3ccSAndroid Build Coastguard Worker "Failed to allocate global motion buffers");
110*77c1e3ccSAndroid Build Coastguard Worker }
111*77c1e3ccSAndroid Build Coastguard Worker continue;
112*77c1e3ccSAndroid Build Coastguard Worker }
113*77c1e3ccSAndroid Build Coastguard Worker
114*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < RANSAC_NUM_MOTIONS; ++i) {
115*77c1e3ccSAndroid Build Coastguard Worker if (motion_models[i].num_inliers == 0) continue;
116*77c1e3ccSAndroid Build Coastguard Worker
117*77c1e3ccSAndroid Build Coastguard Worker WarpedMotionParams tmp_wm_params;
118*77c1e3ccSAndroid Build Coastguard Worker av1_convert_model_to_params(motion_models[i].params, &tmp_wm_params);
119*77c1e3ccSAndroid Build Coastguard Worker
120*77c1e3ccSAndroid Build Coastguard Worker // Check that the generated model is warp-able
121*77c1e3ccSAndroid Build Coastguard Worker if (!av1_get_shear_params(&tmp_wm_params)) continue;
122*77c1e3ccSAndroid Build Coastguard Worker
123*77c1e3ccSAndroid Build Coastguard Worker // Skip models that we won't use (IDENTITY or TRANSLATION)
124*77c1e3ccSAndroid Build Coastguard Worker //
125*77c1e3ccSAndroid Build Coastguard Worker // For IDENTITY type models, we don't need to evaluate anything because
126*77c1e3ccSAndroid Build Coastguard Worker // all the following logic is effectively comparing the estimated model
127*77c1e3ccSAndroid Build Coastguard Worker // to an identity model.
128*77c1e3ccSAndroid Build Coastguard Worker //
129*77c1e3ccSAndroid Build Coastguard Worker // For TRANSLATION type global motion models, gm_get_motion_vector() gives
130*77c1e3ccSAndroid Build Coastguard Worker // the wrong motion vector (see comments in that function for details).
131*77c1e3ccSAndroid Build Coastguard Worker // As translation-type models do not give much gain, we can avoid this bug
132*77c1e3ccSAndroid Build Coastguard Worker // by never choosing a TRANSLATION type model
133*77c1e3ccSAndroid Build Coastguard Worker if (tmp_wm_params.wmtype <= TRANSLATION) continue;
134*77c1e3ccSAndroid Build Coastguard Worker
135*77c1e3ccSAndroid Build Coastguard Worker av1_compute_feature_segmentation_map(
136*77c1e3ccSAndroid Build Coastguard Worker segment_map, segment_map_w, segment_map_h, motion_models[i].inliers,
137*77c1e3ccSAndroid Build Coastguard Worker motion_models[i].num_inliers);
138*77c1e3ccSAndroid Build Coastguard Worker
139*77c1e3ccSAndroid Build Coastguard Worker int64_t ref_frame_error = av1_segmented_frame_error(
140*77c1e3ccSAndroid Build Coastguard Worker is_cur_buf_hbd(xd), xd->bd, ref_buf[frame]->y_buffer,
141*77c1e3ccSAndroid Build Coastguard Worker ref_buf[frame]->y_stride, cpi->source->y_buffer, src_stride,
142*77c1e3ccSAndroid Build Coastguard Worker src_width, src_height, segment_map, segment_map_w);
143*77c1e3ccSAndroid Build Coastguard Worker
144*77c1e3ccSAndroid Build Coastguard Worker if (ref_frame_error == 0) continue;
145*77c1e3ccSAndroid Build Coastguard Worker
146*77c1e3ccSAndroid Build Coastguard Worker const int64_t warp_error = av1_refine_integerized_param(
147*77c1e3ccSAndroid Build Coastguard Worker &tmp_wm_params, tmp_wm_params.wmtype, is_cur_buf_hbd(xd), xd->bd,
148*77c1e3ccSAndroid Build Coastguard Worker ref_buf[frame]->y_buffer, ref_buf[frame]->y_crop_width,
149*77c1e3ccSAndroid Build Coastguard Worker ref_buf[frame]->y_crop_height, ref_buf[frame]->y_stride,
150*77c1e3ccSAndroid Build Coastguard Worker cpi->source->y_buffer, src_width, src_height, src_stride,
151*77c1e3ccSAndroid Build Coastguard Worker num_refinements, ref_frame_error, segment_map, segment_map_w);
152*77c1e3ccSAndroid Build Coastguard Worker
153*77c1e3ccSAndroid Build Coastguard Worker // av1_refine_integerized_param() can return a simpler model type than
154*77c1e3ccSAndroid Build Coastguard Worker // its input, so re-check model type here
155*77c1e3ccSAndroid Build Coastguard Worker if (tmp_wm_params.wmtype <= TRANSLATION) continue;
156*77c1e3ccSAndroid Build Coastguard Worker
157*77c1e3ccSAndroid Build Coastguard Worker double erroradvantage = (double)warp_error / ref_frame_error;
158*77c1e3ccSAndroid Build Coastguard Worker
159*77c1e3ccSAndroid Build Coastguard Worker // Check that the model signaling cost is not too high
160*77c1e3ccSAndroid Build Coastguard Worker if (!av1_is_enough_erroradvantage(
161*77c1e3ccSAndroid Build Coastguard Worker erroradvantage,
162*77c1e3ccSAndroid Build Coastguard Worker gm_get_params_cost(&tmp_wm_params, ref_params,
163*77c1e3ccSAndroid Build Coastguard Worker cm->features.allow_high_precision_mv))) {
164*77c1e3ccSAndroid Build Coastguard Worker continue;
165*77c1e3ccSAndroid Build Coastguard Worker }
166*77c1e3ccSAndroid Build Coastguard Worker
167*77c1e3ccSAndroid Build Coastguard Worker if (erroradvantage < best_erroradv) {
168*77c1e3ccSAndroid Build Coastguard Worker best_erroradv = erroradvantage;
169*77c1e3ccSAndroid Build Coastguard Worker // Save the wm_params modified by
170*77c1e3ccSAndroid Build Coastguard Worker // av1_refine_integerized_param() rather than motion index to
171*77c1e3ccSAndroid Build Coastguard Worker // avoid rerunning refine() below.
172*77c1e3ccSAndroid Build Coastguard Worker memcpy(&(cm->global_motion[frame]), &tmp_wm_params,
173*77c1e3ccSAndroid Build Coastguard Worker sizeof(WarpedMotionParams));
174*77c1e3ccSAndroid Build Coastguard Worker }
175*77c1e3ccSAndroid Build Coastguard Worker }
176*77c1e3ccSAndroid Build Coastguard Worker }
177*77c1e3ccSAndroid Build Coastguard Worker }
178*77c1e3ccSAndroid Build Coastguard Worker
179*77c1e3ccSAndroid Build Coastguard Worker // Computes global motion for the given reference frame.
av1_compute_gm_for_valid_ref_frames(AV1_COMP * cpi,struct aom_internal_error_info * error_info,YV12_BUFFER_CONFIG * ref_buf[REF_FRAMES],int frame,MotionModel * motion_models,uint8_t * segment_map,int segment_map_w,int segment_map_h)180*77c1e3ccSAndroid Build Coastguard Worker void av1_compute_gm_for_valid_ref_frames(
181*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi, struct aom_internal_error_info *error_info,
182*77c1e3ccSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES], int frame,
183*77c1e3ccSAndroid Build Coastguard Worker MotionModel *motion_models, uint8_t *segment_map, int segment_map_w,
184*77c1e3ccSAndroid Build Coastguard Worker int segment_map_h) {
185*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
186*77c1e3ccSAndroid Build Coastguard Worker const WarpedMotionParams *ref_params =
187*77c1e3ccSAndroid Build Coastguard Worker cm->prev_frame ? &cm->prev_frame->global_motion[frame]
188*77c1e3ccSAndroid Build Coastguard Worker : &default_warp_params;
189*77c1e3ccSAndroid Build Coastguard Worker
190*77c1e3ccSAndroid Build Coastguard Worker compute_global_motion_for_ref_frame(cpi, error_info, ref_buf, frame,
191*77c1e3ccSAndroid Build Coastguard Worker motion_models, segment_map, segment_map_w,
192*77c1e3ccSAndroid Build Coastguard Worker segment_map_h, ref_params);
193*77c1e3ccSAndroid Build Coastguard Worker }
194*77c1e3ccSAndroid Build Coastguard Worker
195*77c1e3ccSAndroid Build Coastguard Worker // Loops over valid reference frames and computes global motion estimation.
compute_global_motion_for_references(AV1_COMP * cpi,YV12_BUFFER_CONFIG * ref_buf[REF_FRAMES],FrameDistPair reference_frame[REF_FRAMES-1],int num_ref_frames,MotionModel * motion_models,uint8_t * segment_map,const int segment_map_w,const int segment_map_h)196*77c1e3ccSAndroid Build Coastguard Worker static inline void compute_global_motion_for_references(
197*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi, YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES],
198*77c1e3ccSAndroid Build Coastguard Worker FrameDistPair reference_frame[REF_FRAMES - 1], int num_ref_frames,
199*77c1e3ccSAndroid Build Coastguard Worker MotionModel *motion_models, uint8_t *segment_map, const int segment_map_w,
200*77c1e3ccSAndroid Build Coastguard Worker const int segment_map_h) {
201*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
202*77c1e3ccSAndroid Build Coastguard Worker struct aom_internal_error_info *const error_info =
203*77c1e3ccSAndroid Build Coastguard Worker cpi->td.mb.e_mbd.error_info;
204*77c1e3ccSAndroid Build Coastguard Worker // Compute global motion w.r.t. reference frames starting from the nearest ref
205*77c1e3ccSAndroid Build Coastguard Worker // frame in a given direction.
206*77c1e3ccSAndroid Build Coastguard Worker for (int frame = 0; frame < num_ref_frames; frame++) {
207*77c1e3ccSAndroid Build Coastguard Worker int ref_frame = reference_frame[frame].frame;
208*77c1e3ccSAndroid Build Coastguard Worker av1_compute_gm_for_valid_ref_frames(cpi, error_info, ref_buf, ref_frame,
209*77c1e3ccSAndroid Build Coastguard Worker motion_models, segment_map,
210*77c1e3ccSAndroid Build Coastguard Worker segment_map_w, segment_map_h);
211*77c1e3ccSAndroid Build Coastguard Worker // If global motion w.r.t. current ref frame is
212*77c1e3ccSAndroid Build Coastguard Worker // INVALID/TRANSLATION/IDENTITY, skip the evaluation of global motion w.r.t
213*77c1e3ccSAndroid Build Coastguard Worker // the remaining ref frames in that direction.
214*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.gm_sf.prune_ref_frame_for_gm_search &&
215*77c1e3ccSAndroid Build Coastguard Worker cm->global_motion[ref_frame].wmtype <= TRANSLATION)
216*77c1e3ccSAndroid Build Coastguard Worker break;
217*77c1e3ccSAndroid Build Coastguard Worker }
218*77c1e3ccSAndroid Build Coastguard Worker }
219*77c1e3ccSAndroid Build Coastguard Worker
220*77c1e3ccSAndroid Build Coastguard Worker // Compares the distance in 'a' and 'b'. Returns 1 if the frame corresponding to
221*77c1e3ccSAndroid Build Coastguard Worker // 'a' is farther, -1 if the frame corresponding to 'b' is farther, 0 otherwise.
compare_distance(const void * a,const void * b)222*77c1e3ccSAndroid Build Coastguard Worker static int compare_distance(const void *a, const void *b) {
223*77c1e3ccSAndroid Build Coastguard Worker const int diff =
224*77c1e3ccSAndroid Build Coastguard Worker ((FrameDistPair *)a)->distance - ((FrameDistPair *)b)->distance;
225*77c1e3ccSAndroid Build Coastguard Worker if (diff > 0)
226*77c1e3ccSAndroid Build Coastguard Worker return 1;
227*77c1e3ccSAndroid Build Coastguard Worker else if (diff < 0)
228*77c1e3ccSAndroid Build Coastguard Worker return -1;
229*77c1e3ccSAndroid Build Coastguard Worker return 0;
230*77c1e3ccSAndroid Build Coastguard Worker }
231*77c1e3ccSAndroid Build Coastguard Worker
disable_gm_search_based_on_stats(const AV1_COMP * const cpi)232*77c1e3ccSAndroid Build Coastguard Worker static int disable_gm_search_based_on_stats(const AV1_COMP *const cpi) {
233*77c1e3ccSAndroid Build Coastguard Worker int is_gm_present = 1;
234*77c1e3ccSAndroid Build Coastguard Worker
235*77c1e3ccSAndroid Build Coastguard Worker // Check number of GM models only in GF groups with ARF frames. GM param
236*77c1e3ccSAndroid Build Coastguard Worker // estimation is always done in the case of GF groups with no ARF frames (flat
237*77c1e3ccSAndroid Build Coastguard Worker // gops)
238*77c1e3ccSAndroid Build Coastguard Worker if (cpi->ppi->gf_group.arf_index > -1) {
239*77c1e3ccSAndroid Build Coastguard Worker // valid_gm_model_found is initialized to INT32_MAX in the beginning of
240*77c1e3ccSAndroid Build Coastguard Worker // every GF group.
241*77c1e3ccSAndroid Build Coastguard Worker // Therefore, GM param estimation is always done for all frames until
242*77c1e3ccSAndroid Build Coastguard Worker // at least 1 frame each of ARF_UPDATE, INTNL_ARF_UPDATE and LF_UPDATE are
243*77c1e3ccSAndroid Build Coastguard Worker // encoded in a GF group For subsequent frames, GM param estimation is
244*77c1e3ccSAndroid Build Coastguard Worker // disabled, if no valid models have been found in all the three update
245*77c1e3ccSAndroid Build Coastguard Worker // types.
246*77c1e3ccSAndroid Build Coastguard Worker is_gm_present = (cpi->ppi->valid_gm_model_found[ARF_UPDATE] != 0) ||
247*77c1e3ccSAndroid Build Coastguard Worker (cpi->ppi->valid_gm_model_found[INTNL_ARF_UPDATE] != 0) ||
248*77c1e3ccSAndroid Build Coastguard Worker (cpi->ppi->valid_gm_model_found[LF_UPDATE] != 0);
249*77c1e3ccSAndroid Build Coastguard Worker }
250*77c1e3ccSAndroid Build Coastguard Worker return !is_gm_present;
251*77c1e3ccSAndroid Build Coastguard Worker }
252*77c1e3ccSAndroid Build Coastguard Worker
253*77c1e3ccSAndroid Build Coastguard Worker // Prunes reference frames for global motion estimation based on the speed
254*77c1e3ccSAndroid Build Coastguard Worker // feature 'gm_search_type'.
do_gm_search_logic(SPEED_FEATURES * const sf,int frame)255*77c1e3ccSAndroid Build Coastguard Worker static int do_gm_search_logic(SPEED_FEATURES *const sf, int frame) {
256*77c1e3ccSAndroid Build Coastguard Worker (void)frame;
257*77c1e3ccSAndroid Build Coastguard Worker switch (sf->gm_sf.gm_search_type) {
258*77c1e3ccSAndroid Build Coastguard Worker case GM_FULL_SEARCH: return 1;
259*77c1e3ccSAndroid Build Coastguard Worker case GM_REDUCED_REF_SEARCH_SKIP_L2_L3:
260*77c1e3ccSAndroid Build Coastguard Worker return !(frame == LAST2_FRAME || frame == LAST3_FRAME);
261*77c1e3ccSAndroid Build Coastguard Worker case GM_REDUCED_REF_SEARCH_SKIP_L2_L3_ARF2:
262*77c1e3ccSAndroid Build Coastguard Worker return !(frame == LAST2_FRAME || frame == LAST3_FRAME ||
263*77c1e3ccSAndroid Build Coastguard Worker (frame == ALTREF2_FRAME));
264*77c1e3ccSAndroid Build Coastguard Worker case GM_SEARCH_CLOSEST_REFS_ONLY: return 1;
265*77c1e3ccSAndroid Build Coastguard Worker case GM_DISABLE_SEARCH: return 0;
266*77c1e3ccSAndroid Build Coastguard Worker default: assert(0);
267*77c1e3ccSAndroid Build Coastguard Worker }
268*77c1e3ccSAndroid Build Coastguard Worker return 1;
269*77c1e3ccSAndroid Build Coastguard Worker }
270*77c1e3ccSAndroid Build Coastguard Worker
271*77c1e3ccSAndroid Build Coastguard Worker // Populates valid reference frames in past/future directions in
272*77c1e3ccSAndroid Build Coastguard Worker // 'reference_frames' and their count in 'num_ref_frames'.
update_valid_ref_frames_for_gm(AV1_COMP * cpi,YV12_BUFFER_CONFIG * ref_buf[REF_FRAMES],FrameDistPair reference_frames[MAX_DIRECTIONS][REF_FRAMES-1],int * num_ref_frames)273*77c1e3ccSAndroid Build Coastguard Worker static inline void update_valid_ref_frames_for_gm(
274*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi, YV12_BUFFER_CONFIG *ref_buf[REF_FRAMES],
275*77c1e3ccSAndroid Build Coastguard Worker FrameDistPair reference_frames[MAX_DIRECTIONS][REF_FRAMES - 1],
276*77c1e3ccSAndroid Build Coastguard Worker int *num_ref_frames) {
277*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
278*77c1e3ccSAndroid Build Coastguard Worker int *num_past_ref_frames = &num_ref_frames[0];
279*77c1e3ccSAndroid Build Coastguard Worker int *num_future_ref_frames = &num_ref_frames[1];
280*77c1e3ccSAndroid Build Coastguard Worker const GF_GROUP *gf_group = &cpi->ppi->gf_group;
281*77c1e3ccSAndroid Build Coastguard Worker int ref_pruning_enabled = is_frame_eligible_for_ref_pruning(
282*77c1e3ccSAndroid Build Coastguard Worker gf_group, cpi->sf.inter_sf.selective_ref_frame, 1, cpi->gf_frame_index);
283*77c1e3ccSAndroid Build Coastguard Worker int cur_frame_gm_disabled = 0;
284*77c1e3ccSAndroid Build Coastguard Worker int pyr_lvl = cm->cur_frame->pyramid_level;
285*77c1e3ccSAndroid Build Coastguard Worker
286*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.gm_sf.disable_gm_search_based_on_stats) {
287*77c1e3ccSAndroid Build Coastguard Worker cur_frame_gm_disabled = disable_gm_search_based_on_stats(cpi);
288*77c1e3ccSAndroid Build Coastguard Worker }
289*77c1e3ccSAndroid Build Coastguard Worker
290*77c1e3ccSAndroid Build Coastguard Worker for (int frame = ALTREF_FRAME; frame >= LAST_FRAME; --frame) {
291*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME ref_frame[2] = { frame, NONE_FRAME };
292*77c1e3ccSAndroid Build Coastguard Worker RefCntBuffer *buf = get_ref_frame_buf(cm, frame);
293*77c1e3ccSAndroid Build Coastguard Worker const int ref_disabled =
294*77c1e3ccSAndroid Build Coastguard Worker !(cpi->ref_frame_flags & av1_ref_frame_flag_list[frame]);
295*77c1e3ccSAndroid Build Coastguard Worker ref_buf[frame] = NULL;
296*77c1e3ccSAndroid Build Coastguard Worker cm->global_motion[frame] = default_warp_params;
297*77c1e3ccSAndroid Build Coastguard Worker // Skip global motion estimation for invalid ref frames
298*77c1e3ccSAndroid Build Coastguard Worker if (buf == NULL ||
299*77c1e3ccSAndroid Build Coastguard Worker (ref_disabled && cpi->sf.hl_sf.recode_loop != DISALLOW_RECODE)) {
300*77c1e3ccSAndroid Build Coastguard Worker continue;
301*77c1e3ccSAndroid Build Coastguard Worker } else {
302*77c1e3ccSAndroid Build Coastguard Worker ref_buf[frame] = &buf->buf;
303*77c1e3ccSAndroid Build Coastguard Worker }
304*77c1e3ccSAndroid Build Coastguard Worker
305*77c1e3ccSAndroid Build Coastguard Worker int prune_ref_frames =
306*77c1e3ccSAndroid Build Coastguard Worker ref_pruning_enabled &&
307*77c1e3ccSAndroid Build Coastguard Worker prune_ref_by_selective_ref_frame(cpi, NULL, ref_frame,
308*77c1e3ccSAndroid Build Coastguard Worker cm->cur_frame->ref_display_order_hint);
309*77c1e3ccSAndroid Build Coastguard Worker int ref_pyr_lvl = buf->pyramid_level;
310*77c1e3ccSAndroid Build Coastguard Worker
311*77c1e3ccSAndroid Build Coastguard Worker if (ref_buf[frame]->y_crop_width == cpi->source->y_crop_width &&
312*77c1e3ccSAndroid Build Coastguard Worker ref_buf[frame]->y_crop_height == cpi->source->y_crop_height &&
313*77c1e3ccSAndroid Build Coastguard Worker do_gm_search_logic(&cpi->sf, frame) && !prune_ref_frames &&
314*77c1e3ccSAndroid Build Coastguard Worker ref_pyr_lvl <= pyr_lvl && !cur_frame_gm_disabled) {
315*77c1e3ccSAndroid Build Coastguard Worker assert(ref_buf[frame] != NULL);
316*77c1e3ccSAndroid Build Coastguard Worker const int relative_frame_dist = av1_encoder_get_relative_dist(
317*77c1e3ccSAndroid Build Coastguard Worker buf->display_order_hint, cm->cur_frame->display_order_hint);
318*77c1e3ccSAndroid Build Coastguard Worker // Populate past and future ref frames.
319*77c1e3ccSAndroid Build Coastguard Worker // reference_frames[0][] indicates past direction and
320*77c1e3ccSAndroid Build Coastguard Worker // reference_frames[1][] indicates future direction.
321*77c1e3ccSAndroid Build Coastguard Worker if (relative_frame_dist == 0) {
322*77c1e3ccSAndroid Build Coastguard Worker // Skip global motion estimation for frames at the same nominal instant.
323*77c1e3ccSAndroid Build Coastguard Worker // This will generally be either a "real" frame coded against a
324*77c1e3ccSAndroid Build Coastguard Worker // temporal filtered version, or a higher spatial layer coded against
325*77c1e3ccSAndroid Build Coastguard Worker // a lower spatial layer. In either case, the optimal motion model will
326*77c1e3ccSAndroid Build Coastguard Worker // be IDENTITY, so we don't need to search explicitly.
327*77c1e3ccSAndroid Build Coastguard Worker } else if (relative_frame_dist < 0) {
328*77c1e3ccSAndroid Build Coastguard Worker reference_frames[0][*num_past_ref_frames].distance =
329*77c1e3ccSAndroid Build Coastguard Worker abs(relative_frame_dist);
330*77c1e3ccSAndroid Build Coastguard Worker reference_frames[0][*num_past_ref_frames].frame = frame;
331*77c1e3ccSAndroid Build Coastguard Worker (*num_past_ref_frames)++;
332*77c1e3ccSAndroid Build Coastguard Worker } else {
333*77c1e3ccSAndroid Build Coastguard Worker reference_frames[1][*num_future_ref_frames].distance =
334*77c1e3ccSAndroid Build Coastguard Worker abs(relative_frame_dist);
335*77c1e3ccSAndroid Build Coastguard Worker reference_frames[1][*num_future_ref_frames].frame = frame;
336*77c1e3ccSAndroid Build Coastguard Worker (*num_future_ref_frames)++;
337*77c1e3ccSAndroid Build Coastguard Worker }
338*77c1e3ccSAndroid Build Coastguard Worker }
339*77c1e3ccSAndroid Build Coastguard Worker }
340*77c1e3ccSAndroid Build Coastguard Worker }
341*77c1e3ccSAndroid Build Coastguard Worker
342*77c1e3ccSAndroid Build Coastguard Worker // Initializes parameters used for computing global motion.
setup_global_motion_info_params(AV1_COMP * cpi)343*77c1e3ccSAndroid Build Coastguard Worker static inline void setup_global_motion_info_params(AV1_COMP *cpi) {
344*77c1e3ccSAndroid Build Coastguard Worker GlobalMotionInfo *const gm_info = &cpi->gm_info;
345*77c1e3ccSAndroid Build Coastguard Worker YV12_BUFFER_CONFIG *source = cpi->source;
346*77c1e3ccSAndroid Build Coastguard Worker
347*77c1e3ccSAndroid Build Coastguard Worker gm_info->segment_map_w =
348*77c1e3ccSAndroid Build Coastguard Worker (source->y_crop_width + WARP_ERROR_BLOCK - 1) >> WARP_ERROR_BLOCK_LOG;
349*77c1e3ccSAndroid Build Coastguard Worker gm_info->segment_map_h =
350*77c1e3ccSAndroid Build Coastguard Worker (source->y_crop_height + WARP_ERROR_BLOCK - 1) >> WARP_ERROR_BLOCK_LOG;
351*77c1e3ccSAndroid Build Coastguard Worker
352*77c1e3ccSAndroid Build Coastguard Worker memset(gm_info->reference_frames, -1,
353*77c1e3ccSAndroid Build Coastguard Worker sizeof(gm_info->reference_frames[0][0]) * MAX_DIRECTIONS *
354*77c1e3ccSAndroid Build Coastguard Worker (REF_FRAMES - 1));
355*77c1e3ccSAndroid Build Coastguard Worker av1_zero(gm_info->num_ref_frames);
356*77c1e3ccSAndroid Build Coastguard Worker
357*77c1e3ccSAndroid Build Coastguard Worker // Populate ref_buf for valid ref frames in global motion
358*77c1e3ccSAndroid Build Coastguard Worker update_valid_ref_frames_for_gm(cpi, gm_info->ref_buf,
359*77c1e3ccSAndroid Build Coastguard Worker gm_info->reference_frames,
360*77c1e3ccSAndroid Build Coastguard Worker gm_info->num_ref_frames);
361*77c1e3ccSAndroid Build Coastguard Worker
362*77c1e3ccSAndroid Build Coastguard Worker // Sort the past and future ref frames in the ascending order of their
363*77c1e3ccSAndroid Build Coastguard Worker // distance from the current frame. reference_frames[0] => past direction
364*77c1e3ccSAndroid Build Coastguard Worker // and reference_frames[1] => future direction.
365*77c1e3ccSAndroid Build Coastguard Worker qsort(gm_info->reference_frames[0], gm_info->num_ref_frames[0],
366*77c1e3ccSAndroid Build Coastguard Worker sizeof(gm_info->reference_frames[0][0]), compare_distance);
367*77c1e3ccSAndroid Build Coastguard Worker qsort(gm_info->reference_frames[1], gm_info->num_ref_frames[1],
368*77c1e3ccSAndroid Build Coastguard Worker sizeof(gm_info->reference_frames[1][0]), compare_distance);
369*77c1e3ccSAndroid Build Coastguard Worker
370*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.gm_sf.gm_search_type == GM_SEARCH_CLOSEST_REFS_ONLY) {
371*77c1e3ccSAndroid Build Coastguard Worker // Filter down to the nearest two ref frames.
372*77c1e3ccSAndroid Build Coastguard Worker // Prefer one past and one future ref over two past refs, even if
373*77c1e3ccSAndroid Build Coastguard Worker // the second past ref is closer
374*77c1e3ccSAndroid Build Coastguard Worker if (gm_info->num_ref_frames[1] > 0) {
375*77c1e3ccSAndroid Build Coastguard Worker gm_info->num_ref_frames[0] = AOMMIN(gm_info->num_ref_frames[0], 1);
376*77c1e3ccSAndroid Build Coastguard Worker gm_info->num_ref_frames[1] = AOMMIN(gm_info->num_ref_frames[1], 1);
377*77c1e3ccSAndroid Build Coastguard Worker } else {
378*77c1e3ccSAndroid Build Coastguard Worker gm_info->num_ref_frames[0] = AOMMIN(gm_info->num_ref_frames[0], 2);
379*77c1e3ccSAndroid Build Coastguard Worker }
380*77c1e3ccSAndroid Build Coastguard Worker }
381*77c1e3ccSAndroid Build Coastguard Worker }
382*77c1e3ccSAndroid Build Coastguard Worker
383*77c1e3ccSAndroid Build Coastguard Worker // Computes global motion w.r.t. valid reference frames.
global_motion_estimation(AV1_COMP * cpi)384*77c1e3ccSAndroid Build Coastguard Worker static inline void global_motion_estimation(AV1_COMP *cpi) {
385*77c1e3ccSAndroid Build Coastguard Worker GlobalMotionInfo *const gm_info = &cpi->gm_info;
386*77c1e3ccSAndroid Build Coastguard Worker GlobalMotionData *gm_data = &cpi->td.gm_data;
387*77c1e3ccSAndroid Build Coastguard Worker
388*77c1e3ccSAndroid Build Coastguard Worker // Compute global motion w.r.t. past reference frames and future reference
389*77c1e3ccSAndroid Build Coastguard Worker // frames
390*77c1e3ccSAndroid Build Coastguard Worker for (int dir = 0; dir < MAX_DIRECTIONS; dir++) {
391*77c1e3ccSAndroid Build Coastguard Worker if (gm_info->num_ref_frames[dir] > 0)
392*77c1e3ccSAndroid Build Coastguard Worker compute_global_motion_for_references(
393*77c1e3ccSAndroid Build Coastguard Worker cpi, gm_info->ref_buf, gm_info->reference_frames[dir],
394*77c1e3ccSAndroid Build Coastguard Worker gm_info->num_ref_frames[dir], gm_data->motion_models,
395*77c1e3ccSAndroid Build Coastguard Worker gm_data->segment_map, gm_info->segment_map_w, gm_info->segment_map_h);
396*77c1e3ccSAndroid Build Coastguard Worker }
397*77c1e3ccSAndroid Build Coastguard Worker }
398*77c1e3ccSAndroid Build Coastguard Worker
399*77c1e3ccSAndroid Build Coastguard Worker // Global motion estimation for the current frame is computed.This computation
400*77c1e3ccSAndroid Build Coastguard Worker // happens once per frame and the winner motion model parameters are stored in
401*77c1e3ccSAndroid Build Coastguard Worker // cm->cur_frame->global_motion.
av1_compute_global_motion_facade(AV1_COMP * cpi)402*77c1e3ccSAndroid Build Coastguard Worker void av1_compute_global_motion_facade(AV1_COMP *cpi) {
403*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
404*77c1e3ccSAndroid Build Coastguard Worker GlobalMotionInfo *const gm_info = &cpi->gm_info;
405*77c1e3ccSAndroid Build Coastguard Worker
406*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.tool_cfg.enable_global_motion) {
407*77c1e3ccSAndroid Build Coastguard Worker if (cpi->gf_frame_index == 0) {
408*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < FRAME_UPDATE_TYPES; i++) {
409*77c1e3ccSAndroid Build Coastguard Worker cpi->ppi->valid_gm_model_found[i] = INT32_MAX;
410*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_FPMT_TEST
411*77c1e3ccSAndroid Build Coastguard Worker if (cpi->ppi->fpmt_unit_test_cfg == PARALLEL_SIMULATION_ENCODE)
412*77c1e3ccSAndroid Build Coastguard Worker cpi->ppi->temp_valid_gm_model_found[i] = INT32_MAX;
413*77c1e3ccSAndroid Build Coastguard Worker #endif
414*77c1e3ccSAndroid Build Coastguard Worker }
415*77c1e3ccSAndroid Build Coastguard Worker }
416*77c1e3ccSAndroid Build Coastguard Worker }
417*77c1e3ccSAndroid Build Coastguard Worker
418*77c1e3ccSAndroid Build Coastguard Worker if (cpi->common.current_frame.frame_type == INTER_FRAME && cpi->source &&
419*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.tool_cfg.enable_global_motion && !gm_info->search_done &&
420*77c1e3ccSAndroid Build Coastguard Worker cpi->sf.gm_sf.gm_search_type != GM_DISABLE_SEARCH) {
421*77c1e3ccSAndroid Build Coastguard Worker setup_global_motion_info_params(cpi);
422*77c1e3ccSAndroid Build Coastguard Worker // Terminate early if the total number of reference frames is zero.
423*77c1e3ccSAndroid Build Coastguard Worker if (cpi->gm_info.num_ref_frames[0] || cpi->gm_info.num_ref_frames[1]) {
424*77c1e3ccSAndroid Build Coastguard Worker gm_alloc_data(cpi, &cpi->td.gm_data);
425*77c1e3ccSAndroid Build Coastguard Worker if (cpi->mt_info.num_workers > 1)
426*77c1e3ccSAndroid Build Coastguard Worker av1_global_motion_estimation_mt(cpi);
427*77c1e3ccSAndroid Build Coastguard Worker else
428*77c1e3ccSAndroid Build Coastguard Worker global_motion_estimation(cpi);
429*77c1e3ccSAndroid Build Coastguard Worker gm_dealloc_data(&cpi->td.gm_data);
430*77c1e3ccSAndroid Build Coastguard Worker gm_info->search_done = 1;
431*77c1e3ccSAndroid Build Coastguard Worker }
432*77c1e3ccSAndroid Build Coastguard Worker }
433*77c1e3ccSAndroid Build Coastguard Worker memcpy(cm->cur_frame->global_motion, cm->global_motion,
434*77c1e3ccSAndroid Build Coastguard Worker sizeof(cm->cur_frame->global_motion));
435*77c1e3ccSAndroid Build Coastguard Worker }
436