1 /*
2 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12 #include "av1/common/common_data.h"
13 #include "av1/common/enums.h"
14 #include "av1/common/idct.h"
15
16 #include "av1/common/reconinter.h"
17 #include "av1/encoder/allintra_vis.h"
18 #include "av1/encoder/hybrid_fwd_txfm.h"
19 #include "av1/encoder/rdopt_utils.h"
20
21 // Process the wiener variance in 16x16 block basis.
qsort_comp(const void * elem1,const void * elem2)22 static int qsort_comp(const void *elem1, const void *elem2) {
23 int a = *((const int *)elem1);
24 int b = *((const int *)elem2);
25 if (a > b) return 1;
26 if (a < b) return -1;
27 return 0;
28 }
29
av1_init_mb_wiener_var_buffer(AV1_COMP * cpi)30 void av1_init_mb_wiener_var_buffer(AV1_COMP *cpi) {
31 AV1_COMMON *cm = &cpi->common;
32
33 cpi->weber_bsize = BLOCK_8X8;
34
35 if (cpi->mb_weber_stats) return;
36
37 CHECK_MEM_ERROR(cm, cpi->mb_weber_stats,
38 aom_calloc(cpi->frame_info.mi_rows * cpi->frame_info.mi_cols,
39 sizeof(*cpi->mb_weber_stats)));
40 }
41
get_satd(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)42 static int64_t get_satd(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
43 int mi_col) {
44 AV1_COMMON *const cm = &cpi->common;
45 const int mi_wide = mi_size_wide[bsize];
46 const int mi_high = mi_size_high[bsize];
47
48 const int mi_step = mi_size_wide[cpi->weber_bsize];
49 int mb_stride = cpi->frame_info.mi_cols;
50 int mb_count = 0;
51 int64_t satd = 0;
52
53 for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
54 for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
55 if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
56 continue;
57
58 satd += cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)]
59 .satd;
60 ++mb_count;
61 }
62 }
63
64 if (mb_count) satd = (int)(satd / mb_count);
65 satd = AOMMAX(1, satd);
66
67 return (int)satd;
68 }
69
get_sse(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)70 static int64_t get_sse(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
71 int mi_col) {
72 AV1_COMMON *const cm = &cpi->common;
73 const int mi_wide = mi_size_wide[bsize];
74 const int mi_high = mi_size_high[bsize];
75
76 const int mi_step = mi_size_wide[cpi->weber_bsize];
77 int mb_stride = cpi->frame_info.mi_cols;
78 int mb_count = 0;
79 int64_t distortion = 0;
80
81 for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
82 for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
83 if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
84 continue;
85
86 distortion +=
87 cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)]
88 .distortion;
89 ++mb_count;
90 }
91 }
92
93 if (mb_count) distortion = (int)(distortion / mb_count);
94 distortion = AOMMAX(1, distortion);
95
96 return (int)distortion;
97 }
98
get_max_scale(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)99 static double get_max_scale(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
100 int mi_col) {
101 AV1_COMMON *const cm = &cpi->common;
102 const int mi_wide = mi_size_wide[bsize];
103 const int mi_high = mi_size_high[bsize];
104 const int mi_step = mi_size_wide[cpi->weber_bsize];
105 int mb_stride = cpi->frame_info.mi_cols;
106 double min_max_scale = 10.0;
107
108 for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
109 for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
110 if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
111 continue;
112 WeberStats *weber_stats =
113 &cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)];
114 if (weber_stats->max_scale < 1.0) continue;
115 if (weber_stats->max_scale < min_max_scale)
116 min_max_scale = weber_stats->max_scale;
117 }
118 }
119 return min_max_scale;
120 }
121
get_window_wiener_var(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)122 static int get_window_wiener_var(AV1_COMP *const cpi, BLOCK_SIZE bsize,
123 int mi_row, int mi_col) {
124 AV1_COMMON *const cm = &cpi->common;
125 const int mi_wide = mi_size_wide[bsize];
126 const int mi_high = mi_size_high[bsize];
127
128 const int mi_step = mi_size_wide[cpi->weber_bsize];
129 int sb_wiener_var = 0;
130 int mb_stride = cpi->frame_info.mi_cols;
131 int mb_count = 0;
132 double base_num = 1;
133 double base_den = 1;
134 double base_reg = 1;
135
136 for (int row = mi_row; row < mi_row + mi_high; row += mi_step) {
137 for (int col = mi_col; col < mi_col + mi_wide; col += mi_step) {
138 if (row >= cm->mi_params.mi_rows || col >= cm->mi_params.mi_cols)
139 continue;
140
141 WeberStats *weber_stats =
142 &cpi->mb_weber_stats[(row / mi_step) * mb_stride + (col / mi_step)];
143
144 base_num += ((double)weber_stats->distortion) *
145 sqrt((double)weber_stats->src_variance) *
146 weber_stats->rec_pix_max;
147
148 base_den += fabs(
149 weber_stats->rec_pix_max * sqrt((double)weber_stats->src_variance) -
150 weber_stats->src_pix_max * sqrt((double)weber_stats->rec_variance));
151
152 base_reg += sqrt((double)weber_stats->distortion) *
153 sqrt((double)weber_stats->src_pix_max) * 0.1;
154 ++mb_count;
155 }
156 }
157
158 sb_wiener_var = (int)((base_num + base_reg) / (base_den + base_reg));
159 sb_wiener_var = AOMMAX(1, sb_wiener_var);
160
161 return (int)sb_wiener_var;
162 }
163
get_var_perceptual_ai(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)164 static int get_var_perceptual_ai(AV1_COMP *const cpi, BLOCK_SIZE bsize,
165 int mi_row, int mi_col) {
166 AV1_COMMON *const cm = &cpi->common;
167 const int mi_wide = mi_size_wide[bsize];
168 const int mi_high = mi_size_high[bsize];
169
170 int sb_wiener_var = get_window_wiener_var(cpi, bsize, mi_row, mi_col);
171
172 if (mi_row >= (mi_high / 2)) {
173 sb_wiener_var =
174 AOMMIN(sb_wiener_var,
175 get_window_wiener_var(cpi, bsize, mi_row - mi_high / 2, mi_col));
176 }
177 if (mi_row <= (cm->mi_params.mi_rows - mi_high - (mi_high / 2))) {
178 sb_wiener_var =
179 AOMMIN(sb_wiener_var,
180 get_window_wiener_var(cpi, bsize, mi_row + mi_high / 2, mi_col));
181 }
182 if (mi_col >= (mi_wide / 2)) {
183 sb_wiener_var =
184 AOMMIN(sb_wiener_var,
185 get_window_wiener_var(cpi, bsize, mi_row, mi_col - mi_wide / 2));
186 }
187 if (mi_col <= (cm->mi_params.mi_cols - mi_wide - (mi_wide / 2))) {
188 sb_wiener_var =
189 AOMMIN(sb_wiener_var,
190 get_window_wiener_var(cpi, bsize, mi_row, mi_col + mi_wide / 2));
191 }
192
193 return sb_wiener_var;
194 }
195
av1_set_mb_wiener_variance(AV1_COMP * cpi)196 void av1_set_mb_wiener_variance(AV1_COMP *cpi) {
197 AV1_COMMON *const cm = &cpi->common;
198 uint8_t *buffer = cpi->source->y_buffer;
199 int buf_stride = cpi->source->y_stride;
200 ThreadData *td = &cpi->td;
201 MACROBLOCK *x = &td->mb;
202 MACROBLOCKD *xd = &x->e_mbd;
203 MB_MODE_INFO mbmi;
204 memset(&mbmi, 0, sizeof(mbmi));
205 MB_MODE_INFO *mbmi_ptr = &mbmi;
206 xd->mi = &mbmi_ptr;
207 xd->cur_buf = cpi->source;
208
209 const SequenceHeader *const seq_params = cm->seq_params;
210 if (aom_realloc_frame_buffer(
211 &cm->cur_frame->buf, cm->width, cm->height, seq_params->subsampling_x,
212 seq_params->subsampling_y, seq_params->use_highbitdepth,
213 cpi->oxcf.border_in_pixels, cm->features.byte_alignment, NULL, NULL,
214 NULL, cpi->oxcf.tool_cfg.enable_global_motion))
215 aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR,
216 "Failed to allocate frame buffer");
217
218 cm->quant_params.base_qindex = cpi->oxcf.rc_cfg.cq_level;
219 av1_frame_init_quantizer(cpi);
220
221 DECLARE_ALIGNED(32, int16_t, src_diff[32 * 32]);
222 DECLARE_ALIGNED(32, tran_low_t, coeff[32 * 32]);
223 DECLARE_ALIGNED(32, tran_low_t, qcoeff[32 * 32]);
224 DECLARE_ALIGNED(32, tran_low_t, dqcoeff[32 * 32]);
225
226 int mi_row, mi_col;
227
228 BLOCK_SIZE bsize = cpi->weber_bsize;
229 const TX_SIZE tx_size = max_txsize_lookup[bsize];
230 const int block_size = tx_size_wide[tx_size];
231 const int coeff_count = block_size * block_size;
232
233 const BitDepthInfo bd_info = get_bit_depth_info(xd);
234 cpi->norm_wiener_variance = 0;
235 int mb_step = mi_size_wide[bsize];
236
237 for (mi_row = 0; mi_row < cpi->frame_info.mi_rows; mi_row += mb_step) {
238 for (mi_col = 0; mi_col < cpi->frame_info.mi_cols; mi_col += mb_step) {
239 PREDICTION_MODE best_mode = DC_PRED;
240 int best_intra_cost = INT_MAX;
241
242 xd->up_available = mi_row > 0;
243 xd->left_available = mi_col > 0;
244
245 const int mi_width = mi_size_wide[bsize];
246 const int mi_height = mi_size_high[bsize];
247 set_mode_info_offsets(&cpi->common.mi_params, &cpi->mbmi_ext_info, x, xd,
248 mi_row, mi_col);
249 set_mi_row_col(xd, &xd->tile, mi_row, mi_height, mi_col, mi_width,
250 cm->mi_params.mi_rows, cm->mi_params.mi_cols);
251 set_plane_n4(xd, mi_size_wide[bsize], mi_size_high[bsize],
252 av1_num_planes(cm));
253 xd->mi[0]->bsize = bsize;
254 xd->mi[0]->motion_mode = SIMPLE_TRANSLATION;
255
256 av1_setup_dst_planes(xd->plane, bsize, &cm->cur_frame->buf, mi_row,
257 mi_col, 0, av1_num_planes(cm));
258
259 int dst_buffer_stride = xd->plane[0].dst.stride;
260 uint8_t *dst_buffer = xd->plane[0].dst.buf;
261 uint8_t *mb_buffer =
262 buffer + mi_row * MI_SIZE * buf_stride + mi_col * MI_SIZE;
263
264 for (PREDICTION_MODE mode = INTRA_MODE_START; mode < INTRA_MODE_END;
265 ++mode) {
266 av1_predict_intra_block(
267 xd, cm->seq_params->sb_size,
268 cm->seq_params->enable_intra_edge_filter, block_size, block_size,
269 tx_size, mode, 0, 0, FILTER_INTRA_MODES, dst_buffer,
270 dst_buffer_stride, dst_buffer, dst_buffer_stride, 0, 0, 0);
271
272 av1_subtract_block(bd_info, block_size, block_size, src_diff,
273 block_size, mb_buffer, buf_stride, dst_buffer,
274 dst_buffer_stride);
275 av1_quick_txfm(0, tx_size, bd_info, src_diff, block_size, coeff);
276 int intra_cost = aom_satd(coeff, coeff_count);
277 if (intra_cost < best_intra_cost) {
278 best_intra_cost = intra_cost;
279 best_mode = mode;
280 }
281 }
282
283 int idx;
284 av1_predict_intra_block(xd, cm->seq_params->sb_size,
285 cm->seq_params->enable_intra_edge_filter,
286 block_size, block_size, tx_size, best_mode, 0, 0,
287 FILTER_INTRA_MODES, dst_buffer, dst_buffer_stride,
288 dst_buffer, dst_buffer_stride, 0, 0, 0);
289 av1_subtract_block(bd_info, block_size, block_size, src_diff, block_size,
290 mb_buffer, buf_stride, dst_buffer, dst_buffer_stride);
291 av1_quick_txfm(0, tx_size, bd_info, src_diff, block_size, coeff);
292
293 const struct macroblock_plane *const p = &x->plane[0];
294 uint16_t eob;
295 const SCAN_ORDER *const scan_order = &av1_scan_orders[tx_size][DCT_DCT];
296 QUANT_PARAM quant_param;
297 int pix_num = 1 << num_pels_log2_lookup[txsize_to_bsize[tx_size]];
298 av1_setup_quant(tx_size, 0, AV1_XFORM_QUANT_FP, 0, &quant_param);
299 #if CONFIG_AV1_HIGHBITDEPTH
300 if (is_cur_buf_hbd(xd)) {
301 av1_highbd_quantize_fp_facade(coeff, pix_num, p, qcoeff, dqcoeff, &eob,
302 scan_order, &quant_param);
303 } else {
304 av1_quantize_fp_facade(coeff, pix_num, p, qcoeff, dqcoeff, &eob,
305 scan_order, &quant_param);
306 }
307 #else
308 av1_quantize_fp_facade(coeff, pix_num, p, qcoeff, dqcoeff, &eob,
309 scan_order, &quant_param);
310 #endif // CONFIG_AV1_HIGHBITDEPTH
311 av1_inverse_transform_block(xd, dqcoeff, 0, DCT_DCT, tx_size, dst_buffer,
312 dst_buffer_stride, eob, 0);
313 WeberStats *weber_stats =
314 &cpi->mb_weber_stats[(mi_row / mb_step) * cpi->frame_info.mi_cols +
315 (mi_col / mb_step)];
316
317 weber_stats->rec_pix_max = 1;
318 weber_stats->rec_variance = 0;
319 weber_stats->src_pix_max = 1;
320 weber_stats->src_variance = 0;
321 weber_stats->distortion = 0;
322
323 int64_t src_mean = 0;
324 int64_t rec_mean = 0;
325 int64_t dist_mean = 0;
326
327 for (int pix_row = 0; pix_row < block_size; ++pix_row) {
328 for (int pix_col = 0; pix_col < block_size; ++pix_col) {
329 int src_pix, rec_pix;
330 #if CONFIG_AV1_HIGHBITDEPTH
331 if (is_cur_buf_hbd(xd)) {
332 uint16_t *src = CONVERT_TO_SHORTPTR(mb_buffer);
333 uint16_t *rec = CONVERT_TO_SHORTPTR(dst_buffer);
334 src_pix = src[pix_row * buf_stride + pix_col];
335 rec_pix = rec[pix_row * dst_buffer_stride + pix_col];
336 } else {
337 src_pix = mb_buffer[pix_row * buf_stride + pix_col];
338 rec_pix = dst_buffer[pix_row * dst_buffer_stride + pix_col];
339 }
340 #else
341 src_pix = mb_buffer[pix_row * buf_stride + pix_col];
342 rec_pix = dst_buffer[pix_row * dst_buffer_stride + pix_col];
343 #endif
344 src_mean += src_pix;
345 rec_mean += rec_pix;
346 dist_mean += src_pix - rec_pix;
347 weber_stats->src_variance += src_pix * src_pix;
348 weber_stats->rec_variance += rec_pix * rec_pix;
349 weber_stats->src_pix_max = AOMMAX(weber_stats->src_pix_max, src_pix);
350 weber_stats->rec_pix_max = AOMMAX(weber_stats->rec_pix_max, rec_pix);
351 weber_stats->distortion += (src_pix - rec_pix) * (src_pix - rec_pix);
352 }
353 }
354
355 weber_stats->src_variance -= (src_mean * src_mean) / pix_num;
356 weber_stats->rec_variance -= (rec_mean * rec_mean) / pix_num;
357 weber_stats->distortion -= (dist_mean * dist_mean) / pix_num;
358 weber_stats->satd = best_intra_cost;
359
360 double reg = sqrt((double)weber_stats->distortion) *
361 sqrt((double)weber_stats->src_pix_max) * 0.1;
362 double alpha_den = fabs(weber_stats->rec_pix_max *
363 sqrt((double)weber_stats->src_variance) -
364 weber_stats->src_pix_max *
365 sqrt((double)weber_stats->rec_variance)) +
366 reg;
367 double alpha_num = ((double)weber_stats->distortion) *
368 sqrt((double)weber_stats->src_variance) *
369 weber_stats->rec_pix_max +
370 reg;
371
372 weber_stats->alpha = AOMMAX(alpha_num, 1.0) / AOMMAX(alpha_den, 1.0);
373
374 qcoeff[0] = 0;
375 for (idx = 1; idx < coeff_count; ++idx) qcoeff[idx] = abs(qcoeff[idx]);
376 qsort(qcoeff, coeff_count, sizeof(*coeff), qsort_comp);
377
378 weber_stats->max_scale = (double)qcoeff[coeff_count - 1];
379 }
380 }
381
382 int sb_step = mi_size_wide[cm->seq_params->sb_size];
383 double sb_wiener_log = 0;
384 double sb_count = 0;
385
386 for (mi_row = 0; mi_row < cm->mi_params.mi_rows; mi_row += sb_step) {
387 for (mi_col = 0; mi_col < cm->mi_params.mi_cols; mi_col += sb_step) {
388 int sb_wiener_var =
389 get_var_perceptual_ai(cpi, cm->seq_params->sb_size, mi_row, mi_col);
390 int64_t satd = get_satd(cpi, cm->seq_params->sb_size, mi_row, mi_col);
391 int64_t sse = get_sse(cpi, cm->seq_params->sb_size, mi_row, mi_col);
392 double scaled_satd = (double)satd / sqrt((double)sse);
393 sb_wiener_log += scaled_satd * log(sb_wiener_var);
394 sb_count += scaled_satd;
395 }
396 }
397
398 if (sb_count > 0)
399 cpi->norm_wiener_variance = (int64_t)(exp(sb_wiener_log / sb_count));
400 cpi->norm_wiener_variance = AOMMAX(1, cpi->norm_wiener_variance);
401
402 for (int its_cnt = 0; its_cnt < 2; ++its_cnt) {
403 sb_wiener_log = 0;
404 sb_count = 0;
405 for (mi_row = 0; mi_row < cm->mi_params.mi_rows; mi_row += sb_step) {
406 for (mi_col = 0; mi_col < cm->mi_params.mi_cols; mi_col += sb_step) {
407 int sb_wiener_var =
408 get_var_perceptual_ai(cpi, cm->seq_params->sb_size, mi_row, mi_col);
409
410 double beta = (double)cpi->norm_wiener_variance / sb_wiener_var;
411 double min_max_scale =
412 AOMMAX(1.0, get_max_scale(cpi, bsize, mi_row, mi_col));
413 beta = 1.0 / AOMMIN(1.0 / beta, min_max_scale);
414 beta = AOMMIN(beta, 4);
415 beta = AOMMAX(beta, 0.25);
416
417 sb_wiener_var = (int)(cpi->norm_wiener_variance / beta);
418
419 int64_t satd = get_satd(cpi, cm->seq_params->sb_size, mi_row, mi_col);
420 int64_t sse = get_sse(cpi, cm->seq_params->sb_size, mi_row, mi_col);
421 double scaled_satd = (double)satd / sqrt((double)sse);
422 sb_wiener_log += scaled_satd * log(sb_wiener_var);
423 sb_count += scaled_satd;
424 }
425 }
426
427 if (sb_count > 0)
428 cpi->norm_wiener_variance = (int64_t)(exp(sb_wiener_log / sb_count));
429 cpi->norm_wiener_variance = AOMMAX(1, cpi->norm_wiener_variance);
430 }
431
432 aom_free_frame_buffer(&cm->cur_frame->buf);
433 }
434
av1_get_sbq_perceptual_ai(AV1_COMP * const cpi,BLOCK_SIZE bsize,int mi_row,int mi_col)435 int av1_get_sbq_perceptual_ai(AV1_COMP *const cpi, BLOCK_SIZE bsize, int mi_row,
436 int mi_col) {
437 AV1_COMMON *const cm = &cpi->common;
438 const int base_qindex = cm->quant_params.base_qindex;
439 int sb_wiener_var = get_var_perceptual_ai(cpi, bsize, mi_row, mi_col);
440 int offset = 0;
441 double beta = (double)cpi->norm_wiener_variance / sb_wiener_var;
442 double min_max_scale = AOMMAX(1.0, get_max_scale(cpi, bsize, mi_row, mi_col));
443 beta = 1.0 / AOMMIN(1.0 / beta, min_max_scale);
444
445 // Cap beta such that the delta q value is not much far away from the base q.
446 beta = AOMMIN(beta, 4);
447 beta = AOMMAX(beta, 0.25);
448 offset = av1_get_deltaq_offset(cm->seq_params->bit_depth, base_qindex, beta);
449 const DeltaQInfo *const delta_q_info = &cm->delta_q_info;
450 offset = AOMMIN(offset, delta_q_info->delta_q_res * 20 - 1);
451 offset = AOMMAX(offset, -delta_q_info->delta_q_res * 20 + 1);
452 int qindex = cm->quant_params.base_qindex + offset;
453 qindex = AOMMIN(qindex, MAXQ);
454 qindex = AOMMAX(qindex, MINQ);
455 if (base_qindex > MINQ) qindex = AOMMAX(qindex, MINQ + 1);
456
457 return qindex;
458 }
459
av1_init_mb_ur_var_buffer(AV1_COMP * cpi)460 void av1_init_mb_ur_var_buffer(AV1_COMP *cpi) {
461 AV1_COMMON *cm = &cpi->common;
462
463 if (cpi->mb_delta_q) return;
464
465 CHECK_MEM_ERROR(cm, cpi->mb_delta_q,
466 aom_calloc(cpi->frame_info.mb_rows * cpi->frame_info.mb_cols,
467 sizeof(*cpi->mb_delta_q)));
468 }
469
av1_set_mb_ur_variance(AV1_COMP * cpi)470 void av1_set_mb_ur_variance(AV1_COMP *cpi) {
471 const CommonModeInfoParams *const mi_params = &cpi->common.mi_params;
472 ThreadData *td = &cpi->td;
473 MACROBLOCK *x = &td->mb;
474 MACROBLOCKD *xd = &x->e_mbd;
475 uint8_t *y_buffer = cpi->source->y_buffer;
476 const int y_stride = cpi->source->y_stride;
477 const int block_size = cpi->common.seq_params->sb_size;
478
479 const int num_mi_w = mi_size_wide[block_size];
480 const int num_mi_h = mi_size_high[block_size];
481 const int num_cols = (mi_params->mi_cols + num_mi_w - 1) / num_mi_w;
482 const int num_rows = (mi_params->mi_rows + num_mi_h - 1) / num_mi_h;
483 const int use_hbd = cpi->source->flags & YV12_FLAG_HIGHBITDEPTH;
484
485 double a = -23.06 * 4.0, b = 0.004065, c = 30.516 * 4.0;
486 int delta_q_avg = 0;
487 // Loop through each SB block.
488 for (int row = 0; row < num_rows; ++row) {
489 for (int col = 0; col < num_cols; ++col) {
490 double var = 0.0, num_of_var = 0.0;
491 const int index = row * num_cols + col;
492
493 // Loop through each 8x8 block.
494 for (int mi_row = row * num_mi_h;
495 mi_row < mi_params->mi_rows && mi_row < (row + 1) * num_mi_h;
496 mi_row += 2) {
497 for (int mi_col = col * num_mi_w;
498 mi_col < mi_params->mi_cols && mi_col < (col + 1) * num_mi_w;
499 mi_col += 2) {
500 struct buf_2d buf;
501 const int row_offset_y = mi_row << 2;
502 const int col_offset_y = mi_col << 2;
503
504 buf.buf = y_buffer + row_offset_y * y_stride + col_offset_y;
505 buf.stride = y_stride;
506
507 double block_variance;
508 if (use_hbd) {
509 block_variance = av1_high_get_sby_perpixel_variance(
510 cpi, &buf, BLOCK_8X8, xd->bd);
511 } else {
512 block_variance =
513 av1_get_sby_perpixel_variance(cpi, &buf, BLOCK_8X8);
514 }
515
516 block_variance = block_variance < 1.0 ? 1.0 : block_variance;
517 var += log(block_variance);
518 num_of_var += 1.0;
519 }
520 }
521 var = exp(var / num_of_var);
522 cpi->mb_delta_q[index] = (int)(a * exp(-b * var) + c + 0.5);
523 delta_q_avg += cpi->mb_delta_q[index];
524 }
525 }
526
527 delta_q_avg = (int)((double)delta_q_avg / (num_rows * num_cols) + 0.5);
528
529 for (int row = 0; row < num_rows; ++row) {
530 for (int col = 0; col < num_cols; ++col) {
531 const int index = row * num_cols + col;
532 cpi->mb_delta_q[index] -= delta_q_avg;
533 }
534 }
535 }
536
av1_get_sbq_user_rating_based(AV1_COMP * const cpi,int mi_row,int mi_col)537 int av1_get_sbq_user_rating_based(AV1_COMP *const cpi, int mi_row, int mi_col) {
538 const BLOCK_SIZE bsize = cpi->common.seq_params->sb_size;
539 const CommonModeInfoParams *const mi_params = &cpi->common.mi_params;
540 AV1_COMMON *const cm = &cpi->common;
541 const int base_qindex = cm->quant_params.base_qindex;
542 if (base_qindex == MINQ || base_qindex == MAXQ) return base_qindex;
543
544 const int num_mi_w = mi_size_wide[bsize];
545 const int num_mi_h = mi_size_high[bsize];
546 const int num_cols = (mi_params->mi_cols + num_mi_w - 1) / num_mi_w;
547 const int index = (mi_row / num_mi_h) * num_cols + (mi_col / num_mi_w);
548 const int delta_q = cpi->mb_delta_q[index];
549
550 int qindex = base_qindex + delta_q;
551 qindex = AOMMIN(qindex, MAXQ);
552 qindex = AOMMAX(qindex, MINQ + 1);
553
554 return qindex;
555 }
556