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/onyxc_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_base_ctx_from_count_mag(int row,int col,int count,int sig_mag)81 static INLINE int get_base_ctx_from_count_mag(int row, int col, int count,
82                                               int sig_mag) {
83   const int ctx = base_level_count_to_index[count];
84   int ctx_idx = -1;
85 
86   if (row == 0 && col == 0) {
87     if (sig_mag >= 2) return ctx_idx = 0;
88     if (sig_mag == 1) {
89       if (count >= 2)
90         ctx_idx = 1;
91       else
92         ctx_idx = 2;
93 
94       return ctx_idx;
95     }
96 
97     ctx_idx = 3 + ctx;
98     assert(ctx_idx <= 6);
99     return ctx_idx;
100   } else if (row == 0) {
101     if (sig_mag >= 2) return ctx_idx = 6;
102     if (sig_mag == 1) {
103       if (count >= 2)
104         ctx_idx = 7;
105       else
106         ctx_idx = 8;
107       return ctx_idx;
108     }
109 
110     ctx_idx = 9 + ctx;
111     assert(ctx_idx <= 11);
112     return ctx_idx;
113   } else if (col == 0) {
114     if (sig_mag >= 2) return ctx_idx = 12;
115     if (sig_mag == 1) {
116       if (count >= 2)
117         ctx_idx = 13;
118       else
119         ctx_idx = 14;
120 
121       return ctx_idx;
122     }
123 
124     ctx_idx = 15 + ctx;
125     assert(ctx_idx <= 17);
126     // TODO(angiebird): turn this on once the optimization is finalized
127     // assert(ctx_idx < 28);
128   } else {
129     if (sig_mag >= 2) return ctx_idx = 18;
130     if (sig_mag == 1) {
131       if (count >= 2)
132         ctx_idx = 19;
133       else
134         ctx_idx = 20;
135       return ctx_idx;
136     }
137 
138     ctx_idx = 21 + ctx;
139 
140     assert(ctx_idx <= 24);
141   }
142   return ctx_idx;
143 }
144 
get_br_ctx_2d(const uint8_t * const levels,const int c,const int bwl)145 static INLINE int get_br_ctx_2d(const uint8_t *const levels,
146                                 const int c,  // raster order
147                                 const int bwl) {
148   assert(c > 0);
149   const int row = c >> bwl;
150   const int col = c - (row << bwl);
151   const int stride = (1 << bwl) + TX_PAD_HOR;
152   const int pos = row * stride + col;
153   int mag = AOMMIN(levels[pos + 1], MAX_BASE_BR_RANGE) +
154             AOMMIN(levels[pos + stride], MAX_BASE_BR_RANGE) +
155             AOMMIN(levels[pos + 1 + stride], MAX_BASE_BR_RANGE);
156   mag = AOMMIN((mag + 1) >> 1, 6);
157   //((row | col) < 2) is equivalent to ((row < 2) && (col < 2))
158   if ((row | col) < 2) return mag + 7;
159   return mag + 14;
160 }
161 
get_br_ctx_eob(const int c,const int bwl,const TX_CLASS tx_class)162 static AOM_FORCE_INLINE int get_br_ctx_eob(const int c,  // raster order
163                                            const int bwl,
164                                            const TX_CLASS tx_class) {
165   const int row = c >> bwl;
166   const int col = c - (row << bwl);
167   if (c == 0) return 0;
168   if ((tx_class == TX_CLASS_2D && row < 2 && col < 2) ||
169       (tx_class == TX_CLASS_HORIZ && col == 0) ||
170       (tx_class == TX_CLASS_VERT && row == 0))
171     return 7;
172   return 14;
173 }
174 
get_br_ctx(const uint8_t * const levels,const int c,const int bwl,const TX_CLASS tx_class)175 static AOM_FORCE_INLINE int get_br_ctx(const uint8_t *const levels,
176                                        const int c,  // raster order
177                                        const int bwl, const TX_CLASS tx_class) {
178   const int row = c >> bwl;
179   const int col = c - (row << bwl);
180   const int stride = (1 << bwl) + TX_PAD_HOR;
181   const int pos = row * stride + col;
182   int mag = levels[pos + 1];
183   mag += levels[pos + stride];
184   switch (tx_class) {
185     case TX_CLASS_2D:
186       mag += levels[pos + stride + 1];
187       mag = AOMMIN((mag + 1) >> 1, 6);
188       if (c == 0) return mag;
189       if ((row < 2) && (col < 2)) return mag + 7;
190       break;
191     case TX_CLASS_HORIZ:
192       mag += levels[pos + 2];
193       mag = AOMMIN((mag + 1) >> 1, 6);
194       if (c == 0) return mag;
195       if (col == 0) return mag + 7;
196       break;
197     case TX_CLASS_VERT:
198       mag += levels[pos + (stride << 1)];
199       mag = AOMMIN((mag + 1) >> 1, 6);
200       if (c == 0) return mag;
201       if (row == 0) return mag + 7;
202       break;
203     default: break;
204   }
205 
206   return mag + 14;
207 }
208 
209 static const uint8_t clip_max3[256] = {
210   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,
211   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,
212   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,
213   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,
214   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,
215   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,
216   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,
217   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,
218   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,
219   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
220 };
221 
get_nz_mag(const uint8_t * const levels,const int bwl,const TX_CLASS tx_class)222 static AOM_FORCE_INLINE int get_nz_mag(const uint8_t *const levels,
223                                        const int bwl, const TX_CLASS tx_class) {
224   int mag;
225 
226   // Note: AOMMIN(level, 3) is useless for decoder since level < 3.
227   mag = clip_max3[levels[1]];                         // { 0, 1 }
228   mag += clip_max3[levels[(1 << bwl) + TX_PAD_HOR]];  // { 1, 0 }
229 
230   if (tx_class == TX_CLASS_2D) {
231     mag += clip_max3[levels[(1 << bwl) + TX_PAD_HOR + 1]];          // { 1, 1 }
232     mag += clip_max3[levels[2]];                                    // { 0, 2 }
233     mag += clip_max3[levels[(2 << bwl) + (2 << TX_PAD_HOR_LOG2)]];  // { 2, 0 }
234   } else if (tx_class == TX_CLASS_VERT) {
235     mag += clip_max3[levels[(2 << bwl) + (2 << TX_PAD_HOR_LOG2)]];  // { 2, 0 }
236     mag += clip_max3[levels[(3 << bwl) + (3 << TX_PAD_HOR_LOG2)]];  // { 3, 0 }
237     mag += clip_max3[levels[(4 << bwl) + (4 << TX_PAD_HOR_LOG2)]];  // { 4, 0 }
238   } else {
239     mag += clip_max3[levels[2]];  // { 0, 2 }
240     mag += clip_max3[levels[3]];  // { 0, 3 }
241     mag += clip_max3[levels[4]];  // { 0, 4 }
242   }
243 
244   return mag;
245 }
246 
247 #define NZ_MAP_CTX_0 SIG_COEF_CONTEXTS_2D
248 #define NZ_MAP_CTX_5 (NZ_MAP_CTX_0 + 5)
249 #define NZ_MAP_CTX_10 (NZ_MAP_CTX_0 + 10)
250 
251 static const int nz_map_ctx_offset_1d[32] = {
252   NZ_MAP_CTX_0,  NZ_MAP_CTX_5,  NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
253   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
254   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
255   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
256   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
257   NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10, NZ_MAP_CTX_10,
258   NZ_MAP_CTX_10, NZ_MAP_CTX_10,
259 };
260 
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)261 static AOM_FORCE_INLINE int get_nz_map_ctx_from_stats(
262     const int stats,
263     const int coeff_idx,  // raster order
264     const int bwl, const TX_SIZE tx_size, const TX_CLASS tx_class) {
265   // tx_class == 0(TX_CLASS_2D)
266   if ((tx_class | coeff_idx) == 0) return 0;
267   int ctx = (stats + 1) >> 1;
268   ctx = AOMMIN(ctx, 4);
269   switch (tx_class) {
270     case TX_CLASS_2D: {
271       // This is the algorithm to generate av1_nz_map_ctx_offset[][]
272       //   const int width = tx_size_wide[tx_size];
273       //   const int height = tx_size_high[tx_size];
274       //   if (width < height) {
275       //     if (row < 2) return 11 + ctx;
276       //   } else if (width > height) {
277       //     if (col < 2) return 16 + ctx;
278       //   }
279       //   if (row + col < 2) return ctx + 1;
280       //   if (row + col < 4) return 5 + ctx + 1;
281       //   return 21 + ctx;
282       return ctx + av1_nz_map_ctx_offset[tx_size][coeff_idx];
283     }
284     case TX_CLASS_HORIZ: {
285       const int row = coeff_idx >> bwl;
286       const int col = coeff_idx - (row << bwl);
287       return ctx + nz_map_ctx_offset_1d[col];
288     }
289     case TX_CLASS_VERT: {
290       const int row = coeff_idx >> bwl;
291       return ctx + nz_map_ctx_offset_1d[row];
292     }
293     default: break;
294   }
295   return 0;
296 }
297 
298 typedef aom_cdf_prob (*base_cdf_arr)[CDF_SIZE(4)];
299 typedef aom_cdf_prob (*br_cdf_arr)[CDF_SIZE(BR_CDF_SIZE)];
300 
get_lower_levels_ctx_eob(int bwl,int height,int scan_idx)301 static INLINE int get_lower_levels_ctx_eob(int bwl, int height, int scan_idx) {
302   if (scan_idx == 0) return 0;
303   if (scan_idx <= (height << bwl) / 8) return 1;
304   if (scan_idx <= (height << bwl) / 4) return 2;
305   return 3;
306 }
307 
get_lower_levels_ctx_2d(const uint8_t * levels,int coeff_idx,int bwl,TX_SIZE tx_size)308 static INLINE int get_lower_levels_ctx_2d(const uint8_t *levels, int coeff_idx,
309                                           int bwl, TX_SIZE tx_size) {
310   assert(coeff_idx > 0);
311   int mag;
312   // Note: AOMMIN(level, 3) is useless for decoder since level < 3.
313   levels = levels + get_padded_idx(coeff_idx, bwl);
314   mag = AOMMIN(levels[1], 3);                                     // { 0, 1 }
315   mag += AOMMIN(levels[(1 << bwl) + TX_PAD_HOR], 3);              // { 1, 0 }
316   mag += AOMMIN(levels[(1 << bwl) + TX_PAD_HOR + 1], 3);          // { 1, 1 }
317   mag += AOMMIN(levels[2], 3);                                    // { 0, 2 }
318   mag += AOMMIN(levels[(2 << bwl) + (2 << TX_PAD_HOR_LOG2)], 3);  // { 2, 0 }
319 
320   const int ctx = AOMMIN((mag + 1) >> 1, 4);
321   return ctx + av1_nz_map_ctx_offset[tx_size][coeff_idx];
322 }
get_lower_levels_ctx(const uint8_t * levels,int coeff_idx,int bwl,TX_SIZE tx_size,TX_CLASS tx_class)323 static AOM_FORCE_INLINE int get_lower_levels_ctx(const uint8_t *levels,
324                                                  int coeff_idx, int bwl,
325                                                  TX_SIZE tx_size,
326                                                  TX_CLASS tx_class) {
327   const int stats =
328       get_nz_mag(levels + get_padded_idx(coeff_idx, bwl), bwl, tx_class);
329   return get_nz_map_ctx_from_stats(stats, coeff_idx, bwl, tx_size, tx_class);
330 }
331 
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)332 static INLINE int get_lower_levels_ctx_general(int is_last, int scan_idx,
333                                                int bwl, int height,
334                                                const uint8_t *levels,
335                                                int coeff_idx, TX_SIZE tx_size,
336                                                TX_CLASS tx_class) {
337   if (is_last) {
338     if (scan_idx == 0) return 0;
339     if (scan_idx <= (height << bwl) >> 3) return 1;
340     if (scan_idx <= (height << bwl) >> 2) return 2;
341     return 3;
342   }
343   return get_lower_levels_ctx(levels, coeff_idx, bwl, tx_size, tx_class);
344 }
345 
set_dc_sign(int * cul_level,int dc_val)346 static INLINE void set_dc_sign(int *cul_level, int dc_val) {
347   if (dc_val < 0)
348     *cul_level |= 1 << COEFF_CONTEXT_BITS;
349   else if (dc_val > 0)
350     *cul_level += 2 << COEFF_CONTEXT_BITS;
351 }
352 
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)353 static INLINE void get_txb_ctx(const BLOCK_SIZE plane_bsize,
354                                const TX_SIZE tx_size, const int plane,
355                                const ENTROPY_CONTEXT *const a,
356                                const ENTROPY_CONTEXT *const l,
357                                TXB_CTX *const txb_ctx) {
358 #define MAX_TX_SIZE_UNIT 16
359   static const int8_t signs[3] = { 0, -1, 1 };
360   static const int8_t dc_sign_contexts[4 * MAX_TX_SIZE_UNIT + 1] = {
361     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
362     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
363     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
364   };
365   const int txb_w_unit = tx_size_wide_unit[tx_size];
366   const int txb_h_unit = tx_size_high_unit[tx_size];
367   int dc_sign = 0;
368   int k = 0;
369 
370   do {
371     const unsigned int sign = ((uint8_t)a[k]) >> COEFF_CONTEXT_BITS;
372     assert(sign <= 2);
373     dc_sign += signs[sign];
374   } while (++k < txb_w_unit);
375 
376   k = 0;
377   do {
378     const unsigned int sign = ((uint8_t)l[k]) >> COEFF_CONTEXT_BITS;
379     assert(sign <= 2);
380     dc_sign += signs[sign];
381   } while (++k < txb_h_unit);
382 
383   txb_ctx->dc_sign_ctx = dc_sign_contexts[dc_sign + 2 * MAX_TX_SIZE_UNIT];
384 
385   if (plane == 0) {
386     if (plane_bsize == txsize_to_bsize[tx_size]) {
387       txb_ctx->txb_skip_ctx = 0;
388     } else {
389       // This is the algorithm to generate table skip_contexts[top][left].
390       //    const int max = AOMMIN(top | left, 4);
391       //    const int min = AOMMIN(AOMMIN(top, left), 4);
392       //    if (!max)
393       //      txb_skip_ctx = 1;
394       //    else if (!min)
395       //      txb_skip_ctx = 2 + (max > 3);
396       //    else if (max <= 3)
397       //      txb_skip_ctx = 4;
398       //    else if (min <= 3)
399       //      txb_skip_ctx = 5;
400       //    else
401       //      txb_skip_ctx = 6;
402       static const uint8_t skip_contexts[5][5] = { { 1, 2, 2, 2, 3 },
403                                                    { 2, 4, 4, 4, 5 },
404                                                    { 2, 4, 4, 4, 5 },
405                                                    { 2, 4, 4, 4, 5 },
406                                                    { 3, 5, 5, 5, 6 } };
407       // For top and left, we only care about which of the following three
408       // categories they belong to: { 0 }, { 1, 2, 3 }, or { 4, 5, ... }. The
409       // spec calculates top and left with the Max() function. We can calculate
410       // an approximate max with bitwise OR because the real max and the
411       // approximate max belong to the same category.
412       int top = 0;
413       int left = 0;
414 
415       k = 0;
416       do {
417         top |= a[k];
418       } while (++k < txb_w_unit);
419       top &= COEFF_CONTEXT_MASK;
420       top = AOMMIN(top, 4);
421 
422       k = 0;
423       do {
424         left |= l[k];
425       } while (++k < txb_h_unit);
426       left &= COEFF_CONTEXT_MASK;
427       left = AOMMIN(left, 4);
428 
429       txb_ctx->txb_skip_ctx = skip_contexts[top][left];
430     }
431   } else {
432     const int ctx_base = get_entropy_context(tx_size, a, l);
433     const int ctx_offset = (num_pels_log2_lookup[plane_bsize] >
434                             num_pels_log2_lookup[txsize_to_bsize[tx_size]])
435                                ? 10
436                                : 7;
437     txb_ctx->txb_skip_ctx = ctx_base + ctx_offset;
438   }
439 #undef MAX_TX_SIZE_UNIT
440 }
441 
442 #endif  // AOM_AV1_COMMON_TXB_COMMON_H_
443