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