txb_common.h 22.3 KB
Newer Older
Angie Chiang's avatar
Angie Chiang committed
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#ifndef AV1_COMMON_TXB_COMMON_H_
#define AV1_COMMON_TXB_COMMON_H_
14 15 16 17

#define REDUCE_CONTEXT_DEPENDENCY 0
#define MIN_SCAN_IDX_REDUCE_CONTEXT_DEPENDENCY 0

Dake He's avatar
Dake He committed
18 19 20 21 22 23 24
#if CONFIG_EOB_FIRST
extern const int16_t k_eob_group_start[12];
extern const int16_t k_eob_offset_bits[12];
int16_t get_eob_pos_token(int eob, int16_t *extra);
int get_eob_pos_ctx(int eob_token);
#endif

25
extern const int16_t av1_coeff_band_4x4[16];
Angie Chiang's avatar
Angie Chiang committed
26

27
extern const int16_t av1_coeff_band_8x8[64];
Angie Chiang's avatar
Angie Chiang committed
28

29 30 31
extern const int16_t av1_coeff_band_16x16[256];

extern const int16_t av1_coeff_band_32x32[1024];
Angie Chiang's avatar
Angie Chiang committed
32

33 34 35 36 37
typedef struct txb_ctx {
  int txb_skip_ctx;
  int dc_sign_ctx;
} TXB_CTX;

38 39 40 41
static INLINE TX_SIZE get_txsize_context(TX_SIZE tx_size) {
  return txsize_sqr_up_map[tx_size];
}

42
static const int base_ref_offset[BASE_CONTEXT_POSITION_NUM][2] = {
Angie Chiang's avatar
Angie Chiang committed
43 44 45 46 47 48
  /* clang-format off*/
  { -2, 0 }, { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -2 }, { 0, -1 }, { 0, 1 },
  { 0, 2 },  { 1, -1 },  { 1, 0 },  { 1, 1 },  { 2, 0 }
  /* clang-format on*/
};

Linfeng Zhang's avatar
Linfeng Zhang committed
49 50 51
// TODO(linfengz): Some functions have coeff_is_byte_flag to handle different
// types of input coefficients. If possible, unify types to uint8_t* later.

52
static INLINE int get_level_count(const tran_low_t *tcoeffs, int bwl,
53
                                  int height, int row, int col, int level,
54 55 56 57 58
                                  int (*nb_offset)[2], int nb_num) {
  int count = 0;
  for (int idx = 0; idx < nb_num; ++idx) {
    const int ref_row = row + nb_offset[idx][0];
    const int ref_col = col + nb_offset[idx][1];
59 60
    if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
        ref_col >= (1 << bwl))
61
      continue;
62
    const int pos = (ref_row << bwl) + ref_col;
63 64 65 66 67 68
    tran_low_t abs_coeff = abs(tcoeffs[pos]);
    count += abs_coeff > level;
  }
  return count;
}

69
static INLINE void get_mag(int *mag, const tran_low_t *tcoeffs, int bwl,
70 71
                           int height, int row, int col, int (*nb_offset)[2],
                           int nb_num) {
72 73 74 75 76
  mag[0] = 0;
  mag[1] = 0;
  for (int idx = 0; idx < nb_num; ++idx) {
    const int ref_row = row + nb_offset[idx][0];
    const int ref_col = col + nb_offset[idx][1];
77 78
    if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
        ref_col >= (1 << bwl))
79
      continue;
80
    const int pos = (ref_row << bwl) + ref_col;
81 82 83 84 85 86 87 88 89 90 91
    tran_low_t abs_coeff = abs(tcoeffs[pos]);
    if (nb_offset[idx][0] >= 0 && nb_offset[idx][1] >= 0) {
      if (abs_coeff > mag[0]) {
        mag[0] = abs_coeff;
        mag[1] = 1;
      } else if (abs_coeff == mag[0]) {
        ++mag[1];
      }
    }
  }
}
Angie Chiang's avatar
Angie Chiang committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

