xref: /aosp_15_r20/external/libaom/av1/common/txb_common.h (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2017, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #ifndef AOM_AV1_COMMON_TXB_COMMON_H_
13 #define AOM_AV1_COMMON_TXB_COMMON_H_
14 
15 #include "av1/common/av1_common_int.h"
16 
17 extern const int16_t av1_eob_group_start[12];
18 extern const int16_t av1_eob_offset_bits[12];
19 
20 extern const int8_t *av1_nz_map_ctx_offset[TX_SIZES_ALL];
21 
22 typedef struct txb_ctx {
23   int txb_skip_ctx;
24   int dc_sign_ctx;
25 } TXB_CTX;
26 
27 static const int base_level_count_to_index[13] = {
28   0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
29 };
30 
31 static const TX_CLASS tx_type_to_class[TX_TYPES] = {
32   TX_CLASS_2D,     // DCT_DCT
33   TX_CLASS_2D,     // ADST_DCT
34   TX_CLASS_2D,     // DCT_ADST
35   TX_CLASS_2D,     // ADST_ADST
36   TX_CLASS_2D,     // FLIPADST_DCT
37   TX_CLASS_2D,     // DCT_FLIPADST
38   TX_CLASS_2D,     // FLIPADST_FLIPADST
39   TX_CLASS_2D,     // ADST_FLIPADST
40   TX_CLASS_2D,     // FLIPADST_ADST
41   TX_CLASS_2D,     // IDTX
42   TX_CLASS_VERT,   // V_DCT
43   TX_CLASS_HORIZ,  // H_DCT
44   TX_CLASS_VERT,   // V_ADST
45   TX_CLASS_HORIZ,  // H_ADST
46   TX_CLASS_VERT,   // V_FLIPADST
47   TX_CLASS_HORIZ,  // H_FLIPADST
48 };
49 
get_txb_bhl(TX_SIZE tx_size)50 static inline int get_txb_bhl(TX_SIZE tx_size) {
51   tx_size = av1_get_adjusted_tx_size(tx_size);
52   return tx_size_high_log2[tx_size];
53 }
54 
get_txb_wide(TX_SIZE tx_size)55 static inline int get_txb_wide(TX_SIZE tx_size) {
56   tx_size = av1_get_adjusted_tx_size(tx_size);
57   return tx_size_wide[tx_size];
58 }
59 
get_txb_high(TX_SIZE tx_size)60 static inline int get_txb_high(TX_SIZE tx_size) {
61   tx_size = av1_get_adjusted_tx_size(tx_size);
62   return tx_size_high[tx_size];
63 }
64 
set_levels(uint8_t * const levels_buf,const int height)65 static inline uint8_t *set_levels(uint8_t *const levels_buf, const int height) {
66   return levels_buf + TX_PAD_TOP * (height + TX_PAD_HOR);
67 }
68 
get_padded_idx(const int idx,const int bhl)69 static inline int get_padded_idx(const int idx, const int bhl) {
70   return idx + ((idx >> bhl) << TX_PAD_HOR_LOG2);
71 }
72 
get_br_ctx_2d(const uint8_t * const levels,const int c,const int bhl)73 static inline int get_br_ctx_2d(const uint8_t *const levels,
74                                 const int c,  // raster order
75                                 const int bhl) {
76   assert(c > 0);
77   const int col = c >> bhl;
78   const int row = c - (col << bhl);
79   const int stride = (1 << bhl) + TX_PAD_HOR;
80   const int pos = col * stride + row;
81   int mag = AOMMIN(levels[pos + 1], MAX_BASE_BR_RANGE) +
82             AOMMIN(levels[pos + stride], MAX_BASE_BR_RANGE) +
83             AOMMIN(levels[pos + 1 + stride], MAX_BASE_BR_RANGE);
84   mag = AOMMIN((mag + 1) >> 1, 6);
85   //((row | col) < 2) is equivalent to ((row < 2) && (col < 2))
86   if ((row | col) < 2) return mag + 7;
87   return mag + 14;
88 }
89 
get_br_ctx_eob(const int c,const int bhl,const TX_CLASS tx_class)90 static AOM_FORCE_INLINE int get_br_ctx_eob(const int c,  // raster order
91                                            const int bhl,
92                                            const TX_CLASS tx_class) {
93   const int col = c >> bhl;
94   const int row = c - (col << bhl);
95   if (c == 0) return 0;
96   if ((tx_class == TX_CLASS_2D && row < 2 && col < 2) ||
97       (tx_class == TX_CLASS_HORIZ && col == 0) ||
98       (tx_class == TX_CLASS_VERT && row == 0))
99     return 7;
100   return 14;
101 }
102 
get_br_ctx(const uint8_t * const levels,const int c,const int bhl,const TX_CLASS tx_class)103 static AOM_FORCE_INLINE int get_br_ctx(const uint8_t *const levels,
104                                        const int c,  // raster order
105                                        const int bhl, const TX_CLASS tx_class) {
106   const int col = c >> bhl;
107   const int row = c - (col << bhl);
108   const int stride = (1 << bhl) + TX_PAD_HOR;
109   const int pos = col * stride + row;
110   int mag = levels[pos + 1];
111   mag += levels[pos + stride];
112   switch (tx_class) {
113     case TX_CLASS_2D:
114       mag += levels[pos + stride + 1];
115       mag = AOMMIN((mag + 1) >> 1, 6);
116       if (c == 0) return mag;
117       if ((row < 2) && (col < 2)) return mag + 7;
118       break;
119     case TX_CLASS_HORIZ:
120       mag += levels[pos + (stride << 1)];
121       mag = AOMMIN((mag + 1) >> 1, 6);
122       if (c == 0) return mag;
123       if (col == 0) return mag + 7;
124       break;
125     case TX_CLASS_VERT:
126       mag += levels[pos + 2];
127       mag = AOMMIN((mag + 1) >> 1, 6);
128       if (c == 0) return mag;
129       if (row == 0) return mag + 7;
130       break;
131     default: break;
132   }
133 
134   return mag + 14;
135 }
136 
137 static const uint8_t clip_max3[256] = {
138   0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
139   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
140   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
141   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
142   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
143   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
144   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
145   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
146   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
147   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
148 };
149 
get_nz_mag(const uint8_t * const levels,const int bhl,const TX_CLASS tx_class)150 static AOM_FORCE_INLINE int get_nz_mag(const uint8_t *const levels,
151                                        const int bhl, const TX_CLASS tx_class) {
152   int mag;
153 
154   // Note: AOMMIN(level, 3) is useless for decoder since level < 3.
155   mag = clip_max3[levels[(1 << bhl) + TX_PAD_HOR]];  // { 0, 1 }
156   mag += clip_max3[levels[1]];                       // { 1, 0 }
157 
158   if (tx_class == TX_CLASS_2D) {
159     mag += clip_max3[levels[(1 << bhl) + TX_PAD_HOR + 1]];          // { 1, 1 }
160     mag += clip_max3[levels[(2 << bhl) + (2 << TX_PAD_HOR_LOG2)]];  // { 0, 2 }
161     mag += clip_max3[levels[2]];                                    // { 2, 0 }
162   } else if (tx_class == TX_CLASS_VERT) {
163     mag += clip_max3[levels[2]];  // { 2, 0 }
164     mag += clip_max3[levels[3]];  // { 3, 0 }
165     mag += clip_max3[levels[4]];  // { 4, 0 }
166   } else {
167     mag += clip_max3[levels[(2 << bhl) + (2 << TX_PAD_HOR_LOG2)]];  // { 0, 2 }
168     mag += clip_max3[levels[(3 << bhl) + (3 << TX_PAD_HOR_LOG2)]];  // { 0, 3 }
169     mag += clip_max3[levels[(4 << bhl) + (4 << TX_PAD_HOR_LOG2)]];  // { 0, 4 }
170   }
171 
172   return mag;
173 }
174 
175 #define NZ_MAP_CTX_0 SIG_COEF_CONTEXTS_2D
176 #define NZ_MAP_CTX_5 (NZ_MAP_CTX_0 + 5)
177 #define NZ_MAP_CTX_10 (NZ_MAP_CTX_0 + 10)
178 
179 static const int nz_map_ctx_offset_1d[32] = {
180   NZ_MAP_CTX_0,  NZ_MAP_CTX_5,  NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
181   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
182   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
183   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
184   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
185   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
186   NZ_MAP_CTX_10, NZ_MAP_CTX_10,
187 };
188 
get_nz_map_ctx_from_stats(const int stats,const int coeff_idx,const int bhl,const TX_SIZE tx_size,const TX_CLASS tx_class)189 static AOM_FORCE_INLINE int get_nz_map_ctx_from_stats(
190     const int stats,
191     const int coeff_idx,  // raster order
192     const int bhl, const TX_SIZE tx_size, const TX_CLASS tx_class) {
193   // tx_class == 0(TX_CLASS_2D)
194   if ((tx_class | coeff_idx) == 0) return 0;
195   int ctx = (stats + 1) >> 1;
196   ctx = AOMMIN(ctx, 4);
197   switch (tx_class) {
198     case TX_CLASS_2D: {
199       // This is the algorithm to generate av1_nz_map_ctx_offset[][]
200       //   const int width = tx_size_wide[tx_size];
201       //   const int height = tx_size_high[tx_size];
202       //   if (width < height) {
203       //     if (row < 2) return 11 + ctx;
204       //   } else if (width > height) {
205       //     if (col < 2) return 16 + ctx;
206       //   }
207       //   if (row + col < 2) return ctx + 1;
208       //   if (row + col < 4) return 5 + ctx + 1;
209       //   return 21 + ctx;
210       return ctx + av1_nz_map_ctx_offset[tx_size][coeff_idx];
211     }
212     case TX_CLASS_HORIZ: {
213       const int col = coeff_idx >> bhl;
214       return ctx + nz_map_ctx_offset_1d[col];
215     }
216     case TX_CLASS_VERT: {
217       const int col = coeff_idx >> bhl;
218       const int row = coeff_idx - (col << bhl);
219       return ctx + nz_map_ctx_offset_1d[row];
220     }
221     default: break;
222   }
223   return 0;
224 }
225 
226 typedef aom_cdf_prob (*base_cdf_arr)[CDF_SIZE(4)];
227 typedef aom_cdf_prob (*br_cdf_arr)[CDF_SIZE(BR_CDF_SIZE)];
228 
get_lower_levels_ctx_eob(int bhl,int width,int scan_idx)229 static inline int get_lower_levels_ctx_eob(int bhl, int width, int scan_idx) {
230   if (scan_idx == 0) return 0;
231   if (scan_idx <= (width << bhl) / 8) return 1;
232   if (scan_idx <= (width << bhl) / 4) return 2;
233   return 3;
234 }
235 
get_lower_levels_ctx_2d(const uint8_t * levels,int coeff_idx,int bhl,TX_SIZE tx_size)236 static inline int get_lower_levels_ctx_2d(const uint8_t *levels, int coeff_idx,
237                                           int bhl, TX_SIZE tx_size) {
238   assert(coeff_idx > 0);
239   int mag;
240   // Note: AOMMIN(level, 3) is useless for decoder since level < 3.
241   levels = levels + get_padded_idx(coeff_idx, bhl);
242   mag = AOMMIN(levels[(1 << bhl) + TX_PAD_HOR], 3);               // { 0, 1 }
243   mag += AOMMIN(levels[1], 3);                                    // { 1, 0 }
244   mag += AOMMIN(levels[(1 << bhl) + TX_PAD_HOR + 1], 3);          // { 1, 1 }
245   mag += AOMMIN(levels[(2 << bhl) + (2 << TX_PAD_HOR_LOG2)], 3);  // { 0, 2 }
246   mag += AOMMIN(levels[2], 3);                                    // { 2, 0 }
247 
248   const int ctx = AOMMIN((mag + 1) >> 1, 4);
249   return ctx + av1_nz_map_ctx_offset[tx_size][coeff_idx];
250 }
get_lower_levels_ctx(const uint8_t * levels,int coeff_idx,int bhl,TX_SIZE tx_size,TX_CLASS tx_class)251 static AOM_FORCE_INLINE int get_lower_levels_ctx(const uint8_t *levels,
252                                                  int coeff_idx, int bhl,
253                                                  TX_SIZE tx_size,
254                                                  TX_CLASS tx_class) {
255   const int stats =
256       get_nz_mag(levels + get_padded_idx(coeff_idx, bhl), bhl, tx_class);
257   return get_nz_map_ctx_from_stats(stats, coeff_idx, bhl, tx_size, tx_class);
258 }
259 
get_lower_levels_ctx_general(int is_last,int scan_idx,int bhl,int width,const uint8_t * levels,int coeff_idx,TX_SIZE tx_size,TX_CLASS tx_class)260 static inline int get_lower_levels_ctx_general(int is_last, int scan_idx,
261                                                int bhl, int width,
262                                                const uint8_t *levels,
263                                                int coeff_idx, TX_SIZE tx_size,
264                                                TX_CLASS tx_class) {
265   if (is_last) {
266     if (scan_idx == 0) return 0;
267     if (scan_idx <= (width << bhl) >> 3) return 1;
268     if (scan_idx <= (width << bhl) >> 2) return 2;
269     return 3;
270   }
271   return get_lower_levels_ctx(levels, coeff_idx, bhl, tx_size, tx_class);
272 }
273 
set_dc_sign(int * cul_level,int dc_val)274 static inline void set_dc_sign(int *cul_level, int dc_val) {
275   if (dc_val < 0)
276     *cul_level |= 1 << COEFF_CONTEXT_BITS;
277   else if (dc_val > 0)
278     *cul_level += 2 << COEFF_CONTEXT_BITS;
279 }
280 
get_txb_ctx_general(const BLOCK_SIZE plane_bsize,const TX_SIZE tx_size,const int plane,const ENTROPY_CONTEXT * const a,const ENTROPY_CONTEXT * const l,TXB_CTX * const txb_ctx)281 static void get_txb_ctx_general(const BLOCK_SIZE plane_bsize,
282                                 const TX_SIZE tx_size, const int plane,
283                                 const ENTROPY_CONTEXT *const a,
284                                 const ENTROPY_CONTEXT *const l,
285                                 TXB_CTX *const txb_ctx) {
286 #define MAX_TX_SIZE_UNIT 16
287   static const int8_t signs[3] = { 0, -1, 1 };
288   static const int8_t dc_sign_contexts[4 * MAX_TX_SIZE_UNIT + 1] = {
289     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
290     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
291     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
292   };
293   const int txb_w_unit = tx_size_wide_unit[tx_size];
294   const int txb_h_unit = tx_size_high_unit[tx_size];
295   int dc_sign = 0;
296   int k = 0;
297 
298   do {
299     const unsigned int sign = ((uint8_t)a[k]) >> COEFF_CONTEXT_BITS;
300     assert(sign <= 2);
301     dc_sign += signs[sign];
302   } while (++k < txb_w_unit);
303 
304   k = 0;
305   do {
306     const unsigned int sign = ((uint8_t)l[k]) >> COEFF_CONTEXT_BITS;
307     assert(sign <= 2);
308     dc_sign += signs[sign];
309   } while (++k < txb_h_unit);
310 
311   txb_ctx->dc_sign_ctx = dc_sign_contexts[dc_sign + 2 * MAX_TX_SIZE_UNIT];
312 
313   if (plane == 0) {
314     if (plane_bsize == txsize_to_bsize[tx_size]) {
315       txb_ctx->txb_skip_ctx = 0;
316     } else {
317       // This is the algorithm to generate table skip_contexts[top][left].
318       //    const int max = AOMMIN(top | left, 4);
319       //    const int min = AOMMIN(AOMMIN(top, left), 4);
320       //    if (!max)
321       //      txb_skip_ctx = 1;
322       //    else if (!min)
323       //      txb_skip_ctx = 2 + (max > 3);
324       //    else if (max <= 3)
325       //      txb_skip_ctx = 4;
326       //    else if (min <= 3)
327       //      txb_skip_ctx = 5;
328       //    else
329       //      txb_skip_ctx = 6;
330       static const uint8_t skip_contexts[5][5] = { { 1, 2, 2, 2, 3 },
331                                                    { 2, 4, 4, 4, 5 },
332                                                    { 2, 4, 4, 4, 5 },
333                                                    { 2, 4, 4, 4, 5 },
334                                                    { 3, 5, 5, 5, 6 } };
335       // For top and left, we only care about which of the following three
336       // categories they belong to: { 0 }, { 1, 2, 3 }, or { 4, 5, ... }. The
337       // spec calculates top and left with the Max() function. We can calculate
338       // an approximate max with bitwise OR because the real max and the
339       // approximate max belong to the same category.
340       int top = 0;
341       int left = 0;
342 
343       k = 0;
344       do {
345         top |= a[k];
346       } while (++k < txb_w_unit);
347       top &= COEFF_CONTEXT_MASK;
348       top = AOMMIN(top, 4);
349 
350       k = 0;
351       do {
352         left |= l[k];
353       } while (++k < txb_h_unit);
354       left &= COEFF_CONTEXT_MASK;
355       left = AOMMIN(left, 4);
356 
357       txb_ctx->txb_skip_ctx = skip_contexts[top][left];
358     }
359   } else {
360     const int ctx_base = get_entropy_context(tx_size, a, l);
361     const int ctx_offset = (num_pels_log2_lookup[plane_bsize] >
362                             num_pels_log2_lookup[txsize_to_bsize[tx_size]])
363                                ? 10
364                                : 7;
365     txb_ctx->txb_skip_ctx = ctx_base + ctx_offset;
366   }
367 }
368 
369 #define SPECIALIZE_GET_TXB_CTX(w, h)                                          \
370   static void get_txb_ctx_##w##x##h(                                          \
371       const BLOCK_SIZE plane_bsize, const int plane,                          \
372       const ENTROPY_CONTEXT *const a, const ENTROPY_CONTEXT *const l,         \
373       TXB_CTX *const txb_ctx) {                                               \
374     static const int8_t signs[3] = { 0, -1, 1 };                              \
375     static const int8_t dc_sign_contexts[4 * MAX_TX_SIZE_UNIT + 1] = {        \
376       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,       \
377       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,       \
378       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2           \
379     };                                                                        \
380     const TX_SIZE tx_size = TX_##w##X##h;                                     \
381     const int txb_w_unit = tx_size_wide_unit[tx_size];                        \
382     const int txb_h_unit = tx_size_high_unit[tx_size];                        \
383     int dc_sign = 0;                                                          \
384     int k = 0;                                                                \
385                                                                               \
386     do {                                                                      \
387       const unsigned int sign = ((uint8_t)a[k]) >> COEFF_CONTEXT_BITS;        \
388       assert(sign <= 2);                                                      \
389       dc_sign += signs[sign];                                                 \
390     } while (++k < txb_w_unit);                                               \
391                                                                               \
392     k = 0;                                                                    \
393     do {                                                                      \
394       const unsigned int sign = ((uint8_t)l[k]) >> COEFF_CONTEXT_BITS;        \
395       assert(sign <= 2);                                                      \
396       dc_sign += signs[sign];                                                 \
397     } while (++k < txb_h_unit);                                               \
398                                                                               \
399     txb_ctx->dc_sign_ctx = dc_sign_contexts[dc_sign + 2 * MAX_TX_SIZE_UNIT];  \
400                                                                               \
401     if (plane == 0) {                                                         \
402       if (plane_bsize == txsize_to_bsize[tx_size]) {                          \
403         txb_ctx->txb_skip_ctx = 0;                                            \
404       } else {                                                                \
405         static const uint8_t skip_contexts[5][5] = { { 1, 2, 2, 2, 3 },       \
406                                                      { 2, 4, 4, 4, 5 },       \
407                                                      { 2, 4, 4, 4, 5 },       \
408                                                      { 2, 4, 4, 4, 5 },       \
409                                                      { 3, 5, 5, 5, 6 } };     \
410         int top = 0;                                                          \
411         int left = 0;                                                         \
412                                                                               \
413         k = 0;                                                                \
414         do {                                                                  \
415           top |= a[k];                                                        \
416         } while (++k < txb_w_unit);                                           \
417         top &= COEFF_CONTEXT_MASK;                                            \
418         top = AOMMIN(top, 4);                                                 \
419                                                                               \
420         k = 0;                                                                \
421         do {                                                                  \
422           left |= l[k];                                                       \
423         } while (++k < txb_h_unit);                                           \
424         left &= COEFF_CONTEXT_MASK;                                           \
425         left = AOMMIN(left, 4);                                               \
426                                                                               \
427         txb_ctx->txb_skip_ctx = skip_contexts[top][left];                     \
428       }                                                                       \
429     } else {                                                                  \
430       const int ctx_base = get_entropy_context(tx_size, a, l);                \
431       const int ctx_offset = (num_pels_log2_lookup[plane_bsize] >             \
432                               num_pels_log2_lookup[txsize_to_bsize[tx_size]]) \
433                                  ? 10                                         \
434                                  : 7;                                         \
435       txb_ctx->txb_skip_ctx = ctx_base + ctx_offset;                          \
436     }                                                                         \
437   }
438 
439 SPECIALIZE_GET_TXB_CTX(4, 4)
440 SPECIALIZE_GET_TXB_CTX(8, 8)
441 SPECIALIZE_GET_TXB_CTX(16, 16)
442 SPECIALIZE_GET_TXB_CTX(32, 32)
443 
444 // Wrapper for get_txb_ctx that calls the specialized version of get_txb_ctc_*
445 // so that the compiler can compile away the while loops.
get_txb_ctx(const BLOCK_SIZE plane_bsize,const TX_SIZE tx_size,const int plane,const ENTROPY_CONTEXT * const a,const ENTROPY_CONTEXT * const l,TXB_CTX * const txb_ctx)446 static inline void get_txb_ctx(const BLOCK_SIZE plane_bsize,
447                                const TX_SIZE tx_size, const int plane,
448                                const ENTROPY_CONTEXT *const a,
449                                const ENTROPY_CONTEXT *const l,
450                                TXB_CTX *const txb_ctx) {
451   switch (tx_size) {
452     case TX_4X4: get_txb_ctx_4x4(plane_bsize, plane, a, l, txb_ctx); break;
453     case TX_8X8: get_txb_ctx_8x8(plane_bsize, plane, a, l, txb_ctx); break;
454     case TX_16X16: get_txb_ctx_16x16(plane_bsize, plane, a, l, txb_ctx); break;
455     case TX_32X32: get_txb_ctx_32x32(plane_bsize, plane, a, l, txb_ctx); break;
456     default:
457       get_txb_ctx_general(plane_bsize, tx_size, plane, a, l, txb_ctx);
458       break;
459   }
460 }
461 #undef MAX_TX_SIZE_UNIT
462 
463 #endif  // AOM_AV1_COMMON_TXB_COMMON_H_
464