1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2021, 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 <assert.h>
13*77c1e3ccSAndroid Build Coastguard Worker
14*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h"
15*77c1e3ccSAndroid Build Coastguard Worker
16*77c1e3ccSAndroid Build Coastguard Worker #include "aom_util/aom_pthread.h"
17*77c1e3ccSAndroid Build Coastguard Worker
18*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_TFLITE
19*77c1e3ccSAndroid Build Coastguard Worker #include "tensorflow/lite/c/c_api.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/deltaq4_model.c"
21*77c1e3ccSAndroid Build Coastguard Worker #endif
22*77c1e3ccSAndroid Build Coastguard Worker
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/common_data.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/enums.h"
25*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/idct.h"
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/reconinter.h"
27*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/allintra_vis.h"
28*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder.h"
29*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/ethread.h"
30*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/hybrid_fwd_txfm.h"
31*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/model_rd.h"
32*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rdopt_utils.h"
33*77c1e3ccSAndroid Build Coastguard Worker
34*77c1e3ccSAndroid Build Coastguard Worker #define MB_WIENER_PRED_BLOCK_SIZE BLOCK_128X128
35*77c1e3ccSAndroid Build Coastguard Worker #define MB_WIENER_PRED_BUF_STRIDE 128
36*77c1e3ccSAndroid Build Coastguard Worker
av1_alloc_mb_wiener_var_pred_buf(AV1_COMMON * cm,ThreadData * td)37*77c1e3ccSAndroid Build Coastguard Worker void av1_alloc_mb_wiener_var_pred_buf(AV1_COMMON *cm, ThreadData *td) {
38*77c1e3ccSAndroid Build Coastguard Worker const int is_high_bitdepth = is_cur_buf_hbd(&td->mb.e_mbd);
39*77c1e3ccSAndroid Build Coastguard Worker assert(MB_WIENER_PRED_BLOCK_SIZE < BLOCK_SIZES_ALL);
40*77c1e3ccSAndroid Build Coastguard Worker const int buf_width = block_size_wide[MB_WIENER_PRED_BLOCK_SIZE];
41*77c1e3ccSAndroid Build Coastguard Worker const int buf_height = block_size_high[MB_WIENER_PRED_BLOCK_SIZE];
42*77c1e3ccSAndroid Build Coastguard Worker assert(buf_width == MB_WIENER_PRED_BUF_STRIDE);
43*77c1e3ccSAndroid Build Coastguard Worker const size_t buf_size =
44*77c1e3ccSAndroid Build Coastguard Worker (buf_width * buf_height * sizeof(*td->wiener_tmp_pred_buf))
45*77c1e3ccSAndroid Build Coastguard Worker << is_high_bitdepth;
46*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, td->wiener_tmp_pred_buf, aom_memalign(32, buf_size));
47*77c1e3ccSAndroid Build Coastguard Worker }
48*77c1e3ccSAndroid Build Coastguard Worker
av1_dealloc_mb_wiener_var_pred_buf(ThreadData * td)49*77c1e3ccSAndroid Build Coastguard Worker void av1_dealloc_mb_wiener_var_pred_buf(ThreadData *td) {
50*77c1e3ccSAndroid Build Coastguard Worker aom_free(td->wiener_tmp_pred_buf);
51*77c1e3ccSAndroid Build Coastguard Worker td->wiener_tmp_pred_buf = NULL;
52*77c1e3ccSAndroid Build Coastguard Worker }
53*77c1e3ccSAndroid Build Coastguard Worker
av1_init_mb_wiener_var_buffer(AV1_COMP * cpi)54*77c1e3ccSAndroid Build Coastguard Worker void av1_init_mb_wiener_var_buffer(AV1_COMP *cpi) {
55*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *cm = &cpi->common;
56*77c1e3ccSAndroid Build Coastguard Worker
57*77c1e3ccSAndroid Build Coastguard Worker // This block size is also used to determine number of workers in
58*77c1e3ccSAndroid Build Coastguard Worker // multi-threading. If it is changed, one needs to change it accordingly in
59*77c1e3ccSAndroid Build Coastguard Worker // "compute_num_ai_workers()".
60*77c1e3ccSAndroid Build Coastguard Worker cpi->weber_bsize = BLOCK_8X8;
61*77c1e3ccSAndroid Build Coastguard Worker
62*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.enable_rate_guide_deltaq) {
63*77c1e3ccSAndroid Build Coastguard Worker if (cpi->mb_weber_stats && cpi->prep_rate_estimates &&
64*77c1e3ccSAndroid Build Coastguard Worker cpi->ext_rate_distribution)
65*77c1e3ccSAndroid Build Coastguard Worker return;
66*77c1e3ccSAndroid Build Coastguard Worker } else {
67*77c1e3ccSAndroid Build Coastguard Worker if (cpi->mb_weber_stats) return;
68*77c1e3ccSAndroid Build Coastguard Worker }
69*77c1e3ccSAndroid Build Coastguard Worker
70*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, cpi->mb_weber_stats,
71*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(cpi->frame_info.mi_rows * cpi->frame_info.mi_cols,
72*77c1e3ccSAndroid Build Coastguard Worker sizeof(*cpi->mb_weber_stats)));
73*77c1e3ccSAndroid Build Coastguard Worker
74*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.enable_rate_guide_deltaq) {
75*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
76*77c1e3ccSAndroid Build Coastguard Worker cm, cpi->prep_rate_estimates,
77*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(cpi->frame_info.mi_rows * cpi->frame_info.mi_cols,
78*77c1e3ccSAndroid Build Coastguard Worker sizeof(*cpi->prep_rate_estimates)));
79*77c1e3ccSAndroid Build Coastguard Worker
80*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
81*77c1e3ccSAndroid Build Coastguard Worker cm, cpi->ext_rate_distribution,
82*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(cpi->frame_info.mi_rows * cpi->frame_info.mi_cols,
83*77c1e3ccSAndroid Build Coastguard Worker sizeof(*cpi->ext_rate_distribution)));
84*77c1e3ccSAndroid Build Coastguard Worker }
85*77c1e3ccSAndroid Build Coastguard Worker }
86*77c1e3ccSAndroid Build Coastguard Worker
get_satd(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)87*77c1e3ccSAndroid Build Coastguard Worker static int64_t get_satd(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
88*77c1e3ccSAndroid Build Coastguard Worker int mi_col) {
89*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
90*77c1e3ccSAndroid Build Coastguard Worker const int mi_wide = mi_size_wide[bsize];
91*77c1e3ccSAndroid Build Coastguard Worker const int mi_high = mi_size_high[bsize];
92*77c1e3ccSAndroid Build Coastguard Worker
93*77c1e3ccSAndroid Build Coastguard Worker const int mi_step = mi_size_wide[cpi->weber_bsize];
94*77c1e3ccSAndroid Build Coastguard Worker int mb_stride = cpi->frame_info.mi_cols;
95*77c1e3ccSAndroid Build Coastguard Worker int mb_count = 0;
96*77c1e3ccSAndroid Build Coastguard Worker int64_t satd = 0;
97*77c1e3ccSAndroid Build Coastguard Worker
98*77c1e3ccSAndroid Build Coastguard Worker for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
99*77c1e3ccSAndroid Build Coastguard Worker for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
100*77c1e3ccSAndroid Build Coastguard Worker if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
101*77c1e3ccSAndroid Build Coastguard Worker continue;
102*77c1e3ccSAndroid Build Coastguard Worker
103*77c1e3ccSAndroid Build Coastguard Worker satd += cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)]
104*77c1e3ccSAndroid Build Coastguard Worker .satd;
105*77c1e3ccSAndroid Build Coastguard Worker ++mb_count;
106*77c1e3ccSAndroid Build Coastguard Worker }
107*77c1e3ccSAndroid Build Coastguard Worker }
108*77c1e3ccSAndroid Build Coastguard Worker
109*77c1e3ccSAndroid Build Coastguard Worker if (mb_count) satd = (int)(satd / mb_count);
110*77c1e3ccSAndroid Build Coastguard Worker satd = AOMMAX(1, satd);
111*77c1e3ccSAndroid Build Coastguard Worker
112*77c1e3ccSAndroid Build Coastguard Worker return (int)satd;
113*77c1e3ccSAndroid Build Coastguard Worker }
114*77c1e3ccSAndroid Build Coastguard Worker
get_sse(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)115*77c1e3ccSAndroid Build Coastguard Worker static int64_t get_sse(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
116*77c1e3ccSAndroid Build Coastguard Worker int mi_col) {
117*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
118*77c1e3ccSAndroid Build Coastguard Worker const int mi_wide = mi_size_wide[bsize];
119*77c1e3ccSAndroid Build Coastguard Worker const int mi_high = mi_size_high[bsize];
120*77c1e3ccSAndroid Build Coastguard Worker
121*77c1e3ccSAndroid Build Coastguard Worker const int mi_step = mi_size_wide[cpi->weber_bsize];
122*77c1e3ccSAndroid Build Coastguard Worker int mb_stride = cpi->frame_info.mi_cols;
123*77c1e3ccSAndroid Build Coastguard Worker int mb_count = 0;
124*77c1e3ccSAndroid Build Coastguard Worker int64_t distortion = 0;
125*77c1e3ccSAndroid Build Coastguard Worker
126*77c1e3ccSAndroid Build Coastguard Worker for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
127*77c1e3ccSAndroid Build Coastguard Worker for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
128*77c1e3ccSAndroid Build Coastguard Worker if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
129*77c1e3ccSAndroid Build Coastguard Worker continue;
130*77c1e3ccSAndroid Build Coastguard Worker
131*77c1e3ccSAndroid Build Coastguard Worker distortion +=
132*77c1e3ccSAndroid Build Coastguard Worker cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)]
133*77c1e3ccSAndroid Build Coastguard Worker .distortion;
134*77c1e3ccSAndroid Build Coastguard Worker ++mb_count;
135*77c1e3ccSAndroid Build Coastguard Worker }
136*77c1e3ccSAndroid Build Coastguard Worker }
137*77c1e3ccSAndroid Build Coastguard Worker
138*77c1e3ccSAndroid Build Coastguard Worker if (mb_count) distortion = (int)(distortion / mb_count);
139*77c1e3ccSAndroid Build Coastguard Worker distortion = AOMMAX(1, distortion);
140*77c1e3ccSAndroid Build Coastguard Worker
141*77c1e3ccSAndroid Build Coastguard Worker return (int)distortion;
142*77c1e3ccSAndroid Build Coastguard Worker }
143*77c1e3ccSAndroid Build Coastguard Worker
get_max_scale(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)144*77c1e3ccSAndroid Build Coastguard Worker static double get_max_scale(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
145*77c1e3ccSAndroid Build Coastguard Worker int mi_col) {
146*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
147*77c1e3ccSAndroid Build Coastguard Worker const int mi_wide = mi_size_wide[bsize];
148*77c1e3ccSAndroid Build Coastguard Worker const int mi_high = mi_size_high[bsize];
149*77c1e3ccSAndroid Build Coastguard Worker const int mi_step = mi_size_wide[cpi->weber_bsize];
150*77c1e3ccSAndroid Build Coastguard Worker int mb_stride = cpi->frame_info.mi_cols;
151*77c1e3ccSAndroid Build Coastguard Worker double min_max_scale = 10.0;
152*77c1e3ccSAndroid Build Coastguard Worker
153*77c1e3ccSAndroid Build Coastguard Worker for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
154*77c1e3ccSAndroid Build Coastguard Worker for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
155*77c1e3ccSAndroid Build Coastguard Worker if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
156*77c1e3ccSAndroid Build Coastguard Worker continue;
157*77c1e3ccSAndroid Build Coastguard Worker WeberStats *weber_stats =
158*77c1e3ccSAndroid Build Coastguard Worker &cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)];
159*77c1e3ccSAndroid Build Coastguard Worker if (weber_stats->max_scale < 1.0) continue;
160*77c1e3ccSAndroid Build Coastguard Worker if (weber_stats->max_scale < min_max_scale)
161*77c1e3ccSAndroid Build Coastguard Worker min_max_scale = weber_stats->max_scale;
162*77c1e3ccSAndroid Build Coastguard Worker }
163*77c1e3ccSAndroid Build Coastguard Worker }
164*77c1e3ccSAndroid Build Coastguard Worker return min_max_scale;
165*77c1e3ccSAndroid Build Coastguard Worker }
166*77c1e3ccSAndroid Build Coastguard Worker
get_window_wiener_var(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)167*77c1e3ccSAndroid Build Coastguard Worker static int get_window_wiener_var(AV1_COMP *const cpi, BLOCK_SIZE bsize,
168*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col) {
169*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
170*77c1e3ccSAndroid Build Coastguard Worker const int mi_wide = mi_size_wide[bsize];
171*77c1e3ccSAndroid Build Coastguard Worker const int mi_high = mi_size_high[bsize];
172*77c1e3ccSAndroid Build Coastguard Worker
173*77c1e3ccSAndroid Build Coastguard Worker const int mi_step = mi_size_wide[cpi->weber_bsize];
174*77c1e3ccSAndroid Build Coastguard Worker int sb_wiener_var = 0;
175*77c1e3ccSAndroid Build Coastguard Worker int mb_stride = cpi->frame_info.mi_cols;
176*77c1e3ccSAndroid Build Coastguard Worker int mb_count = 0;
177*77c1e3ccSAndroid Build Coastguard Worker double base_num = 1;
178*77c1e3ccSAndroid Build Coastguard Worker double base_den = 1;
179*77c1e3ccSAndroid Build Coastguard Worker double base_reg = 1;
180*77c1e3ccSAndroid Build Coastguard Worker
181*77c1e3ccSAndroid Build Coastguard Worker for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
182*77c1e3ccSAndroid Build Coastguard Worker for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
183*77c1e3ccSAndroid Build Coastguard Worker if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
184*77c1e3ccSAndroid Build Coastguard Worker continue;
185*77c1e3ccSAndroid Build Coastguard Worker
186*77c1e3ccSAndroid Build Coastguard Worker WeberStats *weber_stats =
187*77c1e3ccSAndroid Build Coastguard Worker &cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)];
188*77c1e3ccSAndroid Build Coastguard Worker
189*77c1e3ccSAndroid Build Coastguard Worker base_num += ((double)weber_stats->distortion) *
190*77c1e3ccSAndroid Build Coastguard Worker sqrt((double)weber_stats->src_variance) *
191*77c1e3ccSAndroid Build Coastguard Worker weber_stats->rec_pix_max;
192*77c1e3ccSAndroid Build Coastguard Worker
193*77c1e3ccSAndroid Build Coastguard Worker base_den += fabs(
194*77c1e3ccSAndroid Build Coastguard Worker weber_stats->rec_pix_max * sqrt((double)weber_stats->src_variance) -
195*77c1e3ccSAndroid Build Coastguard Worker weber_stats->src_pix_max * sqrt((double)weber_stats->rec_variance));
196*77c1e3ccSAndroid Build Coastguard Worker
197*77c1e3ccSAndroid Build Coastguard Worker base_reg += sqrt((double)weber_stats->distortion) *
198*77c1e3ccSAndroid Build Coastguard Worker sqrt((double)weber_stats->src_pix_max) * 0.1;
199*77c1e3ccSAndroid Build Coastguard Worker ++mb_count;
200*77c1e3ccSAndroid Build Coastguard Worker }
201*77c1e3ccSAndroid Build Coastguard Worker }
202*77c1e3ccSAndroid Build Coastguard Worker
203*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_var =
204*77c1e3ccSAndroid Build Coastguard Worker (int)(((base_num + base_reg) / (base_den + base_reg)) / mb_count);
205*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_var = AOMMAX(1, sb_wiener_var);
206*77c1e3ccSAndroid Build Coastguard Worker
207*77c1e3ccSAndroid Build Coastguard Worker return (int)sb_wiener_var;
208*77c1e3ccSAndroid Build Coastguard Worker }
209*77c1e3ccSAndroid Build Coastguard Worker
get_var_perceptual_ai(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)210*77c1e3ccSAndroid Build Coastguard Worker static int get_var_perceptual_ai(AV1_COMP *const cpi, BLOCK_SIZE bsize,
211*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col) {
212*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
213*77c1e3ccSAndroid Build Coastguard Worker const int mi_wide = mi_size_wide[bsize];
214*77c1e3ccSAndroid Build Coastguard Worker const int mi_high = mi_size_high[bsize];
215*77c1e3ccSAndroid Build Coastguard Worker
216*77c1e3ccSAndroid Build Coastguard Worker int sb_wiener_var = get_window_wiener_var(cpi, bsize, mi_row, mi_col);
217*77c1e3ccSAndroid Build Coastguard Worker
218*77c1e3ccSAndroid Build Coastguard Worker if (mi_row >= (mi_high / 2)) {
219*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_var =
220*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(sb_wiener_var,
221*77c1e3ccSAndroid Build Coastguard Worker get_window_wiener_var(cpi, bsize, mi_row - mi_high / 2, mi_col));
222*77c1e3ccSAndroid Build Coastguard Worker }
223*77c1e3ccSAndroid Build Coastguard Worker if (mi_row <= (cm->mi_params.mi_rows - mi_high - (mi_high / 2))) {
224*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_var =
225*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(sb_wiener_var,
226*77c1e3ccSAndroid Build Coastguard Worker get_window_wiener_var(cpi, bsize, mi_row + mi_high / 2, mi_col));
227*77c1e3ccSAndroid Build Coastguard Worker }
228*77c1e3ccSAndroid Build Coastguard Worker if (mi_col >= (mi_wide / 2)) {
229*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_var =
230*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(sb_wiener_var,
231*77c1e3ccSAndroid Build Coastguard Worker get_window_wiener_var(cpi, bsize, mi_row, mi_col - mi_wide / 2));
232*77c1e3ccSAndroid Build Coastguard Worker }
233*77c1e3ccSAndroid Build Coastguard Worker if (mi_col <= (cm->mi_params.mi_cols - mi_wide - (mi_wide / 2))) {
234*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_var =
235*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(sb_wiener_var,
236*77c1e3ccSAndroid Build Coastguard Worker get_window_wiener_var(cpi, bsize, mi_row, mi_col + mi_wide / 2));
237*77c1e3ccSAndroid Build Coastguard Worker }
238*77c1e3ccSAndroid Build Coastguard Worker
239*77c1e3ccSAndroid Build Coastguard Worker return sb_wiener_var;
240*77c1e3ccSAndroid Build Coastguard Worker }
241*77c1e3ccSAndroid Build Coastguard Worker
rate_estimator(const tran_low_t * qcoeff,int eob,TX_SIZE tx_size)242*77c1e3ccSAndroid Build Coastguard Worker static int rate_estimator(const tran_low_t *qcoeff, int eob, TX_SIZE tx_size) {
243*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order = &av1_scan_orders[tx_size][DCT_DCT];
244*77c1e3ccSAndroid Build Coastguard Worker
245*77c1e3ccSAndroid Build Coastguard Worker assert((1 << num_pels_log2_lookup[txsize_to_bsize[tx_size]]) >= eob);
246*77c1e3ccSAndroid Build Coastguard Worker int rate_cost = 1;
247*77c1e3ccSAndroid Build Coastguard Worker
248*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < eob; ++idx) {
249*77c1e3ccSAndroid Build Coastguard Worker int abs_level = abs(qcoeff[scan_order->scan[idx]]);
250*77c1e3ccSAndroid Build Coastguard Worker rate_cost += (int)(log1p(abs_level) / log(2.0)) + 1 + (abs_level > 0);
251*77c1e3ccSAndroid Build Coastguard Worker }
252*77c1e3ccSAndroid Build Coastguard Worker
253*77c1e3ccSAndroid Build Coastguard Worker return (rate_cost << AV1_PROB_COST_SHIFT);
254*77c1e3ccSAndroid Build Coastguard Worker }
255*77c1e3ccSAndroid Build Coastguard Worker
av1_calc_mb_wiener_var_row(AV1_COMP * const cpi,MACROBLOCK * x,MACROBLOCKD * xd,const int mi_row,int16_t * src_diff,tran_low_t * coeff,tran_low_t * qcoeff,tran_low_t * dqcoeff,double * sum_rec_distortion,double * sum_est_rate,uint8_t * pred_buffer)256*77c1e3ccSAndroid Build Coastguard Worker void av1_calc_mb_wiener_var_row(AV1_COMP *const cpi, MACROBLOCK *x,
257*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd, const int mi_row,
258*77c1e3ccSAndroid Build Coastguard Worker int16_t *src_diff, tran_low_t *coeff,
259*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff, tran_low_t *dqcoeff,
260*77c1e3ccSAndroid Build Coastguard Worker double *sum_rec_distortion,
261*77c1e3ccSAndroid Build Coastguard Worker double *sum_est_rate, uint8_t *pred_buffer) {
262*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
263*77c1e3ccSAndroid Build Coastguard Worker uint8_t *buffer = cpi->source->y_buffer;
264*77c1e3ccSAndroid Build Coastguard Worker int buf_stride = cpi->source->y_stride;
265*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO mbmi;
266*77c1e3ccSAndroid Build Coastguard Worker memset(&mbmi, 0, sizeof(mbmi));
267*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi_ptr = &mbmi;
268*77c1e3ccSAndroid Build Coastguard Worker xd->mi = &mbmi_ptr;
269*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE bsize = cpi->weber_bsize;
270*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE tx_size = max_txsize_lookup[bsize];
271*77c1e3ccSAndroid Build Coastguard Worker const int block_size = tx_size_wide[tx_size];
272*77c1e3ccSAndroid Build Coastguard Worker const int coeff_count = block_size * block_size;
273*77c1e3ccSAndroid Build Coastguard Worker const int mb_step = mi_size_wide[bsize];
274*77c1e3ccSAndroid Build Coastguard Worker const BitDepthInfo bd_info = get_bit_depth_info(xd);
275*77c1e3ccSAndroid Build Coastguard Worker const MultiThreadInfo *const mt_info = &cpi->mt_info;
276*77c1e3ccSAndroid Build Coastguard Worker const AV1EncAllIntraMultiThreadInfo *const intra_mt = &mt_info->intra_mt;
277*77c1e3ccSAndroid Build Coastguard Worker AV1EncRowMultiThreadSync *const intra_row_mt_sync =
278*77c1e3ccSAndroid Build Coastguard Worker &cpi->ppi->intra_row_mt_sync;
279*77c1e3ccSAndroid Build Coastguard Worker const int mi_cols = cm->mi_params.mi_cols;
280*77c1e3ccSAndroid Build Coastguard Worker const int mt_thread_id = mi_row / mb_step;
281*77c1e3ccSAndroid Build Coastguard Worker // TODO(chengchen): test different unit step size
282*77c1e3ccSAndroid Build Coastguard Worker const int mt_unit_step = mi_size_wide[MB_WIENER_MT_UNIT_SIZE];
283*77c1e3ccSAndroid Build Coastguard Worker const int mt_unit_cols = (mi_cols + (mt_unit_step >> 1)) / mt_unit_step;
284*77c1e3ccSAndroid Build Coastguard Worker int mt_unit_col = 0;
285*77c1e3ccSAndroid Build Coastguard Worker const int is_high_bitdepth = is_cur_buf_hbd(xd);
286*77c1e3ccSAndroid Build Coastguard Worker
287*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst_buffer = pred_buffer;
288*77c1e3ccSAndroid Build Coastguard Worker const int dst_buffer_stride = MB_WIENER_PRED_BUF_STRIDE;
289*77c1e3ccSAndroid Build Coastguard Worker
290*77c1e3ccSAndroid Build Coastguard Worker if (is_high_bitdepth) {
291*77c1e3ccSAndroid Build Coastguard Worker uint16_t *pred_buffer_16 = (uint16_t *)pred_buffer;
292*77c1e3ccSAndroid Build Coastguard Worker dst_buffer = CONVERT_TO_BYTEPTR(pred_buffer_16);
293*77c1e3ccSAndroid Build Coastguard Worker }
294*77c1e3ccSAndroid Build Coastguard Worker
295*77c1e3ccSAndroid Build Coastguard Worker for (int mi_col = 0; mi_col < mi_cols; mi_col += mb_step) {
296*77c1e3ccSAndroid Build Coastguard Worker if (mi_col % mt_unit_step == 0) {
297*77c1e3ccSAndroid Build Coastguard Worker intra_mt->intra_sync_read_ptr(intra_row_mt_sync, mt_thread_id,
298*77c1e3ccSAndroid Build Coastguard Worker mt_unit_col);
299*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
300*77c1e3ccSAndroid Build Coastguard Worker const int num_workers =
301*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mt_info->num_mod_workers[MOD_AI], mt_info->num_workers);
302*77c1e3ccSAndroid Build Coastguard Worker if (num_workers > 1) {
303*77c1e3ccSAndroid Build Coastguard Worker const AV1EncRowMultiThreadInfo *const enc_row_mt = &mt_info->enc_row_mt;
304*77c1e3ccSAndroid Build Coastguard Worker pthread_mutex_lock(enc_row_mt->mutex_);
305*77c1e3ccSAndroid Build Coastguard Worker const bool exit = enc_row_mt->mb_wiener_mt_exit;
306*77c1e3ccSAndroid Build Coastguard Worker pthread_mutex_unlock(enc_row_mt->mutex_);
307*77c1e3ccSAndroid Build Coastguard Worker // Stop further processing in case any worker has encountered an error.
308*77c1e3ccSAndroid Build Coastguard Worker if (exit) break;
309*77c1e3ccSAndroid Build Coastguard Worker }
310*77c1e3ccSAndroid Build Coastguard Worker #endif
311*77c1e3ccSAndroid Build Coastguard Worker }
312*77c1e3ccSAndroid Build Coastguard Worker
313*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE best_mode = DC_PRED;
314*77c1e3ccSAndroid Build Coastguard Worker int best_intra_cost = INT_MAX;
315*77c1e3ccSAndroid Build Coastguard Worker const int mi_width = mi_size_wide[bsize];
316*77c1e3ccSAndroid Build Coastguard Worker const int mi_height = mi_size_high[bsize];
317*77c1e3ccSAndroid Build Coastguard Worker set_mode_info_offsets(&cpi->common.mi_params, &cpi->mbmi_ext_info, x, xd,
318*77c1e3ccSAndroid Build Coastguard Worker mi_row, mi_col);
319*77c1e3ccSAndroid Build Coastguard Worker set_mi_row_col(xd, &xd->tile, mi_row, mi_height, mi_col, mi_width,
320*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mi_row + mi_height, cm->mi_params.mi_rows),
321*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mi_col + mi_width, cm->mi_params.mi_cols));
322*77c1e3ccSAndroid Build Coastguard Worker set_plane_n4(xd, mi_size_wide[bsize], mi_size_high[bsize],
323*77c1e3ccSAndroid Build Coastguard Worker av1_num_planes(cm));
324*77c1e3ccSAndroid Build Coastguard Worker xd->mi[0]->bsize = bsize;
325*77c1e3ccSAndroid Build Coastguard Worker xd->mi[0]->motion_mode = SIMPLE_TRANSLATION;
326*77c1e3ccSAndroid Build Coastguard Worker // Set above and left mbmi to NULL as they are not available in the
327*77c1e3ccSAndroid Build Coastguard Worker // preprocessing stage.
328*77c1e3ccSAndroid Build Coastguard Worker // They are used to detemine intra edge filter types in intra prediction.
329*77c1e3ccSAndroid Build Coastguard Worker if (xd->up_available) {
330*77c1e3ccSAndroid Build Coastguard Worker xd->above_mbmi = NULL;
331*77c1e3ccSAndroid Build Coastguard Worker }
332*77c1e3ccSAndroid Build Coastguard Worker if (xd->left_available) {
333*77c1e3ccSAndroid Build Coastguard Worker xd->left_mbmi = NULL;
334*77c1e3ccSAndroid Build Coastguard Worker }
335*77c1e3ccSAndroid Build Coastguard Worker uint8_t *mb_buffer =
336*77c1e3ccSAndroid Build Coastguard Worker buffer + mi_row * MI_SIZE * buf_stride + mi_col * MI_SIZE;
337*77c1e3ccSAndroid Build Coastguard Worker for (PREDICTION_MODE mode = INTRA_MODE_START; mode < INTRA_MODE_END;
338*77c1e3ccSAndroid Build Coastguard Worker ++mode) {
339*77c1e3ccSAndroid Build Coastguard Worker // TODO(chengchen): Here we use src instead of reconstructed frame as
340*77c1e3ccSAndroid Build Coastguard Worker // the intra predictor to make single and multithread version match.
341*77c1e3ccSAndroid Build Coastguard Worker // Ideally we want to use the reconstructed.
342*77c1e3ccSAndroid Build Coastguard Worker av1_predict_intra_block(
343*77c1e3ccSAndroid Build Coastguard Worker xd, cm->seq_params->sb_size, cm->seq_params->enable_intra_edge_filter,
344*77c1e3ccSAndroid Build Coastguard Worker block_size, block_size, tx_size, mode, 0, 0, FILTER_INTRA_MODES,
345*77c1e3ccSAndroid Build Coastguard Worker mb_buffer, buf_stride, dst_buffer, dst_buffer_stride, 0, 0, 0);
346*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_block(bd_info, block_size, block_size, src_diff, block_size,
347*77c1e3ccSAndroid Build Coastguard Worker mb_buffer, buf_stride, dst_buffer, dst_buffer_stride);
348*77c1e3ccSAndroid Build Coastguard Worker av1_quick_txfm(0, tx_size, bd_info, src_diff, block_size, coeff);
349*77c1e3ccSAndroid Build Coastguard Worker int intra_cost = aom_satd(coeff, coeff_count);
350*77c1e3ccSAndroid Build Coastguard Worker if (intra_cost < best_intra_cost) {
351*77c1e3ccSAndroid Build Coastguard Worker best_intra_cost = intra_cost;
352*77c1e3ccSAndroid Build Coastguard Worker best_mode = mode;
353*77c1e3ccSAndroid Build Coastguard Worker }
354*77c1e3ccSAndroid Build Coastguard Worker }
355*77c1e3ccSAndroid Build Coastguard Worker
356*77c1e3ccSAndroid Build Coastguard Worker av1_predict_intra_block(
357*77c1e3ccSAndroid Build Coastguard Worker xd, cm->seq_params->sb_size, cm->seq_params->enable_intra_edge_filter,
358*77c1e3ccSAndroid Build Coastguard Worker block_size, block_size, tx_size, best_mode, 0, 0, FILTER_INTRA_MODES,
359*77c1e3ccSAndroid Build Coastguard Worker mb_buffer, buf_stride, dst_buffer, dst_buffer_stride, 0, 0, 0);
360*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_block(bd_info, block_size, block_size, src_diff, block_size,
361*77c1e3ccSAndroid Build Coastguard Worker mb_buffer, buf_stride, dst_buffer, dst_buffer_stride);
362*77c1e3ccSAndroid Build Coastguard Worker av1_quick_txfm(0, tx_size, bd_info, src_diff, block_size, coeff);
363*77c1e3ccSAndroid Build Coastguard Worker
364*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *const p = &x->plane[0];
365*77c1e3ccSAndroid Build Coastguard Worker uint16_t eob;
366*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order = &av1_scan_orders[tx_size][DCT_DCT];
367*77c1e3ccSAndroid Build Coastguard Worker QUANT_PARAM quant_param;
368*77c1e3ccSAndroid Build Coastguard Worker int pix_num = 1 << num_pels_log2_lookup[txsize_to_bsize[tx_size]];
369*77c1e3ccSAndroid Build Coastguard Worker av1_setup_quant(tx_size, 0, AV1_XFORM_QUANT_FP, 0, &quant_param);
370*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
371*77c1e3ccSAndroid Build Coastguard Worker if (is_cur_buf_hbd(xd)) {
372*77c1e3ccSAndroid Build Coastguard Worker av1_highbd_quantize_fp_facade(coeff, pix_num, p, qcoeff, dqcoeff, &eob,
373*77c1e3ccSAndroid Build Coastguard Worker scan_order, &quant_param);
374*77c1e3ccSAndroid Build Coastguard Worker } else {
375*77c1e3ccSAndroid Build Coastguard Worker av1_quantize_fp_facade(coeff, pix_num, p, qcoeff, dqcoeff, &eob,
376*77c1e3ccSAndroid Build Coastguard Worker scan_order, &quant_param);
377*77c1e3ccSAndroid Build Coastguard Worker }
378*77c1e3ccSAndroid Build Coastguard Worker #else
379*77c1e3ccSAndroid Build Coastguard Worker av1_quantize_fp_facade(coeff, pix_num, p, qcoeff, dqcoeff, &eob, scan_order,
380*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
381*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_AV1_HIGHBITDEPTH
382*77c1e3ccSAndroid Build Coastguard Worker
383*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.enable_rate_guide_deltaq) {
384*77c1e3ccSAndroid Build Coastguard Worker const int rate_cost = rate_estimator(qcoeff, eob, tx_size);
385*77c1e3ccSAndroid Build Coastguard Worker cpi->prep_rate_estimates[(mi_row / mb_step) * cpi->frame_info.mi_cols +
386*77c1e3ccSAndroid Build Coastguard Worker (mi_col / mb_step)] = rate_cost;
387*77c1e3ccSAndroid Build Coastguard Worker }
388*77c1e3ccSAndroid Build Coastguard Worker
389*77c1e3ccSAndroid Build Coastguard Worker av1_inverse_transform_block(xd, dqcoeff, 0, DCT_DCT, tx_size, dst_buffer,
390*77c1e3ccSAndroid Build Coastguard Worker dst_buffer_stride, eob, 0);
391*77c1e3ccSAndroid Build Coastguard Worker WeberStats *weber_stats =
392*77c1e3ccSAndroid Build Coastguard Worker &cpi->mb_weber_stats[(mi_row / mb_step) * cpi->frame_info.mi_cols +
393*77c1e3ccSAndroid Build Coastguard Worker (mi_col / mb_step)];
394*77c1e3ccSAndroid Build Coastguard Worker
395*77c1e3ccSAndroid Build Coastguard Worker weber_stats->rec_pix_max = 1;
396*77c1e3ccSAndroid Build Coastguard Worker weber_stats->rec_variance = 0;
397*77c1e3ccSAndroid Build Coastguard Worker weber_stats->src_pix_max = 1;
398*77c1e3ccSAndroid Build Coastguard Worker weber_stats->src_variance = 0;
399*77c1e3ccSAndroid Build Coastguard Worker weber_stats->distortion = 0;
400*77c1e3ccSAndroid Build Coastguard Worker
401*77c1e3ccSAndroid Build Coastguard Worker int64_t src_mean = 0;
402*77c1e3ccSAndroid Build Coastguard Worker int64_t rec_mean = 0;
403*77c1e3ccSAndroid Build Coastguard Worker int64_t dist_mean = 0;
404*77c1e3ccSAndroid Build Coastguard Worker
405*77c1e3ccSAndroid Build Coastguard Worker for (int pix_row = 0; pix_row < block_size; ++pix_row) {
406*77c1e3ccSAndroid Build Coastguard Worker for (int pix_col = 0; pix_col < block_size; ++pix_col) {
407*77c1e3ccSAndroid Build Coastguard Worker int src_pix, rec_pix;
408*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
409*77c1e3ccSAndroid Build Coastguard Worker if (is_cur_buf_hbd(xd)) {
410*77c1e3ccSAndroid Build Coastguard Worker uint16_t *src = CONVERT_TO_SHORTPTR(mb_buffer);
411*77c1e3ccSAndroid Build Coastguard Worker uint16_t *rec = CONVERT_TO_SHORTPTR(dst_buffer);
412*77c1e3ccSAndroid Build Coastguard Worker src_pix = src[pix_row * buf_stride + pix_col];
413*77c1e3ccSAndroid Build Coastguard Worker rec_pix = rec[pix_row * dst_buffer_stride + pix_col];
414*77c1e3ccSAndroid Build Coastguard Worker } else {
415*77c1e3ccSAndroid Build Coastguard Worker src_pix = mb_buffer[pix_row * buf_stride + pix_col];
416*77c1e3ccSAndroid Build Coastguard Worker rec_pix = dst_buffer[pix_row * dst_buffer_stride + pix_col];
417*77c1e3ccSAndroid Build Coastguard Worker }
418*77c1e3ccSAndroid Build Coastguard Worker #else
419*77c1e3ccSAndroid Build Coastguard Worker src_pix = mb_buffer[pix_row * buf_stride + pix_col];
420*77c1e3ccSAndroid Build Coastguard Worker rec_pix = dst_buffer[pix_row * dst_buffer_stride + pix_col];
421*77c1e3ccSAndroid Build Coastguard Worker #endif
422*77c1e3ccSAndroid Build Coastguard Worker src_mean += src_pix;
423*77c1e3ccSAndroid Build Coastguard Worker rec_mean += rec_pix;
424*77c1e3ccSAndroid Build Coastguard Worker dist_mean += src_pix - rec_pix;
425*77c1e3ccSAndroid Build Coastguard Worker weber_stats->src_variance += src_pix * src_pix;
426*77c1e3ccSAndroid Build Coastguard Worker weber_stats->rec_variance += rec_pix * rec_pix;
427*77c1e3ccSAndroid Build Coastguard Worker weber_stats->src_pix_max = AOMMAX(weber_stats->src_pix_max, src_pix);
428*77c1e3ccSAndroid Build Coastguard Worker weber_stats->rec_pix_max = AOMMAX(weber_stats->rec_pix_max, rec_pix);
429*77c1e3ccSAndroid Build Coastguard Worker weber_stats->distortion += (src_pix - rec_pix) * (src_pix - rec_pix);
430*77c1e3ccSAndroid Build Coastguard Worker }
431*77c1e3ccSAndroid Build Coastguard Worker }
432*77c1e3ccSAndroid Build Coastguard Worker
433*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.intra_mode_cfg.auto_intra_tools_off) {
434*77c1e3ccSAndroid Build Coastguard Worker *sum_rec_distortion += weber_stats->distortion;
435*77c1e3ccSAndroid Build Coastguard Worker int est_block_rate = 0;
436*77c1e3ccSAndroid Build Coastguard Worker int64_t est_block_dist = 0;
437*77c1e3ccSAndroid Build Coastguard Worker model_rd_sse_fn[MODELRD_LEGACY](cpi, x, bsize, 0, weber_stats->distortion,
438*77c1e3ccSAndroid Build Coastguard Worker pix_num, &est_block_rate,
439*77c1e3ccSAndroid Build Coastguard Worker &est_block_dist);
440*77c1e3ccSAndroid Build Coastguard Worker *sum_est_rate += est_block_rate;
441*77c1e3ccSAndroid Build Coastguard Worker }
442*77c1e3ccSAndroid Build Coastguard Worker
443*77c1e3ccSAndroid Build Coastguard Worker weber_stats->src_variance -= (src_mean * src_mean) / pix_num;
444*77c1e3ccSAndroid Build Coastguard Worker weber_stats->rec_variance -= (rec_mean * rec_mean) / pix_num;
445*77c1e3ccSAndroid Build Coastguard Worker weber_stats->distortion -= (dist_mean * dist_mean) / pix_num;
446*77c1e3ccSAndroid Build Coastguard Worker weber_stats->satd = best_intra_cost;
447*77c1e3ccSAndroid Build Coastguard Worker
448*77c1e3ccSAndroid Build Coastguard Worker qcoeff[0] = 0;
449*77c1e3ccSAndroid Build Coastguard Worker int max_scale = 0;
450*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 1; idx < coeff_count; ++idx) {
451*77c1e3ccSAndroid Build Coastguard Worker const int abs_qcoeff = abs(qcoeff[idx]);
452*77c1e3ccSAndroid Build Coastguard Worker max_scale = AOMMAX(max_scale, abs_qcoeff);
453*77c1e3ccSAndroid Build Coastguard Worker }
454*77c1e3ccSAndroid Build Coastguard Worker weber_stats->max_scale = max_scale;
455*77c1e3ccSAndroid Build Coastguard Worker
456*77c1e3ccSAndroid Build Coastguard Worker if ((mi_col + mb_step) % mt_unit_step == 0 ||
457*77c1e3ccSAndroid Build Coastguard Worker (mi_col + mb_step) >= mi_cols) {
458*77c1e3ccSAndroid Build Coastguard Worker intra_mt->intra_sync_write_ptr(intra_row_mt_sync, mt_thread_id,
459*77c1e3ccSAndroid Build Coastguard Worker mt_unit_col, mt_unit_cols);
460*77c1e3ccSAndroid Build Coastguard Worker ++mt_unit_col;
461*77c1e3ccSAndroid Build Coastguard Worker }
462*77c1e3ccSAndroid Build Coastguard Worker }
463*77c1e3ccSAndroid Build Coastguard Worker // Set the pointer to null since mbmi is only allocated inside this function.
464*77c1e3ccSAndroid Build Coastguard Worker xd->mi = NULL;
465*77c1e3ccSAndroid Build Coastguard Worker }
466*77c1e3ccSAndroid Build Coastguard Worker
calc_mb_wiener_var(AV1_COMP * const cpi,double * sum_rec_distortion,double * sum_est_rate)467*77c1e3ccSAndroid Build Coastguard Worker static void calc_mb_wiener_var(AV1_COMP *const cpi, double *sum_rec_distortion,
468*77c1e3ccSAndroid Build Coastguard Worker double *sum_est_rate) {
469*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x = &cpi->td.mb;
470*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
471*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE bsize = cpi->weber_bsize;
472*77c1e3ccSAndroid Build Coastguard Worker const int mb_step = mi_size_wide[bsize];
473*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, int16_t, src_diff[32 * 32]);
474*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, tran_low_t, coeff[32 * 32]);
475*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, tran_low_t, qcoeff[32 * 32]);
476*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(32, tran_low_t, dqcoeff[32 * 32]);
477*77c1e3ccSAndroid Build Coastguard Worker for (int mi_row = 0; mi_row < cpi->frame_info.mi_rows; mi_row += mb_step) {
478*77c1e3ccSAndroid Build Coastguard Worker av1_calc_mb_wiener_var_row(cpi, x, xd, mi_row, src_diff, coeff, qcoeff,
479*77c1e3ccSAndroid Build Coastguard Worker dqcoeff, sum_rec_distortion, sum_est_rate,
480*77c1e3ccSAndroid Build Coastguard Worker cpi->td.wiener_tmp_pred_buf);
481*77c1e3ccSAndroid Build Coastguard Worker }
482*77c1e3ccSAndroid Build Coastguard Worker }
483*77c1e3ccSAndroid Build Coastguard Worker
estimate_wiener_var_norm(AV1_COMP * const cpi,const BLOCK_SIZE norm_block_size)484*77c1e3ccSAndroid Build Coastguard Worker static int64_t estimate_wiener_var_norm(AV1_COMP *const cpi,
485*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE norm_block_size) {
486*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
487*77c1e3ccSAndroid Build Coastguard Worker int64_t norm_factor = 1;
488*77c1e3ccSAndroid Build Coastguard Worker assert(norm_block_size >= BLOCK_16X16 && norm_block_size <= BLOCK_128X128);
489*77c1e3ccSAndroid Build Coastguard Worker const int norm_step = mi_size_wide[norm_block_size];
490*77c1e3ccSAndroid Build Coastguard Worker double sb_wiener_log = 0;
491*77c1e3ccSAndroid Build Coastguard Worker double sb_count = 0;
492*77c1e3ccSAndroid Build Coastguard Worker for (int mi_row = 0; mi_row < cm->mi_params.mi_rows; mi_row += norm_step) {
493*77c1e3ccSAndroid Build Coastguard Worker for (int mi_col = 0; mi_col < cm->mi_params.mi_cols; mi_col += norm_step) {
494*77c1e3ccSAndroid Build Coastguard Worker const int sb_wiener_var =
495*77c1e3ccSAndroid Build Coastguard Worker get_var_perceptual_ai(cpi, norm_block_size, mi_row, mi_col);
496*77c1e3ccSAndroid Build Coastguard Worker const int64_t satd = get_satd(cpi, norm_block_size, mi_row, mi_col);
497*77c1e3ccSAndroid Build Coastguard Worker const int64_t sse = get_sse(cpi, norm_block_size, mi_row, mi_col);
498*77c1e3ccSAndroid Build Coastguard Worker const double scaled_satd = (double)satd / sqrt((double)sse);
499*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_log += scaled_satd * log(sb_wiener_var);
500*77c1e3ccSAndroid Build Coastguard Worker sb_count += scaled_satd;
501*77c1e3ccSAndroid Build Coastguard Worker }
502*77c1e3ccSAndroid Build Coastguard Worker }
503*77c1e3ccSAndroid Build Coastguard Worker if (sb_count > 0) norm_factor = (int64_t)(exp(sb_wiener_log / sb_count));
504*77c1e3ccSAndroid Build Coastguard Worker norm_factor = AOMMAX(1, norm_factor);
505*77c1e3ccSAndroid Build Coastguard Worker
506*77c1e3ccSAndroid Build Coastguard Worker return norm_factor;
507*77c1e3ccSAndroid Build Coastguard Worker }
508*77c1e3ccSAndroid Build Coastguard Worker
automatic_intra_tools_off(AV1_COMP * cpi,const double sum_rec_distortion,const double sum_est_rate)509*77c1e3ccSAndroid Build Coastguard Worker static void automatic_intra_tools_off(AV1_COMP *cpi,
510*77c1e3ccSAndroid Build Coastguard Worker const double sum_rec_distortion,
511*77c1e3ccSAndroid Build Coastguard Worker const double sum_est_rate) {
512*77c1e3ccSAndroid Build Coastguard Worker if (!cpi->oxcf.intra_mode_cfg.auto_intra_tools_off) return;
513*77c1e3ccSAndroid Build Coastguard Worker
514*77c1e3ccSAndroid Build Coastguard Worker // Thresholds
515*77c1e3ccSAndroid Build Coastguard Worker const int high_quality_qindex = 128;
516*77c1e3ccSAndroid Build Coastguard Worker const double high_quality_bpp = 2.0;
517*77c1e3ccSAndroid Build Coastguard Worker const double high_quality_dist_per_pix = 4.0;
518*77c1e3ccSAndroid Build Coastguard Worker
519*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
520*77c1e3ccSAndroid Build Coastguard Worker const int qindex = cm->quant_params.base_qindex;
521*77c1e3ccSAndroid Build Coastguard Worker const double dist_per_pix =
522*77c1e3ccSAndroid Build Coastguard Worker (double)sum_rec_distortion / (cm->width * cm->height);
523*77c1e3ccSAndroid Build Coastguard Worker // The estimate bpp is not accurate, an empirical constant 100 is divided.
524*77c1e3ccSAndroid Build Coastguard Worker const double estimate_bpp = sum_est_rate / (cm->width * cm->height * 100);
525*77c1e3ccSAndroid Build Coastguard Worker
526*77c1e3ccSAndroid Build Coastguard Worker if (qindex < high_quality_qindex && estimate_bpp > high_quality_bpp &&
527*77c1e3ccSAndroid Build Coastguard Worker dist_per_pix < high_quality_dist_per_pix) {
528*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.intra_mode_cfg.enable_smooth_intra = 0;
529*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.intra_mode_cfg.enable_paeth_intra = 0;
530*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.intra_mode_cfg.enable_cfl_intra = 0;
531*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.intra_mode_cfg.enable_diagonal_intra = 0;
532*77c1e3ccSAndroid Build Coastguard Worker }
533*77c1e3ccSAndroid Build Coastguard Worker }
534*77c1e3ccSAndroid Build Coastguard Worker
ext_rate_guided_quantization(AV1_COMP * cpi)535*77c1e3ccSAndroid Build Coastguard Worker static void ext_rate_guided_quantization(AV1_COMP *cpi) {
536*77c1e3ccSAndroid Build Coastguard Worker // Calculation uses 8x8.
537*77c1e3ccSAndroid Build Coastguard Worker const int mb_step = mi_size_wide[cpi->weber_bsize];
538*77c1e3ccSAndroid Build Coastguard Worker // Accumulate to 16x16, step size is in the unit of mi.
539*77c1e3ccSAndroid Build Coastguard Worker const int block_step = 4;
540*77c1e3ccSAndroid Build Coastguard Worker
541*77c1e3ccSAndroid Build Coastguard Worker const char *filename = cpi->oxcf.rate_distribution_info;
542*77c1e3ccSAndroid Build Coastguard Worker FILE *pfile = fopen(filename, "r");
543*77c1e3ccSAndroid Build Coastguard Worker if (pfile == NULL) {
544*77c1e3ccSAndroid Build Coastguard Worker assert(pfile != NULL);
545*77c1e3ccSAndroid Build Coastguard Worker return;
546*77c1e3ccSAndroid Build Coastguard Worker }
547*77c1e3ccSAndroid Build Coastguard Worker
548*77c1e3ccSAndroid Build Coastguard Worker double ext_rate_sum = 0.0;
549*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < cpi->frame_info.mi_rows; row += block_step) {
550*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < cpi->frame_info.mi_cols; col += block_step) {
551*77c1e3ccSAndroid Build Coastguard Worker float val;
552*77c1e3ccSAndroid Build Coastguard Worker const int fields_converted = fscanf(pfile, "%f", &val);
553*77c1e3ccSAndroid Build Coastguard Worker if (fields_converted != 1) {
554*77c1e3ccSAndroid Build Coastguard Worker assert(fields_converted == 1);
555*77c1e3ccSAndroid Build Coastguard Worker fclose(pfile);
556*77c1e3ccSAndroid Build Coastguard Worker return;
557*77c1e3ccSAndroid Build Coastguard Worker }
558*77c1e3ccSAndroid Build Coastguard Worker ext_rate_sum += val;
559*77c1e3ccSAndroid Build Coastguard Worker cpi->ext_rate_distribution[(row / mb_step) * cpi->frame_info.mi_cols +
560*77c1e3ccSAndroid Build Coastguard Worker (col / mb_step)] = val;
561*77c1e3ccSAndroid Build Coastguard Worker }
562*77c1e3ccSAndroid Build Coastguard Worker }
563*77c1e3ccSAndroid Build Coastguard Worker fclose(pfile);
564*77c1e3ccSAndroid Build Coastguard Worker
565*77c1e3ccSAndroid Build Coastguard Worker int uniform_rate_sum = 0;
566*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < cpi->frame_info.mi_rows; row += block_step) {
567*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < cpi->frame_info.mi_cols; col += block_step) {
568*77c1e3ccSAndroid Build Coastguard Worker int rate_sum = 0;
569*77c1e3ccSAndroid Build Coastguard Worker for (int r = 0; r < block_step; r += mb_step) {
570*77c1e3ccSAndroid Build Coastguard Worker for (int c = 0; c < block_step; c += mb_step) {
571*77c1e3ccSAndroid Build Coastguard Worker const int mi_row = row + r;
572*77c1e3ccSAndroid Build Coastguard Worker const int mi_col = col + c;
573*77c1e3ccSAndroid Build Coastguard Worker rate_sum += cpi->prep_rate_estimates[(mi_row / mb_step) *
574*77c1e3ccSAndroid Build Coastguard Worker cpi->frame_info.mi_cols +
575*77c1e3ccSAndroid Build Coastguard Worker (mi_col / mb_step)];
576*77c1e3ccSAndroid Build Coastguard Worker }
577*77c1e3ccSAndroid Build Coastguard Worker }
578*77c1e3ccSAndroid Build Coastguard Worker uniform_rate_sum += rate_sum;
579*77c1e3ccSAndroid Build Coastguard Worker }
580*77c1e3ccSAndroid Build Coastguard Worker }
581*77c1e3ccSAndroid Build Coastguard Worker
582*77c1e3ccSAndroid Build Coastguard Worker const double scale = uniform_rate_sum / ext_rate_sum;
583*77c1e3ccSAndroid Build Coastguard Worker cpi->ext_rate_scale = scale;
584*77c1e3ccSAndroid Build Coastguard Worker }
585*77c1e3ccSAndroid Build Coastguard Worker
av1_set_mb_wiener_variance(AV1_COMP * cpi)586*77c1e3ccSAndroid Build Coastguard Worker void av1_set_mb_wiener_variance(AV1_COMP *cpi) {
587*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
588*77c1e3ccSAndroid Build Coastguard Worker const SequenceHeader *const seq_params = cm->seq_params;
589*77c1e3ccSAndroid Build Coastguard Worker if (aom_realloc_frame_buffer(
590*77c1e3ccSAndroid Build Coastguard Worker &cm->cur_frame->buf, cm->width, cm->height, seq_params->subsampling_x,
591*77c1e3ccSAndroid Build Coastguard Worker seq_params->subsampling_y, seq_params->use_highbitdepth,
592*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.border_in_pixels, cm->features.byte_alignment, NULL, NULL,
593*77c1e3ccSAndroid Build Coastguard Worker NULL, cpi->alloc_pyramid, 0))
594*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR,
595*77c1e3ccSAndroid Build Coastguard Worker "Failed to allocate frame buffer");
596*77c1e3ccSAndroid Build Coastguard Worker av1_alloc_mb_wiener_var_pred_buf(&cpi->common, &cpi->td);
597*77c1e3ccSAndroid Build Coastguard Worker cpi->norm_wiener_variance = 0;
598*77c1e3ccSAndroid Build Coastguard Worker
599*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x = &cpi->td.mb;
600*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
601*77c1e3ccSAndroid Build Coastguard Worker // xd->mi needs to be setup since it is used in av1_frame_init_quantizer.
602*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO mbmi;
603*77c1e3ccSAndroid Build Coastguard Worker memset(&mbmi, 0, sizeof(mbmi));
604*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi_ptr = &mbmi;
605*77c1e3ccSAndroid Build Coastguard Worker xd->mi = &mbmi_ptr;
606*77c1e3ccSAndroid Build Coastguard Worker cm->quant_params.base_qindex = cpi->oxcf.rc_cfg.cq_level;
607*77c1e3ccSAndroid Build Coastguard Worker av1_frame_init_quantizer(cpi);
608*77c1e3ccSAndroid Build Coastguard Worker
609*77c1e3ccSAndroid Build Coastguard Worker double sum_rec_distortion = 0.0;
610*77c1e3ccSAndroid Build Coastguard Worker double sum_est_rate = 0.0;
611*77c1e3ccSAndroid Build Coastguard Worker
612*77c1e3ccSAndroid Build Coastguard Worker MultiThreadInfo *const mt_info = &cpi->mt_info;
613*77c1e3ccSAndroid Build Coastguard Worker const int num_workers =
614*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mt_info->num_mod_workers[MOD_AI], mt_info->num_workers);
615*77c1e3ccSAndroid Build Coastguard Worker AV1EncAllIntraMultiThreadInfo *const intra_mt = &mt_info->intra_mt;
616*77c1e3ccSAndroid Build Coastguard Worker intra_mt->intra_sync_read_ptr = av1_row_mt_sync_read_dummy;
617*77c1e3ccSAndroid Build Coastguard Worker intra_mt->intra_sync_write_ptr = av1_row_mt_sync_write_dummy;
618*77c1e3ccSAndroid Build Coastguard Worker // Calculate differential contrast for each block for the entire image.
619*77c1e3ccSAndroid Build Coastguard Worker // TODO(chengchen): properly accumulate the distortion and rate in
620*77c1e3ccSAndroid Build Coastguard Worker // av1_calc_mb_wiener_var_mt(). Until then, call calc_mb_wiener_var() if
621*77c1e3ccSAndroid Build Coastguard Worker // auto_intra_tools_off is true.
622*77c1e3ccSAndroid Build Coastguard Worker if (num_workers > 1 && !cpi->oxcf.intra_mode_cfg.auto_intra_tools_off) {
623*77c1e3ccSAndroid Build Coastguard Worker intra_mt->intra_sync_read_ptr = av1_row_mt_sync_read;
624*77c1e3ccSAndroid Build Coastguard Worker intra_mt->intra_sync_write_ptr = av1_row_mt_sync_write;
625*77c1e3ccSAndroid Build Coastguard Worker av1_calc_mb_wiener_var_mt(cpi, num_workers, &sum_rec_distortion,
626*77c1e3ccSAndroid Build Coastguard Worker &sum_est_rate);
627*77c1e3ccSAndroid Build Coastguard Worker } else {
628*77c1e3ccSAndroid Build Coastguard Worker calc_mb_wiener_var(cpi, &sum_rec_distortion, &sum_est_rate);
629*77c1e3ccSAndroid Build Coastguard Worker }
630*77c1e3ccSAndroid Build Coastguard Worker
631*77c1e3ccSAndroid Build Coastguard Worker // Determine whether to turn off several intra coding tools.
632*77c1e3ccSAndroid Build Coastguard Worker automatic_intra_tools_off(cpi, sum_rec_distortion, sum_est_rate);
633*77c1e3ccSAndroid Build Coastguard Worker
634*77c1e3ccSAndroid Build Coastguard Worker // Read external rate distribution and use it to guide delta quantization
635*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.enable_rate_guide_deltaq) ext_rate_guided_quantization(cpi);
636*77c1e3ccSAndroid Build Coastguard Worker
637*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE norm_block_size = cm->seq_params->sb_size;
638*77c1e3ccSAndroid Build Coastguard Worker cpi->norm_wiener_variance = estimate_wiener_var_norm(cpi, norm_block_size);
639*77c1e3ccSAndroid Build Coastguard Worker const int norm_step = mi_size_wide[norm_block_size];
640*77c1e3ccSAndroid Build Coastguard Worker
641*77c1e3ccSAndroid Build Coastguard Worker double sb_wiener_log = 0;
642*77c1e3ccSAndroid Build Coastguard Worker double sb_count = 0;
643*77c1e3ccSAndroid Build Coastguard Worker for (int its_cnt = 0; its_cnt < 2; ++its_cnt) {
644*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_log = 0;
645*77c1e3ccSAndroid Build Coastguard Worker sb_count = 0;
646*77c1e3ccSAndroid Build Coastguard Worker for (int mi_row = 0; mi_row < cm->mi_params.mi_rows; mi_row += norm_step) {
647*77c1e3ccSAndroid Build Coastguard Worker for (int mi_col = 0; mi_col < cm->mi_params.mi_cols;
648*77c1e3ccSAndroid Build Coastguard Worker mi_col += norm_step) {
649*77c1e3ccSAndroid Build Coastguard Worker int sb_wiener_var =
650*77c1e3ccSAndroid Build Coastguard Worker get_var_perceptual_ai(cpi, norm_block_size, mi_row, mi_col);
651*77c1e3ccSAndroid Build Coastguard Worker
652*77c1e3ccSAndroid Build Coastguard Worker double beta = (double)cpi->norm_wiener_variance / sb_wiener_var;
653*77c1e3ccSAndroid Build Coastguard Worker double min_max_scale = AOMMAX(
654*77c1e3ccSAndroid Build Coastguard Worker 1.0, get_max_scale(cpi, cm->seq_params->sb_size, mi_row, mi_col));
655*77c1e3ccSAndroid Build Coastguard Worker
656*77c1e3ccSAndroid Build Coastguard Worker beta = AOMMIN(beta, 4);
657*77c1e3ccSAndroid Build Coastguard Worker beta = AOMMAX(beta, 0.25);
658*77c1e3ccSAndroid Build Coastguard Worker
659*77c1e3ccSAndroid Build Coastguard Worker if (beta < 1 / min_max_scale) continue;
660*77c1e3ccSAndroid Build Coastguard Worker
661*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_var = (int)(cpi->norm_wiener_variance / beta);
662*77c1e3ccSAndroid Build Coastguard Worker
663*77c1e3ccSAndroid Build Coastguard Worker int64_t satd = get_satd(cpi, norm_block_size, mi_row, mi_col);
664*77c1e3ccSAndroid Build Coastguard Worker int64_t sse = get_sse(cpi, norm_block_size, mi_row, mi_col);
665*77c1e3ccSAndroid Build Coastguard Worker double scaled_satd = (double)satd / sqrt((double)sse);
666*77c1e3ccSAndroid Build Coastguard Worker sb_wiener_log += scaled_satd * log(sb_wiener_var);
667*77c1e3ccSAndroid Build Coastguard Worker sb_count += scaled_satd;
668*77c1e3ccSAndroid Build Coastguard Worker }
669*77c1e3ccSAndroid Build Coastguard Worker }
670*77c1e3ccSAndroid Build Coastguard Worker
671*77c1e3ccSAndroid Build Coastguard Worker if (sb_count > 0)
672*77c1e3ccSAndroid Build Coastguard Worker cpi->norm_wiener_variance = (int64_t)(exp(sb_wiener_log / sb_count));
673*77c1e3ccSAndroid Build Coastguard Worker cpi->norm_wiener_variance = AOMMAX(1, cpi->norm_wiener_variance);
674*77c1e3ccSAndroid Build Coastguard Worker }
675*77c1e3ccSAndroid Build Coastguard Worker
676*77c1e3ccSAndroid Build Coastguard Worker // Set the pointer to null since mbmi is only allocated inside this function.
677*77c1e3ccSAndroid Build Coastguard Worker xd->mi = NULL;
678*77c1e3ccSAndroid Build Coastguard Worker aom_free_frame_buffer(&cm->cur_frame->buf);
679*77c1e3ccSAndroid Build Coastguard Worker av1_dealloc_mb_wiener_var_pred_buf(&cpi->td);
680*77c1e3ccSAndroid Build Coastguard Worker }
681*77c1e3ccSAndroid Build Coastguard Worker
get_rate_guided_quantizer(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)682*77c1e3ccSAndroid Build Coastguard Worker static int get_rate_guided_quantizer(AV1_COMP *const cpi, BLOCK_SIZE bsize,
683*77c1e3ccSAndroid Build Coastguard Worker int mi_row, int mi_col) {
684*77c1e3ccSAndroid Build Coastguard Worker // Calculation uses 8x8.
685*77c1e3ccSAndroid Build Coastguard Worker const int mb_step = mi_size_wide[cpi->weber_bsize];
686*77c1e3ccSAndroid Build Coastguard Worker // Accumulate to 16x16
687*77c1e3ccSAndroid Build Coastguard Worker const int block_step = mi_size_wide[BLOCK_16X16];
688*77c1e3ccSAndroid Build Coastguard Worker double sb_rate_hific = 0.0;
689*77c1e3ccSAndroid Build Coastguard Worker double sb_rate_uniform = 0.0;
690*77c1e3ccSAndroid Build Coastguard Worker for (int row = mi_row; row < mi_row + mi_size_wide[bsize];
691*77c1e3ccSAndroid Build Coastguard Worker row += block_step) {
692*77c1e3ccSAndroid Build Coastguard Worker for (int col = mi_col; col < mi_col + mi_size_high[bsize];
693*77c1e3ccSAndroid Build Coastguard Worker col += block_step) {
694*77c1e3ccSAndroid Build Coastguard Worker sb_rate_hific +=
695*77c1e3ccSAndroid Build Coastguard Worker cpi->ext_rate_distribution[(row / mb_step) * cpi->frame_info.mi_cols +
696*77c1e3ccSAndroid Build Coastguard Worker (col / mb_step)];
697*77c1e3ccSAndroid Build Coastguard Worker
698*77c1e3ccSAndroid Build Coastguard Worker for (int r = 0; r < block_step; r += mb_step) {
699*77c1e3ccSAndroid Build Coastguard Worker for (int c = 0; c < block_step; c += mb_step) {
700*77c1e3ccSAndroid Build Coastguard Worker const int this_row = row + r;
701*77c1e3ccSAndroid Build Coastguard Worker const int this_col = col + c;
702*77c1e3ccSAndroid Build Coastguard Worker sb_rate_uniform +=
703*77c1e3ccSAndroid Build Coastguard Worker cpi->prep_rate_estimates[(this_row / mb_step) *
704*77c1e3ccSAndroid Build Coastguard Worker cpi->frame_info.mi_cols +
705*77c1e3ccSAndroid Build Coastguard Worker (this_col / mb_step)];
706*77c1e3ccSAndroid Build Coastguard Worker }
707*77c1e3ccSAndroid Build Coastguard Worker }
708*77c1e3ccSAndroid Build Coastguard Worker }
709*77c1e3ccSAndroid Build Coastguard Worker }
710*77c1e3ccSAndroid Build Coastguard Worker sb_rate_hific *= cpi->ext_rate_scale;
711*77c1e3ccSAndroid Build Coastguard Worker
712*77c1e3ccSAndroid Build Coastguard Worker const double weight = 1.0;
713*77c1e3ccSAndroid Build Coastguard Worker const double rate_diff =
714*77c1e3ccSAndroid Build Coastguard Worker weight * (sb_rate_hific - sb_rate_uniform) / sb_rate_uniform;
715*77c1e3ccSAndroid Build Coastguard Worker double scale = pow(2, rate_diff);
716*77c1e3ccSAndroid Build Coastguard Worker
717*77c1e3ccSAndroid Build Coastguard Worker scale = scale * scale;
718*77c1e3ccSAndroid Build Coastguard Worker double min_max_scale = AOMMAX(1.0, get_max_scale(cpi, bsize, mi_row, mi_col));
719*77c1e3ccSAndroid Build Coastguard Worker scale = 1.0 / AOMMIN(1.0 / scale, min_max_scale);
720*77c1e3ccSAndroid Build Coastguard Worker
721*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
722*77c1e3ccSAndroid Build Coastguard Worker const int base_qindex = cm->quant_params.base_qindex;
723*77c1e3ccSAndroid Build Coastguard Worker int offset =
724*77c1e3ccSAndroid Build Coastguard Worker av1_get_deltaq_offset(cm->seq_params->bit_depth, base_qindex, scale);
725*77c1e3ccSAndroid Build Coastguard Worker const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
726*77c1e3ccSAndroid Build Coastguard Worker const int max_offset = delta_q_info->delta_q_res * 10;
727*77c1e3ccSAndroid Build Coastguard Worker offset = AOMMIN(offset, max_offset - 1);
728*77c1e3ccSAndroid Build Coastguard Worker offset = AOMMAX(offset, -max_offset + 1);
729*77c1e3ccSAndroid Build Coastguard Worker int qindex = cm->quant_params.base_qindex + offset;
730*77c1e3ccSAndroid Build Coastguard Worker qindex = AOMMIN(qindex, MAXQ);
731*77c1e3ccSAndroid Build Coastguard Worker qindex = AOMMAX(qindex, MINQ);
732*77c1e3ccSAndroid Build Coastguard Worker if (base_qindex > MINQ) qindex = AOMMAX(qindex, MINQ + 1);
733*77c1e3ccSAndroid Build Coastguard Worker
734*77c1e3ccSAndroid Build Coastguard Worker return qindex;
735*77c1e3ccSAndroid Build Coastguard Worker }
736*77c1e3ccSAndroid Build Coastguard Worker
av1_get_sbq_perceptual_ai(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)737*77c1e3ccSAndroid Build Coastguard Worker int av1_get_sbq_perceptual_ai(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
738*77c1e3ccSAndroid Build Coastguard Worker int mi_col) {
739*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.enable_rate_guide_deltaq) {
740*77c1e3ccSAndroid Build Coastguard Worker return get_rate_guided_quantizer(cpi, bsize, mi_row, mi_col);
741*77c1e3ccSAndroid Build Coastguard Worker }
742*77c1e3ccSAndroid Build Coastguard Worker
743*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
744*77c1e3ccSAndroid Build Coastguard Worker const int base_qindex = cm->quant_params.base_qindex;
745*77c1e3ccSAndroid Build Coastguard Worker int sb_wiener_var = get_var_perceptual_ai(cpi, bsize, mi_row, mi_col);
746*77c1e3ccSAndroid Build Coastguard Worker int offset = 0;
747*77c1e3ccSAndroid Build Coastguard Worker double beta = (double)cpi->norm_wiener_variance / sb_wiener_var;
748*77c1e3ccSAndroid Build Coastguard Worker double min_max_scale = AOMMAX(1.0, get_max_scale(cpi, bsize, mi_row, mi_col));
749*77c1e3ccSAndroid Build Coastguard Worker beta = 1.0 / AOMMIN(1.0 / beta, min_max_scale);
750*77c1e3ccSAndroid Build Coastguard Worker
751*77c1e3ccSAndroid Build Coastguard Worker // Cap beta such that the delta q value is not much far away from the base q.
752*77c1e3ccSAndroid Build Coastguard Worker beta = AOMMIN(beta, 4);
753*77c1e3ccSAndroid Build Coastguard Worker beta = AOMMAX(beta, 0.25);
754*77c1e3ccSAndroid Build Coastguard Worker offset = av1_get_deltaq_offset(cm->seq_params->bit_depth, base_qindex, beta);
755*77c1e3ccSAndroid Build Coastguard Worker const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
756*77c1e3ccSAndroid Build Coastguard Worker offset = AOMMIN(offset, delta_q_info->delta_q_res * 20 - 1);
757*77c1e3ccSAndroid Build Coastguard Worker offset = AOMMAX(offset, -delta_q_info->delta_q_res * 20 + 1);
758*77c1e3ccSAndroid Build Coastguard Worker int qindex = cm->quant_params.base_qindex + offset;
759*77c1e3ccSAndroid Build Coastguard Worker qindex = AOMMIN(qindex, MAXQ);
760*77c1e3ccSAndroid Build Coastguard Worker qindex = AOMMAX(qindex, MINQ);
761*77c1e3ccSAndroid Build Coastguard Worker if (base_qindex > MINQ) qindex = AOMMAX(qindex, MINQ + 1);
762*77c1e3ccSAndroid Build Coastguard Worker
763*77c1e3ccSAndroid Build Coastguard Worker return qindex;
764*77c1e3ccSAndroid Build Coastguard Worker }
765*77c1e3ccSAndroid Build Coastguard Worker
av1_init_mb_ur_var_buffer(AV1_COMP * cpi)766*77c1e3ccSAndroid Build Coastguard Worker void av1_init_mb_ur_var_buffer(AV1_COMP *cpi) {
767*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *cm = &cpi->common;
768*77c1e3ccSAndroid Build Coastguard Worker
769*77c1e3ccSAndroid Build Coastguard Worker if (cpi->mb_delta_q) return;
770*77c1e3ccSAndroid Build Coastguard Worker
771*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, cpi->mb_delta_q,
772*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(cpi->frame_info.mb_rows * cpi->frame_info.mb_cols,
773*77c1e3ccSAndroid Build Coastguard Worker sizeof(*cpi->mb_delta_q)));
774*77c1e3ccSAndroid Build Coastguard Worker }
775*77c1e3ccSAndroid Build Coastguard Worker
776*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_TFLITE
model_predict(BLOCK_SIZE block_size,int num_cols,int num_rows,int bit_depth,uint8_t * y_buffer,int y_stride,float * predicts0,float * predicts1)777*77c1e3ccSAndroid Build Coastguard Worker static int model_predict(BLOCK_SIZE block_size, int num_cols, int num_rows,
778*77c1e3ccSAndroid Build Coastguard Worker int bit_depth, uint8_t *y_buffer, int y_stride,
779*77c1e3ccSAndroid Build Coastguard Worker float *predicts0, float *predicts1) {
780*77c1e3ccSAndroid Build Coastguard Worker // Create the model and interpreter options.
781*77c1e3ccSAndroid Build Coastguard Worker TfLiteModel *model =
782*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelCreate(av1_deltaq4_model_file, av1_deltaq4_model_fsize);
783*77c1e3ccSAndroid Build Coastguard Worker if (model == NULL) return 1;
784*77c1e3ccSAndroid Build Coastguard Worker
785*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptions *options = TfLiteInterpreterOptionsCreate();
786*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptionsSetNumThreads(options, 2);
787*77c1e3ccSAndroid Build Coastguard Worker if (options == NULL) {
788*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelDelete(model);
789*77c1e3ccSAndroid Build Coastguard Worker return 1;
790*77c1e3ccSAndroid Build Coastguard Worker }
791*77c1e3ccSAndroid Build Coastguard Worker
792*77c1e3ccSAndroid Build Coastguard Worker // Create the interpreter.
793*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreter *interpreter = TfLiteInterpreterCreate(model, options);
794*77c1e3ccSAndroid Build Coastguard Worker if (interpreter == NULL) {
795*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptionsDelete(options);
796*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelDelete(model);
797*77c1e3ccSAndroid Build Coastguard Worker return 1;
798*77c1e3ccSAndroid Build Coastguard Worker }
799*77c1e3ccSAndroid Build Coastguard Worker
800*77c1e3ccSAndroid Build Coastguard Worker // Allocate tensors and populate the input tensor data.
801*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterAllocateTensors(interpreter);
802*77c1e3ccSAndroid Build Coastguard Worker TfLiteTensor *input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);
803*77c1e3ccSAndroid Build Coastguard Worker if (input_tensor == NULL) {
804*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterDelete(interpreter);
805*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptionsDelete(options);
806*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelDelete(model);
807*77c1e3ccSAndroid Build Coastguard Worker return 1;
808*77c1e3ccSAndroid Build Coastguard Worker }
809*77c1e3ccSAndroid Build Coastguard Worker
810*77c1e3ccSAndroid Build Coastguard Worker size_t input_size = TfLiteTensorByteSize(input_tensor);
811*77c1e3ccSAndroid Build Coastguard Worker float *input_data = aom_calloc(input_size, 1);
812*77c1e3ccSAndroid Build Coastguard Worker if (input_data == NULL) {
813*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterDelete(interpreter);
814*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptionsDelete(options);
815*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelDelete(model);
816*77c1e3ccSAndroid Build Coastguard Worker return 1;
817*77c1e3ccSAndroid Build Coastguard Worker }
818*77c1e3ccSAndroid Build Coastguard Worker
819*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_w = mi_size_wide[block_size];
820*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_h = mi_size_high[block_size];
821*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < num_rows; ++row) {
822*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < num_cols; ++col) {
823*77c1e3ccSAndroid Build Coastguard Worker const int row_offset = (row * num_mi_h) << 2;
824*77c1e3ccSAndroid Build Coastguard Worker const int col_offset = (col * num_mi_w) << 2;
825*77c1e3ccSAndroid Build Coastguard Worker
826*77c1e3ccSAndroid Build Coastguard Worker uint8_t *buf = y_buffer + row_offset * y_stride + col_offset;
827*77c1e3ccSAndroid Build Coastguard Worker int r = row_offset, pos = 0;
828*77c1e3ccSAndroid Build Coastguard Worker const float base = (float)((1 << bit_depth) - 1);
829*77c1e3ccSAndroid Build Coastguard Worker while (r < row_offset + (num_mi_h << 2)) {
830*77c1e3ccSAndroid Build Coastguard Worker for (int c = 0; c < (num_mi_w << 2); ++c) {
831*77c1e3ccSAndroid Build Coastguard Worker input_data[pos++] = bit_depth > 8
832*77c1e3ccSAndroid Build Coastguard Worker ? (float)*CONVERT_TO_SHORTPTR(buf + c) / base
833*77c1e3ccSAndroid Build Coastguard Worker : (float)*(buf + c) / base;
834*77c1e3ccSAndroid Build Coastguard Worker }
835*77c1e3ccSAndroid Build Coastguard Worker buf += y_stride;
836*77c1e3ccSAndroid Build Coastguard Worker ++r;
837*77c1e3ccSAndroid Build Coastguard Worker }
838*77c1e3ccSAndroid Build Coastguard Worker TfLiteTensorCopyFromBuffer(input_tensor, input_data, input_size);
839*77c1e3ccSAndroid Build Coastguard Worker
840*77c1e3ccSAndroid Build Coastguard Worker // Execute inference.
841*77c1e3ccSAndroid Build Coastguard Worker if (TfLiteInterpreterInvoke(interpreter) != kTfLiteOk) {
842*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterDelete(interpreter);
843*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptionsDelete(options);
844*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelDelete(model);
845*77c1e3ccSAndroid Build Coastguard Worker return 1;
846*77c1e3ccSAndroid Build Coastguard Worker }
847*77c1e3ccSAndroid Build Coastguard Worker
848*77c1e3ccSAndroid Build Coastguard Worker // Extract the output tensor data.
849*77c1e3ccSAndroid Build Coastguard Worker const TfLiteTensor *output_tensor =
850*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterGetOutputTensor(interpreter, 0);
851*77c1e3ccSAndroid Build Coastguard Worker if (output_tensor == NULL) {
852*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterDelete(interpreter);
853*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptionsDelete(options);
854*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelDelete(model);
855*77c1e3ccSAndroid Build Coastguard Worker return 1;
856*77c1e3ccSAndroid Build Coastguard Worker }
857*77c1e3ccSAndroid Build Coastguard Worker
858*77c1e3ccSAndroid Build Coastguard Worker size_t output_size = TfLiteTensorByteSize(output_tensor);
859*77c1e3ccSAndroid Build Coastguard Worker float output_data[2];
860*77c1e3ccSAndroid Build Coastguard Worker
861*77c1e3ccSAndroid Build Coastguard Worker TfLiteTensorCopyToBuffer(output_tensor, output_data, output_size);
862*77c1e3ccSAndroid Build Coastguard Worker predicts0[row * num_cols + col] = output_data[0];
863*77c1e3ccSAndroid Build Coastguard Worker predicts1[row * num_cols + col] = output_data[1];
864*77c1e3ccSAndroid Build Coastguard Worker }
865*77c1e3ccSAndroid Build Coastguard Worker }
866*77c1e3ccSAndroid Build Coastguard Worker
867*77c1e3ccSAndroid Build Coastguard Worker // Dispose of the model and interpreter objects.
868*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterDelete(interpreter);
869*77c1e3ccSAndroid Build Coastguard Worker TfLiteInterpreterOptionsDelete(options);
870*77c1e3ccSAndroid Build Coastguard Worker TfLiteModelDelete(model);
871*77c1e3ccSAndroid Build Coastguard Worker aom_free(input_data);
872*77c1e3ccSAndroid Build Coastguard Worker return 0;
873*77c1e3ccSAndroid Build Coastguard Worker }
874*77c1e3ccSAndroid Build Coastguard Worker
av1_set_mb_ur_variance(AV1_COMP * cpi)875*77c1e3ccSAndroid Build Coastguard Worker void av1_set_mb_ur_variance(AV1_COMP *cpi) {
876*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
877*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = &cm->mi_params;
878*77c1e3ccSAndroid Build Coastguard Worker uint8_t *y_buffer = cpi->source->y_buffer;
879*77c1e3ccSAndroid Build Coastguard Worker const int y_stride = cpi->source->y_stride;
880*77c1e3ccSAndroid Build Coastguard Worker const int block_size = cpi->common.seq_params->sb_size;
881*77c1e3ccSAndroid Build Coastguard Worker const uint32_t bit_depth = cpi->td.mb.e_mbd.bd;
882*77c1e3ccSAndroid Build Coastguard Worker
883*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_w = mi_size_wide[block_size];
884*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_h = mi_size_high[block_size];
885*77c1e3ccSAndroid Build Coastguard Worker const int num_cols = (mi_params->mi_cols + num_mi_w - 1) / num_mi_w;
886*77c1e3ccSAndroid Build Coastguard Worker const int num_rows = (mi_params->mi_rows + num_mi_h - 1) / num_mi_h;
887*77c1e3ccSAndroid Build Coastguard Worker
888*77c1e3ccSAndroid Build Coastguard Worker // TODO(sdeng): fit a better model_1; disable it at this time.
889*77c1e3ccSAndroid Build Coastguard Worker float *mb_delta_q0, *mb_delta_q1, delta_q_avg0 = 0.0f;
890*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, mb_delta_q0,
891*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(num_rows * num_cols, sizeof(float)));
892*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, mb_delta_q1,
893*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(num_rows * num_cols, sizeof(float)));
894*77c1e3ccSAndroid Build Coastguard Worker
895*77c1e3ccSAndroid Build Coastguard Worker if (model_predict(block_size, num_cols, num_rows, bit_depth, y_buffer,
896*77c1e3ccSAndroid Build Coastguard Worker y_stride, mb_delta_q0, mb_delta_q1)) {
897*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(cm->error, AOM_CODEC_ERROR,
898*77c1e3ccSAndroid Build Coastguard Worker "Failed to call TFlite functions.");
899*77c1e3ccSAndroid Build Coastguard Worker }
900*77c1e3ccSAndroid Build Coastguard Worker
901*77c1e3ccSAndroid Build Coastguard Worker // Loop through each SB block.
902*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < num_rows; ++row) {
903*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < num_cols; ++col) {
904*77c1e3ccSAndroid Build Coastguard Worker const int index = row * num_cols + col;
905*77c1e3ccSAndroid Build Coastguard Worker delta_q_avg0 += mb_delta_q0[index];
906*77c1e3ccSAndroid Build Coastguard Worker }
907*77c1e3ccSAndroid Build Coastguard Worker }
908*77c1e3ccSAndroid Build Coastguard Worker
909*77c1e3ccSAndroid Build Coastguard Worker delta_q_avg0 /= (float)(num_rows * num_cols);
910*77c1e3ccSAndroid Build Coastguard Worker
911*77c1e3ccSAndroid Build Coastguard Worker float scaling_factor;
912*77c1e3ccSAndroid Build Coastguard Worker const float cq_level = (float)cpi->oxcf.rc_cfg.cq_level / (float)MAXQ;
913*77c1e3ccSAndroid Build Coastguard Worker if (cq_level < delta_q_avg0) {
914*77c1e3ccSAndroid Build Coastguard Worker scaling_factor = cq_level / delta_q_avg0;
915*77c1e3ccSAndroid Build Coastguard Worker } else {
916*77c1e3ccSAndroid Build Coastguard Worker scaling_factor = 1.0f - (cq_level - delta_q_avg0) / (1.0f - delta_q_avg0);
917*77c1e3ccSAndroid Build Coastguard Worker }
918*77c1e3ccSAndroid Build Coastguard Worker
919*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < num_rows; ++row) {
920*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < num_cols; ++col) {
921*77c1e3ccSAndroid Build Coastguard Worker const int index = row * num_cols + col;
922*77c1e3ccSAndroid Build Coastguard Worker cpi->mb_delta_q[index] =
923*77c1e3ccSAndroid Build Coastguard Worker RINT((float)cpi->oxcf.q_cfg.deltaq_strength / 100.0f * (float)MAXQ *
924*77c1e3ccSAndroid Build Coastguard Worker scaling_factor * (mb_delta_q0[index] - delta_q_avg0));
925*77c1e3ccSAndroid Build Coastguard Worker }
926*77c1e3ccSAndroid Build Coastguard Worker }
927*77c1e3ccSAndroid Build Coastguard Worker
928*77c1e3ccSAndroid Build Coastguard Worker aom_free(mb_delta_q0);
929*77c1e3ccSAndroid Build Coastguard Worker aom_free(mb_delta_q1);
930*77c1e3ccSAndroid Build Coastguard Worker }
931*77c1e3ccSAndroid Build Coastguard Worker #else // !CONFIG_TFLITE
av1_set_mb_ur_variance(AV1_COMP * cpi)932*77c1e3ccSAndroid Build Coastguard Worker void av1_set_mb_ur_variance(AV1_COMP *cpi) {
933*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
934*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = &cm->mi_params;
935*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
936*77c1e3ccSAndroid Build Coastguard Worker uint8_t *y_buffer = cpi->source->y_buffer;
937*77c1e3ccSAndroid Build Coastguard Worker const int y_stride = cpi->source->y_stride;
938*77c1e3ccSAndroid Build Coastguard Worker const int block_size = cpi->common.seq_params->sb_size;
939*77c1e3ccSAndroid Build Coastguard Worker
940*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_w = mi_size_wide[block_size];
941*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_h = mi_size_high[block_size];
942*77c1e3ccSAndroid Build Coastguard Worker const int num_cols = (mi_params->mi_cols + num_mi_w - 1) / num_mi_w;
943*77c1e3ccSAndroid Build Coastguard Worker const int num_rows = (mi_params->mi_rows + num_mi_h - 1) / num_mi_h;
944*77c1e3ccSAndroid Build Coastguard Worker
945*77c1e3ccSAndroid Build Coastguard Worker int *mb_delta_q[2];
946*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, mb_delta_q[0],
947*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(num_rows * num_cols, sizeof(*mb_delta_q[0])));
948*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, mb_delta_q[1],
949*77c1e3ccSAndroid Build Coastguard Worker aom_calloc(num_rows * num_cols, sizeof(*mb_delta_q[1])));
950*77c1e3ccSAndroid Build Coastguard Worker
951*77c1e3ccSAndroid Build Coastguard Worker // Approximates the model change between current version (Spet 2021) and the
952*77c1e3ccSAndroid Build Coastguard Worker // baseline (July 2021).
953*77c1e3ccSAndroid Build Coastguard Worker const double model_change[] = { 3.0, 3.0 };
954*77c1e3ccSAndroid Build Coastguard Worker // The following parameters are fitted from user labeled data.
955*77c1e3ccSAndroid Build Coastguard Worker const double a[] = { -24.50 * 4.0, -17.20 * 4.0 };
956*77c1e3ccSAndroid Build Coastguard Worker const double b[] = { 0.004898, 0.003093 };
957*77c1e3ccSAndroid Build Coastguard Worker const double c[] = { (29.932 + model_change[0]) * 4.0,
958*77c1e3ccSAndroid Build Coastguard Worker (42.100 + model_change[1]) * 4.0 };
959*77c1e3ccSAndroid Build Coastguard Worker int delta_q_avg[2] = { 0, 0 };
960*77c1e3ccSAndroid Build Coastguard Worker // Loop through each SB block.
961*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < num_rows; ++row) {
962*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < num_cols; ++col) {
963*77c1e3ccSAndroid Build Coastguard Worker double var = 0.0, num_of_var = 0.0;
964*77c1e3ccSAndroid Build Coastguard Worker const int index = row * num_cols + col;
965*77c1e3ccSAndroid Build Coastguard Worker
966*77c1e3ccSAndroid Build Coastguard Worker // Loop through each 8x8 block.
967*77c1e3ccSAndroid Build Coastguard Worker for (int mi_row = row * num_mi_h;
968*77c1e3ccSAndroid Build Coastguard Worker mi_row < mi_params->mi_rows && mi_row < (row + 1) * num_mi_h;
969*77c1e3ccSAndroid Build Coastguard Worker mi_row += 2) {
970*77c1e3ccSAndroid Build Coastguard Worker for (int mi_col = col * num_mi_w;
971*77c1e3ccSAndroid Build Coastguard Worker mi_col < mi_params->mi_cols && mi_col < (col + 1) * num_mi_w;
972*77c1e3ccSAndroid Build Coastguard Worker mi_col += 2) {
973*77c1e3ccSAndroid Build Coastguard Worker struct buf_2d buf;
974*77c1e3ccSAndroid Build Coastguard Worker const int row_offset_y = mi_row << 2;
975*77c1e3ccSAndroid Build Coastguard Worker const int col_offset_y = mi_col << 2;
976*77c1e3ccSAndroid Build Coastguard Worker
977*77c1e3ccSAndroid Build Coastguard Worker buf.buf = y_buffer + row_offset_y * y_stride + col_offset_y;
978*77c1e3ccSAndroid Build Coastguard Worker buf.stride = y_stride;
979*77c1e3ccSAndroid Build Coastguard Worker
980*77c1e3ccSAndroid Build Coastguard Worker unsigned int block_variance;
981*77c1e3ccSAndroid Build Coastguard Worker block_variance = av1_get_perpixel_variance_facade(
982*77c1e3ccSAndroid Build Coastguard Worker cpi, xd, &buf, BLOCK_8X8, AOM_PLANE_Y);
983*77c1e3ccSAndroid Build Coastguard Worker
984*77c1e3ccSAndroid Build Coastguard Worker block_variance = AOMMAX(block_variance, 1);
985*77c1e3ccSAndroid Build Coastguard Worker var += log((double)block_variance);
986*77c1e3ccSAndroid Build Coastguard Worker num_of_var += 1.0;
987*77c1e3ccSAndroid Build Coastguard Worker }
988*77c1e3ccSAndroid Build Coastguard Worker }
989*77c1e3ccSAndroid Build Coastguard Worker var = exp(var / num_of_var);
990*77c1e3ccSAndroid Build Coastguard Worker mb_delta_q[0][index] = RINT(a[0] * exp(-b[0] * var) + c[0]);
991*77c1e3ccSAndroid Build Coastguard Worker mb_delta_q[1][index] = RINT(a[1] * exp(-b[1] * var) + c[1]);
992*77c1e3ccSAndroid Build Coastguard Worker delta_q_avg[0] += mb_delta_q[0][index];
993*77c1e3ccSAndroid Build Coastguard Worker delta_q_avg[1] += mb_delta_q[1][index];
994*77c1e3ccSAndroid Build Coastguard Worker }
995*77c1e3ccSAndroid Build Coastguard Worker }
996*77c1e3ccSAndroid Build Coastguard Worker
997*77c1e3ccSAndroid Build Coastguard Worker delta_q_avg[0] = RINT((double)delta_q_avg[0] / (num_rows * num_cols));
998*77c1e3ccSAndroid Build Coastguard Worker delta_q_avg[1] = RINT((double)delta_q_avg[1] / (num_rows * num_cols));
999*77c1e3ccSAndroid Build Coastguard Worker
1000*77c1e3ccSAndroid Build Coastguard Worker int model_idx;
1001*77c1e3ccSAndroid Build Coastguard Worker double scaling_factor;
1002*77c1e3ccSAndroid Build Coastguard Worker const int cq_level = cpi->oxcf.rc_cfg.cq_level;
1003*77c1e3ccSAndroid Build Coastguard Worker if (cq_level < delta_q_avg[0]) {
1004*77c1e3ccSAndroid Build Coastguard Worker model_idx = 0;
1005*77c1e3ccSAndroid Build Coastguard Worker scaling_factor = (double)cq_level / delta_q_avg[0];
1006*77c1e3ccSAndroid Build Coastguard Worker } else if (cq_level < delta_q_avg[1]) {
1007*77c1e3ccSAndroid Build Coastguard Worker model_idx = 2;
1008*77c1e3ccSAndroid Build Coastguard Worker scaling_factor =
1009*77c1e3ccSAndroid Build Coastguard Worker (double)(cq_level - delta_q_avg[0]) / (delta_q_avg[1] - delta_q_avg[0]);
1010*77c1e3ccSAndroid Build Coastguard Worker } else {
1011*77c1e3ccSAndroid Build Coastguard Worker model_idx = 1;
1012*77c1e3ccSAndroid Build Coastguard Worker scaling_factor = (double)(MAXQ - cq_level) / (MAXQ - delta_q_avg[1]);
1013*77c1e3ccSAndroid Build Coastguard Worker }
1014*77c1e3ccSAndroid Build Coastguard Worker
1015*77c1e3ccSAndroid Build Coastguard Worker const double new_delta_q_avg =
1016*77c1e3ccSAndroid Build Coastguard Worker delta_q_avg[0] + scaling_factor * (delta_q_avg[1] - delta_q_avg[0]);
1017*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < num_rows; ++row) {
1018*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < num_cols; ++col) {
1019*77c1e3ccSAndroid Build Coastguard Worker const int index = row * num_cols + col;
1020*77c1e3ccSAndroid Build Coastguard Worker if (model_idx == 2) {
1021*77c1e3ccSAndroid Build Coastguard Worker const double delta_q =
1022*77c1e3ccSAndroid Build Coastguard Worker mb_delta_q[0][index] +
1023*77c1e3ccSAndroid Build Coastguard Worker scaling_factor * (mb_delta_q[1][index] - mb_delta_q[0][index]);
1024*77c1e3ccSAndroid Build Coastguard Worker cpi->mb_delta_q[index] = RINT((double)cpi->oxcf.q_cfg.deltaq_strength /
1025*77c1e3ccSAndroid Build Coastguard Worker 100.0 * (delta_q - new_delta_q_avg));
1026*77c1e3ccSAndroid Build Coastguard Worker } else {
1027*77c1e3ccSAndroid Build Coastguard Worker cpi->mb_delta_q[index] = RINT(
1028*77c1e3ccSAndroid Build Coastguard Worker (double)cpi->oxcf.q_cfg.deltaq_strength / 100.0 * scaling_factor *
1029*77c1e3ccSAndroid Build Coastguard Worker (mb_delta_q[model_idx][index] - delta_q_avg[model_idx]));
1030*77c1e3ccSAndroid Build Coastguard Worker }
1031*77c1e3ccSAndroid Build Coastguard Worker }
1032*77c1e3ccSAndroid Build Coastguard Worker }
1033*77c1e3ccSAndroid Build Coastguard Worker
1034*77c1e3ccSAndroid Build Coastguard Worker aom_free(mb_delta_q[0]);
1035*77c1e3ccSAndroid Build Coastguard Worker aom_free(mb_delta_q[1]);
1036*77c1e3ccSAndroid Build Coastguard Worker }
1037*77c1e3ccSAndroid Build Coastguard Worker #endif
1038*77c1e3ccSAndroid Build Coastguard Worker
av1_get_sbq_user_rating_based(AV1_COMP * const cpi,int mi_row,int mi_col)1039*77c1e3ccSAndroid Build Coastguard Worker int av1_get_sbq_user_rating_based(AV1_COMP *const cpi, int mi_row, int mi_col) {
1040*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE bsize = cpi->common.seq_params->sb_size;
1041*77c1e3ccSAndroid Build Coastguard Worker const CommonModeInfoParams *const mi_params = &cpi->common.mi_params;
1042*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *const cm = &cpi->common;
1043*77c1e3ccSAndroid Build Coastguard Worker const int base_qindex = cm->quant_params.base_qindex;
1044*77c1e3ccSAndroid Build Coastguard Worker if (base_qindex == MINQ || base_qindex == MAXQ) return base_qindex;
1045*77c1e3ccSAndroid Build Coastguard Worker
1046*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_w = mi_size_wide[bsize];
1047*77c1e3ccSAndroid Build Coastguard Worker const int num_mi_h = mi_size_high[bsize];
1048*77c1e3ccSAndroid Build Coastguard Worker const int num_cols = (mi_params->mi_cols + num_mi_w - 1) / num_mi_w;
1049*77c1e3ccSAndroid Build Coastguard Worker const int index = (mi_row / num_mi_h) * num_cols + (mi_col / num_mi_w);
1050*77c1e3ccSAndroid Build Coastguard Worker const int delta_q = cpi->mb_delta_q[index];
1051*77c1e3ccSAndroid Build Coastguard Worker
1052*77c1e3ccSAndroid Build Coastguard Worker int qindex = base_qindex + delta_q;
1053*77c1e3ccSAndroid Build Coastguard Worker qindex = AOMMIN(qindex, MAXQ);
1054*77c1e3ccSAndroid Build Coastguard Worker qindex = AOMMAX(qindex, MINQ + 1);
1055*77c1e3ccSAndroid Build Coastguard Worker
1056*77c1e3ccSAndroid Build Coastguard Worker return qindex;
1057*77c1e3ccSAndroid Build Coastguard Worker }
1058