static INLINE void get_base_count_mag(int *mag, int *count,
                                      const tran_low_t *tcoeffs, int bwl,
                                      int height, int row, int col) {
  mag[0] = 0;
  mag[1] = 0;
  for (int i = 0; i < NUM_BASE_LEVELS; ++i) count[i] = 0;
  for (int idx = 0; idx < BASE_CONTEXT_POSITION_NUM; ++idx) {
    const int ref_row = row + base_ref_offset[idx][0];
    const int ref_col = col + base_ref_offset[idx][1];
    if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
        ref_col >= (1 << bwl))
      continue;
    const int pos = (ref_row << bwl) + ref_col;
    tran_low_t abs_coeff = abs(tcoeffs[pos]);
    // count
    for (int i = 0; i < NUM_BASE_LEVELS; ++i) {
      count[i] += abs_coeff > i;
    }
    // mag
    if (base_ref_offset[idx][0] >= 0 && base_ref_offset[idx][1] >= 0) {
      if (abs_coeff > mag[0]) {
        mag[0] = abs_coeff;
        mag[1] = 1;
      } else if (abs_coeff == mag[0]) {
        ++mag[1];
      }
    }
  }
}

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
static INLINE int get_level_count_mag(
    int *const mag, const uint8_t *const levels, const int bwl,
    const int height, const int row, const int col, const int level,
    const int (*nb_offset)[2], const int nb_num) {
  const int stride = 1 << bwl;
  int count = 0;
  *mag = 0;
  for (int idx = 0; idx < nb_num; ++idx) {
    const int ref_row = row + nb_offset[idx][0];
    const int ref_col = col + nb_offset[idx][1];
    if (ref_row < 0 || ref_col < 0 || ref_row >= height || ref_col >= stride)
      continue;
    const int pos = (ref_row << bwl) + ref_col;
    count += levels[pos] > level;
    if (nb_offset[idx][0] >= 0 && nb_offset[idx][1] >= 0)
      *mag = AOMMAX(*mag, levels[pos]);
  }
  return count;
}

static INLINE int get_level_count_mag_coeff(
    int *const mag, const tran_low_t *const tcoeffs, const int bwl,
    const int height, const int row, const int col, const int level,
    const int (*nb_offset)[2], const int nb_num) {
147
  const int stride = 1 << bwl;
Angie Chiang's avatar
Angie Chiang committed
148 149 150
  int count = 0;
  *mag = 0;
  for (int idx = 0; idx < nb_num; ++idx) {
151 152
    const int ref_row = row + nb_offset[idx][0];
    const int ref_col = col + nb_offset[idx][1];
153
    if (ref_row < 0 || ref_col < 0 || ref_row >= height || ref_col >= stride)
Angie Chiang's avatar
Angie Chiang committed
154
      continue;
Yaowu Xu's avatar
Yaowu Xu committed
155
    const int pos = (ref_row << bwl) + ref_col;
Angie Chiang's avatar
Angie Chiang committed
156 157 158 159
    tran_low_t abs_coeff = abs(tcoeffs[pos]);
    count += abs_coeff > level;
    if (nb_offset[idx][0] >= 0 && nb_offset[idx][1] >= 0)
      *mag = AOMMAX(*mag, abs_coeff);
Angie Chiang's avatar
Angie Chiang committed
160
  }
Angie Chiang's avatar
Angie Chiang committed
161 162 163
  return count;
}

164
static INLINE int get_base_ctx_from_count_mag(int row, int col, int count,
165
                                              int sig_mag) {
166
  const int ctx = (count + 1) >> 1;
Angie Chiang's avatar
Angie Chiang committed
167
  int ctx_idx = -1;
Angie Chiang's avatar
Angie Chiang committed
168
  if (row == 0 && col == 0) {
169
    ctx_idx = (ctx << 1) + sig_mag;
170 171
    // TODO(angiebird): turn this on once the optimization is finalized
    // assert(ctx_idx < 8);
Angie Chiang's avatar
Angie Chiang committed
172
  } else if (row == 0) {
173
    ctx_idx = 8 + (ctx << 1) + sig_mag;
174 175
    // TODO(angiebird): turn this on once the optimization is finalized
    // assert(ctx_idx < 18);
Angie Chiang's avatar
Angie Chiang committed
176
  } else if (col == 0) {
177
    ctx_idx = 8 + 10 + (ctx << 1) + sig_mag;
178 179
    // TODO(angiebird): turn this on once the optimization is finalized
    // assert(ctx_idx < 28);
Angie Chiang's avatar
Angie Chiang committed
180
  } else {
181
    ctx_idx = 8 + 10 + 10 + (ctx << 1) + sig_mag;
Angie Chiang's avatar
Angie Chiang committed
182 183 184 185 186
    assert(ctx_idx < COEFF_BASE_CONTEXTS);
  }
  return ctx_idx;
}

