xref: /aosp_15_r20/external/libaom/av1/encoder/encodetxb.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
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