1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2017, 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 "av1/encoder/encodetxb.h"
13*77c1e3ccSAndroid Build Coastguard Worker
14*77c1e3ccSAndroid Build Coastguard Worker #include <stdint.h>
15*77c1e3ccSAndroid Build Coastguard Worker
16*77c1e3ccSAndroid Build Coastguard Worker #include "aom_ports/mem.h"
17*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/blockd.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/idct.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/pred_common.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "av1/common/scan.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/bitstream.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/cost.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encodeframe.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/hash.h"
25*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rdopt.h"
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/tokenize.h"
27*77c1e3ccSAndroid Build Coastguard Worker
av1_alloc_txb_buf(AV1_COMP * cpi)28*77c1e3ccSAndroid Build Coastguard Worker void av1_alloc_txb_buf(AV1_COMP *cpi) {
29*77c1e3ccSAndroid Build Coastguard Worker AV1_COMMON *cm = &cpi->common;
30*77c1e3ccSAndroid Build Coastguard Worker CoeffBufferPool *coeff_buf_pool = &cpi->coeff_buffer_pool;
31*77c1e3ccSAndroid Build Coastguard Worker const int num_sb_rows =
32*77c1e3ccSAndroid Build Coastguard Worker CEIL_POWER_OF_TWO(cm->mi_params.mi_rows, cm->seq_params->mib_size_log2);
33*77c1e3ccSAndroid Build Coastguard Worker const int num_sb_cols =
34*77c1e3ccSAndroid Build Coastguard Worker CEIL_POWER_OF_TWO(cm->mi_params.mi_cols, cm->seq_params->mib_size_log2);
35*77c1e3ccSAndroid Build Coastguard Worker const int size = num_sb_rows * num_sb_cols;
36*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
37*77c1e3ccSAndroid Build Coastguard Worker const int subsampling_x = cm->seq_params->subsampling_x;
38*77c1e3ccSAndroid Build Coastguard Worker const int subsampling_y = cm->seq_params->subsampling_y;
39*77c1e3ccSAndroid Build Coastguard Worker const int luma_max_sb_square =
40*77c1e3ccSAndroid Build Coastguard Worker 1 << num_pels_log2_lookup[cm->seq_params->sb_size];
41*77c1e3ccSAndroid Build Coastguard Worker const int chroma_max_sb_square =
42*77c1e3ccSAndroid Build Coastguard Worker luma_max_sb_square >> (subsampling_x + subsampling_y);
43*77c1e3ccSAndroid Build Coastguard Worker const int total_max_sb_square =
44*77c1e3ccSAndroid Build Coastguard Worker (luma_max_sb_square + (num_planes - 1) * chroma_max_sb_square);
45*77c1e3ccSAndroid Build Coastguard Worker if ((size_t)size > SIZE_MAX / (size_t)total_max_sb_square) {
46*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(cm->error, AOM_CODEC_ERROR,
47*77c1e3ccSAndroid Build Coastguard Worker "A multiplication would overflow size_t");
48*77c1e3ccSAndroid Build Coastguard Worker }
49*77c1e3ccSAndroid Build Coastguard Worker const size_t num_tcoeffs = (size_t)size * (size_t)total_max_sb_square;
50*77c1e3ccSAndroid Build Coastguard Worker const int txb_unit_size = TX_SIZE_W_MIN * TX_SIZE_H_MIN;
51*77c1e3ccSAndroid Build Coastguard Worker
52*77c1e3ccSAndroid Build Coastguard Worker av1_free_txb_buf(cpi);
53*77c1e3ccSAndroid Build Coastguard Worker // TODO(jingning): This should be further reduced.
54*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, cpi->coeff_buffer_base,
55*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(sizeof(*cpi->coeff_buffer_base) * size));
56*77c1e3ccSAndroid Build Coastguard Worker if (sizeof(*coeff_buf_pool->tcoeff) > SIZE_MAX / num_tcoeffs) {
57*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(cm->error, AOM_CODEC_ERROR,
58*77c1e3ccSAndroid Build Coastguard Worker "A multiplication would overflow size_t");
59*77c1e3ccSAndroid Build Coastguard Worker }
60*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
61*77c1e3ccSAndroid Build Coastguard Worker cm, coeff_buf_pool->tcoeff,
62*77c1e3ccSAndroid Build Coastguard Worker aom_memalign(32, sizeof(*coeff_buf_pool->tcoeff) * num_tcoeffs));
63*77c1e3ccSAndroid Build Coastguard Worker if (sizeof(*coeff_buf_pool->eobs) > SIZE_MAX / num_tcoeffs) {
64*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(cm->error, AOM_CODEC_ERROR,
65*77c1e3ccSAndroid Build Coastguard Worker "A multiplication would overflow size_t");
66*77c1e3ccSAndroid Build Coastguard Worker }
67*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(
68*77c1e3ccSAndroid Build Coastguard Worker cm, coeff_buf_pool->eobs,
69*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(sizeof(*coeff_buf_pool->eobs) * num_tcoeffs / txb_unit_size));
70*77c1e3ccSAndroid Build Coastguard Worker if (sizeof(*coeff_buf_pool->entropy_ctx) > SIZE_MAX / num_tcoeffs) {
71*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(cm->error, AOM_CODEC_ERROR,
72*77c1e3ccSAndroid Build Coastguard Worker "A multiplication would overflow size_t");
73*77c1e3ccSAndroid Build Coastguard Worker }
74*77c1e3ccSAndroid Build Coastguard Worker CHECK_MEM_ERROR(cm, coeff_buf_pool->entropy_ctx,
75*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(sizeof(*coeff_buf_pool->entropy_ctx) *
76*77c1e3ccSAndroid Build Coastguard Worker num_tcoeffs / txb_unit_size));
77*77c1e3ccSAndroid Build Coastguard Worker
78*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *tcoeff_ptr = coeff_buf_pool->tcoeff;
79*77c1e3ccSAndroid Build Coastguard Worker uint16_t *eob_ptr = coeff_buf_pool->eobs;
80*77c1e3ccSAndroid Build Coastguard Worker uint8_t *entropy_ctx_ptr = coeff_buf_pool->entropy_ctx;
81*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < size; i++) {
82*77c1e3ccSAndroid Build Coastguard Worker for (int plane = 0; plane < num_planes; plane++) {
83*77c1e3ccSAndroid Build Coastguard Worker const int max_sb_square =
84*77c1e3ccSAndroid Build Coastguard Worker (plane == AOM_PLANE_Y) ? luma_max_sb_square : chroma_max_sb_square;
85*77c1e3ccSAndroid Build Coastguard Worker cpi->coeff_buffer_base[i].tcoeff[plane] = tcoeff_ptr;
86*77c1e3ccSAndroid Build Coastguard Worker cpi->coeff_buffer_base[i].eobs[plane] = eob_ptr;
87*77c1e3ccSAndroid Build Coastguard Worker cpi->coeff_buffer_base[i].entropy_ctx[plane] = entropy_ctx_ptr;
88*77c1e3ccSAndroid Build Coastguard Worker tcoeff_ptr += max_sb_square;
89*77c1e3ccSAndroid Build Coastguard Worker eob_ptr += max_sb_square / txb_unit_size;
90*77c1e3ccSAndroid Build Coastguard Worker entropy_ctx_ptr += max_sb_square / txb_unit_size;
91*77c1e3ccSAndroid Build Coastguard Worker }
92*77c1e3ccSAndroid Build Coastguard Worker }
93*77c1e3ccSAndroid Build Coastguard Worker }
94*77c1e3ccSAndroid Build Coastguard Worker
av1_free_txb_buf(AV1_COMP * cpi)95*77c1e3ccSAndroid Build Coastguard Worker void av1_free_txb_buf(AV1_COMP *cpi) {
96*77c1e3ccSAndroid Build Coastguard Worker CoeffBufferPool *coeff_buf_pool = &cpi->coeff_buffer_pool;
97*77c1e3ccSAndroid Build Coastguard Worker aom_free(cpi->coeff_buffer_base);
98*77c1e3ccSAndroid Build Coastguard Worker cpi->coeff_buffer_base = NULL;
99*77c1e3ccSAndroid Build Coastguard Worker aom_free(coeff_buf_pool->tcoeff);
100*77c1e3ccSAndroid Build Coastguard Worker coeff_buf_pool->tcoeff = NULL;
101*77c1e3ccSAndroid Build Coastguard Worker aom_free(coeff_buf_pool->eobs);
102*77c1e3ccSAndroid Build Coastguard Worker coeff_buf_pool->eobs = NULL;
103*77c1e3ccSAndroid Build Coastguard Worker aom_free(coeff_buf_pool->entropy_ctx);
104*77c1e3ccSAndroid Build Coastguard Worker coeff_buf_pool->entropy_ctx = NULL;
105*77c1e3ccSAndroid Build Coastguard Worker }
106*77c1e3ccSAndroid Build Coastguard Worker
write_golomb(aom_writer * w,int level)107*77c1e3ccSAndroid Build Coastguard Worker static void write_golomb(aom_writer *w, int level) {
108*77c1e3ccSAndroid Build Coastguard Worker int x = level + 1;
109*77c1e3ccSAndroid Build Coastguard Worker int i = x;
110*77c1e3ccSAndroid Build Coastguard Worker int length = 0;
111*77c1e3ccSAndroid Build Coastguard Worker
112*77c1e3ccSAndroid Build Coastguard Worker while (i) {
113*77c1e3ccSAndroid Build Coastguard Worker i >>= 1;
114*77c1e3ccSAndroid Build Coastguard Worker ++length;
115*77c1e3ccSAndroid Build Coastguard Worker }
116*77c1e3ccSAndroid Build Coastguard Worker assert(length > 0);
117*77c1e3ccSAndroid Build Coastguard Worker
118*77c1e3ccSAndroid Build Coastguard Worker for (i = 0; i < length - 1; ++i) aom_write_bit(w, 0);
119*77c1e3ccSAndroid Build Coastguard Worker
120*77c1e3ccSAndroid Build Coastguard Worker for (i = length - 1; i >= 0; --i) aom_write_bit(w, (x >> i) & 0x01);
121*77c1e3ccSAndroid Build Coastguard Worker }
122*77c1e3ccSAndroid Build Coastguard Worker
123*77c1e3ccSAndroid Build Coastguard Worker static const int8_t eob_to_pos_small[33] = {
124*77c1e3ccSAndroid Build Coastguard Worker 0, 1, 2, // 0-2
125*77c1e3ccSAndroid Build Coastguard Worker 3, 3, // 3-4
126*77c1e3ccSAndroid Build Coastguard Worker 4, 4, 4, 4, // 5-8
127*77c1e3ccSAndroid Build Coastguard Worker 5, 5, 5, 5, 5, 5, 5, 5, // 9-16
128*77c1e3ccSAndroid Build Coastguard Worker 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 // 17-32
129*77c1e3ccSAndroid Build Coastguard Worker };
130*77c1e3ccSAndroid Build Coastguard Worker
131*77c1e3ccSAndroid Build Coastguard Worker static const int8_t eob_to_pos_large[17] = {
132*77c1e3ccSAndroid Build Coastguard Worker 6, // place holder
133*77c1e3ccSAndroid Build Coastguard Worker 7, // 33-64
134*77c1e3ccSAndroid Build Coastguard Worker 8, 8, // 65-128
135*77c1e3ccSAndroid Build Coastguard Worker 9, 9, 9, 9, // 129-256
136*77c1e3ccSAndroid Build Coastguard Worker 10, 10, 10, 10, 10, 10, 10, 10, // 257-512
137*77c1e3ccSAndroid Build Coastguard Worker 11 // 513-
138*77c1e3ccSAndroid Build Coastguard Worker };
139*77c1e3ccSAndroid Build Coastguard Worker
av1_get_eob_pos_token(const int eob,int * const extra)140*77c1e3ccSAndroid Build Coastguard Worker int av1_get_eob_pos_token(const int eob, int *const extra) {
141*77c1e3ccSAndroid Build Coastguard Worker int t;
142*77c1e3ccSAndroid Build Coastguard Worker
143*77c1e3ccSAndroid Build Coastguard Worker if (eob < 33) {
144*77c1e3ccSAndroid Build Coastguard Worker t = eob_to_pos_small[eob];
145*77c1e3ccSAndroid Build Coastguard Worker } else {
146*77c1e3ccSAndroid Build Coastguard Worker const int e = AOMMIN((eob - 1) >> 5, 16);
147*77c1e3ccSAndroid Build Coastguard Worker t = eob_to_pos_large[e];
148*77c1e3ccSAndroid Build Coastguard Worker }
149*77c1e3ccSAndroid Build Coastguard Worker
150*77c1e3ccSAndroid Build Coastguard Worker *extra = eob - av1_eob_group_start[t];
151*77c1e3ccSAndroid Build Coastguard Worker
152*77c1e3ccSAndroid Build Coastguard Worker return t;
153*77c1e3ccSAndroid Build Coastguard Worker }
154*77c1e3ccSAndroid Build Coastguard Worker
155*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
update_eob_context(int cdf_idx,int eob,TX_SIZE tx_size,TX_CLASS tx_class,PLANE_TYPE plane,FRAME_CONTEXT * ec_ctx,FRAME_COUNTS * counts,uint8_t allow_update_cdf)156*77c1e3ccSAndroid Build Coastguard Worker static void update_eob_context(int cdf_idx, int eob, TX_SIZE tx_size,
157*77c1e3ccSAndroid Build Coastguard Worker TX_CLASS tx_class, PLANE_TYPE plane,
158*77c1e3ccSAndroid Build Coastguard Worker FRAME_CONTEXT *ec_ctx, FRAME_COUNTS *counts,
159*77c1e3ccSAndroid Build Coastguard Worker uint8_t allow_update_cdf) {
160*77c1e3ccSAndroid Build Coastguard Worker #else
161*77c1e3ccSAndroid Build Coastguard Worker static void update_eob_context(int eob, TX_SIZE tx_size, TX_CLASS tx_class,
162*77c1e3ccSAndroid Build Coastguard Worker PLANE_TYPE plane, FRAME_CONTEXT *ec_ctx,
163*77c1e3ccSAndroid Build Coastguard Worker uint8_t allow_update_cdf) {
164*77c1e3ccSAndroid Build Coastguard Worker #endif
165*77c1e3ccSAndroid Build Coastguard Worker int eob_extra;
166*77c1e3ccSAndroid Build Coastguard Worker const int eob_pt = av1_get_eob_pos_token(eob, &eob_extra);
167*77c1e3ccSAndroid Build Coastguard Worker TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
168*77c1e3ccSAndroid Build Coastguard Worker
169*77c1e3ccSAndroid Build Coastguard Worker const int eob_multi_size = txsize_log2_minus4[tx_size];
170*77c1e3ccSAndroid Build Coastguard Worker const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
171*77c1e3ccSAndroid Build Coastguard Worker
172*77c1e3ccSAndroid Build Coastguard Worker switch (eob_multi_size) {
173*77c1e3ccSAndroid Build Coastguard Worker case 0:
174*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
175*77c1e3ccSAndroid Build Coastguard Worker ++counts->eob_multi16[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
176*77c1e3ccSAndroid Build Coastguard Worker #endif
177*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf)
178*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_flag_cdf16[plane][eob_multi_ctx], eob_pt - 1, 5);
179*77c1e3ccSAndroid Build Coastguard Worker break;
180*77c1e3ccSAndroid Build Coastguard Worker case 1:
181*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
182*77c1e3ccSAndroid Build Coastguard Worker ++counts->eob_multi32[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
183*77c1e3ccSAndroid Build Coastguard Worker #endif
184*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf)
185*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_flag_cdf32[plane][eob_multi_ctx], eob_pt - 1, 6);
186*77c1e3ccSAndroid Build Coastguard Worker break;
187*77c1e3ccSAndroid Build Coastguard Worker case 2:
188*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
189*77c1e3ccSAndroid Build Coastguard Worker ++counts->eob_multi64[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
190*77c1e3ccSAndroid Build Coastguard Worker #endif
191*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf)
192*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_flag_cdf64[plane][eob_multi_ctx], eob_pt - 1, 7);
193*77c1e3ccSAndroid Build Coastguard Worker break;
194*77c1e3ccSAndroid Build Coastguard Worker case 3:
195*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
196*77c1e3ccSAndroid Build Coastguard Worker ++counts->eob_multi128[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
197*77c1e3ccSAndroid Build Coastguard Worker #endif
198*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
199*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_flag_cdf128[plane][eob_multi_ctx], eob_pt - 1,
200*77c1e3ccSAndroid Build Coastguard Worker 8);
201*77c1e3ccSAndroid Build Coastguard Worker }
202*77c1e3ccSAndroid Build Coastguard Worker break;
203*77c1e3ccSAndroid Build Coastguard Worker case 4:
204*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
205*77c1e3ccSAndroid Build Coastguard Worker ++counts->eob_multi256[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
206*77c1e3ccSAndroid Build Coastguard Worker #endif
207*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
208*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_flag_cdf256[plane][eob_multi_ctx], eob_pt - 1,
209*77c1e3ccSAndroid Build Coastguard Worker 9);
210*77c1e3ccSAndroid Build Coastguard Worker }
211*77c1e3ccSAndroid Build Coastguard Worker break;
212*77c1e3ccSAndroid Build Coastguard Worker case 5:
213*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
214*77c1e3ccSAndroid Build Coastguard Worker ++counts->eob_multi512[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
215*77c1e3ccSAndroid Build Coastguard Worker #endif
216*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
217*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_flag_cdf512[plane][eob_multi_ctx], eob_pt - 1,
218*77c1e3ccSAndroid Build Coastguard Worker 10);
219*77c1e3ccSAndroid Build Coastguard Worker }
220*77c1e3ccSAndroid Build Coastguard Worker break;
221*77c1e3ccSAndroid Build Coastguard Worker case 6:
222*77c1e3ccSAndroid Build Coastguard Worker default:
223*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
224*77c1e3ccSAndroid Build Coastguard Worker ++counts->eob_multi1024[cdf_idx][plane][eob_multi_ctx][eob_pt - 1];
225*77c1e3ccSAndroid Build Coastguard Worker #endif
226*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
227*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_flag_cdf1024[plane][eob_multi_ctx], eob_pt - 1,
228*77c1e3ccSAndroid Build Coastguard Worker 11);
229*77c1e3ccSAndroid Build Coastguard Worker }
230*77c1e3ccSAndroid Build Coastguard Worker break;
231*77c1e3ccSAndroid Build Coastguard Worker }
232*77c1e3ccSAndroid Build Coastguard Worker
233*77c1e3ccSAndroid Build Coastguard Worker if (av1_eob_offset_bits[eob_pt] > 0) {
234*77c1e3ccSAndroid Build Coastguard Worker int eob_ctx = eob_pt - 3;
235*77c1e3ccSAndroid Build Coastguard Worker int eob_shift = av1_eob_offset_bits[eob_pt] - 1;
236*77c1e3ccSAndroid Build Coastguard Worker int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
237*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
238*77c1e3ccSAndroid Build Coastguard Worker counts->eob_extra[cdf_idx][txs_ctx][plane][eob_pt][bit]++;
239*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
240*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf)
241*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->eob_extra_cdf[txs_ctx][plane][eob_ctx], bit, 2);
242*77c1e3ccSAndroid Build Coastguard Worker }
243*77c1e3ccSAndroid Build Coastguard Worker }
244*77c1e3ccSAndroid Build Coastguard Worker
245*77c1e3ccSAndroid Build Coastguard Worker static inline int get_nz_map_ctx(const uint8_t *const levels,
246*77c1e3ccSAndroid Build Coastguard Worker const int coeff_idx, const int bhl,
247*77c1e3ccSAndroid Build Coastguard Worker const int width, const int scan_idx,
248*77c1e3ccSAndroid Build Coastguard Worker const int is_eob, const TX_SIZE tx_size,
249*77c1e3ccSAndroid Build Coastguard Worker const TX_CLASS tx_class) {
250*77c1e3ccSAndroid Build Coastguard Worker if (is_eob) {
251*77c1e3ccSAndroid Build Coastguard Worker if (scan_idx == 0) return 0;
252*77c1e3ccSAndroid Build Coastguard Worker if (scan_idx <= (width << bhl) / 8) return 1;
253*77c1e3ccSAndroid Build Coastguard Worker if (scan_idx <= (width << bhl) / 4) return 2;
254*77c1e3ccSAndroid Build Coastguard Worker return 3;
255*77c1e3ccSAndroid Build Coastguard Worker }
256*77c1e3ccSAndroid Build Coastguard Worker const int stats =
257*77c1e3ccSAndroid Build Coastguard Worker get_nz_mag(levels + get_padded_idx(coeff_idx, bhl), bhl, tx_class);
258*77c1e3ccSAndroid Build Coastguard Worker return get_nz_map_ctx_from_stats(stats, coeff_idx, bhl, tx_size, tx_class);
259*77c1e3ccSAndroid Build Coastguard Worker }
260*77c1e3ccSAndroid Build Coastguard Worker
261*77c1e3ccSAndroid Build Coastguard Worker void av1_txb_init_levels_c(const tran_low_t *const coeff, const int width,
262*77c1e3ccSAndroid Build Coastguard Worker const int height, uint8_t *const levels) {
263*77c1e3ccSAndroid Build Coastguard Worker const int stride = height + TX_PAD_HOR;
264*77c1e3ccSAndroid Build Coastguard Worker uint8_t *ls = levels;
265*77c1e3ccSAndroid Build Coastguard Worker
266*77c1e3ccSAndroid Build Coastguard Worker memset(levels + stride * width, 0,
267*77c1e3ccSAndroid Build Coastguard Worker sizeof(*levels) * (TX_PAD_BOTTOM * stride + TX_PAD_END));
268*77c1e3ccSAndroid Build Coastguard Worker
269*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < width; i++) {
270*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < height; j++) {
271*77c1e3ccSAndroid Build Coastguard Worker *ls++ = (uint8_t)clamp(abs(coeff[i * height + j]), 0, INT8_MAX);
272*77c1e3ccSAndroid Build Coastguard Worker }
273*77c1e3ccSAndroid Build Coastguard Worker for (int j = 0; j < TX_PAD_HOR; j++) {
274*77c1e3ccSAndroid Build Coastguard Worker *ls++ = 0;
275*77c1e3ccSAndroid Build Coastguard Worker }
276*77c1e3ccSAndroid Build Coastguard Worker }
277*77c1e3ccSAndroid Build Coastguard Worker }
278*77c1e3ccSAndroid Build Coastguard Worker
279*77c1e3ccSAndroid Build Coastguard Worker void av1_get_nz_map_contexts_c(const uint8_t *const levels,
280*77c1e3ccSAndroid Build Coastguard Worker const int16_t *const scan, const uint16_t eob,
281*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE tx_size, const TX_CLASS tx_class,
282*77c1e3ccSAndroid Build Coastguard Worker int8_t *const coeff_contexts) {
283*77c1e3ccSAndroid Build Coastguard Worker const int bhl = get_txb_bhl(tx_size);
284*77c1e3ccSAndroid Build Coastguard Worker const int width = get_txb_wide(tx_size);
285*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < eob; ++i) {
286*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[i];
287*77c1e3ccSAndroid Build Coastguard Worker coeff_contexts[pos] = get_nz_map_ctx(levels, pos, bhl, width, i,
288*77c1e3ccSAndroid Build Coastguard Worker i == eob - 1, tx_size, tx_class);
289*77c1e3ccSAndroid Build Coastguard Worker }
290*77c1e3ccSAndroid Build Coastguard Worker }
291*77c1e3ccSAndroid Build Coastguard Worker
292*77c1e3ccSAndroid Build Coastguard Worker void av1_write_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCK *const x,
293*77c1e3ccSAndroid Build Coastguard Worker aom_writer *w, int blk_row, int blk_col, int plane,
294*77c1e3ccSAndroid Build Coastguard Worker int block, TX_SIZE tx_size) {
295*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
296*77c1e3ccSAndroid Build Coastguard Worker const CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
297*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type = get_plane_type(plane);
298*77c1e3ccSAndroid Build Coastguard Worker const int txb_offset = x->mbmi_ext_frame->cb_offset[plane_type] /
299*77c1e3ccSAndroid Build Coastguard Worker (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
300*77c1e3ccSAndroid Build Coastguard Worker const uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
301*77c1e3ccSAndroid Build Coastguard Worker const uint16_t eob = eob_txb[block];
302*77c1e3ccSAndroid Build Coastguard Worker const uint8_t *entropy_ctx = cb_coef_buff->entropy_ctx[plane] + txb_offset;
303*77c1e3ccSAndroid Build Coastguard Worker const int txb_skip_ctx = entropy_ctx[block] & TXB_SKIP_CTX_MASK;
304*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
305*77c1e3ccSAndroid Build Coastguard Worker FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
306*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob == 0, ec_ctx->txb_skip_cdf[txs_ctx][txb_skip_ctx], 2);
307*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0) return;
308*77c1e3ccSAndroid Build Coastguard Worker
309*77c1e3ccSAndroid Build Coastguard Worker const TX_TYPE tx_type =
310*77c1e3ccSAndroid Build Coastguard Worker av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
311*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
312*77c1e3ccSAndroid Build Coastguard Worker // Only y plane's tx_type is transmitted
313*77c1e3ccSAndroid Build Coastguard Worker if (plane == 0) {
314*77c1e3ccSAndroid Build Coastguard Worker av1_write_tx_type(cm, xd, tx_type, tx_size, w);
315*77c1e3ccSAndroid Build Coastguard Worker }
316*77c1e3ccSAndroid Build Coastguard Worker
317*77c1e3ccSAndroid Build Coastguard Worker int eob_extra;
318*77c1e3ccSAndroid Build Coastguard Worker const int eob_pt = av1_get_eob_pos_token(eob, &eob_extra);
319*77c1e3ccSAndroid Build Coastguard Worker const int eob_multi_size = txsize_log2_minus4[tx_size];
320*77c1e3ccSAndroid Build Coastguard Worker const TX_CLASS tx_class = tx_type_to_class[tx_type];
321*77c1e3ccSAndroid Build Coastguard Worker const int eob_multi_ctx = (tx_class == TX_CLASS_2D) ? 0 : 1;
322*77c1e3ccSAndroid Build Coastguard Worker switch (eob_multi_size) {
323*77c1e3ccSAndroid Build Coastguard Worker case 0:
324*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob_pt - 1,
325*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_flag_cdf16[plane_type][eob_multi_ctx], 5);
326*77c1e3ccSAndroid Build Coastguard Worker break;
327*77c1e3ccSAndroid Build Coastguard Worker case 1:
328*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob_pt - 1,
329*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_flag_cdf32[plane_type][eob_multi_ctx], 6);
330*77c1e3ccSAndroid Build Coastguard Worker break;
331*77c1e3ccSAndroid Build Coastguard Worker case 2:
332*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob_pt - 1,
333*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_flag_cdf64[plane_type][eob_multi_ctx], 7);
334*77c1e3ccSAndroid Build Coastguard Worker break;
335*77c1e3ccSAndroid Build Coastguard Worker case 3:
336*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob_pt - 1,
337*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_flag_cdf128[plane_type][eob_multi_ctx], 8);
338*77c1e3ccSAndroid Build Coastguard Worker break;
339*77c1e3ccSAndroid Build Coastguard Worker case 4:
340*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob_pt - 1,
341*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_flag_cdf256[plane_type][eob_multi_ctx], 9);
342*77c1e3ccSAndroid Build Coastguard Worker break;
343*77c1e3ccSAndroid Build Coastguard Worker case 5:
344*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob_pt - 1,
345*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_flag_cdf512[plane_type][eob_multi_ctx], 10);
346*77c1e3ccSAndroid Build Coastguard Worker break;
347*77c1e3ccSAndroid Build Coastguard Worker default:
348*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, eob_pt - 1,
349*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_flag_cdf1024[plane_type][eob_multi_ctx], 11);
350*77c1e3ccSAndroid Build Coastguard Worker break;
351*77c1e3ccSAndroid Build Coastguard Worker }
352*77c1e3ccSAndroid Build Coastguard Worker
353*77c1e3ccSAndroid Build Coastguard Worker const int eob_offset_bits = av1_eob_offset_bits[eob_pt];
354*77c1e3ccSAndroid Build Coastguard Worker if (eob_offset_bits > 0) {
355*77c1e3ccSAndroid Build Coastguard Worker const int eob_ctx = eob_pt - 3;
356*77c1e3ccSAndroid Build Coastguard Worker int eob_shift = eob_offset_bits - 1;
357*77c1e3ccSAndroid Build Coastguard Worker int bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
358*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, bit,
359*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->eob_extra_cdf[txs_ctx][plane_type][eob_ctx], 2);
360*77c1e3ccSAndroid Build Coastguard Worker for (int i = 1; i < eob_offset_bits; i++) {
361*77c1e3ccSAndroid Build Coastguard Worker eob_shift = eob_offset_bits - 1 - i;
362*77c1e3ccSAndroid Build Coastguard Worker bit = (eob_extra & (1 << eob_shift)) ? 1 : 0;
363*77c1e3ccSAndroid Build Coastguard Worker aom_write_bit(w, bit);
364*77c1e3ccSAndroid Build Coastguard Worker }
365*77c1e3ccSAndroid Build Coastguard Worker }
366*77c1e3ccSAndroid Build Coastguard Worker
367*77c1e3ccSAndroid Build Coastguard Worker const int width = get_txb_wide(tx_size);
368*77c1e3ccSAndroid Build Coastguard Worker const int height = get_txb_high(tx_size);
369*77c1e3ccSAndroid Build Coastguard Worker uint8_t levels_buf[TX_PAD_2D];
370*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const levels = set_levels(levels_buf, height);
371*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t *tcoeff_txb =
372*77c1e3ccSAndroid Build Coastguard Worker cb_coef_buff->tcoeff[plane] + x->mbmi_ext_frame->cb_offset[plane_type];
373*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t *tcoeff = tcoeff_txb + BLOCK_OFFSET(block);
374*77c1e3ccSAndroid Build Coastguard Worker av1_txb_init_levels(tcoeff, width, height, levels);
375*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
376*77c1e3ccSAndroid Build Coastguard Worker const int16_t *const scan = scan_order->scan;
377*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
378*77c1e3ccSAndroid Build Coastguard Worker av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class, coeff_contexts);
379*77c1e3ccSAndroid Build Coastguard Worker
380*77c1e3ccSAndroid Build Coastguard Worker const int bhl = get_txb_bhl(tx_size);
381*77c1e3ccSAndroid Build Coastguard Worker for (int c = eob - 1; c >= 0; --c) {
382*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
383*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = coeff_contexts[pos];
384*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = tcoeff[pos];
385*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t level = abs(v);
386*77c1e3ccSAndroid Build Coastguard Worker
387*77c1e3ccSAndroid Build Coastguard Worker if (c == eob - 1) {
388*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(
389*77c1e3ccSAndroid Build Coastguard Worker w, AOMMIN(level, 3) - 1,
390*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->coeff_base_eob_cdf[txs_ctx][plane_type][coeff_ctx], 3);
391*77c1e3ccSAndroid Build Coastguard Worker } else {
392*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, AOMMIN(level, 3),
393*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->coeff_base_cdf[txs_ctx][plane_type][coeff_ctx],
394*77c1e3ccSAndroid Build Coastguard Worker 4);
395*77c1e3ccSAndroid Build Coastguard Worker }
396*77c1e3ccSAndroid Build Coastguard Worker if (level > NUM_BASE_LEVELS) {
397*77c1e3ccSAndroid Build Coastguard Worker // level is above 1.
398*77c1e3ccSAndroid Build Coastguard Worker const int base_range = level - 1 - NUM_BASE_LEVELS;
399*77c1e3ccSAndroid Build Coastguard Worker const int br_ctx = get_br_ctx(levels, pos, bhl, tx_class);
400*77c1e3ccSAndroid Build Coastguard Worker aom_cdf_prob *cdf =
401*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->coeff_br_cdf[AOMMIN(txs_ctx, TX_32X32)][plane_type][br_ctx];
402*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
403*77c1e3ccSAndroid Build Coastguard Worker const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
404*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, k, cdf, BR_CDF_SIZE);
405*77c1e3ccSAndroid Build Coastguard Worker if (k < BR_CDF_SIZE - 1) break;
406*77c1e3ccSAndroid Build Coastguard Worker }
407*77c1e3ccSAndroid Build Coastguard Worker }
408*77c1e3ccSAndroid Build Coastguard Worker }
409*77c1e3ccSAndroid Build Coastguard Worker
410*77c1e3ccSAndroid Build Coastguard Worker // Loop to code all signs in the transform block,
411*77c1e3ccSAndroid Build Coastguard Worker // starting with the sign of DC (if applicable)
412*77c1e3ccSAndroid Build Coastguard Worker for (int c = 0; c < eob; ++c) {
413*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = tcoeff[scan[c]];
414*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t level = abs(v);
415*77c1e3ccSAndroid Build Coastguard Worker const int sign = (v < 0) ? 1 : 0;
416*77c1e3ccSAndroid Build Coastguard Worker if (level) {
417*77c1e3ccSAndroid Build Coastguard Worker if (c == 0) {
418*77c1e3ccSAndroid Build Coastguard Worker const int dc_sign_ctx =
419*77c1e3ccSAndroid Build Coastguard Worker (entropy_ctx[block] >> DC_SIGN_CTX_SHIFT) & DC_SIGN_CTX_MASK;
420*77c1e3ccSAndroid Build Coastguard Worker aom_write_symbol(w, sign, ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx],
421*77c1e3ccSAndroid Build Coastguard Worker 2);
422*77c1e3ccSAndroid Build Coastguard Worker } else {
423*77c1e3ccSAndroid Build Coastguard Worker aom_write_bit(w, sign);
424*77c1e3ccSAndroid Build Coastguard Worker }
425*77c1e3ccSAndroid Build Coastguard Worker if (level > COEFF_BASE_RANGE + NUM_BASE_LEVELS)
426*77c1e3ccSAndroid Build Coastguard Worker write_golomb(w, level - COEFF_BASE_RANGE - 1 - NUM_BASE_LEVELS);
427*77c1e3ccSAndroid Build Coastguard Worker }
428*77c1e3ccSAndroid Build Coastguard Worker }
429*77c1e3ccSAndroid Build Coastguard Worker }
430*77c1e3ccSAndroid Build Coastguard Worker
431*77c1e3ccSAndroid Build Coastguard Worker void av1_write_intra_coeffs_mb(const AV1_COMMON *const cm, MACROBLOCK *x,
432*77c1e3ccSAndroid Build Coastguard Worker aom_writer *w, BLOCK_SIZE bsize) {
433*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd = &x->e_mbd;
434*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
435*77c1e3ccSAndroid Build Coastguard Worker int block[MAX_MB_PLANE] = { 0 };
436*77c1e3ccSAndroid Build Coastguard Worker int row, col;
437*77c1e3ccSAndroid Build Coastguard Worker assert(bsize == get_plane_block_size(bsize, xd->plane[0].subsampling_x,
438*77c1e3ccSAndroid Build Coastguard Worker xd->plane[0].subsampling_y));
439*77c1e3ccSAndroid Build Coastguard Worker const int max_blocks_wide = max_block_wide(xd, bsize, 0);
440*77c1e3ccSAndroid Build Coastguard Worker const int max_blocks_high = max_block_high(xd, bsize, 0);
441*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE max_unit_bsize = BLOCK_64X64;
442*77c1e3ccSAndroid Build Coastguard Worker int mu_blocks_wide = mi_size_wide[max_unit_bsize];
443*77c1e3ccSAndroid Build Coastguard Worker int mu_blocks_high = mi_size_high[max_unit_bsize];
444*77c1e3ccSAndroid Build Coastguard Worker mu_blocks_wide = AOMMIN(max_blocks_wide, mu_blocks_wide);
445*77c1e3ccSAndroid Build Coastguard Worker mu_blocks_high = AOMMIN(max_blocks_high, mu_blocks_high);
446*77c1e3ccSAndroid Build Coastguard Worker
447*77c1e3ccSAndroid Build Coastguard Worker for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
448*77c1e3ccSAndroid Build Coastguard Worker for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
449*77c1e3ccSAndroid Build Coastguard Worker for (int plane = 0; plane < num_planes; ++plane) {
450*77c1e3ccSAndroid Build Coastguard Worker if (plane && !xd->is_chroma_ref) break;
451*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
452*77c1e3ccSAndroid Build Coastguard Worker const int stepr = tx_size_high_unit[tx_size];
453*77c1e3ccSAndroid Build Coastguard Worker const int stepc = tx_size_wide_unit[tx_size];
454*77c1e3ccSAndroid Build Coastguard Worker const int step = stepr * stepc;
455*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
456*77c1e3ccSAndroid Build Coastguard Worker const int unit_height = ROUND_POWER_OF_TWO(
457*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mu_blocks_high + row, max_blocks_high), pd->subsampling_y);
458*77c1e3ccSAndroid Build Coastguard Worker const int unit_width = ROUND_POWER_OF_TWO(
459*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(mu_blocks_wide + col, max_blocks_wide), pd->subsampling_x);
460*77c1e3ccSAndroid Build Coastguard Worker for (int blk_row = row >> pd->subsampling_y; blk_row < unit_height;
461*77c1e3ccSAndroid Build Coastguard Worker blk_row += stepr) {
462*77c1e3ccSAndroid Build Coastguard Worker for (int blk_col = col >> pd->subsampling_x; blk_col < unit_width;
463*77c1e3ccSAndroid Build Coastguard Worker blk_col += stepc) {
464*77c1e3ccSAndroid Build Coastguard Worker av1_write_coeffs_txb(cm, x, w, blk_row, blk_col, plane,
465*77c1e3ccSAndroid Build Coastguard Worker block[plane], tx_size);
466*77c1e3ccSAndroid Build Coastguard Worker block[plane] += step;
467*77c1e3ccSAndroid Build Coastguard Worker }
468*77c1e3ccSAndroid Build Coastguard Worker }
469*77c1e3ccSAndroid Build Coastguard Worker }
470*77c1e3ccSAndroid Build Coastguard Worker }
471*77c1e3ccSAndroid Build Coastguard Worker }
472*77c1e3ccSAndroid Build Coastguard Worker }
473*77c1e3ccSAndroid Build Coastguard Worker
474*77c1e3ccSAndroid Build Coastguard Worker uint8_t av1_get_txb_entropy_context(const tran_low_t *qcoeff,
475*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *scan_order, int eob) {
476*77c1e3ccSAndroid Build Coastguard Worker const int16_t *const scan = scan_order->scan;
477*77c1e3ccSAndroid Build Coastguard Worker int cul_level = 0;
478*77c1e3ccSAndroid Build Coastguard Worker int c;
479*77c1e3ccSAndroid Build Coastguard Worker
480*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0) return 0;
481*77c1e3ccSAndroid Build Coastguard Worker for (c = 0; c < eob; ++c) {
482*77c1e3ccSAndroid Build Coastguard Worker cul_level += abs(qcoeff[scan[c]]);
483*77c1e3ccSAndroid Build Coastguard Worker if (cul_level > COEFF_CONTEXT_MASK) break;
484*77c1e3ccSAndroid Build Coastguard Worker }
485*77c1e3ccSAndroid Build Coastguard Worker
486*77c1e3ccSAndroid Build Coastguard Worker cul_level = AOMMIN(COEFF_CONTEXT_MASK, cul_level);
487*77c1e3ccSAndroid Build Coastguard Worker set_dc_sign(&cul_level, qcoeff[0]);
488*77c1e3ccSAndroid Build Coastguard Worker
489*77c1e3ccSAndroid Build Coastguard Worker return (uint8_t)cul_level;
490*77c1e3ccSAndroid Build Coastguard Worker }
491*77c1e3ccSAndroid Build Coastguard Worker
492*77c1e3ccSAndroid Build Coastguard Worker static void update_tx_type_count(const AV1_COMP *cpi, const AV1_COMMON *cm,
493*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *xd, int blk_row, int blk_col,
494*77c1e3ccSAndroid Build Coastguard Worker int plane, TX_SIZE tx_size,
495*77c1e3ccSAndroid Build Coastguard Worker FRAME_COUNTS *counts,
496*77c1e3ccSAndroid Build Coastguard Worker uint8_t allow_update_cdf) {
497*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
498*77c1e3ccSAndroid Build Coastguard Worker int is_inter = is_inter_block(mbmi);
499*77c1e3ccSAndroid Build Coastguard Worker const int reduced_tx_set_used = cm->features.reduced_tx_set_used;
500*77c1e3ccSAndroid Build Coastguard Worker FRAME_CONTEXT *fc = xd->tile_ctx;
501*77c1e3ccSAndroid Build Coastguard Worker #if !CONFIG_ENTROPY_STATS
502*77c1e3ccSAndroid Build Coastguard Worker (void)counts;
503*77c1e3ccSAndroid Build Coastguard Worker #endif // !CONFIG_ENTROPY_STATS
504*77c1e3ccSAndroid Build Coastguard Worker
505*77c1e3ccSAndroid Build Coastguard Worker // Only y plane's tx_type is updated
506*77c1e3ccSAndroid Build Coastguard Worker if (plane > 0) return;
507*77c1e3ccSAndroid Build Coastguard Worker const TX_TYPE tx_type = av1_get_tx_type(xd, PLANE_TYPE_Y, blk_row, blk_col,
508*77c1e3ccSAndroid Build Coastguard Worker tx_size, reduced_tx_set_used);
509*77c1e3ccSAndroid Build Coastguard Worker if (is_inter) {
510*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.txfm_cfg.use_inter_dct_only) {
511*77c1e3ccSAndroid Build Coastguard Worker assert(tx_type == DCT_DCT);
512*77c1e3ccSAndroid Build Coastguard Worker }
513*77c1e3ccSAndroid Build Coastguard Worker } else {
514*77c1e3ccSAndroid Build Coastguard Worker if (cpi->oxcf.txfm_cfg.use_intra_dct_only) {
515*77c1e3ccSAndroid Build Coastguard Worker assert(tx_type == DCT_DCT);
516*77c1e3ccSAndroid Build Coastguard Worker } else if (cpi->oxcf.txfm_cfg.use_intra_default_tx_only) {
517*77c1e3ccSAndroid Build Coastguard Worker const TX_TYPE default_type = get_default_tx_type(
518*77c1e3ccSAndroid Build Coastguard Worker PLANE_TYPE_Y, xd, tx_size, cpi->use_screen_content_tools);
519*77c1e3ccSAndroid Build Coastguard Worker (void)default_type;
520*77c1e3ccSAndroid Build Coastguard Worker // TODO(kyslov): We don't always respect use_intra_default_tx_only flag in
521*77c1e3ccSAndroid Build Coastguard Worker // NonRD and REALTIME case. Specifically we ignore it in hybrid inta mode
522*77c1e3ccSAndroid Build Coastguard Worker // search, when picking up intra mode in nonRD inter mode search and in RD
523*77c1e3ccSAndroid Build Coastguard Worker // REALTIME mode when we limit TX type usage.
524*77c1e3ccSAndroid Build Coastguard Worker // We need to fix txfm cfg for these cases. Meanwhile relieving the
525*77c1e3ccSAndroid Build Coastguard Worker // assert.
526*77c1e3ccSAndroid Build Coastguard Worker assert(tx_type == default_type || cpi->sf.rt_sf.use_nonrd_pick_mode ||
527*77c1e3ccSAndroid Build Coastguard Worker cpi->oxcf.mode == REALTIME);
528*77c1e3ccSAndroid Build Coastguard Worker }
529*77c1e3ccSAndroid Build Coastguard Worker }
530*77c1e3ccSAndroid Build Coastguard Worker
531*77c1e3ccSAndroid Build Coastguard Worker if (get_ext_tx_types(tx_size, is_inter, reduced_tx_set_used) > 1 &&
532*77c1e3ccSAndroid Build Coastguard Worker cm->quant_params.base_qindex > 0 && !mbmi->skip_txfm &&
533*77c1e3ccSAndroid Build Coastguard Worker !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
534*77c1e3ccSAndroid Build Coastguard Worker const int eset = get_ext_tx_set(tx_size, is_inter, reduced_tx_set_used);
535*77c1e3ccSAndroid Build Coastguard Worker if (eset > 0) {
536*77c1e3ccSAndroid Build Coastguard Worker const TxSetType tx_set_type =
537*77c1e3ccSAndroid Build Coastguard Worker av1_get_ext_tx_set_type(tx_size, is_inter, reduced_tx_set_used);
538*77c1e3ccSAndroid Build Coastguard Worker if (is_inter) {
539*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
540*77c1e3ccSAndroid Build Coastguard Worker update_cdf(fc->inter_ext_tx_cdf[eset][txsize_sqr_map[tx_size]],
541*77c1e3ccSAndroid Build Coastguard Worker av1_ext_tx_ind[tx_set_type][tx_type],
542*77c1e3ccSAndroid Build Coastguard Worker av1_num_ext_tx_set[tx_set_type]);
543*77c1e3ccSAndroid Build Coastguard Worker }
544*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
545*77c1e3ccSAndroid Build Coastguard Worker ++counts->inter_ext_tx[eset][txsize_sqr_map[tx_size]]
546*77c1e3ccSAndroid Build Coastguard Worker [av1_ext_tx_ind[tx_set_type][tx_type]];
547*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
548*77c1e3ccSAndroid Build Coastguard Worker } else {
549*77c1e3ccSAndroid Build Coastguard Worker PREDICTION_MODE intra_dir;
550*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->filter_intra_mode_info.use_filter_intra)
551*77c1e3ccSAndroid Build Coastguard Worker intra_dir = fimode_to_intradir[mbmi->filter_intra_mode_info
552*77c1e3ccSAndroid Build Coastguard Worker .filter_intra_mode];
553*77c1e3ccSAndroid Build Coastguard Worker else
554*77c1e3ccSAndroid Build Coastguard Worker intra_dir = mbmi->mode;
555*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
556*77c1e3ccSAndroid Build Coastguard Worker ++counts->intra_ext_tx[eset][txsize_sqr_map[tx_size]][intra_dir]
557*77c1e3ccSAndroid Build Coastguard Worker [av1_ext_tx_ind[tx_set_type][tx_type]];
558*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
559*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
560*77c1e3ccSAndroid Build Coastguard Worker update_cdf(
561*77c1e3ccSAndroid Build Coastguard Worker fc->intra_ext_tx_cdf[eset][txsize_sqr_map[tx_size]][intra_dir],
562*77c1e3ccSAndroid Build Coastguard Worker av1_ext_tx_ind[tx_set_type][tx_type],
563*77c1e3ccSAndroid Build Coastguard Worker av1_num_ext_tx_set[tx_set_type]);
564*77c1e3ccSAndroid Build Coastguard Worker }
565*77c1e3ccSAndroid Build Coastguard Worker }
566*77c1e3ccSAndroid Build Coastguard Worker }
567*77c1e3ccSAndroid Build Coastguard Worker }
568*77c1e3ccSAndroid Build Coastguard Worker }
569*77c1e3ccSAndroid Build Coastguard Worker
570*77c1e3ccSAndroid Build Coastguard Worker void av1_update_and_record_txb_context(int plane, int block, int blk_row,
571*77c1e3ccSAndroid Build Coastguard Worker int blk_col, BLOCK_SIZE plane_bsize,
572*77c1e3ccSAndroid Build Coastguard Worker TX_SIZE tx_size, void *arg) {
573*77c1e3ccSAndroid Build Coastguard Worker struct tokenize_b_args *const args = arg;
574*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi = args->cpi;
575*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
576*77c1e3ccSAndroid Build Coastguard Worker ThreadData *const td = args->td;
577*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x = &td->mb;
578*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
579*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *p = &x->plane[plane];
580*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *pd = &xd->plane[plane];
581*77c1e3ccSAndroid Build Coastguard Worker const int eob = p->eobs[block];
582*77c1e3ccSAndroid Build Coastguard Worker const int block_offset = BLOCK_OFFSET(block);
583*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff = p->qcoeff + block_offset;
584*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type = pd->plane_type;
585*77c1e3ccSAndroid Build Coastguard Worker const TX_TYPE tx_type =
586*77c1e3ccSAndroid Build Coastguard Worker av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
587*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
588*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
589*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *tcoeff;
590*77c1e3ccSAndroid Build Coastguard Worker assert(args->dry_run != DRY_RUN_COSTCOEFFS);
591*77c1e3ccSAndroid Build Coastguard Worker if (args->dry_run == OUTPUT_ENABLED) {
592*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
593*77c1e3ccSAndroid Build Coastguard Worker TXB_CTX txb_ctx;
594*77c1e3ccSAndroid Build Coastguard Worker get_txb_ctx(plane_bsize, tx_size, plane,
595*77c1e3ccSAndroid Build Coastguard Worker pd->above_entropy_context + blk_col,
596*77c1e3ccSAndroid Build Coastguard Worker pd->left_entropy_context + blk_row, &txb_ctx);
597*77c1e3ccSAndroid Build Coastguard Worker const int bhl = get_txb_bhl(tx_size);
598*77c1e3ccSAndroid Build Coastguard Worker const int width = get_txb_wide(tx_size);
599*77c1e3ccSAndroid Build Coastguard Worker const int height = get_txb_high(tx_size);
600*77c1e3ccSAndroid Build Coastguard Worker const uint8_t allow_update_cdf = args->allow_update_cdf;
601*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
602*77c1e3ccSAndroid Build Coastguard Worker FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
603*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
604*77c1e3ccSAndroid Build Coastguard Worker int cdf_idx = cm->coef_cdf_category;
605*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->txb_skip[cdf_idx][txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
606*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
607*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
608*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->txb_skip_cdf[txsize_ctx][txb_ctx.txb_skip_ctx],
609*77c1e3ccSAndroid Build Coastguard Worker eob == 0, 2);
610*77c1e3ccSAndroid Build Coastguard Worker }
611*77c1e3ccSAndroid Build Coastguard Worker
612*77c1e3ccSAndroid Build Coastguard Worker CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
613*77c1e3ccSAndroid Build Coastguard Worker const int txb_offset = x->mbmi_ext_frame->cb_offset[plane_type] /
614*77c1e3ccSAndroid Build Coastguard Worker (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
615*77c1e3ccSAndroid Build Coastguard Worker uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
616*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const entropy_ctx = cb_coef_buff->entropy_ctx[plane] + txb_offset;
617*77c1e3ccSAndroid Build Coastguard Worker entropy_ctx[block] = txb_ctx.txb_skip_ctx;
618*77c1e3ccSAndroid Build Coastguard Worker eob_txb[block] = eob;
619*77c1e3ccSAndroid Build Coastguard Worker
620*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0) {
621*77c1e3ccSAndroid Build Coastguard Worker av1_set_entropy_contexts(xd, pd, plane, plane_bsize, tx_size, 0, blk_col,
622*77c1e3ccSAndroid Build Coastguard Worker blk_row);
623*77c1e3ccSAndroid Build Coastguard Worker return;
624*77c1e3ccSAndroid Build Coastguard Worker }
625*77c1e3ccSAndroid Build Coastguard Worker const int segment_id = mbmi->segment_id;
626*77c1e3ccSAndroid Build Coastguard Worker const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
627*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *tcoeff_txb =
628*77c1e3ccSAndroid Build Coastguard Worker cb_coef_buff->tcoeff[plane] + x->mbmi_ext_frame->cb_offset[plane_type];
629*77c1e3ccSAndroid Build Coastguard Worker tcoeff = tcoeff_txb + block_offset;
630*77c1e3ccSAndroid Build Coastguard Worker memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
631*77c1e3ccSAndroid Build Coastguard Worker
632*77c1e3ccSAndroid Build Coastguard Worker uint8_t levels_buf[TX_PAD_2D];
633*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const levels = set_levels(levels_buf, height);
634*77c1e3ccSAndroid Build Coastguard Worker av1_txb_init_levels(tcoeff, width, height, levels);
635*77c1e3ccSAndroid Build Coastguard Worker update_tx_type_count(cpi, cm, xd, blk_row, blk_col, plane, tx_size,
636*77c1e3ccSAndroid Build Coastguard Worker td->counts, allow_update_cdf);
637*77c1e3ccSAndroid Build Coastguard Worker
638*77c1e3ccSAndroid Build Coastguard Worker const TX_CLASS tx_class = tx_type_to_class[tx_type];
639*77c1e3ccSAndroid Build Coastguard Worker const int16_t *const scan = scan_order->scan;
640*77c1e3ccSAndroid Build Coastguard Worker
641*77c1e3ccSAndroid Build Coastguard Worker // record tx type usage
642*77c1e3ccSAndroid Build Coastguard Worker td->rd_counts.tx_type_used[tx_size][tx_type]++;
643*77c1e3ccSAndroid Build Coastguard Worker
644*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
645*77c1e3ccSAndroid Build Coastguard Worker update_eob_context(cdf_idx, eob, tx_size, tx_class, plane_type, ec_ctx,
646*77c1e3ccSAndroid Build Coastguard Worker td->counts, allow_update_cdf);
647*77c1e3ccSAndroid Build Coastguard Worker #else
648*77c1e3ccSAndroid Build Coastguard Worker update_eob_context(eob, tx_size, tx_class, plane_type, ec_ctx,
649*77c1e3ccSAndroid Build Coastguard Worker allow_update_cdf);
650*77c1e3ccSAndroid Build Coastguard Worker #endif
651*77c1e3ccSAndroid Build Coastguard Worker
652*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
653*77c1e3ccSAndroid Build Coastguard Worker av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class,
654*77c1e3ccSAndroid Build Coastguard Worker coeff_contexts);
655*77c1e3ccSAndroid Build Coastguard Worker
656*77c1e3ccSAndroid Build Coastguard Worker for (int c = eob - 1; c >= 0; --c) {
657*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
658*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = coeff_contexts[pos];
659*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = qcoeff[pos];
660*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t level = abs(v);
661*77c1e3ccSAndroid Build Coastguard Worker /* abs_sum_level is needed to decide the job scheduling order of
662*77c1e3ccSAndroid Build Coastguard Worker * pack bitstream multi-threading. This data is not needed if
663*77c1e3ccSAndroid Build Coastguard Worker * multi-threading is disabled. */
664*77c1e3ccSAndroid Build Coastguard Worker if (cpi->mt_info.pack_bs_mt_enabled) td->abs_sum_level += level;
665*77c1e3ccSAndroid Build Coastguard Worker
666*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
667*77c1e3ccSAndroid Build Coastguard Worker if (c == eob - 1) {
668*77c1e3ccSAndroid Build Coastguard Worker assert(coeff_ctx < 4);
669*77c1e3ccSAndroid Build Coastguard Worker update_cdf(
670*77c1e3ccSAndroid Build Coastguard Worker ec_ctx->coeff_base_eob_cdf[txsize_ctx][plane_type][coeff_ctx],
671*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(level, 3) - 1, 3);
672*77c1e3ccSAndroid Build Coastguard Worker } else {
673*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->coeff_base_cdf[txsize_ctx][plane_type][coeff_ctx],
674*77c1e3ccSAndroid Build Coastguard Worker AOMMIN(level, 3), 4);
675*77c1e3ccSAndroid Build Coastguard Worker }
676*77c1e3ccSAndroid Build Coastguard Worker }
677*77c1e3ccSAndroid Build Coastguard Worker if (c == eob - 1) {
678*77c1e3ccSAndroid Build Coastguard Worker assert(coeff_ctx < 4);
679*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
680*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_base_eob_multi[cdf_idx][txsize_ctx][plane_type]
681*77c1e3ccSAndroid Build Coastguard Worker [coeff_ctx][AOMMIN(level, 3) - 1];
682*77c1e3ccSAndroid Build Coastguard Worker } else {
683*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_base_multi[cdf_idx][txsize_ctx][plane_type]
684*77c1e3ccSAndroid Build Coastguard Worker [coeff_ctx][AOMMIN(level, 3)];
685*77c1e3ccSAndroid Build Coastguard Worker #endif
686*77c1e3ccSAndroid Build Coastguard Worker }
687*77c1e3ccSAndroid Build Coastguard Worker if (level > NUM_BASE_LEVELS) {
688*77c1e3ccSAndroid Build Coastguard Worker const int base_range = level - 1 - NUM_BASE_LEVELS;
689*77c1e3ccSAndroid Build Coastguard Worker const int br_ctx = get_br_ctx(levels, pos, bhl, tx_class);
690*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
691*77c1e3ccSAndroid Build Coastguard Worker const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
692*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf) {
693*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->coeff_br_cdf[AOMMIN(txsize_ctx, TX_32X32)]
694*77c1e3ccSAndroid Build Coastguard Worker [plane_type][br_ctx],
695*77c1e3ccSAndroid Build Coastguard Worker k, BR_CDF_SIZE);
696*77c1e3ccSAndroid Build Coastguard Worker }
697*77c1e3ccSAndroid Build Coastguard Worker for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
698*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
699*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type]
700*77c1e3ccSAndroid Build Coastguard Worker [lps][br_ctx][lps == k];
701*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
702*77c1e3ccSAndroid Build Coastguard Worker if (lps == k) break;
703*77c1e3ccSAndroid Build Coastguard Worker }
704*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
705*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_lps_multi[cdf_idx][AOMMIN(txsize_ctx, TX_32X32)]
706*77c1e3ccSAndroid Build Coastguard Worker [plane_type][br_ctx][k];
707*77c1e3ccSAndroid Build Coastguard Worker #endif
708*77c1e3ccSAndroid Build Coastguard Worker if (k < BR_CDF_SIZE - 1) break;
709*77c1e3ccSAndroid Build Coastguard Worker }
710*77c1e3ccSAndroid Build Coastguard Worker }
711*77c1e3ccSAndroid Build Coastguard Worker }
712*77c1e3ccSAndroid Build Coastguard Worker // Update the context needed to code the DC sign (if applicable)
713*77c1e3ccSAndroid Build Coastguard Worker if (tcoeff[0] != 0) {
714*77c1e3ccSAndroid Build Coastguard Worker const int dc_sign = (tcoeff[0] < 0) ? 1 : 0;
715*77c1e3ccSAndroid Build Coastguard Worker const int dc_sign_ctx = txb_ctx.dc_sign_ctx;
716*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
717*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->dc_sign[plane_type][dc_sign_ctx][dc_sign];
718*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
719*77c1e3ccSAndroid Build Coastguard Worker if (allow_update_cdf)
720*77c1e3ccSAndroid Build Coastguard Worker update_cdf(ec_ctx->dc_sign_cdf[plane_type][dc_sign_ctx], dc_sign, 2);
721*77c1e3ccSAndroid Build Coastguard Worker entropy_ctx[block] |= dc_sign_ctx << DC_SIGN_CTX_SHIFT;
722*77c1e3ccSAndroid Build Coastguard Worker }
723*77c1e3ccSAndroid Build Coastguard Worker } else {
724*77c1e3ccSAndroid Build Coastguard Worker tcoeff = qcoeff;
725*77c1e3ccSAndroid Build Coastguard Worker }
726*77c1e3ccSAndroid Build Coastguard Worker const uint8_t cul_level =
727*77c1e3ccSAndroid Build Coastguard Worker av1_get_txb_entropy_context(tcoeff, scan_order, eob);
728*77c1e3ccSAndroid Build Coastguard Worker av1_set_entropy_contexts(xd, pd, plane, plane_bsize, tx_size, cul_level,
729*77c1e3ccSAndroid Build Coastguard Worker blk_col, blk_row);
730*77c1e3ccSAndroid Build Coastguard Worker }
731*77c1e3ccSAndroid Build Coastguard Worker
732*77c1e3ccSAndroid Build Coastguard Worker void av1_record_txb_context(int plane, int block, int blk_row, int blk_col,
733*77c1e3ccSAndroid Build Coastguard Worker BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
734*77c1e3ccSAndroid Build Coastguard Worker void *arg) {
735*77c1e3ccSAndroid Build Coastguard Worker struct tokenize_b_args *const args = arg;
736*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMP *cpi = args->cpi;
737*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *cm = &cpi->common;
738*77c1e3ccSAndroid Build Coastguard Worker ThreadData *const td = args->td;
739*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x = &td->mb;
740*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
741*77c1e3ccSAndroid Build Coastguard Worker struct macroblock_plane *p = &x->plane[plane];
742*77c1e3ccSAndroid Build Coastguard Worker struct macroblockd_plane *pd = &xd->plane[plane];
743*77c1e3ccSAndroid Build Coastguard Worker const int eob = p->eobs[block];
744*77c1e3ccSAndroid Build Coastguard Worker const int block_offset = BLOCK_OFFSET(block);
745*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *qcoeff = p->qcoeff + block_offset;
746*77c1e3ccSAndroid Build Coastguard Worker const PLANE_TYPE plane_type = pd->plane_type;
747*77c1e3ccSAndroid Build Coastguard Worker const TX_TYPE tx_type =
748*77c1e3ccSAndroid Build Coastguard Worker av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
749*77c1e3ccSAndroid Build Coastguard Worker cm->features.reduced_tx_set_used);
750*77c1e3ccSAndroid Build Coastguard Worker const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
751*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *tcoeff;
752*77c1e3ccSAndroid Build Coastguard Worker assert(args->dry_run != DRY_RUN_COSTCOEFFS);
753*77c1e3ccSAndroid Build Coastguard Worker if (args->dry_run == OUTPUT_ENABLED) {
754*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *mbmi = xd->mi[0];
755*77c1e3ccSAndroid Build Coastguard Worker TXB_CTX txb_ctx;
756*77c1e3ccSAndroid Build Coastguard Worker get_txb_ctx(plane_bsize, tx_size, plane,
757*77c1e3ccSAndroid Build Coastguard Worker pd->above_entropy_context + blk_col,
758*77c1e3ccSAndroid Build Coastguard Worker pd->left_entropy_context + blk_row, &txb_ctx);
759*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
760*77c1e3ccSAndroid Build Coastguard Worker const TX_SIZE txsize_ctx = get_txsize_entropy_ctx(tx_size);
761*77c1e3ccSAndroid Build Coastguard Worker const int bhl = get_txb_bhl(tx_size);
762*77c1e3ccSAndroid Build Coastguard Worker const int width = get_txb_wide(tx_size);
763*77c1e3ccSAndroid Build Coastguard Worker const int height = get_txb_high(tx_size);
764*77c1e3ccSAndroid Build Coastguard Worker int cdf_idx = cm->coef_cdf_category;
765*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->txb_skip[cdf_idx][txsize_ctx][txb_ctx.txb_skip_ctx][eob == 0];
766*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
767*77c1e3ccSAndroid Build Coastguard Worker
768*77c1e3ccSAndroid Build Coastguard Worker CB_COEFF_BUFFER *cb_coef_buff = x->cb_coef_buff;
769*77c1e3ccSAndroid Build Coastguard Worker const int txb_offset = x->mbmi_ext_frame->cb_offset[plane_type] /
770*77c1e3ccSAndroid Build Coastguard Worker (TX_SIZE_W_MIN * TX_SIZE_H_MIN);
771*77c1e3ccSAndroid Build Coastguard Worker uint16_t *eob_txb = cb_coef_buff->eobs[plane] + txb_offset;
772*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const entropy_ctx = cb_coef_buff->entropy_ctx[plane] + txb_offset;
773*77c1e3ccSAndroid Build Coastguard Worker entropy_ctx[block] = txb_ctx.txb_skip_ctx;
774*77c1e3ccSAndroid Build Coastguard Worker eob_txb[block] = eob;
775*77c1e3ccSAndroid Build Coastguard Worker
776*77c1e3ccSAndroid Build Coastguard Worker if (eob == 0) {
777*77c1e3ccSAndroid Build Coastguard Worker av1_set_entropy_contexts(xd, pd, plane, plane_bsize, tx_size, 0, blk_col,
778*77c1e3ccSAndroid Build Coastguard Worker blk_row);
779*77c1e3ccSAndroid Build Coastguard Worker return;
780*77c1e3ccSAndroid Build Coastguard Worker }
781*77c1e3ccSAndroid Build Coastguard Worker const int segment_id = mbmi->segment_id;
782*77c1e3ccSAndroid Build Coastguard Worker const int seg_eob = av1_get_tx_eob(&cpi->common.seg, segment_id, tx_size);
783*77c1e3ccSAndroid Build Coastguard Worker tran_low_t *tcoeff_txb =
784*77c1e3ccSAndroid Build Coastguard Worker cb_coef_buff->tcoeff[plane] + x->mbmi_ext_frame->cb_offset[plane_type];
785*77c1e3ccSAndroid Build Coastguard Worker tcoeff = tcoeff_txb + block_offset;
786*77c1e3ccSAndroid Build Coastguard Worker memcpy(tcoeff, qcoeff, sizeof(*tcoeff) * seg_eob);
787*77c1e3ccSAndroid Build Coastguard Worker
788*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
789*77c1e3ccSAndroid Build Coastguard Worker uint8_t levels_buf[TX_PAD_2D];
790*77c1e3ccSAndroid Build Coastguard Worker uint8_t *const levels = set_levels(levels_buf, height);
791*77c1e3ccSAndroid Build Coastguard Worker av1_txb_init_levels(tcoeff, width, height, levels);
792*77c1e3ccSAndroid Build Coastguard Worker update_tx_type_count(cpi, cm, xd, blk_row, blk_col, plane, tx_size,
793*77c1e3ccSAndroid Build Coastguard Worker td->counts, 0 /*allow_update_cdf*/);
794*77c1e3ccSAndroid Build Coastguard Worker
795*77c1e3ccSAndroid Build Coastguard Worker const TX_CLASS tx_class = tx_type_to_class[tx_type];
796*77c1e3ccSAndroid Build Coastguard Worker const bool do_coeff_scan = true;
797*77c1e3ccSAndroid Build Coastguard Worker #else
798*77c1e3ccSAndroid Build Coastguard Worker const bool do_coeff_scan = cpi->mt_info.pack_bs_mt_enabled;
799*77c1e3ccSAndroid Build Coastguard Worker #endif
800*77c1e3ccSAndroid Build Coastguard Worker const int16_t *const scan = scan_order->scan;
801*77c1e3ccSAndroid Build Coastguard Worker
802*77c1e3ccSAndroid Build Coastguard Worker // record tx type usage
803*77c1e3ccSAndroid Build Coastguard Worker td->rd_counts.tx_type_used[tx_size][tx_type]++;
804*77c1e3ccSAndroid Build Coastguard Worker
805*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
806*77c1e3ccSAndroid Build Coastguard Worker FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
807*77c1e3ccSAndroid Build Coastguard Worker update_eob_context(cdf_idx, eob, tx_size, tx_class, plane_type, ec_ctx,
808*77c1e3ccSAndroid Build Coastguard Worker td->counts, 0 /*allow_update_cdf*/);
809*77c1e3ccSAndroid Build Coastguard Worker
810*77c1e3ccSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, int8_t, coeff_contexts[MAX_TX_SQUARE]);
811*77c1e3ccSAndroid Build Coastguard Worker av1_get_nz_map_contexts(levels, scan, eob, tx_size, tx_class,
812*77c1e3ccSAndroid Build Coastguard Worker coeff_contexts);
813*77c1e3ccSAndroid Build Coastguard Worker #endif
814*77c1e3ccSAndroid Build Coastguard Worker
815*77c1e3ccSAndroid Build Coastguard Worker for (int c = eob - 1; (c >= 0) && do_coeff_scan; --c) {
816*77c1e3ccSAndroid Build Coastguard Worker const int pos = scan[c];
817*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t v = qcoeff[pos];
818*77c1e3ccSAndroid Build Coastguard Worker const tran_low_t level = abs(v);
819*77c1e3ccSAndroid Build Coastguard Worker /* abs_sum_level is needed to decide the job scheduling order of
820*77c1e3ccSAndroid Build Coastguard Worker * pack bitstream multi-threading. This data is not needed if
821*77c1e3ccSAndroid Build Coastguard Worker * multi-threading is disabled. */
822*77c1e3ccSAndroid Build Coastguard Worker if (cpi->mt_info.pack_bs_mt_enabled) td->abs_sum_level += level;
823*77c1e3ccSAndroid Build Coastguard Worker
824*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
825*77c1e3ccSAndroid Build Coastguard Worker const int coeff_ctx = coeff_contexts[pos];
826*77c1e3ccSAndroid Build Coastguard Worker if (c == eob - 1) {
827*77c1e3ccSAndroid Build Coastguard Worker assert(coeff_ctx < 4);
828*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_base_eob_multi[cdf_idx][txsize_ctx][plane_type]
829*77c1e3ccSAndroid Build Coastguard Worker [coeff_ctx][AOMMIN(level, 3) - 1];
830*77c1e3ccSAndroid Build Coastguard Worker } else {
831*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_base_multi[cdf_idx][txsize_ctx][plane_type]
832*77c1e3ccSAndroid Build Coastguard Worker [coeff_ctx][AOMMIN(level, 3)];
833*77c1e3ccSAndroid Build Coastguard Worker }
834*77c1e3ccSAndroid Build Coastguard Worker if (level > NUM_BASE_LEVELS) {
835*77c1e3ccSAndroid Build Coastguard Worker const int base_range = level - 1 - NUM_BASE_LEVELS;
836*77c1e3ccSAndroid Build Coastguard Worker const int br_ctx = get_br_ctx(levels, pos, bhl, tx_class);
837*77c1e3ccSAndroid Build Coastguard Worker for (int idx = 0; idx < COEFF_BASE_RANGE; idx += BR_CDF_SIZE - 1) {
838*77c1e3ccSAndroid Build Coastguard Worker const int k = AOMMIN(base_range - idx, BR_CDF_SIZE - 1);
839*77c1e3ccSAndroid Build Coastguard Worker for (int lps = 0; lps < BR_CDF_SIZE - 1; lps++) {
840*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_lps[AOMMIN(txsize_ctx, TX_32X32)][plane_type]
841*77c1e3ccSAndroid Build Coastguard Worker [lps][br_ctx][lps == k];
842*77c1e3ccSAndroid Build Coastguard Worker if (lps == k) break;
843*77c1e3ccSAndroid Build Coastguard Worker }
844*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->coeff_lps_multi[cdf_idx][AOMMIN(txsize_ctx, TX_32X32)]
845*77c1e3ccSAndroid Build Coastguard Worker [plane_type][br_ctx][k];
846*77c1e3ccSAndroid Build Coastguard Worker if (k < BR_CDF_SIZE - 1) break;
847*77c1e3ccSAndroid Build Coastguard Worker }
848*77c1e3ccSAndroid Build Coastguard Worker }
849*77c1e3ccSAndroid Build Coastguard Worker #endif
850*77c1e3ccSAndroid Build Coastguard Worker }
851*77c1e3ccSAndroid Build Coastguard Worker // Update the context needed to code the DC sign (if applicable)
852*77c1e3ccSAndroid Build Coastguard Worker if (tcoeff[0] != 0) {
853*77c1e3ccSAndroid Build Coastguard Worker const int dc_sign_ctx = txb_ctx.dc_sign_ctx;
854*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_ENTROPY_STATS
855*77c1e3ccSAndroid Build Coastguard Worker const int dc_sign = (tcoeff[0] < 0) ? 1 : 0;
856*77c1e3ccSAndroid Build Coastguard Worker ++td->counts->dc_sign[plane_type][dc_sign_ctx][dc_sign];
857*77c1e3ccSAndroid Build Coastguard Worker #endif // CONFIG_ENTROPY_STATS
858*77c1e3ccSAndroid Build Coastguard Worker entropy_ctx[block] |= dc_sign_ctx << DC_SIGN_CTX_SHIFT;
859*77c1e3ccSAndroid Build Coastguard Worker }
860*77c1e3ccSAndroid Build Coastguard Worker } else {
861*77c1e3ccSAndroid Build Coastguard Worker tcoeff = qcoeff;
862*77c1e3ccSAndroid Build Coastguard Worker }
863*77c1e3ccSAndroid Build Coastguard Worker const uint8_t cul_level =
864*77c1e3ccSAndroid Build Coastguard Worker av1_get_txb_entropy_context(tcoeff, scan_order, eob);
865*77c1e3ccSAndroid Build Coastguard Worker av1_set_entropy_contexts(xd, pd, plane, plane_bsize, tx_size, cul_level,
866*77c1e3ccSAndroid Build Coastguard Worker blk_col, blk_row);
867*77c1e3ccSAndroid Build Coastguard Worker }
868*77c1e3ccSAndroid Build Coastguard Worker
869*77c1e3ccSAndroid Build Coastguard Worker void av1_update_intra_mb_txb_context(const AV1_COMP *cpi, ThreadData *td,
870*77c1e3ccSAndroid Build Coastguard Worker RUN_TYPE dry_run, BLOCK_SIZE bsize,
871*77c1e3ccSAndroid Build Coastguard Worker uint8_t allow_update_cdf) {
872*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
873*77c1e3ccSAndroid Build Coastguard Worker const int num_planes = av1_num_planes(cm);
874*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCK *const x = &td->mb;
875*77c1e3ccSAndroid Build Coastguard Worker MACROBLOCKD *const xd = &x->e_mbd;
876*77c1e3ccSAndroid Build Coastguard Worker MB_MODE_INFO *const mbmi = xd->mi[0];
877*77c1e3ccSAndroid Build Coastguard Worker struct tokenize_b_args arg = { cpi, td, 0, allow_update_cdf, dry_run };
878*77c1e3ccSAndroid Build Coastguard Worker if (mbmi->skip_txfm) {
879*77c1e3ccSAndroid Build Coastguard Worker av1_reset_entropy_context(xd, bsize, num_planes);
880*77c1e3ccSAndroid Build Coastguard Worker return;
881*77c1e3ccSAndroid Build Coastguard Worker }
882*77c1e3ccSAndroid Build Coastguard Worker const foreach_transformed_block_visitor visit =
883*77c1e3ccSAndroid Build Coastguard Worker allow_update_cdf ? av1_update_and_record_txb_context
884*77c1e3ccSAndroid Build Coastguard Worker : av1_record_txb_context;
885*77c1e3ccSAndroid Build Coastguard Worker
886*77c1e3ccSAndroid Build Coastguard Worker for (int plane = 0; plane < num_planes; ++plane) {
887*77c1e3ccSAndroid Build Coastguard Worker if (plane && !xd->is_chroma_ref) break;
888*77c1e3ccSAndroid Build Coastguard Worker const struct macroblockd_plane *const pd = &xd->plane[plane];
889*77c1e3ccSAndroid Build Coastguard Worker const int ss_x = pd->subsampling_x;
890*77c1e3ccSAndroid Build Coastguard Worker const int ss_y = pd->subsampling_y;
891*77c1e3ccSAndroid Build Coastguard Worker const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, ss_x, ss_y);
892*77c1e3ccSAndroid Build Coastguard Worker av1_foreach_transformed_block_in_plane(xd, plane_bsize, plane, visit, &arg);
893*77c1e3ccSAndroid Build Coastguard Worker }
894*77c1e3ccSAndroid Build Coastguard Worker }
895*77c1e3ccSAndroid Build Coastguard Worker
896*77c1e3ccSAndroid Build Coastguard Worker CB_COEFF_BUFFER *av1_get_cb_coeff_buffer(const struct AV1_COMP *cpi, int mi_row,
897*77c1e3ccSAndroid Build Coastguard Worker int mi_col) {
898*77c1e3ccSAndroid Build Coastguard Worker const AV1_COMMON *const cm = &cpi->common;
899*77c1e3ccSAndroid Build Coastguard Worker const int mib_size_log2 = cm->seq_params->mib_size_log2;
900*77c1e3ccSAndroid Build Coastguard Worker const int stride =
901*77c1e3ccSAndroid Build Coastguard Worker CEIL_POWER_OF_TWO(cm->mi_params.mi_cols, cm->seq_params->mib_size_log2);
902*77c1e3ccSAndroid Build Coastguard Worker const int offset =
903*77c1e3ccSAndroid Build Coastguard Worker (mi_row >> mib_size_log2) * stride + (mi_col >> mib_size_log2);
904*77c1e3ccSAndroid Build Coastguard Worker return cpi->coeff_buffer_base + offset;
905*77c1e3ccSAndroid Build Coastguard Worker }
906