1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2019, 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 "config/aom_config.h"
13*77c1e3ccSAndroid Build Coastguard Worker
14*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encodemv.h"
15*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
16*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/misc_model_weights.h"
17*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_REALTIME_ONLY
18*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/mv_prec.h"
19*77c1e3ccSAndroid Build Coastguard Worker
20*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
get_ref_mv_for_mv_stats(const MB_MODE_INFO * mbmi,const MB_MODE_INFO_EXT_FRAME * mbmi_ext_frame,int ref_idx)21*77c1e3ccSAndroid Build Coastguard Worker static inline int_mv get_ref_mv_for_mv_stats(
22*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT_FRAME *mbmi_ext_frame,
23*77c1e3ccSAndroid Build Coastguard Worker int ref_idx) {
24*77c1e3ccSAndroid Build Coastguard Worker int ref_mv_idx = mbmi->ref_mv_idx;
25*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->mode == NEAR_NEWMV || mbmi->mode == NEW_NEARMV) {
26*77c1e3ccSAndroid Build Coastguard Worker assert(has_second_ref(mbmi));
27*77c1e3ccSAndroid Build Coastguard Worker ref_mv_idx += 1;
28*77c1e3ccSAndroid Build Coastguard Worker }
29*77c1e3ccSAndroid Build Coastguard Worker
30*77c1e3ccSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME *ref_frames = mbmi->ref_frame;
31*77c1e3ccSAndroid Build Coastguard Worker const int8_t ref_frame_type = av1_ref_frame_type(ref_frames);
32*77c1e3ccSAndroid Build Coastguard Worker const CANDIDATE_MV *curr_ref_mv_stack = mbmi_ext_frame->ref_mv_stack;
33*77c1e3ccSAndroid Build Coastguard Worker
34*77c1e3ccSAndroid Build Coastguard Worker if (ref_frames[1] > INTRA_FRAME) {
35*77c1e3ccSAndroid Build Coastguard Worker assert(ref_idx == 0 || ref_idx == 1);
36*77c1e3ccSAndroid Build Coastguard Worker return ref_idx ? curr_ref_mv_stack[ref_mv_idx].comp_mv
37*77c1e3ccSAndroid Build Coastguard Worker : curr_ref_mv_stack[ref_mv_idx].this_mv;
38*77c1e3ccSAndroid Build Coastguard Worker }
39*77c1e3ccSAndroid Build Coastguard Worker
40*77c1e3ccSAndroid Build Coastguard Worker assert(ref_idx == 0);
41*77c1e3ccSAndroid Build Coastguard Worker return ref_mv_idx < mbmi_ext_frame->ref_mv_count
42*77c1e3ccSAndroid Build Coastguard Worker ? curr_ref_mv_stack[ref_mv_idx].this_mv
43*77c1e3ccSAndroid Build Coastguard Worker : mbmi_ext_frame->global_mvs[ref_frame_type];
44*77c1e3ccSAndroid Build Coastguard Worker }
45*77c1e3ccSAndroid Build Coastguard Worker
get_symbol_cost(const aom_cdf_prob * cdf,int symbol)46*77c1e3ccSAndroid Build Coastguard Worker static inline int get_symbol_cost(const aom_cdf_prob *cdf, int symbol) {
47*77c1e3ccSAndroid Build Coastguard Worker const aom_cdf_prob cur_cdf = AOM_ICDF(cdf[symbol]);
48*77c1e3ccSAndroid Build Coastguard Worker const aom_cdf_prob prev_cdf = symbol ? AOM_ICDF(cdf[symbol - 1]) : 0;
49*77c1e3ccSAndroid Build Coastguard Worker const aom_cdf_prob p15 = AOMMAX(cur_cdf - prev_cdf, EC_MIN_PROB);
50*77c1e3ccSAndroid Build Coastguard Worker
51*77c1e3ccSAndroid Build Coastguard Worker return av1_cost_symbol(p15);
52*77c1e3ccSAndroid Build Coastguard Worker }
53*77c1e3ccSAndroid Build Coastguard Worker
keep_one_comp_stat(MV_STATS * mv_stats,int comp_val,int comp_idx,const AV1_COMP * cpi,int * rates)54*77c1e3ccSAndroid Build Coastguard Worker static inline int keep_one_comp_stat(MV_STATS *mv_stats, int comp_val,
55*77c1e3ccSAndroid Build Coastguard Worker int comp_idx, const AV1_COMP *cpi,
56*77c1e3ccSAndroid Build Coastguard Worker int *rates) {
57*77c1e3ccSAndroid Build Coastguard Worker assert(comp_val != 0 && "mv component should not have zero value!");
58*77c1e3ccSAndroid Build Coastguard Worker const int sign = comp_val < 0;
59*77c1e3ccSAndroid Build Coastguard Worker const int mag = sign ? -comp_val : comp_val;
60*77c1e3ccSAndroid Build Coastguard Worker const int mag_minus_1 = mag - 1;
61*77c1e3ccSAndroid Build Coastguard Worker int offset;
62*77c1e3ccSAndroid Build Coastguard Worker const int mv_class = av1_get_mv_class(mag_minus_1, &offset);
63*77c1e3ccSAndroid Build Coastguard Worker const int int_part = offset >> 3; // int mv data
64*77c1e3ccSAndroid Build Coastguard Worker const int frac_part = (offset >> 1) & 3; // fractional mv data
65*77c1e3ccSAndroid Build Coastguard Worker const int high_part = offset & 1; // high precision mv data
66*77c1e3ccSAndroid Build Coastguard Worker const int use_hp = cpi->common.features.allow_high_precision_mv;
67*77c1e3ccSAndroid Build Coastguard Worker int r_idx = 0;
68*77c1e3ccSAndroid Build Coastguard Worker
69*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *const x = &cpi->td.mb;
70*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
71*77c1e3ccSAndroid Build Coastguard Worker FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
72*77c1e3ccSAndroid Build Coastguard Worker nmv_context *nmvc = &ec_ctx->nmvc;
73*77c1e3ccSAndroid Build Coastguard Worker nmv_component *mvcomp_ctx = nmvc->comps;
74*77c1e3ccSAndroid Build Coastguard Worker nmv_component *cur_mvcomp_ctx = &mvcomp_ctx[comp_idx];
75*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob *sign_cdf = cur_mvcomp_ctx->sign_cdf;
76*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob *class_cdf = cur_mvcomp_ctx->classes_cdf;
77*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob *class0_cdf = cur_mvcomp_ctx->class0_cdf;
78*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob(*bits_cdf)[3] = cur_mvcomp_ctx->bits_cdf;
79*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob *frac_part_cdf = mv_class
80*77c1e3ccSAndroid Build Coastguard Worker ? (cur_mvcomp_ctx->fp_cdf)
81*77c1e3ccSAndroid Build Coastguard Worker : (cur_mvcomp_ctx->class0_fp_cdf[int_part]);
82*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob *high_part_cdf =
83*77c1e3ccSAndroid Build Coastguard Worker mv_class ? (cur_mvcomp_ctx->hp_cdf) : (cur_mvcomp_ctx->class0_hp_cdf);
84*77c1e3ccSAndroid Build Coastguard Worker
85*77c1e3ccSAndroid Build Coastguard Worker const int sign_rate = get_symbol_cost(sign_cdf, sign);
86*77c1e3ccSAndroid Build Coastguard Worker rates[r_idx++] = sign_rate;
87*77c1e3ccSAndroid Build Coastguard Worker update_cdf(sign_cdf, sign, 2);
88*77c1e3ccSAndroid Build Coastguard Worker
89*77c1e3ccSAndroid Build Coastguard Worker const int class_rate = get_symbol_cost(class_cdf, mv_class);
90*77c1e3ccSAndroid Build Coastguard Worker rates[r_idx++] = class_rate;
91*77c1e3ccSAndroid Build Coastguard Worker update_cdf(class_cdf, mv_class, MV_CLASSES);
92*77c1e3ccSAndroid Build Coastguard Worker
93*77c1e3ccSAndroid Build Coastguard Worker int int_bit_rate = 0;
94*77c1e3ccSAndroid Build Coastguard Worker if (mv_class == MV_CLASS_0) {
95*77c1e3ccSAndroid Build Coastguard Worker int_bit_rate = get_symbol_cost(class0_cdf, int_part);
96*77c1e3ccSAndroid Build Coastguard Worker update_cdf(class0_cdf, int_part, CLASS0_SIZE);
97*77c1e3ccSAndroid Build Coastguard Worker } else {
98*77c1e3ccSAndroid Build Coastguard Worker const int n = mv_class + CLASS0_BITS - 1; // number of bits
99*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < n; ++i) {
100*77c1e3ccSAndroid Build Coastguard Worker int_bit_rate += get_symbol_cost(bits_cdf[i], (int_part >> i) & 1);
101*77c1e3ccSAndroid Build Coastguard Worker update_cdf(bits_cdf[i], (int_part >> i) & 1, 2);
102*77c1e3ccSAndroid Build Coastguard Worker }
103*77c1e3ccSAndroid Build Coastguard Worker }
104*77c1e3ccSAndroid Build Coastguard Worker rates[r_idx++] = int_bit_rate;
105*77c1e3ccSAndroid Build Coastguard Worker const int frac_part_rate = get_symbol_cost(frac_part_cdf, frac_part);
106*77c1e3ccSAndroid Build Coastguard Worker rates[r_idx++] = frac_part_rate;
107*77c1e3ccSAndroid Build Coastguard Worker update_cdf(frac_part_cdf, frac_part, MV_FP_SIZE);
108*77c1e3ccSAndroid Build Coastguard Worker const int high_part_rate =
109*77c1e3ccSAndroid Build Coastguard Worker use_hp ? get_symbol_cost(high_part_cdf, high_part) : 0;
110*77c1e3ccSAndroid Build Coastguard Worker if (use_hp) {
111*77c1e3ccSAndroid Build Coastguard Worker update_cdf(high_part_cdf, high_part, 2);
112*77c1e3ccSAndroid Build Coastguard Worker }
113*77c1e3ccSAndroid Build Coastguard Worker rates[r_idx++] = high_part_rate;
114*77c1e3ccSAndroid Build Coastguard Worker
115*77c1e3ccSAndroid Build Coastguard Worker mv_stats->last_bit_zero += !high_part;
116*77c1e3ccSAndroid Build Coastguard Worker mv_stats->last_bit_nonzero += high_part;
117*77c1e3ccSAndroid Build Coastguard Worker const int total_rate =
118*77c1e3ccSAndroid Build Coastguard Worker (sign_rate + class_rate + int_bit_rate + frac_part_rate + high_part_rate);
119*77c1e3ccSAndroid Build Coastguard Worker return total_rate;
120*77c1e3ccSAndroid Build Coastguard Worker }
121*77c1e3ccSAndroid Build Coastguard Worker
keep_one_mv_stat(MV_STATS * mv_stats,const MV * ref_mv,const MV * cur_mv,const AV1_COMP * cpi)122*77c1e3ccSAndroid Build Coastguard Worker static inline void keep_one_mv_stat(MV_STATS *mv_stats, const MV *ref_mv,
123*77c1e3ccSAndroid Build Coastguard Worker const MV *cur_mv, const AV1_COMP *cpi) {
124*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCK *const x = &cpi->td.mb;
125*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
126*77c1e3ccSAndroid Build Coastguard Worker FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
127*77c1e3ccSAndroid Build Coastguard Worker nmv_context *nmvc = &ec_ctx->nmvc;
128*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob *joint_cdf = nmvc->joints_cdf;
129*77c1e3ccSAndroid Build Coastguard Worker const int use_hp = cpi->common.features.allow_high_precision_mv;
130*77c1e3ccSAndroid Build Coastguard Worker
131*77c1e3ccSAndroid Build Coastguard Worker const MV diff = { cur_mv->row - ref_mv->row, cur_mv->col - ref_mv->col };
132*77c1e3ccSAndroid Build Coastguard Worker const int mv_joint = av1_get_mv_joint(&diff);
133*77c1e3ccSAndroid Build Coastguard Worker // TODO([email protected]): Estimate hp_diff when we are using lp
134*77c1e3ccSAndroid Build Coastguard Worker const MV hp_diff = diff;
135*77c1e3ccSAndroid Build Coastguard Worker const int hp_mv_joint = av1_get_mv_joint(&hp_diff);
136*77c1e3ccSAndroid Build Coastguard Worker const MV truncated_diff = { (diff.row / 2) * 2, (diff.col / 2) * 2 };
137*77c1e3ccSAndroid Build Coastguard Worker const MV lp_diff = use_hp ? truncated_diff : diff;
138*77c1e3ccSAndroid Build Coastguard Worker const int lp_mv_joint = av1_get_mv_joint(&lp_diff);
139*77c1e3ccSAndroid Build Coastguard Worker
140*77c1e3ccSAndroid Build Coastguard Worker const int mv_joint_rate = get_symbol_cost(joint_cdf, mv_joint);
141*77c1e3ccSAndroid Build Coastguard Worker const int hp_mv_joint_rate = get_symbol_cost(joint_cdf, hp_mv_joint);
142*77c1e3ccSAndroid Build Coastguard Worker const int lp_mv_joint_rate = get_symbol_cost(joint_cdf, lp_mv_joint);
143*77c1e3ccSAndroid Build Coastguard Worker
144*77c1e3ccSAndroid Build Coastguard Worker update_cdf(joint_cdf, mv_joint, MV_JOINTS);
145*77c1e3ccSAndroid Build Coastguard Worker
146*77c1e3ccSAndroid Build Coastguard Worker mv_stats->total_mv_rate += mv_joint_rate;
147*77c1e3ccSAndroid Build Coastguard Worker mv_stats->hp_total_mv_rate += hp_mv_joint_rate;
148*77c1e3ccSAndroid Build Coastguard Worker mv_stats->lp_total_mv_rate += lp_mv_joint_rate;
149*77c1e3ccSAndroid Build Coastguard Worker mv_stats->mv_joint_count[mv_joint]++;
150*77c1e3ccSAndroid Build Coastguard Worker
151*77c1e3ccSAndroid Build Coastguard Worker for (int comp_idx = 0; comp_idx < 2; comp_idx++) {
152*77c1e3ccSAndroid Build Coastguard Worker const int comp_val = comp_idx ? diff.col : diff.row;
153*77c1e3ccSAndroid Build Coastguard Worker const int hp_comp_val = comp_idx ? hp_diff.col : hp_diff.row;
154*77c1e3ccSAndroid Build Coastguard Worker const int lp_comp_val = comp_idx ? lp_diff.col : lp_diff.row;
155*77c1e3ccSAndroid Build Coastguard Worker int rates[5];
156*77c1e3ccSAndroid Build Coastguard Worker av1_zero_array(rates, 5);
157*77c1e3ccSAndroid Build Coastguard Worker
158*77c1e3ccSAndroid Build Coastguard Worker const int comp_rate =
159*77c1e3ccSAndroid Build Coastguard Worker comp_val ? keep_one_comp_stat(mv_stats, comp_val, comp_idx, cpi, rates)
160*77c1e3ccSAndroid Build Coastguard Worker : 0;
161*77c1e3ccSAndroid Build Coastguard Worker // TODO([email protected]): Properly get hp rate when use_hp is false
162*77c1e3ccSAndroid Build Coastguard Worker const int hp_rate =
163*77c1e3ccSAndroid Build Coastguard Worker hp_comp_val ? rates[0] + rates[1] + rates[2] + rates[3] + rates[4] : 0;
164*77c1e3ccSAndroid Build Coastguard Worker const int lp_rate =
165*77c1e3ccSAndroid Build Coastguard Worker lp_comp_val ? rates[0] + rates[1] + rates[2] + rates[3] : 0;
166*77c1e3ccSAndroid Build Coastguard Worker
167*77c1e3ccSAndroid Build Coastguard Worker mv_stats->total_mv_rate += comp_rate;
168*77c1e3ccSAndroid Build Coastguard Worker mv_stats->hp_total_mv_rate += hp_rate;
169*77c1e3ccSAndroid Build Coastguard Worker mv_stats->lp_total_mv_rate += lp_rate;
170*77c1e3ccSAndroid Build Coastguard Worker }
171*77c1e3ccSAndroid Build Coastguard Worker }
172*77c1e3ccSAndroid Build Coastguard Worker
collect_mv_stats_b(MV_STATS * mv_stats,const AV1_COMP * cpi,int mi_row,int mi_col)173*77c1e3ccSAndroid Build Coastguard Worker static inline void collect_mv_stats_b(MV_STATS *mv_stats, const AV1_COMP *cpi,
174*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col) {
175*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
176*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = &cm->mi_params;
177*77c1e3ccSAndroid Build Coastguard Worker
178*77c1e3ccSAndroid Build Coastguard Worker if (mi_row >= mi_params->mi_rows || mi_col >= mi_params->mi_cols) {
179*77c1e3ccSAndroid Build Coastguard Worker return;
180*77c1e3ccSAndroid Build Coastguard Worker }
181*77c1e3ccSAndroid Build Coastguard Worker
182*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO *mbmi =
183*77c1e3ccSAndroid Build Coastguard Worker mi_params->mi_grid_base[mi_row * mi_params->mi_stride + mi_col];
184*77c1e3ccSAndroid Build Coastguard Worker const MB_MODE_INFO_EXT_FRAME *mbmi_ext_frame =
185*77c1e3ccSAndroid Build Coastguard Worker cpi->mbmi_ext_info.frame_base +
186*77c1e3ccSAndroid Build Coastguard Worker get_mi_ext_idx(mi_row, mi_col, cm->mi_params.mi_alloc_bsize,
187*77c1e3ccSAndroid Build Coastguard Worker cpi->mbmi_ext_info.stride);
188*77c1e3ccSAndroid Build Coastguard Worker
189*77c1e3ccSAndroid Build Coastguard Worker if (!is_inter_block(mbmi)) {
190*77c1e3ccSAndroid Build Coastguard Worker mv_stats->intra_count++;
191*77c1e3ccSAndroid Build Coastguard Worker return;
192*77c1e3ccSAndroid Build Coastguard Worker }
193*77c1e3ccSAndroid Build Coastguard Worker mv_stats->inter_count++;
194*77c1e3ccSAndroid Build Coastguard Worker
195*77c1e3ccSAndroid Build Coastguard Worker const PREDICTION_MODE mode = mbmi->mode;
196*77c1e3ccSAndroid Build Coastguard Worker const int is_compound = has_second_ref(mbmi);
197*77c1e3ccSAndroid Build Coastguard Worker
198*77c1e3ccSAndroid Build Coastguard Worker if (mode == NEWMV || mode == NEW_NEWMV) {
199*77c1e3ccSAndroid Build Coastguard Worker // All mvs are new
200*77c1e3ccSAndroid Build Coastguard Worker for (int ref_idx = 0; ref_idx < 1 + is_compound; ++ref_idx) {
201*77c1e3ccSAndroid Build Coastguard Worker const MV ref_mv =
202*77c1e3ccSAndroid Build Coastguard Worker get_ref_mv_for_mv_stats(mbmi, mbmi_ext_frame, ref_idx).as_mv;
203*77c1e3ccSAndroid Build Coastguard Worker const MV cur_mv = mbmi->mv[ref_idx].as_mv;
204*77c1e3ccSAndroid Build Coastguard Worker keep_one_mv_stat(mv_stats, &ref_mv, &cur_mv, cpi);
205*77c1e3ccSAndroid Build Coastguard Worker }
206*77c1e3ccSAndroid Build Coastguard Worker } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV ||
207*77c1e3ccSAndroid Build Coastguard Worker mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
208*77c1e3ccSAndroid Build Coastguard Worker // has exactly one new_mv
209*77c1e3ccSAndroid Build Coastguard Worker mv_stats->default_mvs += 1;
210*77c1e3ccSAndroid Build Coastguard Worker
211*77c1e3ccSAndroid Build Coastguard Worker const int ref_idx = (mode == NEAREST_NEWMV || mode == NEAR_NEWMV);
212*77c1e3ccSAndroid Build Coastguard Worker const MV ref_mv =
213*77c1e3ccSAndroid Build Coastguard Worker get_ref_mv_for_mv_stats(mbmi, mbmi_ext_frame, ref_idx).as_mv;
214*77c1e3ccSAndroid Build Coastguard Worker const MV cur_mv = mbmi->mv[ref_idx].as_mv;
215*77c1e3ccSAndroid Build Coastguard Worker
216*77c1e3ccSAndroid Build Coastguard Worker keep_one_mv_stat(mv_stats, &ref_mv, &cur_mv, cpi);
217*77c1e3ccSAndroid Build Coastguard Worker } else {
218*77c1e3ccSAndroid Build Coastguard Worker // No new_mv
219*77c1e3ccSAndroid Build Coastguard Worker mv_stats->default_mvs += 1 + is_compound;
220*77c1e3ccSAndroid Build Coastguard Worker }
221*77c1e3ccSAndroid Build Coastguard Worker
222*77c1e3ccSAndroid Build Coastguard Worker // Add texture information
223*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE bsize = mbmi->bsize;
224*77c1e3ccSAndroid Build Coastguard Worker const int num_rows = block_size_high[bsize];
225*77c1e3ccSAndroid Build Coastguard Worker const int num_cols = block_size_wide[bsize];
226*77c1e3ccSAndroid Build Coastguard Worker const int y_stride = cpi->source->y_stride;
227*77c1e3ccSAndroid Build Coastguard Worker const int px_row = 4 * mi_row, px_col = 4 * mi_col;
228*77c1e3ccSAndroid Build Coastguard Worker const int buf_is_hbd = cpi->source->flags & YV12_FLAG_HIGHBITDEPTH;
229*77c1e3ccSAndroid Build Coastguard Worker const int bd = cm->seq_params->bit_depth;
230*77c1e3ccSAndroid Build Coastguard Worker if (buf_is_hbd) {
231*77c1e3ccSAndroid Build Coastguard Worker uint16_t *source_buf =
232*77c1e3ccSAndroid Build Coastguard Worker CONVERT_TO_SHORTPTR(cpi->source->y_buffer) + px_row * y_stride + px_col;
233*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < num_rows - 1; row++) {
234*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < num_cols - 1; col++) {
235*77c1e3ccSAndroid Build Coastguard Worker const int offset = row * y_stride + col;
236*77c1e3ccSAndroid Build Coastguard Worker const int horz_diff =
237*77c1e3ccSAndroid Build Coastguard Worker abs(source_buf[offset + 1] - source_buf[offset]) >> (bd - 8);
238*77c1e3ccSAndroid Build Coastguard Worker const int vert_diff =
239*77c1e3ccSAndroid Build Coastguard Worker abs(source_buf[offset + y_stride] - source_buf[offset]) >> (bd - 8);
240*77c1e3ccSAndroid Build Coastguard Worker mv_stats->horz_text += horz_diff;
241*77c1e3ccSAndroid Build Coastguard Worker mv_stats->vert_text += vert_diff;
242*77c1e3ccSAndroid Build Coastguard Worker mv_stats->diag_text += horz_diff * vert_diff;
243*77c1e3ccSAndroid Build Coastguard Worker }
244*77c1e3ccSAndroid Build Coastguard Worker }
245*77c1e3ccSAndroid Build Coastguard Worker } else {
246*77c1e3ccSAndroid Build Coastguard Worker uint8_t *source_buf = cpi->source->y_buffer + px_row * y_stride + px_col;
247*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < num_rows - 1; row++) {
248*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < num_cols - 1; col++) {
249*77c1e3ccSAndroid Build Coastguard Worker const int offset = row * y_stride + col;
250*77c1e3ccSAndroid Build Coastguard Worker const int horz_diff = abs(source_buf[offset + 1] - source_buf[offset]);
251*77c1e3ccSAndroid Build Coastguard Worker const int vert_diff =
252*77c1e3ccSAndroid Build Coastguard Worker abs(source_buf[offset + y_stride] - source_buf[offset]);
253*77c1e3ccSAndroid Build Coastguard Worker mv_stats->horz_text += horz_diff;
254*77c1e3ccSAndroid Build Coastguard Worker mv_stats->vert_text += vert_diff;
255*77c1e3ccSAndroid Build Coastguard Worker mv_stats->diag_text += horz_diff * vert_diff;
256*77c1e3ccSAndroid Build Coastguard Worker }
257*77c1e3ccSAndroid Build Coastguard Worker }
258*77c1e3ccSAndroid Build Coastguard Worker }
259*77c1e3ccSAndroid Build Coastguard Worker }
260*77c1e3ccSAndroid Build Coastguard Worker
261*77c1e3ccSAndroid Build Coastguard Worker // Split block
collect_mv_stats_sb(MV_STATS * mv_stats,const AV1_COMP * cpi,int mi_row,int mi_col,BLOCK_SIZE bsize)262*77c1e3ccSAndroid Build Coastguard Worker static inline void collect_mv_stats_sb(MV_STATS *mv_stats, const AV1_COMP *cpi,
263*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col,
264*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize) {
265*77c1e3ccSAndroid Build Coastguard Worker assert(bsize < BLOCK_SIZES_ALL);
266*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
267*77c1e3ccSAndroid Build Coastguard Worker
268*77c1e3ccSAndroid Build Coastguard Worker if (mi_row >= cm->mi_params.mi_rows || mi_col >= cm->mi_params.mi_cols)
269*77c1e3ccSAndroid Build Coastguard Worker return;
270*77c1e3ccSAndroid Build Coastguard Worker
271*77c1e3ccSAndroid Build Coastguard Worker const PARTITION_TYPE partition = get_partition(cm, mi_row, mi_col, bsize);
272*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE subsize = get_partition_subsize(bsize, partition);
273*77c1e3ccSAndroid Build Coastguard Worker
274*77c1e3ccSAndroid Build Coastguard Worker const int hbs = mi_size_wide[bsize] / 2;
275*77c1e3ccSAndroid Build Coastguard Worker const int qbs = mi_size_wide[bsize] / 4;
276*77c1e3ccSAndroid Build Coastguard Worker switch (partition) {
277*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_NONE:
278*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col);
279*77c1e3ccSAndroid Build Coastguard Worker break;
280*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_HORZ:
281*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col);
282*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row + hbs, mi_col);
283*77c1e3ccSAndroid Build Coastguard Worker break;
284*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_VERT:
285*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col);
286*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col + hbs);
287*77c1e3ccSAndroid Build Coastguard Worker break;
288*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_SPLIT:
289*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_sb(mv_stats, cpi, mi_row, mi_col, subsize);
290*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_sb(mv_stats, cpi, mi_row, mi_col + hbs, subsize);
291*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_sb(mv_stats, cpi, mi_row + hbs, mi_col, subsize);
292*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_sb(mv_stats, cpi, mi_row + hbs, mi_col + hbs, subsize);
293*77c1e3ccSAndroid Build Coastguard Worker break;
294*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_HORZ_A:
295*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col);
296*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col + hbs);
297*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row + hbs, mi_col);
298*77c1e3ccSAndroid Build Coastguard Worker break;
299*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_HORZ_B:
300*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col);
301*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row + hbs, mi_col);
302*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row + hbs, mi_col + hbs);
303*77c1e3ccSAndroid Build Coastguard Worker break;
304*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_VERT_A:
305*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col);
306*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row + hbs, mi_col);
307*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col + hbs);
308*77c1e3ccSAndroid Build Coastguard Worker break;
309*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_VERT_B:
310*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col);
311*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, mi_col + hbs);
312*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row + hbs, mi_col + hbs);
313*77c1e3ccSAndroid Build Coastguard Worker break;
314*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_HORZ_4:
315*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
316*77c1e3ccSAndroid Build Coastguard Worker const int this_mi_row = mi_row + i * qbs;
317*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, this_mi_row, mi_col);
318*77c1e3ccSAndroid Build Coastguard Worker }
319*77c1e3ccSAndroid Build Coastguard Worker break;
320*77c1e3ccSAndroid Build Coastguard Worker case PARTITION_VERT_4:
321*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
322*77c1e3ccSAndroid Build Coastguard Worker const int this_mi_col = mi_col + i * qbs;
323*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_b(mv_stats, cpi, mi_row, this_mi_col);
324*77c1e3ccSAndroid Build Coastguard Worker }
325*77c1e3ccSAndroid Build Coastguard Worker break;
326*77c1e3ccSAndroid Build Coastguard Worker default: assert(0);
327*77c1e3ccSAndroid Build Coastguard Worker }
328*77c1e3ccSAndroid Build Coastguard Worker }
329*77c1e3ccSAndroid Build Coastguard Worker
collect_mv_stats_tile(MV_STATS * mv_stats,const AV1_COMP * cpi,const TileInfo * tile_info)330*77c1e3ccSAndroid Build Coastguard Worker static inline void collect_mv_stats_tile(MV_STATS *mv_stats,
331*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi,
332*77c1e3ccSAndroid Build Coastguard Worker const TileInfo *tile_info) {
333*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
334*77c1e3ccSAndroid Build Coastguard Worker const int mi_row_start = tile_info->mi_row_start;
335*77c1e3ccSAndroid Build Coastguard Worker const int mi_row_end = tile_info->mi_row_end;
336*77c1e3ccSAndroid Build Coastguard Worker const int mi_col_start = tile_info->mi_col_start;
337*77c1e3ccSAndroid Build Coastguard Worker const int mi_col_end = tile_info->mi_col_end;
338*77c1e3ccSAndroid Build Coastguard Worker const int sb_size_mi = cm->seq_params->mib_size;
339*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE sb_size = cm->seq_params->sb_size;
340*77c1e3ccSAndroid Build Coastguard Worker for (int mi_row = mi_row_start; mi_row < mi_row_end; mi_row += sb_size_mi) {
341*77c1e3ccSAndroid Build Coastguard Worker for (int mi_col = mi_col_start; mi_col < mi_col_end; mi_col += sb_size_mi) {
342*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_sb(mv_stats, cpi, mi_row, mi_col, sb_size);
343*77c1e3ccSAndroid Build Coastguard Worker }
344*77c1e3ccSAndroid Build Coastguard Worker }
345*77c1e3ccSAndroid Build Coastguard Worker }
346*77c1e3ccSAndroid Build Coastguard Worker
av1_collect_mv_stats(AV1_COMP * cpi,int current_q)347*77c1e3ccSAndroid Build Coastguard Worker void av1_collect_mv_stats(AV1_COMP *cpi, int current_q) {
348*77c1e3ccSAndroid Build Coastguard Worker MV_STATS *mv_stats = &cpi->mv_stats;
349*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
350*77c1e3ccSAndroid Build Coastguard Worker const int tile_cols = cm->tiles.cols;
351*77c1e3ccSAndroid Build Coastguard Worker const int tile_rows = cm->tiles.rows;
352*77c1e3ccSAndroid Build Coastguard Worker
353*77c1e3ccSAndroid Build Coastguard Worker for (int tile_row = 0; tile_row < tile_rows; tile_row++) {
354*77c1e3ccSAndroid Build Coastguard Worker TileInfo tile_info;
355*77c1e3ccSAndroid Build Coastguard Worker av1_tile_set_row(&tile_info, cm, tile_row);
356*77c1e3ccSAndroid Build Coastguard Worker for (int tile_col = 0; tile_col < tile_cols; tile_col++) {
357*77c1e3ccSAndroid Build Coastguard Worker const int tile_idx = tile_row * tile_cols + tile_col;
358*77c1e3ccSAndroid Build Coastguard Worker av1_tile_set_col(&tile_info, cm, tile_col);
359*77c1e3ccSAndroid Build Coastguard Worker cpi->tile_data[tile_idx].tctx = *cm->fc;
360*77c1e3ccSAndroid Build Coastguard Worker cpi->td.mb.e_mbd.tile_ctx = &cpi->tile_data[tile_idx].tctx;
361*77c1e3ccSAndroid Build Coastguard Worker collect_mv_stats_tile(mv_stats, cpi, &tile_info);
362*77c1e3ccSAndroid Build Coastguard Worker }
363*77c1e3ccSAndroid Build Coastguard Worker }
364*77c1e3ccSAndroid Build Coastguard Worker
365*77c1e3ccSAndroid Build Coastguard Worker mv_stats->q = current_q;
366*77c1e3ccSAndroid Build Coastguard Worker mv_stats->order = cpi->common.current_frame.order_hint;
367*77c1e3ccSAndroid Build Coastguard Worker mv_stats->valid = 1;
368*77c1e3ccSAndroid Build Coastguard Worker }
369*77c1e3ccSAndroid Build Coastguard Worker
get_smart_mv_prec(AV1_COMP * cpi,const MV_STATS * mv_stats,int current_q)370*77c1e3ccSAndroid Build Coastguard Worker static inline int get_smart_mv_prec(AV1_COMP *cpi, const MV_STATS *mv_stats,
371*77c1e3ccSAndroid Build Coastguard Worker int current_q) {
372*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
373*77c1e3ccSAndroid Build Coastguard Worker const int order_hint = cpi->common.current_frame.order_hint;
374*77c1e3ccSAndroid Build Coastguard Worker const int order_diff = order_hint - mv_stats->order;
375*77c1e3ccSAndroid Build Coastguard Worker const float area = (float)(cm->width * cm->height);
376*77c1e3ccSAndroid Build Coastguard Worker float features[MV_PREC_FEATURE_SIZE] = {
377*77c1e3ccSAndroid Build Coastguard Worker (float)current_q,
378*77c1e3ccSAndroid Build Coastguard Worker (float)mv_stats->q,
379*77c1e3ccSAndroid Build Coastguard Worker (float)order_diff,
380*77c1e3ccSAndroid Build Coastguard Worker mv_stats->inter_count / area,
381*77c1e3ccSAndroid Build Coastguard Worker mv_stats->intra_count / area,
382*77c1e3ccSAndroid Build Coastguard Worker mv_stats->default_mvs / area,
383*77c1e3ccSAndroid Build Coastguard Worker mv_stats->mv_joint_count[0] / area,
384*77c1e3ccSAndroid Build Coastguard Worker mv_stats->mv_joint_count[1] / area,
385*77c1e3ccSAndroid Build Coastguard Worker mv_stats->mv_joint_count[2] / area,
386*77c1e3ccSAndroid Build Coastguard Worker mv_stats->mv_joint_count[3] / area,
387*77c1e3ccSAndroid Build Coastguard Worker mv_stats->last_bit_zero / area,
388*77c1e3ccSAndroid Build Coastguard Worker mv_stats->last_bit_nonzero / area,
389*77c1e3ccSAndroid Build Coastguard Worker mv_stats->total_mv_rate / area,
390*77c1e3ccSAndroid Build Coastguard Worker mv_stats->hp_total_mv_rate / area,
391*77c1e3ccSAndroid Build Coastguard Worker mv_stats->lp_total_mv_rate / area,
392*77c1e3ccSAndroid Build Coastguard Worker mv_stats->horz_text / area,
393*77c1e3ccSAndroid Build Coastguard Worker mv_stats->vert_text / area,
394*77c1e3ccSAndroid Build Coastguard Worker mv_stats->diag_text / area,
395*77c1e3ccSAndroid Build Coastguard Worker };
396*77c1e3ccSAndroid Build Coastguard Worker
397*77c1e3ccSAndroid Build Coastguard Worker for (int f_idx = 0; f_idx < MV_PREC_FEATURE_SIZE; f_idx++) {
398*77c1e3ccSAndroid Build Coastguard Worker features[f_idx] =
399*77c1e3ccSAndroid Build Coastguard Worker (features[f_idx] - av1_mv_prec_mean[f_idx]) / av1_mv_prec_std[f_idx];
400*77c1e3ccSAndroid Build Coastguard Worker }
401*77c1e3ccSAndroid Build Coastguard Worker float score = 0.0f;
402*77c1e3ccSAndroid Build Coastguard Worker
403*77c1e3ccSAndroid Build Coastguard Worker av1_nn_predict(features, &av1_mv_prec_dnn_config, 1, &score);
404*77c1e3ccSAndroid Build Coastguard Worker
405*77c1e3ccSAndroid Build Coastguard Worker const int use_high_hp = score >= 0.0f;
406*77c1e3ccSAndroid Build Coastguard Worker return use_high_hp;
407*77c1e3ccSAndroid Build Coastguard Worker }
408*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_REALTIME_ONLY
409*77c1e3ccSAndroid Build Coastguard Worker
av1_pick_and_set_high_precision_mv(AV1_COMP * cpi,int qindex)410*77c1e3ccSAndroid Build Coastguard Worker void av1_pick_and_set_high_precision_mv(AV1_COMP *cpi, int qindex) {
411*77c1e3ccSAndroid Build Coastguard Worker int use_hp = qindex < HIGH_PRECISION_MV_QTHRESH;
412*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
413*77c1e3ccSAndroid Build Coastguard Worker MV_STATS *mv_stats = &cpi->mv_stats;
414*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_REALTIME_ONLY
415*77c1e3ccSAndroid Build Coastguard Worker
416*77c1e3ccSAndroid Build Coastguard Worker if (cpi->sf.hl_sf.high_precision_mv_usage == QTR_ONLY) {
417*77c1e3ccSAndroid Build Coastguard Worker use_hp = 0;
418*77c1e3ccSAndroid Build Coastguard Worker }
419*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
420*77c1e3ccSAndroid Build Coastguard Worker else if (cpi->sf.hl_sf.high_precision_mv_usage == LAST_MV_DATA &&
421*77c1e3ccSAndroid Build Coastguard Worker av1_frame_allows_smart_mv(cpi) && mv_stats->valid) {
422*77c1e3ccSAndroid Build Coastguard Worker use_hp = get_smart_mv_prec(cpi, mv_stats, qindex);
423*77c1e3ccSAndroid Build Coastguard Worker }
424*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_REALTIME_ONLY
425*77c1e3ccSAndroid Build Coastguard Worker
426*77c1e3ccSAndroid Build Coastguard Worker av1_set_high_precision_mv(cpi, use_hp,
427*77c1e3ccSAndroid Build Coastguard Worker cpi->common.features.cur_frame_force_integer_mv);
428*77c1e3ccSAndroid Build Coastguard Worker }
429