• 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/onyxc_int.h"
16 
17 extern const int16_t k_eob_group_start[12];
18 extern const int16_t k_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[min][max].
390       //    if (!max)
391       //      txb_skip_ctx = 1;
392       //    else if (!min)
393       //      txb_skip_ctx = 2 + (max > 3);
394       //    else if (max <= 3)
395       //      txb_skip_ctx = 4;
396       //    else if (min <= 3)
397       //      txb_skip_ctx = 5;
398       //    else
399       //      txb_skip_ctx = 6;
400       static const uint8_t skip_contexts[5][5] = { { 1, 2, 2, 2, 3 },
401                                                    { 1, 4, 4, 4, 5 },
402                                                    { 1, 4, 4, 4, 5 },
403                                                    { 1, 4, 4, 4, 5 },
404                                                    { 1, 4, 4, 4, 6 } };
405       int top = 0;
406       int left = 0;
407 
408       k = 0;
409       do {
410         top |= a[k];
411       } while (++k < txb_w_unit);
412       top &= COEFF_CONTEXT_MASK;
413 
414       k = 0;
415       do {
416         left |= l[k];
417       } while (++k < txb_h_unit);
418       left &= COEFF_CONTEXT_MASK;
419       const int max = AOMMIN(top | left, 4);
420       const int min = AOMMIN(AOMMIN(top, left), 4);
421 
422       txb_ctx->txb_skip_ctx = skip_contexts[min][max];
423     }
424   } else {
425     const int ctx_base = get_entropy_context(tx_size, a, l);
426     const int ctx_offset = (num_pels_log2_lookup[plane_bsize] >
427                             num_pels_log2_lookup[txsize_to_bsize[tx_size]])
428                                ? 10
429                                : 7;
430     txb_ctx->txb_skip_ctx = ctx_base + ctx_offset;
431   }
432 #undef MAX_TX_SIZE_UNIT
433 }
434 
435 #endif  // AOM_AV1_COMMON_TXB_COMMON_H_
436