187 188
static INLINE int get_base_ctx(const uint8_t *const levels,
                               const int c,  // raster order
189 190
                               const int bwl, const int height,
                               const int level) {
191 192 193 194
  const int row = c >> bwl;
  const int col = c - (row << bwl);
  const int level_minus_1 = level - 1;
  int mag;
195 196
  const int count =
      get_level_count_mag(&mag, levels, bwl, height, row, col, level_minus_1,
197
                          base_ref_offset, BASE_CONTEXT_POSITION_NUM);
198
  const int ctx_idx = get_base_ctx_from_count_mag(row, col, count, mag > level);
199 200 201
  return ctx_idx;
}

Angie Chiang's avatar
Angie Chiang committed
202
#define BR_CONTEXT_POSITION_NUM 8  // Base range coefficient context
Dake He's avatar
Dake He committed
203
#if CONFIG_EOB_FIRST
204
static const int br_ref_offset[BR_CONTEXT_POSITION_NUM][2] = {
Angie Chiang's avatar
Angie Chiang committed
205 206 207 208 209
  /* clang-format off*/
  { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 },
  { 0, 1 },   { 1, -1 }, { 1, 0 },  { 1, 1 },
  /* clang-format on*/
};
Dake He's avatar
Dake He committed
210 211 212 213 214 215 216 217
#else
static const int br_ref_offset[BR_CONTEXT_POSITION_NUM][2] = {
  /* clang-format off*/
  { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 },
  { 0, 1 },   { 1, -1 }, { 1, 0 },  { 1, 1 },
  /* clang-format on*/
};
#endif
Angie Chiang's avatar
Angie Chiang committed
218

219
static const int br_level_map[9] = {
Angie Chiang's avatar
Angie Chiang committed
220 221 222
  0, 0, 1, 1, 2, 2, 3, 3, 3,
};

223 224 225 226 227 228 229 230 231 232 233 234
static const int coeff_to_br_index[COEFF_BASE_RANGE] = {
  0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
};

static const int br_index_to_coeff[BASE_RANGE_SETS] = {
  0, 2, 6,
};

static const int br_extra_bits[BASE_RANGE_SETS] = {
  1, 2, 3,
};

235 236 237
#define BR_MAG_OFFSET 1
// TODO(angiebird): optimize this function by using a table to map from
// count/mag to ctx
Angie Chiang's avatar
Angie Chiang committed
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264

static INLINE int get_br_count_mag(int *mag, const tran_low_t *tcoeffs, int bwl,
                                   int height, int row, int col, int level) {
  mag[0] = 0;
  mag[1] = 0;
  int count = 0;
  for (int idx = 0; idx < BR_CONTEXT_POSITION_NUM; ++idx) {
    const int ref_row = row + br_ref_offset[idx][0];
    const int ref_col = col + br_ref_offset[idx][1];
    if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
        ref_col >= (1 << bwl))
      continue;
    const int pos = (ref_row << bwl) + ref_col;
    tran_low_t abs_coeff = abs(tcoeffs[pos]);
    count += abs_coeff > level;
    if (br_ref_offset[idx][0] >= 0 && br_ref_offset[idx][1] >= 0) {
      if (abs_coeff > mag[0]) {
        mag[0] = abs_coeff;
        mag[1] = 1;
      } else if (abs_coeff == mag[0]) {
        ++mag[1];
      }
    }
  }
  return count;
}

265 266
static INLINE int get_br_ctx_from_count_mag(int row, int col, int count,
                                            int mag) {
267
  int offset = 0;
268
  if (mag <= BR_MAG_OFFSET)
Angie Chiang's avatar
Angie Chiang committed
269 270 271
    offset = 0;
  else if (mag <= 3)
    offset = 1;
272
  else if (mag <= 5)
Angie Chiang's avatar
Angie Chiang committed
273 274 275 276
    offset = 2;
  else
    offset = 3;

277
  int ctx = br_level_map[count];
Angie Chiang's avatar
Angie Chiang committed
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
  ctx += offset * BR_TMP_OFFSET;

  // DC: 0 - 1
  if (row == 0 && col == 0) return ctx;

  // Top row: 2 - 4
  if (row == 0) return 2 + ctx;

  // Left column: 5 - 7
  if (col == 0) return 5 + ctx;

  // others: 8 - 11
  return 8 + ctx;
}

