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