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 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 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 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 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 77 static INLINE int get_padded_idx(const int idx, const int bwl) { 78 return idx + ((idx >> bwl) << TX_PAD_HOR_LOG2); 79 } 80 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 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 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 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 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 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 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 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 } 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 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 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 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