293
static INLINE int get_br_ctx(const uint8_t *const levels,
294
                             const int c,  // raster order
295
                             const int bwl, const int height) {
296 297 298 299
  const int row = c >> bwl;
  const int col = c - (row << bwl);
  const int level_minus_1 = NUM_BASE_LEVELS;
  int mag;
300
  const int count =
301
      get_level_count_mag(&mag, levels, bwl, height, row, col, level_minus_1,
302
                          br_ref_offset, BR_CONTEXT_POSITION_NUM);
303 304 305 306
  const int ctx = get_br_ctx_from_count_mag(row, col, count, mag);
  return ctx;
}

307 308 309 310 311 312 313 314 315 316 317 318 319 320
static INLINE int get_br_ctx_coeff(const tran_low_t *const tcoeffs,
                                   const int c,  // raster order
                                   const int bwl, const int height) {
  const int row = c >> bwl;
  const int col = c - (row << bwl);
  const int level_minus_1 = NUM_BASE_LEVELS;
  int mag;
  const int count = get_level_count_mag_coeff(&mag, tcoeffs, bwl, height, row,
                                              col, level_minus_1, br_ref_offset,
                                              BR_CONTEXT_POSITION_NUM);
  const int ctx = get_br_ctx_from_count_mag(row, col, count, mag);
  return ctx;
}

Angie Chiang's avatar
Angie Chiang committed
321
#define SIG_REF_OFFSET_NUM 7
Dake He's avatar
Dake He committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
#if CONFIG_EOB_FIRST
static int sig_ref_offset[SIG_REF_OFFSET_NUM][2] = {
  { 2, 1 }, { 2, 0 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 2 }, { 0, 1 },
};

static int sig_ref_offset_vert[SIG_REF_OFFSET_NUM][2] = {
  { 2, 1 }, { 2, 0 }, { 3, 0 }, { 1, 1 }, { 1, 0 }, { 4, 0 }, { 0, 1 },
};

static int sig_ref_offset_horiz[SIG_REF_OFFSET_NUM][2] = {
  { 0, 3 }, { 0, 4 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 2 }, { 0, 1 },
};

static INLINE int get_nz_count(const tran_low_t *tcoeffs, int bwl, int height,
                               int row, int col, TX_CLASS tx_class,
                               const int coeff_is_byte_flag) {
  int count = 0;
  for (int idx = 0; idx < SIG_REF_OFFSET_NUM; ++idx) {
    const int ref_row = row + ((tx_class == TX_CLASS_2D)
                                   ? sig_ref_offset[idx][0]
                                   : ((tx_class == TX_CLASS_VERT)
                                          ? sig_ref_offset_vert[idx][0]
                                          : sig_ref_offset_horiz[idx][0]));
    const int ref_col = col + ((tx_class == TX_CLASS_2D)
                                   ? sig_ref_offset[idx][1]
                                   : ((tx_class == TX_CLASS_VERT)
                                          ? sig_ref_offset_vert[idx][1]
                                          : sig_ref_offset_horiz[idx][1]));
    if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
        ref_col >= (1 << bwl))
      continue;
    const int nb_pos = (ref_row << bwl) + ref_col;
    count +=
        ((coeff_is_byte_flag ? ((const uint8_t *)tcoeffs)[nb_pos]
                             : ((const tran_low_t *)tcoeffs)[nb_pos]) != 0);
  }
  return count;
}
#else
361
static int sig_ref_offset[SIG_REF_OFFSET_NUM][2] = {
Angie Chiang's avatar
Angie Chiang committed
362 363
  { -2, -1 }, { -2, 0 }, { -1, -2 }, { -1, -1 },
  { -1, 0 },  { 0, -2 }, { 0, -1 },
Angie Chiang's avatar
Angie Chiang committed
364 365
};

