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_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