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