366
#if REDUCE_CONTEXT_DEPENDENCY
Linfeng Zhang's avatar
Linfeng Zhang committed
367 368 369 370
static INLINE int get_nz_count(const void *const tcoeffs, const int bwl,
                               const int height, const int row, const int col,
                               const int coeff_is_byte_flag, const int prev_row,
                               const int prev_col) {
371 372 373 374 375 376 377 378
  int count = 0;
  for (int idx = 0; idx < SIG_REF_OFFSET_NUM; ++idx) {
    const int ref_row = row + sig_ref_offset[idx][0];
    const int ref_col = col + sig_ref_offset[idx][1];
    if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
        ref_col >= (1 << bwl) || (prev_row == ref_row && prev_col == ref_col))
      continue;
    const int nb_pos = (ref_row << bwl) + ref_col;
Linfeng Zhang's avatar
Linfeng Zhang committed
379 380 381
    count +=
        ((coeff_is_byte_flag ? ((const uint8_t *)tcoeffs)[nb_pos]
                             : ((const tran_low_t *)tcoeffs)[nb_pos]) != 0);
382 383 384 385
  }
  return count;
}
#else
Linfeng Zhang's avatar
Linfeng Zhang committed
386 387 388
static INLINE int get_nz_count(const void *const tcoeffs, const int bwl,
                               const int height, const int row, const int col,
                               const int coeff_is_byte_flag) {
389 390 391 392
  int count = 0;
  for (int idx = 0; idx < SIG_REF_OFFSET_NUM; ++idx) {
    const int ref_row = row + sig_ref_offset[idx][0];
    const int ref_col = col + sig_ref_offset[idx][1];
393 394
    if (ref_row < 0 || ref_col < 0 || ref_row >= height ||
        ref_col >= (1 << bwl))
395
      continue;
396
    const int nb_pos = (ref_row << bwl) + ref_col;
Linfeng Zhang's avatar
Linfeng Zhang committed
397 398 399
    count +=
        ((coeff_is_byte_flag ? ((const uint8_t *)tcoeffs)[nb_pos]
                             : ((const tran_low_t *)tcoeffs)[nb_pos]) != 0);
400 401 402
  }
  return count;
}
403
#endif
404

Dake He's avatar
Dake He committed
405 406
#endif

407 408 409 410 411 412 413 414 415 416 417 418 419 420
static INLINE TX_CLASS get_tx_class(TX_TYPE tx_type) {
  switch (tx_type) {
#if CONFIG_EXT_TX
    case V_DCT:
    case V_ADST:
    case V_FLIPADST: return TX_CLASS_VERT;
    case H_DCT:
    case H_ADST:
    case H_FLIPADST: return TX_CLASS_HORIZ;
#endif
    default: return TX_CLASS_2D;
  }
}

421 422 423 424
// TODO(angiebird): optimize this function by generate a table that maps from
// count to ctx
static INLINE int get_nz_map_ctx_from_count(int count,
                                            int coeff_idx,  // raster order
Dake He's avatar
Dake He committed
425 426 427 428 429
                                            int bwl,
#if CONFIG_EOB_FIRST
                                            int height,
#endif
                                            TX_TYPE tx_type) {
430
  (void)tx_type;
431 432 433
  const int row = coeff_idx >> bwl;
  const int col = coeff_idx - (row << bwl);
  int ctx = 0;
434 435 436 437 438 439 440 441 442 443 444 445
#if CONFIG_EXT_TX
  int tx_class = get_tx_class(tx_type);
  int offset;
  if (tx_class == TX_CLASS_2D)
    offset = 0;
  else if (tx_class == TX_CLASS_VERT)
    offset = SIG_COEF_CONTEXTS_2D;
  else
    offset = SIG_COEF_CONTEXTS_2D + SIG_COEF_CONTEXTS_1D;
#else
  int offset = 0;
#endif
446

Dake He's avatar
Dake He committed
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
#if CONFIG_EOB_FIRST
  (void)height;
  ctx = (count + 1) >> 1;

  if (tx_class == TX_CLASS_2D) {
    {
      if (row == 0 && col == 0) return offset + 0;

      if (row + col < 2) return offset + ctx + 1;

      if (row + col < 4) return offset + 5 + ctx + 1;

      return offset + 11 + AOMMIN(ctx, 4);
    }
  } else {
    if (tx_class == TX_CLASS_VERT) {
      if (row == 0) return offset + ctx;
      if (row < 2) return offset + 5 + ctx;
      return offset + 10 + ctx;
    } else {
      if (col == 0) return offset + ctx;
      if (col < 2) return offset + 5 + ctx;
      return offset + 10 + ctx;
    }
  }
#else
473
  if (row == 0 && col == 0) return offset + 0;
474

Angie Chiang's avatar
Angie Chiang committed
475
  if (row == 0 && col == 1) return offset + 1 + count;
476

Angie Chiang's avatar
Angie Chiang committed
477
  if (row == 1 && col == 0) return offset + 3 + count;
478 479

  if (row == 1 && col == 1) {
Angie Chiang's avatar
Angie Chiang committed
480
    ctx = (count + 1) >> 1;
481 482 483

    assert(5 + ctx <= 7);

484
    return offset + 5 + ctx;
485 486 487 488 489
  }

  if (row == 0) {
    ctx = (count + 1) >> 1;

Angie Chiang's avatar
Angie Chiang committed
490
    assert(ctx < 2);
491
    return offset + 8 + ctx;
492 493 494 495 496
  }

  if (col == 0) {
    ctx = (count + 1) >> 1;

Angie Chiang's avatar
Angie Chiang committed
497 498
    assert(ctx < 2);
    return offset + 10 + ctx;
499 500 501 502
  }

  ctx = count >> 1;

Angie Chiang's avatar
Angie Chiang committed
503
  assert(12 + ctx < 16);
504

Angie Chiang's avatar
Angie Chiang committed
505
  return offset + 12 + ctx;
Dake He's avatar
Dake He committed
506
#endif
507 508
}

