1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker *
4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker */
11*77c1e3ccSAndroid Build Coastguard Worker
12*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h"
13*77c1e3ccSAndroid Build Coastguard Worker #include "config/av1_rtcd.h"
14*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
15*77c1e3ccSAndroid Build Coastguard Worker
16*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/bitwriter.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/quantize.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "aom_mem/aom_mem.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem.h"
20*77c1e3ccSAndroid Build Coastguard Worker
21*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_BITSTREAM_DEBUG || CONFIG_MISMATCH_DEBUG
22*77c1e3ccSAndroid Build Coastguard Worker #include "aom_util/debug_util.h"
23*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_BITSTREAM_DEBUG || CONFIG_MISMATCH_DEBUG
24*77c1e3ccSAndroid Build Coastguard Worker
25*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/cfl.h"
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/idct.h"
27*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/reconinter.h"
28*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/reconintra.h"
29*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/scan.h"
30*77c1e3ccSAndroid Build Coastguard Worker
31*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/av1_quantize.h"
32*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encodemb.h"
33*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/hybrid_fwd_txfm.h"
34*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/txb_rdopt.h"
35*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rd.h"
36*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rdopt.h"
37*77c1e3ccSAndroid Build Coastguard Worker
av1_subtract_block(BitDepthInfo bd_info,int rows,int cols,int16_t * diff,ptrdiff_t diff_stride,const uint8_t * src8,ptrdiff_t src_stride,const uint8_t * pred8,ptrdiff_t pred_stride)38*77c1e3ccSAndroid Build Coastguard Worker void av1_subtract_block(BitDepthInfo bd_info, int rows, int cols, int16_t *diff,
39*77c1e3ccSAndroid Build Coastguard Worker ptrdiff_t diff_stride, const uint8_t *src8,
40*77c1e3ccSAndroid Build Coastguard Worker ptrdiff_t src_stride, const uint8_t *pred8,
41*77c1e3ccSAndroid Build Coastguard Worker ptrdiff_t pred_stride) {
42*77c1e3ccSAndroid Build Coastguard Worker assert(rows >= 4 && cols >= 4);
43*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
44*77c1e3ccSAndroid Build Coastguard Worker if (bd_info.use_highbitdepth_buf) {
45*77c1e3ccSAndroid Build Coastguard Worker aom_highbd_subtract_block(rows, cols, diff, diff_stride, src8, src_stride,
46*77c1e3ccSAndroid Build Coastguard Worker pred8, pred_stride);
47*77c1e3ccSAndroid Build Coastguard Worker return;
48*77c1e3ccSAndroid Build Coastguard Worker }
49*77c1e3ccSAndroid Build Coastguard Worker #endif
50*77c1e3ccSAndroid Build Coastguard Worker (void)bd_info;
51*77c1e3ccSAndroid Build Coastguard Worker aom_subtract_block(rows, cols, diff, diff_stride, src8, src_stride, pred8,
52*77c1e3ccSAndroid Build Coastguard Worker pred_stride);
53*77c1e3ccSAndroid Build Coastguard Worker }
54*77c1e3ccSAndroid Build Coastguard Worker
av1_subtract_txb(MACROBLOCK * x,int plane,BLOCK_SIZE plane_bsize,int blk_col,int blk_row,TX_SIZE tx_size)55*77c1e3ccSAndroid Build Coastguard Worker void av1_subtract_txb(MACROBLOCK *x, int plane, BLOCK_SIZE plane_bsize,
56*77c1e3ccSAndroid Build Coastguard Worker int blk_col, int blk_row, TX_SIZE tx_size) {
57*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
58*77c1e3ccSAndroid Build Coastguard Worker const BitDepthInfo bd_info = get_bit_depth_info(xd);
59*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *const p = &x->plane[plane];
60*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
61*77c1e3ccSAndroid Build Coastguard Worker const int diff_stride = block_size_wide[plane_bsize];
62*77c1e3ccSAndroid Build Coastguard Worker const int src_stride = p->src.stride;
63*77c1e3ccSAndroid Build Coastguard Worker const int dst_stride = pd->dst.stride;
64*77c1e3ccSAndroid Build Coastguard Worker const int tx1d_width = tx_size_wide[tx_size];
65*77c1e3ccSAndroid Build Coastguard Worker const int tx1d_height = tx_size_high[tx_size];
66*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << MI_SIZE_LOG2];
67*77c1e3ccSAndroid Build Coastguard Worker uint8_t *src = &p->src.buf[(blk_row * src_stride + blk_col) << MI_SIZE_LOG2];
68*77c1e3ccSAndroid Build Coastguard Worker int16_t *src_diff =
69*77c1e3ccSAndroid Build Coastguard Worker &p->src_diff[(blk_row * diff_stride + blk_col) << MI_SIZE_LOG2];
70*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_block(bd_info, tx1d_height, tx1d_width, src_diff, diff_stride,
71*77c1e3ccSAndroid Build Coastguard Worker src, src_stride, dst, dst_stride);
72*77c1e3ccSAndroid Build Coastguard Worker }
73*77c1e3ccSAndroid Build Coastguard Worker
av1_subtract_plane(MACROBLOCK * x,BLOCK_SIZE plane_bsize,int plane)74*77c1e3ccSAndroid Build Coastguard Worker void av1_subtract_plane(MACROBLOCK *x, BLOCK_SIZE plane_bsize, int plane) {
75*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *const p = &x->plane[plane];
76*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &x->e_mbd.plane[plane];
77*77c1e3ccSAndroid Build Coastguard Worker assert(plane_bsize < BLOCK_SIZES_ALL);
78*77c1e3ccSAndroid Build Coastguard Worker const int bw = block_size_wide[plane_bsize];
79*77c1e3ccSAndroid Build Coastguard Worker const int bh = block_size_high[plane_bsize];
80*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *xd = &x->e_mbd;
81*77c1e3ccSAndroid Build Coastguard Worker const BitDepthInfo bd_info = get_bit_depth_info(xd);
82*77c1e3ccSAndroid Build Coastguard Worker
83*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_block(bd_info, bh, bw, p->src_diff, bw, p->src.buf,
84*77c1e3ccSAndroid Build Coastguard Worker p->src.stride, pd->dst.buf, pd->dst.stride);
85*77c1e3ccSAndroid Build Coastguard Worker }
86*77c1e3ccSAndroid Build Coastguard Worker
av1_optimize_b(const struct AV1_COMP * cpi,MACROBLOCK * x,int plane,int block,TX_SIZE tx_size,TX_TYPE tx_type,const TXB_CTX * const txb_ctx,int * rate_cost)87*77c1e3ccSAndroid Build Coastguard Worker int av1_optimize_b(const struct AV1_COMP *cpi, MACROBLOCK *x, int plane,
88*77c1e3ccSAndroid Build Coastguard Worker int block, TX_SIZE tx_size, TX_TYPE tx_type,
89*77c1e3ccSAndroid Build Coastguard Worker const TXB_CTX *const txb_ctx, int *rate_cost) {
90*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
91*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *const p = &x->plane[plane];
92*77c1e3ccSAndroid Build Coastguard Worker const int eob = p->eobs[block];
93*77c1e3ccSAndroid Build Coastguard Worker const int segment_id = xd->mi[0]->segment_id;
94*77c1e3ccSAndroid Build Coastguard Worker
95*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0 || !cpi->optimize_seg_arr[segment_id] ||
96*77c1e3ccSAndroid Build Coastguard Worker xd->lossless[segment_id]) {
97*77c1e3ccSAndroid Build Coastguard Worker *rate_cost = av1_cost_skip_txb(&x->coeff_costs, txb_ctx, plane, tx_size);
98*77c1e3ccSAndroid Build Coastguard Worker return eob;
99*77c1e3ccSAndroid Build Coastguard Worker }
100*77c1e3ccSAndroid Build Coastguard Worker
101*77c1e3ccSAndroid Build Coastguard Worker return av1_optimize_txb(cpi, x, plane, block, tx_size, tx_type, txb_ctx,
102*77c1e3ccSAndroid Build Coastguard Worker rate_cost, cpi->oxcf.algo_cfg.sharpness);
103*77c1e3ccSAndroid Build Coastguard Worker }
104*77c1e3ccSAndroid Build Coastguard Worker
105*77c1e3ccSAndroid Build Coastguard Worker // Hyper-parameters for dropout optimization, based on following logics.
106*77c1e3ccSAndroid Build Coastguard Worker // TODO(yjshen): These settings are tuned by experiments. They may still be
107*77c1e3ccSAndroid Build Coastguard Worker // optimized for better performance.
108*77c1e3ccSAndroid Build Coastguard Worker // (1) Coefficients which are large enough will ALWAYS be kept.
109*77c1e3ccSAndroid Build Coastguard Worker static const tran_low_t DROPOUT_COEFF_MAX = 2; // Max dropout-able coefficient.
110*77c1e3ccSAndroid Build Coastguard Worker // (2) Continuous coefficients will ALWAYS be kept. Here rigorous continuity is
111*77c1e3ccSAndroid Build Coastguard Worker // NOT required. For example, `5 0 0 0 7` is treated as two continuous
112*77c1e3ccSAndroid Build Coastguard Worker // coefficients if three zeros do not fulfill the dropout condition.
113*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_CONTINUITY_MAX =
114*77c1e3ccSAndroid Build Coastguard Worker 2; // Max dropout-able continuous coeff.
115*77c1e3ccSAndroid Build Coastguard Worker // (3) Dropout operation is NOT applicable to blocks with large or small
116*77c1e3ccSAndroid Build Coastguard Worker // quantization index.
117*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_Q_MAX = 128;
118*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_Q_MIN = 16;
119*77c1e3ccSAndroid Build Coastguard Worker // (4) Recall that dropout optimization will forcibly set some quantized
120*77c1e3ccSAndroid Build Coastguard Worker // coefficients to zero. The key logic on determining whether a coefficient
121*77c1e3ccSAndroid Build Coastguard Worker // should be dropped is to check the number of continuous zeros before AND
122*77c1e3ccSAndroid Build Coastguard Worker // after this coefficient. The exact number of zeros for judgement depends
123*77c1e3ccSAndroid Build Coastguard Worker // on block size and quantization index. More concretely, block size
124*77c1e3ccSAndroid Build Coastguard Worker // determines the base number of zeros, while quantization index determines
125*77c1e3ccSAndroid Build Coastguard Worker // the multiplier. Intuitively, larger block requires more zeros and larger
126*77c1e3ccSAndroid Build Coastguard Worker // quantization index also requires more zeros (more information is lost
127*77c1e3ccSAndroid Build Coastguard Worker // when using larger quantization index).
128*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_BEFORE_BASE_MAX =
129*77c1e3ccSAndroid Build Coastguard Worker 32; // Max base number for leading zeros.
130*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_BEFORE_BASE_MIN =
131*77c1e3ccSAndroid Build Coastguard Worker 16; // Min base number for leading zeros.
132*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_AFTER_BASE_MAX =
133*77c1e3ccSAndroid Build Coastguard Worker 32; // Max base number for trailing zeros.
134*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_AFTER_BASE_MIN =
135*77c1e3ccSAndroid Build Coastguard Worker 16; // Min base number for trailing zeros.
136*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_MULTIPLIER_MAX =
137*77c1e3ccSAndroid Build Coastguard Worker 8; // Max multiplier on number of zeros.
138*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_MULTIPLIER_MIN =
139*77c1e3ccSAndroid Build Coastguard Worker 2; // Min multiplier on number of zeros.
140*77c1e3ccSAndroid Build Coastguard Worker static const int DROPOUT_MULTIPLIER_Q_BASE =
141*77c1e3ccSAndroid Build Coastguard Worker 32; // Base Q to compute multiplier.
142*77c1e3ccSAndroid Build Coastguard Worker
av1_dropout_qcoeff(MACROBLOCK * mb,int plane,int block,TX_SIZE tx_size,TX_TYPE tx_type,int qindex)143*77c1e3ccSAndroid Build Coastguard Worker void av1_dropout_qcoeff(MACROBLOCK *mb, int plane, int block, TX_SIZE tx_size,
144*77c1e3ccSAndroid Build Coastguard Worker TX_TYPE tx_type, int qindex) {
145*77c1e3ccSAndroid Build Coastguard Worker const int tx_width = tx_size_wide[tx_size];
146*77c1e3ccSAndroid Build Coastguard Worker const int tx_height = tx_size_high[tx_size];
147*77c1e3ccSAndroid Build Coastguard Worker
148*77c1e3ccSAndroid Build Coastguard Worker // Early return if `qindex` is out of range.
149*77c1e3ccSAndroid Build Coastguard Worker if (qindex > DROPOUT_Q_MAX || qindex < DROPOUT_Q_MIN) {
150*77c1e3ccSAndroid Build Coastguard Worker return;
151*77c1e3ccSAndroid Build Coastguard Worker }
152*77c1e3ccSAndroid Build Coastguard Worker
153*77c1e3ccSAndroid Build Coastguard Worker // Compute number of zeros used for dropout judgement.
154*77c1e3ccSAndroid Build Coastguard Worker const int base_size = AOMMAX(tx_width, tx_height);
155*77c1e3ccSAndroid Build Coastguard Worker const int multiplier = CLIP(qindex / DROPOUT_MULTIPLIER_Q_BASE,
156*77c1e3ccSAndroid Build Coastguard Worker DROPOUT_MULTIPLIER_MIN, DROPOUT_MULTIPLIER_MAX);
157*77c1e3ccSAndroid Build Coastguard Worker const int dropout_num_before =
158*77c1e3ccSAndroid Build Coastguard Worker multiplier *
159*77c1e3ccSAndroid Build Coastguard Worker CLIP(base_size, DROPOUT_BEFORE_BASE_MIN, DROPOUT_BEFORE_BASE_MAX);
160*77c1e3ccSAndroid Build Coastguard Worker const int dropout_num_after =
161*77c1e3ccSAndroid Build Coastguard Worker multiplier *
162*77c1e3ccSAndroid Build Coastguard Worker CLIP(base_size, DROPOUT_AFTER_BASE_MIN, DROPOUT_AFTER_BASE_MAX);
163*77c1e3ccSAndroid Build Coastguard Worker
164*77c1e3ccSAndroid Build Coastguard Worker av1_dropout_qcoeff_num(mb, plane, block, tx_size, tx_type, dropout_num_before,
165*77c1e3ccSAndroid Build Coastguard Worker dropout_num_after);
166*77c1e3ccSAndroid Build Coastguard Worker }
167*77c1e3ccSAndroid Build Coastguard Worker
av1_dropout_qcoeff_num(MACROBLOCK * mb,int plane,int block,TX_SIZE tx_size,TX_TYPE tx_type,int dropout_num_before,int dropout_num_after)168*77c1e3ccSAndroid Build Coastguard Worker void av1_dropout_qcoeff_num(MACROBLOCK *mb, int plane, int block,
169*77c1e3ccSAndroid Build Coastguard Worker TX_SIZE tx_size, TX_TYPE tx_type,
170*77c1e3ccSAndroid Build Coastguard Worker int dropout_num_before, int dropout_num_after) {
171*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *const p = &mb->plane[plane];
172*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const qcoeff = p->qcoeff + BLOCK_OFFSET(block);
173*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
174*77c1e3ccSAndroid Build Coastguard Worker const int max_eob = av1_get_max_eob(tx_size);
175*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
176*77c1e3ccSAndroid Build Coastguard Worker
177*77c1e3ccSAndroid Build Coastguard Worker // Early return if there are not enough non-zero coefficients.
178*77c1e3ccSAndroid Build Coastguard Worker if (p->eobs[block] == 0 || p->eobs[block] <= dropout_num_before ||
179*77c1e3ccSAndroid Build Coastguard Worker max_eob <= dropout_num_before + dropout_num_after) {
180*77c1e3ccSAndroid Build Coastguard Worker return;
181*77c1e3ccSAndroid Build Coastguard Worker }
182*77c1e3ccSAndroid Build Coastguard Worker
183*77c1e3ccSAndroid Build Coastguard Worker int count_zeros_before = 0;
184*77c1e3ccSAndroid Build Coastguard Worker int count_zeros_after = 0;
185*77c1e3ccSAndroid Build Coastguard Worker int count_nonzeros = 0;
186*77c1e3ccSAndroid Build Coastguard Worker // Index of the first non-zero coefficient after sufficient number of
187*77c1e3ccSAndroid Build Coastguard Worker // continuous zeros. If equals to `-1`, it means number of leading zeros
188*77c1e3ccSAndroid Build Coastguard Worker // hasn't reach `dropout_num_before`.
189*77c1e3ccSAndroid Build Coastguard Worker int idx = -1;
190*77c1e3ccSAndroid Build Coastguard Worker int eob = 0; // New end of block.
191*77c1e3ccSAndroid Build Coastguard Worker
192*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < p->eobs[block]; ++i) {
193*77c1e3ccSAndroid Build Coastguard Worker const int scan_idx = scan_order->scan[i];
194*77c1e3ccSAndroid Build Coastguard Worker if (abs(qcoeff[scan_idx]) > DROPOUT_COEFF_MAX) {
195*77c1e3ccSAndroid Build Coastguard Worker // Keep large coefficients.
196*77c1e3ccSAndroid Build Coastguard Worker count_zeros_before = 0;
197*77c1e3ccSAndroid Build Coastguard Worker count_zeros_after = 0;
198*77c1e3ccSAndroid Build Coastguard Worker idx = -1;
199*77c1e3ccSAndroid Build Coastguard Worker eob = i + 1;
200*77c1e3ccSAndroid Build Coastguard Worker } else if (qcoeff[scan_idx] == 0) { // Count zeros.
201*77c1e3ccSAndroid Build Coastguard Worker if (idx == -1) {
202*77c1e3ccSAndroid Build Coastguard Worker ++count_zeros_before;
203*77c1e3ccSAndroid Build Coastguard Worker } else {
204*77c1e3ccSAndroid Build Coastguard Worker ++count_zeros_after;
205*77c1e3ccSAndroid Build Coastguard Worker }
206*77c1e3ccSAndroid Build Coastguard Worker } else { // Count non-zeros.
207*77c1e3ccSAndroid Build Coastguard Worker if (count_zeros_before >= dropout_num_before) {
208*77c1e3ccSAndroid Build Coastguard Worker idx = (idx == -1) ? i : idx;
209*77c1e3ccSAndroid Build Coastguard Worker ++count_nonzeros;
210*77c1e3ccSAndroid Build Coastguard Worker } else {
211*77c1e3ccSAndroid Build Coastguard Worker count_zeros_before = 0;
212*77c1e3ccSAndroid Build Coastguard Worker eob = i + 1;
213*77c1e3ccSAndroid Build Coastguard Worker }
214*77c1e3ccSAndroid Build Coastguard Worker }
215*77c1e3ccSAndroid Build Coastguard Worker
216*77c1e3ccSAndroid Build Coastguard Worker // Handle continuity.
217*77c1e3ccSAndroid Build Coastguard Worker if (count_nonzeros > DROPOUT_CONTINUITY_MAX) {
218*77c1e3ccSAndroid Build Coastguard Worker count_zeros_before = 0;
219*77c1e3ccSAndroid Build Coastguard Worker count_zeros_after = 0;
220*77c1e3ccSAndroid Build Coastguard Worker count_nonzeros = 0;
221*77c1e3ccSAndroid Build Coastguard Worker idx = -1;
222*77c1e3ccSAndroid Build Coastguard Worker eob = i + 1;
223*77c1e3ccSAndroid Build Coastguard Worker }
224*77c1e3ccSAndroid Build Coastguard Worker
225*77c1e3ccSAndroid Build Coastguard Worker // Handle the trailing zeros after original end of block.
226*77c1e3ccSAndroid Build Coastguard Worker if (idx != -1 && i == p->eobs[block] - 1) {
227*77c1e3ccSAndroid Build Coastguard Worker count_zeros_after += (max_eob - p->eobs[block]);
228*77c1e3ccSAndroid Build Coastguard Worker }
229*77c1e3ccSAndroid Build Coastguard Worker
230*77c1e3ccSAndroid Build Coastguard Worker // Set redundant coefficients to zeros if needed.
231*77c1e3ccSAndroid Build Coastguard Worker if (count_zeros_after >= dropout_num_after) {
232*77c1e3ccSAndroid Build Coastguard Worker for (int j = idx; j <= i; ++j) {
233*77c1e3ccSAndroid Build Coastguard Worker qcoeff[scan_order->scan[j]] = 0;
234*77c1e3ccSAndroid Build Coastguard Worker dqcoeff[scan_order->scan[j]] = 0;
235*77c1e3ccSAndroid Build Coastguard Worker }
236*77c1e3ccSAndroid Build Coastguard Worker count_zeros_before += (i - idx + 1);
237*77c1e3ccSAndroid Build Coastguard Worker count_zeros_after = 0;
238*77c1e3ccSAndroid Build Coastguard Worker count_nonzeros = 0;
239*77c1e3ccSAndroid Build Coastguard Worker } else if (i == p->eobs[block] - 1) {
240*77c1e3ccSAndroid Build Coastguard Worker eob = i + 1;
241*77c1e3ccSAndroid Build Coastguard Worker }
242*77c1e3ccSAndroid Build Coastguard Worker }
243*77c1e3ccSAndroid Build Coastguard Worker
244*77c1e3ccSAndroid Build Coastguard Worker if (eob != p->eobs[block]) {
245*77c1e3ccSAndroid Build Coastguard Worker p->eobs[block] = eob;
246*77c1e3ccSAndroid Build Coastguard Worker p->txb_entropy_ctx[block] =
247*77c1e3ccSAndroid Build Coastguard Worker av1_get_txb_entropy_context(qcoeff, scan_order, eob);
248*77c1e3ccSAndroid Build Coastguard Worker }
249*77c1e3ccSAndroid Build Coastguard Worker }
250*77c1e3ccSAndroid Build Coastguard Worker
251*77c1e3ccSAndroid Build Coastguard Worker // Settings for optimization type. NOTE: To set optimization type for all intra
252*77c1e3ccSAndroid Build Coastguard Worker // frames, both `KEY_BLOCK_OPT_TYPE` and `INTRA_BLOCK_OPT_TYPE` should be set.
253*77c1e3ccSAndroid Build Coastguard Worker // TODO(yjshen): These settings are hard-coded and look okay for now. They
254*77c1e3ccSAndroid Build Coastguard Worker // should be made configurable later.
255*77c1e3ccSAndroid Build Coastguard Worker // Blocks of key frames ONLY.
256*77c1e3ccSAndroid Build Coastguard Worker static const OPT_TYPE KEY_BLOCK_OPT_TYPE = TRELLIS_DROPOUT_OPT;
257*77c1e3ccSAndroid Build Coastguard Worker // Blocks of intra frames (key frames EXCLUSIVE).
258*77c1e3ccSAndroid Build Coastguard Worker static const OPT_TYPE INTRA_BLOCK_OPT_TYPE = TRELLIS_DROPOUT_OPT;
259*77c1e3ccSAndroid Build Coastguard Worker // Blocks of inter frames. (NOTE: Dropout optimization is DISABLED by default
260*77c1e3ccSAndroid Build Coastguard Worker // if trellis optimization is on for inter frames.)
261*77c1e3ccSAndroid Build Coastguard Worker static const OPT_TYPE INTER_BLOCK_OPT_TYPE = TRELLIS_DROPOUT_OPT;
262*77c1e3ccSAndroid Build Coastguard Worker
263*77c1e3ccSAndroid Build Coastguard Worker enum {
264*77c1e3ccSAndroid Build Coastguard Worker QUANT_FUNC_LOWBD = 0,
265*77c1e3ccSAndroid Build Coastguard Worker QUANT_FUNC_HIGHBD = 1,
266*77c1e3ccSAndroid Build Coastguard Worker QUANT_FUNC_TYPES = 2
267*77c1e3ccSAndroid Build Coastguard Worker } UENUM1BYTE(QUANT_FUNC);
268*77c1e3ccSAndroid Build Coastguard Worker
269*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
270*77c1e3ccSAndroid Build Coastguard Worker static AV1_QUANT_FACADE
271*77c1e3ccSAndroid Build Coastguard Worker quant_func_list[AV1_XFORM_QUANT_TYPES][QUANT_FUNC_TYPES] = {
272*77c1e3ccSAndroid Build Coastguard Worker { av1_quantize_fp_facade, av1_highbd_quantize_fp_facade },
273*77c1e3ccSAndroid Build Coastguard Worker { av1_quantize_b_facade, av1_highbd_quantize_b_facade },
274*77c1e3ccSAndroid Build Coastguard Worker { av1_quantize_dc_facade, av1_highbd_quantize_dc_facade },
275*77c1e3ccSAndroid Build Coastguard Worker { NULL, NULL }
276*77c1e3ccSAndroid Build Coastguard Worker };
277*77c1e3ccSAndroid Build Coastguard Worker #else
278*77c1e3ccSAndroid Build Coastguard Worker static AV1_QUANT_FACADE quant_func_list[AV1_XFORM_QUANT_TYPES] = {
279*77c1e3ccSAndroid Build Coastguard Worker av1_quantize_fp_facade, av1_quantize_b_facade, av1_quantize_dc_facade, NULL
280*77c1e3ccSAndroid Build Coastguard Worker };
281*77c1e3ccSAndroid Build Coastguard Worker #endif
282*77c1e3ccSAndroid Build Coastguard Worker
283*77c1e3ccSAndroid Build Coastguard Worker // Computes the transform for DC only blocks
av1_xform_dc_only(MACROBLOCK * x,int plane,int block,TxfmParam * txfm_param,int64_t per_px_mean)284*77c1e3ccSAndroid Build Coastguard Worker void av1_xform_dc_only(MACROBLOCK *x, int plane, int block,
285*77c1e3ccSAndroid Build Coastguard Worker TxfmParam *txfm_param, int64_t per_px_mean) {
286*77c1e3ccSAndroid Build Coastguard Worker assert(per_px_mean != INT64_MAX);
287*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *const p = &x->plane[plane];
288*77c1e3ccSAndroid Build Coastguard Worker const int block_offset = BLOCK_OFFSET(block);
289*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const coeff = p->coeff + block_offset;
290*77c1e3ccSAndroid Build Coastguard Worker const int n_coeffs = av1_get_max_eob(txfm_param->tx_size);
291*77c1e3ccSAndroid Build Coastguard Worker memset(coeff, 0, sizeof(*coeff) * n_coeffs);
292*77c1e3ccSAndroid Build Coastguard Worker coeff[0] =
293*77c1e3ccSAndroid Build Coastguard Worker (tran_low_t)((per_px_mean * dc_coeff_scale[txfm_param->tx_size]) >> 12);
294*77c1e3ccSAndroid Build Coastguard Worker }
295*77c1e3ccSAndroid Build Coastguard Worker
av1_xform_quant(MACROBLOCK * x,int plane,int block,int blk_row,int blk_col,BLOCK_SIZE plane_bsize,TxfmParam * txfm_param,const QUANT_PARAM * qparam)296*77c1e3ccSAndroid Build Coastguard Worker void av1_xform_quant(MACROBLOCK *x, int plane, int block, int blk_row,
297*77c1e3ccSAndroid Build Coastguard Worker int blk_col, BLOCK_SIZE plane_bsize, TxfmParam *txfm_param,
298*77c1e3ccSAndroid Build Coastguard Worker const QUANT_PARAM *qparam) {
299*77c1e3ccSAndroid Build Coastguard Worker av1_xform(x, plane, block, blk_row, blk_col, plane_bsize, txfm_param);
300*77c1e3ccSAndroid Build Coastguard Worker av1_quant(x, plane, block, txfm_param, qparam);
301*77c1e3ccSAndroid Build Coastguard Worker }
302*77c1e3ccSAndroid Build Coastguard Worker
av1_xform(MACROBLOCK * x,int plane,int block,int blk_row,int blk_col,BLOCK_SIZE plane_bsize,TxfmParam * txfm_param)303*77c1e3ccSAndroid Build Coastguard Worker void av1_xform(MACROBLOCK *x, int plane, int block, int blk_row, int blk_col,
304*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE plane_bsize, TxfmParam *txfm_param) {
305*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *const p = &x->plane[plane];
306*77c1e3ccSAndroid Build Coastguard Worker const int block_offset = BLOCK_OFFSET(block);
307*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const coeff = p->coeff + block_offset;
308*77c1e3ccSAndroid Build Coastguard Worker const int diff_stride = block_size_wide[plane_bsize];
309*77c1e3ccSAndroid Build Coastguard Worker
310*77c1e3ccSAndroid Build Coastguard Worker const int src_offset = (blk_row * diff_stride + blk_col);
311*77c1e3ccSAndroid Build Coastguard Worker const int16_t *src_diff = &p->src_diff[src_offset << MI_SIZE_LOG2];
312*77c1e3ccSAndroid Build Coastguard Worker
313*77c1e3ccSAndroid Build Coastguard Worker av1_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
314*77c1e3ccSAndroid Build Coastguard Worker }
315*77c1e3ccSAndroid Build Coastguard Worker
av1_quant(MACROBLOCK * x,int plane,int block,TxfmParam * txfm_param,const QUANT_PARAM * qparam)316*77c1e3ccSAndroid Build Coastguard Worker void av1_quant(MACROBLOCK *x, int plane, int block, TxfmParam *txfm_param,
317*77c1e3ccSAndroid Build Coastguard Worker const QUANT_PARAM *qparam) {
318*77c1e3ccSAndroid Build Coastguard Worker const struct macroblock_plane *const p = &x->plane[plane];
319*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order =
320*77c1e3ccSAndroid Build Coastguard Worker get_scan(txfm_param->tx_size, txfm_param->tx_type);
321*77c1e3ccSAndroid Build Coastguard Worker const int block_offset = BLOCK_OFFSET(block);
322*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const coeff = p->coeff + block_offset;
323*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const qcoeff = p->qcoeff + block_offset;
324*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const dqcoeff = p->dqcoeff + block_offset;
325*77c1e3ccSAndroid Build Coastguard Worker uint16_t *const eob = &p->eobs[block];
326*77c1e3ccSAndroid Build Coastguard Worker
327*77c1e3ccSAndroid Build Coastguard Worker if (qparam->xform_quant_idx != AV1_XFORM_QUANT_SKIP_QUANT) {
328*77c1e3ccSAndroid Build Coastguard Worker const int n_coeffs = av1_get_max_eob(txfm_param->tx_size);
329*77c1e3ccSAndroid Build Coastguard Worker if (LIKELY(!x->seg_skip_block)) {
330*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
331*77c1e3ccSAndroid Build Coastguard Worker quant_func_list[qparam->xform_quant_idx][txfm_param->is_hbd](
332*77c1e3ccSAndroid Build Coastguard Worker coeff, n_coeffs, p, qcoeff, dqcoeff, eob, scan_order, qparam);
333*77c1e3ccSAndroid Build Coastguard Worker #else
334*77c1e3ccSAndroid Build Coastguard Worker quant_func_list[qparam->xform_quant_idx](
335*77c1e3ccSAndroid Build Coastguard Worker coeff, n_coeffs, p, qcoeff, dqcoeff, eob, scan_order, qparam);
336*77c1e3ccSAndroid Build Coastguard Worker #endif
337*77c1e3ccSAndroid Build Coastguard Worker } else {
338*77c1e3ccSAndroid Build Coastguard Worker av1_quantize_skip(n_coeffs, qcoeff, dqcoeff, eob);
339*77c1e3ccSAndroid Build Coastguard Worker }
340*77c1e3ccSAndroid Build Coastguard Worker }
341*77c1e3ccSAndroid Build Coastguard Worker // use_optimize_b is true means av1_optimze_b will be called,
342*77c1e3ccSAndroid Build Coastguard Worker // thus cannot update entropy ctx now (performed in optimize_b)
343*77c1e3ccSAndroid Build Coastguard Worker if (qparam->use_optimize_b) {
344*77c1e3ccSAndroid Build Coastguard Worker p->txb_entropy_ctx[block] = 0;
345*77c1e3ccSAndroid Build Coastguard Worker } else {
346*77c1e3ccSAndroid Build Coastguard Worker p->txb_entropy_ctx[block] =
347*77c1e3ccSAndroid Build Coastguard Worker av1_get_txb_entropy_context(qcoeff, scan_order, *eob);
348*77c1e3ccSAndroid Build Coastguard Worker }
349*77c1e3ccSAndroid Build Coastguard Worker }
350*77c1e3ccSAndroid Build Coastguard Worker
av1_setup_xform(const AV1_COMMON * cm,MACROBLOCK * x,TX_SIZE tx_size,TX_TYPE tx_type,TxfmParam * txfm_param)351*77c1e3ccSAndroid Build Coastguard Worker void av1_setup_xform(const AV1_COMMON *cm, MACROBLOCK *x, TX_SIZE tx_size,
352*77c1e3ccSAndroid Build Coastguard Worker TX_TYPE tx_type, TxfmParam *txfm_param) {
353*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
354*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
355*77c1e3ccSAndroid Build Coastguard Worker
356*77c1e3ccSAndroid Build Coastguard Worker txfm_param->tx_type = tx_type;
357*77c1e3ccSAndroid Build Coastguard Worker txfm_param->tx_size = tx_size;
358*77c1e3ccSAndroid Build Coastguard Worker txfm_param->lossless = xd->lossless[mbmi->segment_id];
359*77c1e3ccSAndroid Build Coastguard Worker txfm_param->tx_set_type = av1_get_ext_tx_set_type(
360*77c1e3ccSAndroid Build Coastguard Worker tx_size, is_inter_block(mbmi), cm->features.reduced_tx_set_used);
361*77c1e3ccSAndroid Build Coastguard Worker
362*77c1e3ccSAndroid Build Coastguard Worker txfm_param->bd = xd->bd;
363*77c1e3ccSAndroid Build Coastguard Worker txfm_param->is_hbd = is_cur_buf_hbd(xd);
364*77c1e3ccSAndroid Build Coastguard Worker }
av1_setup_quant(TX_SIZE tx_size,int use_optimize_b,int xform_quant_idx,int use_quant_b_adapt,QUANT_PARAM * qparam)365*77c1e3ccSAndroid Build Coastguard Worker void av1_setup_quant(TX_SIZE tx_size, int use_optimize_b, int xform_quant_idx,
366*77c1e3ccSAndroid Build Coastguard Worker int use_quant_b_adapt, QUANT_PARAM *qparam) {
367*77c1e3ccSAndroid Build Coastguard Worker qparam->log_scale = av1_get_tx_scale(tx_size);
368*77c1e3ccSAndroid Build Coastguard Worker qparam->tx_size = tx_size;
369*77c1e3ccSAndroid Build Coastguard Worker
370*77c1e3ccSAndroid Build Coastguard Worker qparam->use_quant_b_adapt = use_quant_b_adapt;
371*77c1e3ccSAndroid Build Coastguard Worker
372*77c1e3ccSAndroid Build Coastguard Worker // TODO(bohanli): optimize_b and quantization idx has relationship,
373*77c1e3ccSAndroid Build Coastguard Worker // but is kind of buried and complicated in different encoding stages.
374*77c1e3ccSAndroid Build Coastguard Worker // Should have a unified function to derive quant_idx, rather than
375*77c1e3ccSAndroid Build Coastguard Worker // determine and pass in the quant_idx
376*77c1e3ccSAndroid Build Coastguard Worker qparam->use_optimize_b = use_optimize_b;
377*77c1e3ccSAndroid Build Coastguard Worker qparam->xform_quant_idx = xform_quant_idx;
378*77c1e3ccSAndroid Build Coastguard Worker
379*77c1e3ccSAndroid Build Coastguard Worker qparam->qmatrix = NULL;
380*77c1e3ccSAndroid Build Coastguard Worker qparam->iqmatrix = NULL;
381*77c1e3ccSAndroid Build Coastguard Worker }
av1_setup_qmatrix(const CommonQuantParams * quant_params,const MACROBLOCKD * xd,int plane,TX_SIZE tx_size,TX_TYPE tx_type,QUANT_PARAM * qparam)382*77c1e3ccSAndroid Build Coastguard Worker void av1_setup_qmatrix(const CommonQuantParams *quant_params,
383*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *xd, int plane, TX_SIZE tx_size,
384*77c1e3ccSAndroid Build Coastguard Worker TX_TYPE tx_type, QUANT_PARAM *qparam) {
385*77c1e3ccSAndroid Build Coastguard Worker qparam->qmatrix = av1_get_qmatrix(quant_params, xd, plane, tx_size, tx_type);
386*77c1e3ccSAndroid Build Coastguard Worker qparam->iqmatrix =
387*77c1e3ccSAndroid Build Coastguard Worker av1_get_iqmatrix(quant_params, xd, plane, tx_size, tx_type);
388*77c1e3ccSAndroid Build Coastguard Worker }
389*77c1e3ccSAndroid Build Coastguard Worker
encode_block(int plane,int block,int blk_row,int blk_col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg,RUN_TYPE dry_run)390*77c1e3ccSAndroid Build Coastguard Worker static void encode_block(int plane, int block, int blk_row, int blk_col,
391*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE plane_bsize, TX_SIZE tx_size, void *arg,
392*77c1e3ccSAndroid Build Coastguard Worker RUN_TYPE dry_run) {
393*77c1e3ccSAndroid Build Coastguard Worker (void)dry_run;
394*77c1e3ccSAndroid Build Coastguard Worker struct encode_b_args *const args = arg;
395*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *const cpi = args->cpi;
396*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
397*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x = args->x;
398*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
399*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
400*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *const p = &x->plane[plane];
401*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *const pd = &xd->plane[plane];
402*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
403*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst;
404*77c1e3ccSAndroid Build Coastguard Worker ENTROPY_CONTEXT *a, *l;
405*77c1e3ccSAndroid Build Coastguard Worker int dummy_rate_cost = 0;
406*77c1e3ccSAndroid Build Coastguard Worker
407*77c1e3ccSAndroid Build Coastguard Worker const int bw = mi_size_wide[plane_bsize];
408*77c1e3ccSAndroid Build Coastguard Worker dst = &pd->dst.buf[(blk_row * pd->dst.stride + blk_col) << MI_SIZE_LOG2];
409*77c1e3ccSAndroid Build Coastguard Worker
410*77c1e3ccSAndroid Build Coastguard Worker a = &args->ta[blk_col];
411*77c1e3ccSAndroid Build Coastguard Worker l = &args->tl[blk_row];
412*77c1e3ccSAndroid Build Coastguard Worker
413*77c1e3ccSAndroid Build Coastguard Worker TX_TYPE tx_type = DCT_DCT;
414*77c1e3ccSAndroid Build Coastguard Worker const int blk_skip_idx = blk_row * bw + blk_col;
415*77c1e3ccSAndroid Build Coastguard Worker if (!is_blk_skip(x->txfm_search_info.blk_skip, plane, blk_skip_idx) &&
416*77c1e3ccSAndroid Build Coastguard Worker !mbmi->skip_mode) {
417*77c1e3ccSAndroid Build Coastguard Worker tx_type = av1_get_tx_type(xd, pd->plane_type, blk_row, blk_col, tx_size,
418*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
419*77c1e3ccSAndroid Build Coastguard Worker TxfmParam txfm_param;
420*77c1e3ccSAndroid Build Coastguard Worker QUANT_PARAM quant_param;
421*77c1e3ccSAndroid Build Coastguard Worker const int use_trellis = is_trellis_used(args->enable_optimize_b, dry_run);
422*77c1e3ccSAndroid Build Coastguard Worker int quant_idx;
423*77c1e3ccSAndroid Build Coastguard Worker if (use_trellis)
424*77c1e3ccSAndroid Build Coastguard Worker quant_idx = AV1_XFORM_QUANT_FP;
425*77c1e3ccSAndroid Build Coastguard Worker else
426*77c1e3ccSAndroid Build Coastguard Worker quant_idx =
427*77c1e3ccSAndroid Build Coastguard Worker USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
428*77c1e3ccSAndroid Build Coastguard Worker av1_setup_xform(cm, x, tx_size, tx_type, &txfm_param);
429*77c1e3ccSAndroid Build Coastguard Worker av1_setup_quant(tx_size, use_trellis, quant_idx,
430*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.q_cfg.quant_b_adapt, &quant_param);
431*77c1e3ccSAndroid Build Coastguard Worker av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, tx_type,
432*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
433*77c1e3ccSAndroid Build Coastguard Worker av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
434*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
435*77c1e3ccSAndroid Build Coastguard Worker
436*77c1e3ccSAndroid Build Coastguard Worker // Whether trellis or dropout optimization is required for inter frames.
437*77c1e3ccSAndroid Build Coastguard Worker const bool do_trellis = INTER_BLOCK_OPT_TYPE == TRELLIS_OPT ||
438*77c1e3ccSAndroid Build Coastguard Worker INTER_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT;
439*77c1e3ccSAndroid Build Coastguard Worker const bool do_dropout = INTER_BLOCK_OPT_TYPE == DROPOUT_OPT ||
440*77c1e3ccSAndroid Build Coastguard Worker INTER_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT;
441*77c1e3ccSAndroid Build Coastguard Worker
442*77c1e3ccSAndroid Build Coastguard Worker if (quant_param.use_optimize_b && do_trellis) {
443*77c1e3ccSAndroid Build Coastguard Worker TXB_CTX txb_ctx;
444*77c1e3ccSAndroid Build Coastguard Worker get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
445*77c1e3ccSAndroid Build Coastguard Worker av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, &txb_ctx,
446*77c1e3ccSAndroid Build Coastguard Worker &dummy_rate_cost);
447*77c1e3ccSAndroid Build Coastguard Worker }
448*77c1e3ccSAndroid Build Coastguard Worker if (!quant_param.use_optimize_b && do_dropout) {
449*77c1e3ccSAndroid Build Coastguard Worker av1_dropout_qcoeff(x, plane, block, tx_size, tx_type,
450*77c1e3ccSAndroid Build Coastguard Worker cm->quant_params.base_qindex);
451*77c1e3ccSAndroid Build Coastguard Worker }
452*77c1e3ccSAndroid Build Coastguard Worker } else {
453*77c1e3ccSAndroid Build Coastguard Worker p->eobs[block] = 0;
454*77c1e3ccSAndroid Build Coastguard Worker p->txb_entropy_ctx[block] = 0;
455*77c1e3ccSAndroid Build Coastguard Worker }
456*77c1e3ccSAndroid Build Coastguard Worker
457*77c1e3ccSAndroid Build Coastguard Worker av1_set_txb_context(x, plane, block, tx_size, a, l);
458*77c1e3ccSAndroid Build Coastguard Worker
459*77c1e3ccSAndroid Build Coastguard Worker if (p->eobs[block]) {
460*77c1e3ccSAndroid Build Coastguard Worker // As long as any YUV plane has non-zero quantized transform coefficients,
461*77c1e3ccSAndroid Build Coastguard Worker // mbmi->skip_txfm flag is set to 0.
462*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_txfm = 0;
463*77c1e3ccSAndroid Build Coastguard Worker av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, dst,
464*77c1e3ccSAndroid Build Coastguard Worker pd->dst.stride, p->eobs[block],
465*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
466*77c1e3ccSAndroid Build Coastguard Worker } else {
467*77c1e3ccSAndroid Build Coastguard Worker // Only when YUV planes all have zero quantized transform coefficients,
468*77c1e3ccSAndroid Build Coastguard Worker // mbmi->skip_txfm flag is set to 1.
469*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_txfm &= 1;
470*77c1e3ccSAndroid Build Coastguard Worker }
471*77c1e3ccSAndroid Build Coastguard Worker
472*77c1e3ccSAndroid Build Coastguard Worker // TODO(debargha, jingning): Temporarily disable txk_type check for eob=0
473*77c1e3ccSAndroid Build Coastguard Worker // case. It is possible that certain collision in hash index would cause
474*77c1e3ccSAndroid Build Coastguard Worker // the assertion failure. To further optimize the rate-distortion
475*77c1e3ccSAndroid Build Coastguard Worker // performance, we need to re-visit this part and enable this assert
476*77c1e3ccSAndroid Build Coastguard Worker // again.
477*77c1e3ccSAndroid Build Coastguard Worker if (p->eobs[block] == 0 && plane == 0) {
478*77c1e3ccSAndroid Build Coastguard Worker #if 0
479*77c1e3ccSAndroid Build Coastguard Worker if (args->cpi->oxcf.q_cfg.aq_mode == NO_AQ &&
480*77c1e3ccSAndroid Build Coastguard Worker args->cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q) {
481*77c1e3ccSAndroid Build Coastguard Worker // TODO(jingning,angiebird,[email protected]): enable txk_check when
482*77c1e3ccSAndroid Build Coastguard Worker // enable_optimize_b is true to detect potential RD bug.
483*77c1e3ccSAndroid Build Coastguard Worker const uint8_t disable_txk_check = args->enable_optimize_b;
484*77c1e3ccSAndroid Build Coastguard Worker if (!disable_txk_check) {
485*77c1e3ccSAndroid Build Coastguard Worker assert(xd->tx_type_map[blk_row * xd->tx_type_map_stride + blk_col)] ==
486*77c1e3ccSAndroid Build Coastguard Worker DCT_DCT);
487*77c1e3ccSAndroid Build Coastguard Worker }
488*77c1e3ccSAndroid Build Coastguard Worker }
489*77c1e3ccSAndroid Build Coastguard Worker #endif
490*77c1e3ccSAndroid Build Coastguard Worker update_txk_array(xd, blk_row, blk_col, tx_size, DCT_DCT);
491*77c1e3ccSAndroid Build Coastguard Worker }
492*77c1e3ccSAndroid Build Coastguard Worker
493*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_MISMATCH_DEBUG
494*77c1e3ccSAndroid Build Coastguard Worker if (dry_run == OUTPUT_ENABLED) {
495*77c1e3ccSAndroid Build Coastguard Worker int pixel_c, pixel_r;
496*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
497*77c1e3ccSAndroid Build Coastguard Worker int blk_w = block_size_wide[bsize];
498*77c1e3ccSAndroid Build Coastguard Worker int blk_h = block_size_high[bsize];
499*77c1e3ccSAndroid Build Coastguard Worker mi_to_pixel_loc(&pixel_c, &pixel_r, xd->mi_col, xd->mi_row, blk_col,
500*77c1e3ccSAndroid Build Coastguard Worker blk_row, pd->subsampling_x, pd->subsampling_y);
501*77c1e3ccSAndroid Build Coastguard Worker mismatch_record_block_tx(dst, pd->dst.stride, cm->current_frame.order_hint,
502*77c1e3ccSAndroid Build Coastguard Worker plane, pixel_c, pixel_r, blk_w, blk_h,
503*77c1e3ccSAndroid Build Coastguard Worker xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH);
504*77c1e3ccSAndroid Build Coastguard Worker }
505*77c1e3ccSAndroid Build Coastguard Worker #endif
506*77c1e3ccSAndroid Build Coastguard Worker }
507*77c1e3ccSAndroid Build Coastguard Worker
encode_block_inter(int plane,int block,int blk_row,int blk_col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg,RUN_TYPE dry_run)508*77c1e3ccSAndroid Build Coastguard Worker static void encode_block_inter(int plane, int block, int blk_row, int blk_col,
509*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
510*77c1e3ccSAndroid Build Coastguard Worker void *arg, RUN_TYPE dry_run) {
511*77c1e3ccSAndroid Build Coastguard Worker struct encode_b_args *const args = arg;
512*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x = args->x;
513*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
514*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
515*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
516*77c1e3ccSAndroid Build Coastguard Worker const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
517*77c1e3ccSAndroid Build Coastguard Worker const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
518*77c1e3ccSAndroid Build Coastguard Worker
519*77c1e3ccSAndroid Build Coastguard Worker if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
520*77c1e3ccSAndroid Build Coastguard Worker
521*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE plane_tx_size =
522*77c1e3ccSAndroid Build Coastguard Worker plane ? av1_get_max_uv_txsize(mbmi->bsize, pd->subsampling_x,
523*77c1e3ccSAndroid Build Coastguard Worker pd->subsampling_y)
524*77c1e3ccSAndroid Build Coastguard Worker : mbmi->inter_tx_size[av1_get_txb_size_index(plane_bsize, blk_row,
525*77c1e3ccSAndroid Build Coastguard Worker blk_col)];
526*77c1e3ccSAndroid Build Coastguard Worker if (!plane) {
527*77c1e3ccSAndroid Build Coastguard Worker assert(tx_size_wide[tx_size] >= tx_size_wide[plane_tx_size] &&
528*77c1e3ccSAndroid Build Coastguard Worker tx_size_high[tx_size] >= tx_size_high[plane_tx_size]);
529*77c1e3ccSAndroid Build Coastguard Worker }
530*77c1e3ccSAndroid Build Coastguard Worker
531*77c1e3ccSAndroid Build Coastguard Worker if (tx_size == plane_tx_size || plane) {
532*77c1e3ccSAndroid Build Coastguard Worker encode_block(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg,
533*77c1e3ccSAndroid Build Coastguard Worker dry_run);
534*77c1e3ccSAndroid Build Coastguard Worker } else {
535*77c1e3ccSAndroid Build Coastguard Worker assert(tx_size < TX_SIZES_ALL);
536*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
537*77c1e3ccSAndroid Build Coastguard Worker assert(IMPLIES(tx_size <= TX_4X4, sub_txs == tx_size));
538*77c1e3ccSAndroid Build Coastguard Worker assert(IMPLIES(tx_size > TX_4X4, sub_txs < tx_size));
539*77c1e3ccSAndroid Build Coastguard Worker // This is the square transform block partition entry point.
540*77c1e3ccSAndroid Build Coastguard Worker const int bsw = tx_size_wide_unit[sub_txs];
541*77c1e3ccSAndroid Build Coastguard Worker const int bsh = tx_size_high_unit[sub_txs];
542*77c1e3ccSAndroid Build Coastguard Worker const int step = bsh * bsw;
543*77c1e3ccSAndroid Build Coastguard Worker const int row_end =
544*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(tx_size_high_unit[tx_size], max_blocks_high - blk_row);
545*77c1e3ccSAndroid Build Coastguard Worker const int col_end =
546*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(tx_size_wide_unit[tx_size], max_blocks_wide - blk_col);
547*77c1e3ccSAndroid Build Coastguard Worker assert(bsw > 0 && bsh > 0);
548*77c1e3ccSAndroid Build Coastguard Worker
549*77c1e3ccSAndroid Build Coastguard Worker for (int row = 0; row < row_end; row += bsh) {
550*77c1e3ccSAndroid Build Coastguard Worker const int offsetr = blk_row + row;
551*77c1e3ccSAndroid Build Coastguard Worker for (int col = 0; col < col_end; col += bsw) {
552*77c1e3ccSAndroid Build Coastguard Worker const int offsetc = blk_col + col;
553*77c1e3ccSAndroid Build Coastguard Worker
554*77c1e3ccSAndroid Build Coastguard Worker encode_block_inter(plane, block, offsetr, offsetc, plane_bsize, sub_txs,
555*77c1e3ccSAndroid Build Coastguard Worker arg, dry_run);
556*77c1e3ccSAndroid Build Coastguard Worker block += step;
557*77c1e3ccSAndroid Build Coastguard Worker }
558*77c1e3ccSAndroid Build Coastguard Worker }
559*77c1e3ccSAndroid Build Coastguard Worker }
560*77c1e3ccSAndroid Build Coastguard Worker }
561*77c1e3ccSAndroid Build Coastguard Worker
av1_foreach_transformed_block_in_plane(const MACROBLOCKD * const xd,BLOCK_SIZE plane_bsize,int plane,foreach_transformed_block_visitor visit,void * arg)562*77c1e3ccSAndroid Build Coastguard Worker void av1_foreach_transformed_block_in_plane(
563*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd, BLOCK_SIZE plane_bsize, int plane,
564*77c1e3ccSAndroid Build Coastguard Worker foreach_transformed_block_visitor visit, void *arg) {
565*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
566*77c1e3ccSAndroid Build Coastguard Worker // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
567*77c1e3ccSAndroid Build Coastguard Worker // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
568*77c1e3ccSAndroid Build Coastguard Worker // transform size varies per plane, look it up in a common way.
569*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
570*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE tx_bsize = txsize_to_bsize[tx_size];
571*77c1e3ccSAndroid Build Coastguard Worker // Call visit() directly with zero offsets if the current block size is the
572*77c1e3ccSAndroid Build Coastguard Worker // same as the transform block size.
573*77c1e3ccSAndroid Build Coastguard Worker if (plane_bsize == tx_bsize) {
574*77c1e3ccSAndroid Build Coastguard Worker visit(plane, 0, 0, 0, plane_bsize, tx_size, arg);
575*77c1e3ccSAndroid Build Coastguard Worker return;
576*77c1e3ccSAndroid Build Coastguard Worker }
577*77c1e3ccSAndroid Build Coastguard Worker const uint8_t txw_unit = tx_size_wide_unit[tx_size];
578*77c1e3ccSAndroid Build Coastguard Worker const uint8_t txh_unit = tx_size_high_unit[tx_size];
579*77c1e3ccSAndroid Build Coastguard Worker const int step = txw_unit * txh_unit;
580*77c1e3ccSAndroid Build Coastguard Worker
581*77c1e3ccSAndroid Build Coastguard Worker // If mb_to_right_edge is < 0 we are in a situation in which
582*77c1e3ccSAndroid Build Coastguard Worker // the current block size extends into the UMV and we won't
583*77c1e3ccSAndroid Build Coastguard Worker // visit the sub blocks that are wholly within the UMV.
584*77c1e3ccSAndroid Build Coastguard Worker const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
585*77c1e3ccSAndroid Build Coastguard Worker const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
586*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE max_unit_bsize =
587*77c1e3ccSAndroid Build Coastguard Worker get_plane_block_size(BLOCK_64X64, pd->subsampling_x, pd->subsampling_y);
588*77c1e3ccSAndroid Build Coastguard Worker const int mu_blocks_wide =
589*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mi_size_wide[max_unit_bsize], max_blocks_wide);
590*77c1e3ccSAndroid Build Coastguard Worker const int mu_blocks_high =
591*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mi_size_high[max_unit_bsize], max_blocks_high);
592*77c1e3ccSAndroid Build Coastguard Worker
593*77c1e3ccSAndroid Build Coastguard Worker // Keep track of the row and column of the blocks we use so that we know
594*77c1e3ccSAndroid Build Coastguard Worker // if we are in the unrestricted motion border.
595*77c1e3ccSAndroid Build Coastguard Worker int i = 0;
596*77c1e3ccSAndroid Build Coastguard Worker for (int r = 0; r < max_blocks_high; r += mu_blocks_high) {
597*77c1e3ccSAndroid Build Coastguard Worker const int unit_height = AOMMIN(mu_blocks_high + r, max_blocks_high);
598*77c1e3ccSAndroid Build Coastguard Worker // Skip visiting the sub blocks that are wholly within the UMV.
599*77c1e3ccSAndroid Build Coastguard Worker for (int c = 0; c < max_blocks_wide; c += mu_blocks_wide) {
600*77c1e3ccSAndroid Build Coastguard Worker const int unit_width = AOMMIN(mu_blocks_wide + c, max_blocks_wide);
601*77c1e3ccSAndroid Build Coastguard Worker for (int blk_row = r; blk_row < unit_height; blk_row += txh_unit) {
602*77c1e3ccSAndroid Build Coastguard Worker for (int blk_col = c; blk_col < unit_width; blk_col += txw_unit) {
603*77c1e3ccSAndroid Build Coastguard Worker visit(plane, i, blk_row, blk_col, plane_bsize, tx_size, arg);
604*77c1e3ccSAndroid Build Coastguard Worker i += step;
605*77c1e3ccSAndroid Build Coastguard Worker }
606*77c1e3ccSAndroid Build Coastguard Worker }
607*77c1e3ccSAndroid Build Coastguard Worker }
608*77c1e3ccSAndroid Build Coastguard Worker }
609*77c1e3ccSAndroid Build Coastguard Worker // Check if visit() is invoked at least once.
610*77c1e3ccSAndroid Build Coastguard Worker assert(i >= 1);
611*77c1e3ccSAndroid Build Coastguard Worker }
612*77c1e3ccSAndroid Build Coastguard Worker
613*77c1e3ccSAndroid Build Coastguard Worker typedef struct encode_block_pass1_args {
614*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi;
615*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x;
616*77c1e3ccSAndroid Build Coastguard Worker } encode_block_pass1_args;
617*77c1e3ccSAndroid Build Coastguard Worker
encode_block_pass1(int plane,int block,int blk_row,int blk_col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg)618*77c1e3ccSAndroid Build Coastguard Worker static void encode_block_pass1(int plane, int block, int blk_row, int blk_col,
619*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
620*77c1e3ccSAndroid Build Coastguard Worker void *arg) {
621*77c1e3ccSAndroid Build Coastguard Worker encode_block_pass1_args *args = (encode_block_pass1_args *)arg;
622*77c1e3ccSAndroid Build Coastguard Worker AV1_COMP *cpi = args->cpi;
623*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *cm = &cpi->common;
624*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x = args->x;
625*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
626*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *const p = &x->plane[plane];
627*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *const pd = &xd->plane[plane];
628*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *const dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
629*77c1e3ccSAndroid Build Coastguard Worker
630*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst;
631*77c1e3ccSAndroid Build Coastguard Worker dst = &pd->dst.buf[(blk_row * pd->dst.stride + blk_col) << MI_SIZE_LOG2];
632*77c1e3ccSAndroid Build Coastguard Worker
633*77c1e3ccSAndroid Build Coastguard Worker TxfmParam txfm_param;
634*77c1e3ccSAndroid Build Coastguard Worker QUANT_PARAM quant_param;
635*77c1e3ccSAndroid Build Coastguard Worker
636*77c1e3ccSAndroid Build Coastguard Worker av1_setup_xform(cm, x, tx_size, DCT_DCT, &txfm_param);
637*77c1e3ccSAndroid Build Coastguard Worker av1_setup_quant(tx_size, 0, AV1_XFORM_QUANT_B, cpi->oxcf.q_cfg.quant_b_adapt,
638*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
639*77c1e3ccSAndroid Build Coastguard Worker av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, DCT_DCT,
640*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
641*77c1e3ccSAndroid Build Coastguard Worker
642*77c1e3ccSAndroid Build Coastguard Worker av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
643*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
644*77c1e3ccSAndroid Build Coastguard Worker
645*77c1e3ccSAndroid Build Coastguard Worker if (p->eobs[block] > 0) {
646*77c1e3ccSAndroid Build Coastguard Worker txfm_param.eob = p->eobs[block];
647*77c1e3ccSAndroid Build Coastguard Worker if (txfm_param.is_hbd) {
648*77c1e3ccSAndroid Build Coastguard Worker av1_highbd_inv_txfm_add(dqcoeff, dst, pd->dst.stride, &txfm_param);
649*77c1e3ccSAndroid Build Coastguard Worker return;
650*77c1e3ccSAndroid Build Coastguard Worker }
651*77c1e3ccSAndroid Build Coastguard Worker av1_inv_txfm_add(dqcoeff, dst, pd->dst.stride, &txfm_param);
652*77c1e3ccSAndroid Build Coastguard Worker }
653*77c1e3ccSAndroid Build Coastguard Worker }
654*77c1e3ccSAndroid Build Coastguard Worker
av1_encode_sby_pass1(AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize)655*77c1e3ccSAndroid Build Coastguard Worker void av1_encode_sby_pass1(AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize) {
656*77c1e3ccSAndroid Build Coastguard Worker encode_block_pass1_args args = { cpi, x };
657*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_plane(x, bsize, 0);
658*77c1e3ccSAndroid Build Coastguard Worker av1_foreach_transformed_block_in_plane(&x->e_mbd, bsize, 0,
659*77c1e3ccSAndroid Build Coastguard Worker encode_block_pass1, &args);
660*77c1e3ccSAndroid Build Coastguard Worker }
661*77c1e3ccSAndroid Build Coastguard Worker
av1_encode_sb(const struct AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,RUN_TYPE dry_run)662*77c1e3ccSAndroid Build Coastguard Worker void av1_encode_sb(const struct AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize,
663*77c1e3ccSAndroid Build Coastguard Worker RUN_TYPE dry_run) {
664*77c1e3ccSAndroid Build Coastguard Worker assert(bsize < BLOCK_SIZES_ALL);
665*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
666*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
667*77c1e3ccSAndroid Build Coastguard Worker // In the current encoder implementation, for inter blocks,
668*77c1e3ccSAndroid Build Coastguard Worker // only when YUV planes all have zero quantized transform coefficients,
669*77c1e3ccSAndroid Build Coastguard Worker // mbmi->skip_txfm flag is set to 1.
670*77c1e3ccSAndroid Build Coastguard Worker // For intra blocks, this flag is set to 0 since skipped blocks are so rare
671*77c1e3ccSAndroid Build Coastguard Worker // that transmitting skip_txfm = 1 is very expensive.
672*77c1e3ccSAndroid Build Coastguard Worker // mbmi->skip_txfm is init to 1, and will be modified in encode_block() based
673*77c1e3ccSAndroid Build Coastguard Worker // on transform, quantization, and (if exists) trellis optimization.
674*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_txfm = 1;
675*77c1e3ccSAndroid Build Coastguard Worker if (x->txfm_search_info.skip_txfm) return;
676*77c1e3ccSAndroid Build Coastguard Worker
677*77c1e3ccSAndroid Build Coastguard Worker struct optimize_ctx ctx;
678*77c1e3ccSAndroid Build Coastguard Worker struct encode_b_args arg = {
679*77c1e3ccSAndroid Build Coastguard Worker cpi, x, &ctx, NULL, NULL, dry_run, cpi->optimize_seg_arr[mbmi->segment_id]
680*77c1e3ccSAndroid Build Coastguard Worker };
681*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
682*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
683*77c1e3ccSAndroid Build Coastguard Worker for (int plane = 0; plane < num_planes; ++plane) {
684*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
685*77c1e3ccSAndroid Build Coastguard Worker const int subsampling_x = pd->subsampling_x;
686*77c1e3ccSAndroid Build Coastguard Worker const int subsampling_y = pd->subsampling_y;
687*77c1e3ccSAndroid Build Coastguard Worker if (plane && !xd->is_chroma_ref) break;
688*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE plane_bsize =
689*77c1e3ccSAndroid Build Coastguard Worker get_plane_block_size(bsize, subsampling_x, subsampling_y);
690*77c1e3ccSAndroid Build Coastguard Worker assert(plane_bsize < BLOCK_SIZES_ALL);
691*77c1e3ccSAndroid Build Coastguard Worker const int mi_width = mi_size_wide[plane_bsize];
692*77c1e3ccSAndroid Build Coastguard Worker const int mi_height = mi_size_high[plane_bsize];
693*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE max_tx_size = get_vartx_max_txsize(xd, plane_bsize, plane);
694*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE txb_size = txsize_to_bsize[max_tx_size];
695*77c1e3ccSAndroid Build Coastguard Worker const int bw = mi_size_wide[txb_size];
696*77c1e3ccSAndroid Build Coastguard Worker const int bh = mi_size_high[txb_size];
697*77c1e3ccSAndroid Build Coastguard Worker int block = 0;
698*77c1e3ccSAndroid Build Coastguard Worker const int step =
699*77c1e3ccSAndroid Build Coastguard Worker tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
700*77c1e3ccSAndroid Build Coastguard Worker av1_get_entropy_contexts(plane_bsize, pd, ctx.ta[plane], ctx.tl[plane]);
701*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_plane(x, plane_bsize, plane);
702*77c1e3ccSAndroid Build Coastguard Worker arg.ta = ctx.ta[plane];
703*77c1e3ccSAndroid Build Coastguard Worker arg.tl = ctx.tl[plane];
704*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE max_unit_bsize =
705*77c1e3ccSAndroid Build Coastguard Worker get_plane_block_size(BLOCK_64X64, subsampling_x, subsampling_y);
706*77c1e3ccSAndroid Build Coastguard Worker int mu_blocks_wide = mi_size_wide[max_unit_bsize];
707*77c1e3ccSAndroid Build Coastguard Worker int mu_blocks_high = mi_size_high[max_unit_bsize];
708*77c1e3ccSAndroid Build Coastguard Worker mu_blocks_wide = AOMMIN(mi_width, mu_blocks_wide);
709*77c1e3ccSAndroid Build Coastguard Worker mu_blocks_high = AOMMIN(mi_height, mu_blocks_high);
710*77c1e3ccSAndroid Build Coastguard Worker
711*77c1e3ccSAndroid Build Coastguard Worker for (int idy = 0; idy < mi_height; idy += mu_blocks_high) {
712*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < mi_width; idx += mu_blocks_wide) {
713*77c1e3ccSAndroid Build Coastguard Worker int blk_row, blk_col;
714*77c1e3ccSAndroid Build Coastguard Worker const int unit_height = AOMMIN(mu_blocks_high + idy, mi_height);
715*77c1e3ccSAndroid Build Coastguard Worker const int unit_width = AOMMIN(mu_blocks_wide + idx, mi_width);
716*77c1e3ccSAndroid Build Coastguard Worker for (blk_row = idy; blk_row < unit_height; blk_row += bh) {
717*77c1e3ccSAndroid Build Coastguard Worker for (blk_col = idx; blk_col < unit_width; blk_col += bw) {
718*77c1e3ccSAndroid Build Coastguard Worker encode_block_inter(plane, block, blk_row, blk_col, plane_bsize,
719*77c1e3ccSAndroid Build Coastguard Worker max_tx_size, &arg, dry_run);
720*77c1e3ccSAndroid Build Coastguard Worker block += step;
721*77c1e3ccSAndroid Build Coastguard Worker }
722*77c1e3ccSAndroid Build Coastguard Worker }
723*77c1e3ccSAndroid Build Coastguard Worker }
724*77c1e3ccSAndroid Build Coastguard Worker }
725*77c1e3ccSAndroid Build Coastguard Worker }
726*77c1e3ccSAndroid Build Coastguard Worker }
727*77c1e3ccSAndroid Build Coastguard Worker
encode_block_intra(int plane,int block,int blk_row,int blk_col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg)728*77c1e3ccSAndroid Build Coastguard Worker static void encode_block_intra(int plane, int block, int blk_row, int blk_col,
729*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
730*77c1e3ccSAndroid Build Coastguard Worker void *arg) {
731*77c1e3ccSAndroid Build Coastguard Worker struct encode_b_args *const args = arg;
732*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *const cpi = args->cpi;
733*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
734*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x = args->x;
735*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
736*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
737*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *const p = &x->plane[plane];
738*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *const pd = &xd->plane[plane];
739*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *dqcoeff = p->dqcoeff + BLOCK_OFFSET(block);
740*77c1e3ccSAndroid Build Coastguard Worker PLANE_TYPE plane_type = get_plane_type(plane);
741*77c1e3ccSAndroid Build Coastguard Worker uint16_t *eob = &p->eobs[block];
742*77c1e3ccSAndroid Build Coastguard Worker const int dst_stride = pd->dst.stride;
743*77c1e3ccSAndroid Build Coastguard Worker uint8_t *dst = &pd->dst.buf[(blk_row * dst_stride + blk_col) << MI_SIZE_LOG2];
744*77c1e3ccSAndroid Build Coastguard Worker int dummy_rate_cost = 0;
745*77c1e3ccSAndroid Build Coastguard Worker
746*77c1e3ccSAndroid Build Coastguard Worker av1_predict_intra_block_facade(cm, xd, plane, blk_col, blk_row, tx_size);
747*77c1e3ccSAndroid Build Coastguard Worker
748*77c1e3ccSAndroid Build Coastguard Worker TX_TYPE tx_type = DCT_DCT;
749*77c1e3ccSAndroid Build Coastguard Worker const int bw = mi_size_wide[plane_bsize];
750*77c1e3ccSAndroid Build Coastguard Worker if (plane == 0 && is_blk_skip(x->txfm_search_info.blk_skip, plane,
751*77c1e3ccSAndroid Build Coastguard Worker blk_row * bw + blk_col)) {
752*77c1e3ccSAndroid Build Coastguard Worker *eob = 0;
753*77c1e3ccSAndroid Build Coastguard Worker p->txb_entropy_ctx[block] = 0;
754*77c1e3ccSAndroid Build Coastguard Worker } else {
755*77c1e3ccSAndroid Build Coastguard Worker av1_subtract_txb(x, plane, plane_bsize, blk_col, blk_row, tx_size);
756*77c1e3ccSAndroid Build Coastguard Worker
757*77c1e3ccSAndroid Build Coastguard Worker const ENTROPY_CONTEXT *a = &args->ta[blk_col];
758*77c1e3ccSAndroid Build Coastguard Worker const ENTROPY_CONTEXT *l = &args->tl[blk_row];
759*77c1e3ccSAndroid Build Coastguard Worker tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
760*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
761*77c1e3ccSAndroid Build Coastguard Worker TxfmParam txfm_param;
762*77c1e3ccSAndroid Build Coastguard Worker QUANT_PARAM quant_param;
763*77c1e3ccSAndroid Build Coastguard Worker const int use_trellis =
764*77c1e3ccSAndroid Build Coastguard Worker is_trellis_used(args->enable_optimize_b, args->dry_run);
765*77c1e3ccSAndroid Build Coastguard Worker int quant_idx;
766*77c1e3ccSAndroid Build Coastguard Worker if (use_trellis)
767*77c1e3ccSAndroid Build Coastguard Worker quant_idx = AV1_XFORM_QUANT_FP;
768*77c1e3ccSAndroid Build Coastguard Worker else
769*77c1e3ccSAndroid Build Coastguard Worker quant_idx =
770*77c1e3ccSAndroid Build Coastguard Worker USE_B_QUANT_NO_TRELLIS ? AV1_XFORM_QUANT_B : AV1_XFORM_QUANT_FP;
771*77c1e3ccSAndroid Build Coastguard Worker
772*77c1e3ccSAndroid Build Coastguard Worker av1_setup_xform(cm, x, tx_size, tx_type, &txfm_param);
773*77c1e3ccSAndroid Build Coastguard Worker av1_setup_quant(tx_size, use_trellis, quant_idx,
774*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.q_cfg.quant_b_adapt, &quant_param);
775*77c1e3ccSAndroid Build Coastguard Worker av1_setup_qmatrix(&cm->quant_params, xd, plane, tx_size, tx_type,
776*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
777*77c1e3ccSAndroid Build Coastguard Worker
778*77c1e3ccSAndroid Build Coastguard Worker av1_xform_quant(x, plane, block, blk_row, blk_col, plane_bsize, &txfm_param,
779*77c1e3ccSAndroid Build Coastguard Worker &quant_param);
780*77c1e3ccSAndroid Build Coastguard Worker
781*77c1e3ccSAndroid Build Coastguard Worker // Whether trellis or dropout optimization is required for key frames and
782*77c1e3ccSAndroid Build Coastguard Worker // intra frames.
783*77c1e3ccSAndroid Build Coastguard Worker const bool do_trellis = (frame_is_intra_only(cm) &&
784*77c1e3ccSAndroid Build Coastguard Worker (KEY_BLOCK_OPT_TYPE == TRELLIS_OPT ||
785*77c1e3ccSAndroid Build Coastguard Worker KEY_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT)) ||
786*77c1e3ccSAndroid Build Coastguard Worker (!frame_is_intra_only(cm) &&
787*77c1e3ccSAndroid Build Coastguard Worker (INTRA_BLOCK_OPT_TYPE == TRELLIS_OPT ||
788*77c1e3ccSAndroid Build Coastguard Worker INTRA_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT));
789*77c1e3ccSAndroid Build Coastguard Worker const bool do_dropout = (frame_is_intra_only(cm) &&
790*77c1e3ccSAndroid Build Coastguard Worker (KEY_BLOCK_OPT_TYPE == DROPOUT_OPT ||
791*77c1e3ccSAndroid Build Coastguard Worker KEY_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT)) ||
792*77c1e3ccSAndroid Build Coastguard Worker (!frame_is_intra_only(cm) &&
793*77c1e3ccSAndroid Build Coastguard Worker (INTRA_BLOCK_OPT_TYPE == DROPOUT_OPT ||
794*77c1e3ccSAndroid Build Coastguard Worker INTRA_BLOCK_OPT_TYPE == TRELLIS_DROPOUT_OPT));
795*77c1e3ccSAndroid Build Coastguard Worker
796*77c1e3ccSAndroid Build Coastguard Worker if (quant_param.use_optimize_b && do_trellis) {
797*77c1e3ccSAndroid Build Coastguard Worker TXB_CTX txb_ctx;
798*77c1e3ccSAndroid Build Coastguard Worker get_txb_ctx(plane_bsize, tx_size, plane, a, l, &txb_ctx);
799*77c1e3ccSAndroid Build Coastguard Worker av1_optimize_b(args->cpi, x, plane, block, tx_size, tx_type, &txb_ctx,
800*77c1e3ccSAndroid Build Coastguard Worker &dummy_rate_cost);
801*77c1e3ccSAndroid Build Coastguard Worker }
802*77c1e3ccSAndroid Build Coastguard Worker if (do_dropout) {
803*77c1e3ccSAndroid Build Coastguard Worker av1_dropout_qcoeff(x, plane, block, tx_size, tx_type,
804*77c1e3ccSAndroid Build Coastguard Worker cm->quant_params.base_qindex);
805*77c1e3ccSAndroid Build Coastguard Worker }
806*77c1e3ccSAndroid Build Coastguard Worker }
807*77c1e3ccSAndroid Build Coastguard Worker
808*77c1e3ccSAndroid Build Coastguard Worker if (*eob) {
809*77c1e3ccSAndroid Build Coastguard Worker av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, dst,
810*77c1e3ccSAndroid Build Coastguard Worker dst_stride, *eob,
811*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
812*77c1e3ccSAndroid Build Coastguard Worker }
813*77c1e3ccSAndroid Build Coastguard Worker
814*77c1e3ccSAndroid Build Coastguard Worker // TODO(jingning): Temporarily disable txk_type check for eob=0 case.
815*77c1e3ccSAndroid Build Coastguard Worker // It is possible that certain collision in hash index would cause
816*77c1e3ccSAndroid Build Coastguard Worker // the assertion failure. To further optimize the rate-distortion
817*77c1e3ccSAndroid Build Coastguard Worker // performance, we need to re-visit this part and enable this assert
818*77c1e3ccSAndroid Build Coastguard Worker // again.
819*77c1e3ccSAndroid Build Coastguard Worker if (*eob == 0 && plane == 0) {
820*77c1e3ccSAndroid Build Coastguard Worker #if 0
821*77c1e3ccSAndroid Build Coastguard Worker if (args->cpi->oxcf.q_cfg.aq_mode == NO_AQ
822*77c1e3ccSAndroid Build Coastguard Worker && args->cpi->oxcf.q_cfg.deltaq_mode == NO_DELTA_Q) {
823*77c1e3ccSAndroid Build Coastguard Worker assert(xd->tx_type_map[blk_row * xd->tx_type_map_stride + blk_col)] ==
824*77c1e3ccSAndroid Build Coastguard Worker DCT_DCT);
825*77c1e3ccSAndroid Build Coastguard Worker }
826*77c1e3ccSAndroid Build Coastguard Worker #endif
827*77c1e3ccSAndroid Build Coastguard Worker update_txk_array(xd, blk_row, blk_col, tx_size, DCT_DCT);
828*77c1e3ccSAndroid Build Coastguard Worker }
829*77c1e3ccSAndroid Build Coastguard Worker
830*77c1e3ccSAndroid Build Coastguard Worker // For intra mode, skipped blocks are so rare that transmitting
831*77c1e3ccSAndroid Build Coastguard Worker // skip_txfm = 1 is very expensive.
832*77c1e3ccSAndroid Build Coastguard Worker mbmi->skip_txfm = 0;
833*77c1e3ccSAndroid Build Coastguard Worker
834*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_REALTIME_ONLY
835*77c1e3ccSAndroid Build Coastguard Worker if (plane == AOM_PLANE_Y && xd->cfl.store_y) {
836*77c1e3ccSAndroid Build Coastguard Worker cfl_store_tx(xd, blk_row, blk_col, tx_size, plane_bsize);
837*77c1e3ccSAndroid Build Coastguard Worker }
838*77c1e3ccSAndroid Build Coastguard Worker #endif
839*77c1e3ccSAndroid Build Coastguard Worker }
840*77c1e3ccSAndroid Build Coastguard Worker
encode_block_intra_and_set_context(int plane,int block,int blk_row,int blk_col,BLOCK_SIZE plane_bsize,TX_SIZE tx_size,void * arg)841*77c1e3ccSAndroid Build Coastguard Worker static void encode_block_intra_and_set_context(int plane, int block,
842*77c1e3ccSAndroid Build Coastguard Worker int blk_row, int blk_col,
843*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE plane_bsize,
844*77c1e3ccSAndroid Build Coastguard Worker TX_SIZE tx_size, void *arg) {
845*77c1e3ccSAndroid Build Coastguard Worker encode_block_intra(plane, block, blk_row, blk_col, plane_bsize, tx_size, arg);
846*77c1e3ccSAndroid Build Coastguard Worker
847*77c1e3ccSAndroid Build Coastguard Worker struct encode_b_args *const args = arg;
848*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *x = args->x;
849*77c1e3ccSAndroid Build Coastguard Worker ENTROPY_CONTEXT *a = &args->ta[blk_col];
850*77c1e3ccSAndroid Build Coastguard Worker ENTROPY_CONTEXT *l = &args->tl[blk_row];
851*77c1e3ccSAndroid Build Coastguard Worker av1_set_txb_context(x, plane, block, tx_size, a, l);
852*77c1e3ccSAndroid Build Coastguard Worker }
853*77c1e3ccSAndroid Build Coastguard Worker
av1_encode_intra_block_plane(const struct AV1_COMP * cpi,MACROBLOCK * x,BLOCK_SIZE bsize,int plane,RUN_TYPE dry_run,TRELLIS_OPT_TYPE enable_optimize_b)854*77c1e3ccSAndroid Build Coastguard Worker void av1_encode_intra_block_plane(const struct AV1_COMP *cpi, MACROBLOCK *x,
855*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE bsize, int plane, RUN_TYPE dry_run,
856*77c1e3ccSAndroid Build Coastguard Worker TRELLIS_OPT_TYPE enable_optimize_b) {
857*77c1e3ccSAndroid Build Coastguard Worker assert(bsize < BLOCK_SIZES_ALL);
858*77c1e3ccSAndroid Build Coastguard Worker const MACROBLOCKD *const xd = &x->e_mbd;
859*77c1e3ccSAndroid Build Coastguard Worker if (plane && !xd->is_chroma_ref) return;
860*77c1e3ccSAndroid Build Coastguard Worker
861*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
862*77c1e3ccSAndroid Build Coastguard Worker const int ss_x = pd->subsampling_x;
863*77c1e3ccSAndroid Build Coastguard Worker const int ss_y = pd->subsampling_y;
864*77c1e3ccSAndroid Build Coastguard Worker ENTROPY_CONTEXT ta[MAX_MIB_SIZE] = { 0 };
865*77c1e3ccSAndroid Build Coastguard Worker ENTROPY_CONTEXT tl[MAX_MIB_SIZE] = { 0 };
866*77c1e3ccSAndroid Build Coastguard Worker struct encode_b_args arg = {
867*77c1e3ccSAndroid Build Coastguard Worker cpi, x, NULL, ta, tl, dry_run, enable_optimize_b
868*77c1e3ccSAndroid Build Coastguard Worker };
869*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
870*77c1e3ccSAndroid Build Coastguard Worker if (enable_optimize_b) {
871*77c1e3ccSAndroid Build Coastguard Worker av1_get_entropy_contexts(plane_bsize, pd, ta, tl);
872*77c1e3ccSAndroid Build Coastguard Worker }
873*77c1e3ccSAndroid Build Coastguard Worker av1_foreach_transformed_block_in_plane(
874*77c1e3ccSAndroid Build Coastguard Worker xd, plane_bsize, plane, encode_block_intra_and_set_context, &arg);
875*77c1e3ccSAndroid Build Coastguard Worker }
876