Linfeng Zhang's avatar
Linfeng Zhang committed
509 510 511 512
static INLINE int get_nz_map_ctx(const void *const tcoeffs, const int scan_idx,
                                 const int16_t *const scan, const int bwl,
                                 const int height, const TX_TYPE tx_type,
                                 const int coeff_is_byte_flag) {
513
  const int coeff_idx = scan[scan_idx];
514 515
  const int row = coeff_idx >> bwl;
  const int col = coeff_idx - (row << bwl);
516 517 518 519 520 521 522 523 524 525 526 527 528
#if REDUCE_CONTEXT_DEPENDENCY
  int prev_coeff_idx;
  int prev_row;
  int prev_col;
  if (scan_idx > MIN_SCAN_IDX_REDUCE_CONTEXT_DEPENDENCY) {
    prev_coeff_idx = scan[scan_idx - 1];  // raster order
    prev_row = prev_coeff_idx >> bwl;
    prev_col = prev_coeff_idx - (prev_row << bwl);
  } else {
    prev_coeff_idx = -1;
    prev_row = -1;
    prev_col = -1;
  }
Linfeng Zhang's avatar
Linfeng Zhang committed
529 530
  const int count = get_nz_count(tcoeffs, bwl, height, row, col,
                                 coeff_is_byte_flag, prev_row, prev_col);
531
#else
Dake He's avatar
Dake He committed
532 533 534 535 536 537 538 539 540 541 542
#if CONFIG_EOB_FIRST
  int tx_class = get_tx_class(tx_type);
  int count = get_nz_count(tcoeffs, bwl, height, row, col, tx_class,
                           coeff_is_byte_flag);
#else
  int count = get_nz_count(tcoeffs, bwl, height, row, col, coeff_is_byte_flag);
#endif
#endif
  return get_nz_map_ctx_from_count(count, coeff_idx, bwl,
#if CONFIG_EOB_FIRST
                                   height,
543
#endif
Dake He's avatar
Dake He committed
544
                                   tx_type);
545 546
}

Linfeng Zhang's avatar
Linfeng Zhang committed
547 548
static INLINE int get_eob_ctx(const int coeff_idx,  // raster order
                              const TX_SIZE txs_ctx, const TX_TYPE tx_type) {
549 550
  int offset = 0;
#if CONFIG_CTX1D
Linfeng Zhang's avatar
Linfeng Zhang committed
551
  const TX_CLASS tx_class = get_tx_class(tx_type);
552 553 554 555 556
  if (tx_class == TX_CLASS_VERT)
    offset = EOB_COEF_CONTEXTS_2D;
  else if (tx_class == TX_CLASS_HORIZ)
    offset = EOB_COEF_CONTEXTS_2D + EOB_COEF_CONTEXTS_1D;
#else
Angie Chiang's avatar
Angie Chiang committed
557
  (void)tx_type;
558 559 560 561 562 563
#endif

  if (txs_ctx == TX_4X4) return offset + av1_coeff_band_4x4[coeff_idx];
  if (txs_ctx == TX_8X8) return offset + av1_coeff_band_8x8[coeff_idx];
  if (txs_ctx == TX_16X16) return offset + av1_coeff_band_16x16[coeff_idx];
  if (txs_ctx == TX_32X32) return offset + av1_coeff_band_32x32[coeff_idx];
Angie Chiang's avatar
Angie Chiang committed
564

565 566
  assert(0);
  return 0;
Angie Chiang's avatar
Angie Chiang committed
567 568
}

569 570 571 572 573 574
static INLINE void set_dc_sign(int *cul_level, tran_low_t v) {
  if (v < 0)
    *cul_level |= 1 << COEFF_CONTEXT_BITS;
  else if (v > 0)
    *cul_level += 2 << COEFF_CONTEXT_BITS;
}
Angie Chiang's avatar
Angie Chiang committed
575 576 577 578 579 580 581 582 583 584 585

static INLINE int get_dc_sign_ctx(int dc_sign) {
  int dc_sign_ctx = 0;
  if (dc_sign < 0)
    dc_sign_ctx = 1;
  else if (dc_sign > 0)
    dc_sign_ctx = 2;

  return dc_sign_ctx;
}

586 587
static INLINE void get_txb_ctx(BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
                               int plane, const ENTROPY_CONTEXT *a,
588
                               const ENTROPY_CONTEXT *l, TXB_CTX *txb_ctx) {
589 590
  const int txb_w_unit = tx_size_wide_unit[tx_size];
  const int txb_h_unit = tx_size_high_unit[tx_size];
Angie Chiang's avatar
Angie Chiang committed
591 592
  int ctx_offset = (plane == 0) ? 0 : 7;

593
  if (plane_bsize > txsize_to_bsize[tx_size]) ctx_offset += 3;
Angie Chiang's avatar
Angie Chiang committed
594

595
  int dc_sign = 0;
596
  for (int k = 0; k < txb_w_unit; ++k) {
Angie Chiang's avatar
Angie Chiang committed
597
    int sign = ((uint8_t)a[k]) >> COEFF_CONTEXT_BITS;
Angie Chiang's avatar
Angie Chiang committed
598
    if (sign == 1)
599
      --dc_sign;
Angie Chiang's avatar
Angie Chiang committed
600
    else if (sign == 2)
601
      ++dc_sign;
Angie Chiang's avatar
Angie Chiang committed
602
    else if (sign != 0)
Angie Chiang's avatar
Angie Chiang committed
603
      assert(0);
604
  }
Angie Chiang's avatar
Angie Chiang committed
605

606 607
  for (int k = 0; k < txb_h_unit; ++k) {
    int sign = ((uint8_t)l[k]) >> COEFF_CONTEXT_BITS;
Angie Chiang's avatar
Angie Chiang committed
608
    if (sign == 1)
609
      --dc_sign;
Angie Chiang's avatar
Angie Chiang committed
610
    else if (sign == 2)
611
      ++dc_sign;
Angie Chiang's avatar
Angie Chiang committed
612
    else if (sign != 0)
Angie Chiang's avatar
Angie Chiang committed
613
      assert(0);
Angie Chiang's avatar
Angie Chiang committed
614
  }
615

616
  txb_ctx->dc_sign_ctx = get_dc_sign_ctx(dc_sign);
Angie Chiang's avatar
Angie Chiang committed
617 618 619 620

  if (plane == 0) {
    int top = 0;
    int left = 0;
621 622

    for (int k = 0; k < txb_w_unit; ++k) {
Angie Chiang's avatar
Angie Chiang committed
623
      top = AOMMAX(top, ((uint8_t)a[k] & COEFF_CONTEXT_MASK));
624 625 626
    }

    for (int k = 0; k < txb_h_unit; ++k) {
Angie Chiang's avatar
Angie Chiang committed
627
      left = AOMMAX(left, ((uint8_t)l[k] & COEFF_CONTEXT_MASK));
Angie Chiang's avatar
Angie Chiang committed
628
    }
629

Angie Chiang's avatar
Angie Chiang committed
630 631 632
    top = AOMMIN(top, 255);
    left = AOMMIN(left, 255);

633
    if (plane_bsize == txsize_to_bsize[tx_size])
634
      txb_ctx->txb_skip_ctx = 0;
Angie Chiang's avatar
Angie Chiang committed
635
    else if (top == 0 && left == 0)
636
      txb_ctx->txb_skip_ctx = 1;
Angie Chiang's avatar
Angie Chiang committed
637
    else if (top == 0 || left == 0)
638
      txb_ctx->txb_skip_ctx = 2 + (AOMMAX(top, left) > 3);
Angie Chiang's avatar
Angie Chiang committed
639
    else if (AOMMAX(top, left) <= 3)
640
      txb_ctx->txb_skip_ctx = 4;
Angie Chiang's avatar
Angie Chiang committed
641
    else if (AOMMIN(top, left) <= 3)
642
      txb_ctx->txb_skip_ctx = 5;
Angie Chiang's avatar
Angie Chiang committed
643
    else
644
      txb_ctx->txb_skip_ctx = 6;
Angie Chiang's avatar
Angie Chiang committed
645 646
  } else {
    int ctx_base = get_entropy_context(tx_size, a, l);
647
    txb_ctx->txb_skip_ctx = ctx_offset + ctx_base;
Angie Chiang's avatar
Angie Chiang committed
648 649
  }
}
Angie Chiang's avatar
Angie Chiang committed
650

651 652 653 654
#if LV_MAP_PROB
void av1_init_txb_probs(FRAME_CONTEXT *fc);
#endif  // LV_MAP_PROB

Angie Chiang's avatar
Angie Chiang committed
655 656
void av1_adapt_txb_probs(AV1_COMMON *cm, unsigned int count_sat,
                         unsigned int update_factor);
657 658

void av1_init_lv_map(AV1_COMMON *cm);
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732

#if CONFIG_CTX1D
static INLINE void get_eob_vert(int16_t *eob_ls, const tran_low_t *tcoeff,
                                int w, int h) {
  for (int c = 0; c < w; ++c) {
    eob_ls[c] = 0;
    for (int r = h - 1; r >= 0; --r) {
      int coeff_idx = r * w + c;
      if (tcoeff[coeff_idx] != 0) {
        eob_ls[c] = r + 1;
        break;
      }
    }
  }
}

static INLINE void get_eob_horiz(int16_t *eob_ls, const tran_low_t *tcoeff,
                                 int w, int h) {
  for (int r = 0; r < h; ++r) {
    eob_ls[r] = 0;
    for (int c = w - 1; c >= 0; --c) {
      int coeff_idx = r * w + c;
      if (tcoeff[coeff_idx] != 0) {
        eob_ls[r] = c + 1;
        break;
      }
    }
  }
}

static INLINE int get_empty_line_ctx(int line_idx, int16_t *eob_ls) {
  if (line_idx > 0) {
    int prev_eob = eob_ls[line_idx - 1];
    if (prev_eob == 0) {
      return 1;
    } else if (prev_eob < 3) {
      return 2;
    } else if (prev_eob < 6) {
      return 3;
    } else {
      return 4;
    }
  } else {
    return 0;
  }
}

#define MAX_POS_CTX 8
static int pos_ctx[MAX_HVTX_SIZE] = {
  0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
  6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
};
static INLINE int get_hv_eob_ctx(int line_idx, int pos, int16_t *eob_ls) {
  if (line_idx > 0) {
    int prev_eob = eob_ls[line_idx - 1];
    int diff = pos + 1 - prev_eob;
    int abs_diff = abs(diff);
    int ctx_idx = pos_ctx[abs_diff];
    assert(ctx_idx < MAX_POS_CTX);
    if (diff < 0) {
      ctx_idx += MAX_POS_CTX;
      assert(ctx_idx >= MAX_POS_CTX);
      assert(ctx_idx < 2 * MAX_POS_CTX);
    }
    return ctx_idx;
  } else {
    int ctx_idx = MAX_POS_CTX + MAX_POS_CTX + pos_ctx[pos];
    assert(ctx_idx < HV_EOB_CONTEXTS);
    assert(HV_EOB_CONTEXTS == MAX_POS_CTX * 3);
    return ctx_idx;
  }
}
#endif  // CONFIG_CTX1D

Angie Chiang's avatar
Angie Chiang committed
733
#endif  // AV1_COMMON_TXB_COMMON_H_