detokenize.c 10.8 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * 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.
Jingning Han's avatar
Jingning Han committed
10 11
 */

12
#include "./aom_config.h"
13
#if !CONFIG_PVQ
Yaowu Xu's avatar
Yaowu Xu committed
14
#include "aom_mem/aom_mem.h"
15
#include "aom_ports/mem.h"
16 17
#endif  // !CONFIG_PVQ

18
#include "av1/common/blockd.h"
19
#include "av1/decoder/detokenize.h"
20

21 22
#define ACCT_STR __func__

23
#if !CONFIG_PVQ || CONFIG_VAR_TX
24 25 26
#include "av1/common/common.h"
#include "av1/common/entropy.h"
#include "av1/common/idct.h"
Jingning Han's avatar
Jingning Han committed
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#define EOB_CONTEXT_NODE 0
#define ZERO_CONTEXT_NODE 1
#define ONE_CONTEXT_NODE 2
#define LOW_VAL_CONTEXT_NODE 0
#define TWO_CONTEXT_NODE 1
#define THREE_CONTEXT_NODE 2
#define HIGH_LOW_CONTEXT_NODE 3
#define CAT_ONE_CONTEXT_NODE 4
#define CAT_THREEFOUR_CONTEXT_NODE 5
#define CAT_THREE_CONTEXT_NODE 6
#define CAT_FIVE_CONTEXT_NODE 7

#define INCREMENT_COUNT(token)                   \
  do {                                           \
    if (counts) ++coef_counts[band][ctx][token]; \
Jingning Han's avatar
Jingning Han committed
43 44
  } while (0)

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#if CONFIG_NEW_MULTISYMBOL
#define READ_COEFF(prob_name, cdf_name, num, r) read_coeff(cdf_name, num, r);
static INLINE int read_coeff(const aom_cdf_prob *const *cdf, int n,
                             aom_reader *r) {
  int val = 0;
  int i = 0;
  int count = 0;
  while (count < n) {
    const int size = AOMMIN(n - count, 4);
    val |= aom_read_cdf(r, cdf[i++], 1 << size, ACCT_STR) << count;
    count += size;
  }
  return val;
}
#else
#define READ_COEFF(prob_name, cdf_name, num, r) read_coeff(prob_name, num, r);
Yaowu Xu's avatar
Yaowu Xu committed
61
static INLINE int read_coeff(const aom_prob *probs, int n, aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
62
  int i, val = 0;
Michael Bebenita's avatar
Michael Bebenita committed
63
  for (i = 0; i < n; ++i) val = (val << 1) | aom_read(r, probs[i], ACCT_STR);
Jingning Han's avatar
Jingning Han committed
64 65 66
  return val;
}

67 68
#endif

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
static int token_to_value(aom_reader *const r, int token, TX_SIZE tx_size,
                          int bit_depth) {
#if !CONFIG_HIGHBITDEPTH
  assert(bit_depth == 8);
#endif  // !CONFIG_HIGHBITDEPTH

  switch (token) {
    case ZERO_TOKEN:
    case ONE_TOKEN:
    case TWO_TOKEN:
    case THREE_TOKEN:
    case FOUR_TOKEN: return token;
    case CATEGORY1_TOKEN:
      return CAT1_MIN_VAL + READ_COEFF(av1_cat1_prob, av1_cat1_cdf, 1, r);
    case CATEGORY2_TOKEN:
      return CAT2_MIN_VAL + READ_COEFF(av1_cat2_prob, av1_cat2_cdf, 2, r);
    case CATEGORY3_TOKEN:
      return CAT3_MIN_VAL + READ_COEFF(av1_cat3_prob, av1_cat3_cdf, 3, r);
    case CATEGORY4_TOKEN:
      return CAT4_MIN_VAL + READ_COEFF(av1_cat4_prob, av1_cat4_cdf, 4, r);
    case CATEGORY5_TOKEN:
      return CAT5_MIN_VAL + READ_COEFF(av1_cat5_prob, av1_cat5_cdf, 5, r);
    case CATEGORY6_TOKEN: {
      const int skip_bits = (int)sizeof(av1_cat6_prob) -
                            av1_get_cat6_extrabits_size(tx_size, bit_depth);
      return CAT6_MIN_VAL + READ_COEFF(av1_cat6_prob + skip_bits, av1_cat6_cdf,
                                       18 - skip_bits, r);
    }
    default:
      assert(0);  // Invalid token.
      return -1;
  }
}

103 104
static int decode_coefs(MACROBLOCKD *xd, PLANE_TYPE type, tran_low_t *dqcoeff,
                        TX_SIZE tx_size, TX_TYPE tx_type, const int16_t *dq,
105 106 107
#if CONFIG_NEW_QUANT
                        dequant_val_type_nuq *dq_val,
#endif  // CONFIG_NEW_QUANT
108
#if CONFIG_AOM_QM
109
                        const qm_val_t *iqm[2][TX_SIZES_ALL],
110
#endif  // CONFIG_AOM_QM
111 112
                        int ctx, const int16_t *scan, const int16_t *nb,
                        int16_t *max_scan_line, aom_reader *r) {
113
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
114
  const int max_eob = tx_size_2d[tx_size];
Jingning Han's avatar
Jingning Han committed
115
  const int ref = is_inter_block(&xd->mi[0]->mbmi);
116 117
#if CONFIG_AOM_QM
  const qm_val_t *iqmatrix = iqm[!ref][tx_size];
118 119
#else
  (void)tx_type;
120
#endif  // CONFIG_AOM_QM
Jingning Han's avatar
Jingning Han committed
121
  int band, c = 0;
122
  const int tx_size_ctx = txsize_sqr_map[tx_size];
123
  aom_cdf_prob(*coef_head_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
124
      ec_ctx->coef_head_cdfs[tx_size_ctx][type][ref];
125
  aom_cdf_prob(*coef_tail_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
126 127
      ec_ctx->coef_tail_cdfs[tx_size_ctx][type][ref];
  int val = 0;
128

129
  uint8_t token_cache[MAX_TX_SQUARE];
Jingning Han's avatar
Jingning Han committed
130
  const uint8_t *band_translate = get_band_translate(tx_size);
131
  int dq_shift;
Jingning Han's avatar
Jingning Han committed
132 133
  int v, token;
  int16_t dqv = dq[0];
134 135 136
#if CONFIG_NEW_QUANT
  const tran_low_t *dqv_val = &dq_val[0][0];
#endif  // CONFIG_NEW_QUANT
Jingning Han's avatar
Jingning Han committed
137

138
  dq_shift = av1_get_tx_scale(tx_size);
139

140 141
  band = *band_translate++;

142
  int more_data = 1;
143
  while (more_data) {
144
    int comb_token;
145
    int last_pos = (c + 1 == max_eob);
146
    int first_pos = (c == 0);
Jingning Han's avatar
Jingning Han committed
147

148 149 150 151
#if CONFIG_NEW_QUANT
    dqv_val = &dq_val[band][0];
#endif  // CONFIG_NEW_QUANT

152
    comb_token = last_pos ? 2 * aom_read_bit(r, ACCT_STR) + 2
153
                          : aom_read_symbol(r, coef_head_cdfs[band][ctx],
154 155 156
                                            HEAD_TOKENS + first_pos, ACCT_STR) +
                                !first_pos;
    if (first_pos) {
157 158 159
      if (comb_token == 0) return 0;
    }
    token = comb_token >> 1;
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

    while (!token) {
      *max_scan_line = AOMMAX(*max_scan_line, scan[c]);
      token_cache[scan[c]] = 0;
      ++c;
      dqv = dq[1];
      ctx = get_coef_context(nb, token_cache, c);
      band = *band_translate++;

      last_pos = (c + 1 == max_eob);

      comb_token = last_pos ? 2 * aom_read_bit(r, ACCT_STR) + 2
                            : aom_read_symbol(r, coef_head_cdfs[band][ctx],
                                              HEAD_TOKENS, ACCT_STR) +
                                  1;
      token = comb_token >> 1;
    }

178
    more_data = comb_token & 1;
179

180
    if (token > ONE_TOKEN)
181 182
      token +=
          aom_read_symbol(r, coef_tail_cdfs[band][ctx], TAIL_TOKENS, ACCT_STR);
183
#if CONFIG_NEW_QUANT
184
    dqv_val = &dq_val[band][0];
185
#endif  // CONFIG_NEW_QUANT
186 187

    *max_scan_line = AOMMAX(*max_scan_line, scan[c]);
188
    token_cache[scan[c]] = av1_pt_energy_class[token];
189

190
    val = token_to_value(r, token, tx_size, xd->bd);
191 192 193 194 195 196

#if CONFIG_NEW_QUANT
    v = av1_dequant_abscoeff_nuq(val, dqv, dqv_val);
    v = dq_shift ? ROUND_POWER_OF_TWO(v, dq_shift) : v;
#else
#if CONFIG_AOM_QM
197
    // Apply quant matrix only for 2D transforms
198
    if (IS_2D_TRANSFORM(tx_type) && iqmatrix != NULL)
199 200
      dqv = ((iqmatrix[scan[c]] * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >>
            AOM_QM_BITS;
201 202 203
#endif
    v = (val * dqv) >> dq_shift;
#endif
204

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
205
    v = (int)check_range(aom_read_bit(r, ACCT_STR) ? -v : v, xd->bd);
206

207
    dqcoeff[scan[c]] = v;
208

209
    ++c;
210 211
    more_data &= (c < max_eob);
    if (!more_data) break;
212 213
    dqv = dq[1];
    ctx = get_coef_context(nb, token_cache, c);
214
    band = *band_translate++;
Jingning Han's avatar
Jingning Han committed
215 216 217 218
  }

  return c;
}
219
#endif  // !CONFIG_PVQ
Jingning Han's avatar
Jingning Han committed
220

221
#if CONFIG_PALETTE
Fangwen Fu's avatar
Fangwen Fu committed
222 223 224 225 226 227 228
void av1_decode_palette_tokens(MACROBLOCKD *const xd, int plane,
                               aom_reader *r) {
  const MODE_INFO *const mi = xd->mi[0];
  const MB_MODE_INFO *const mbmi = &mi->mbmi;
  uint8_t color_order[PALETTE_MAX_SIZE];
  const int n = mbmi->palette_mode_info.palette_size[plane];
  uint8_t *const color_map = xd->plane[plane].color_index_map;
229 230 231 232
  aom_cdf_prob(
      *palette_cdf)[PALETTE_COLOR_INDEX_CONTEXTS][CDF_SIZE(PALETTE_COLORS)] =
      plane ? xd->tile_ctx->palette_uv_color_index_cdf
            : xd->tile_ctx->palette_y_color_index_cdf;
Fangwen Fu's avatar
Fangwen Fu committed
233 234 235 236 237
  int plane_block_width, plane_block_height, rows, cols;
  av1_get_block_dimensions(mbmi->sb_type, plane, xd, &plane_block_width,
                           &plane_block_height, &rows, &cols);
  assert(plane == 0 || plane == 1);

238 239 240 241
  // The first color index.
  color_map[0] = av1_read_uniform(r, n);
  assert(color_map[0] < n);

Fangwen Fu's avatar
Fangwen Fu committed
242 243
#if CONFIG_PALETTE_THROUGHPUT
  // Run wavefront on the palette map index decoding.
244 245
  for (int i = 1; i < rows + cols - 1; ++i) {
    for (int j = AOMMIN(i, cols - 1); j >= AOMMAX(0, i - rows + 1); --j) {
Fangwen Fu's avatar
Fangwen Fu committed
246
      const int color_ctx = av1_get_palette_color_index_context(
Fangwen Fu's avatar
Fangwen Fu committed
247
          color_map, plane_block_width, (i - j), j, n, color_order, NULL);
248 249
      const int color_idx = aom_read_symbol(
          r, palette_cdf[n - PALETTE_MIN_SIZE][color_ctx], n, ACCT_STR);
Fangwen Fu's avatar
Fangwen Fu committed
250
      assert(color_idx >= 0 && color_idx < n);
Fangwen Fu's avatar
Fangwen Fu committed
251
      color_map[(i - j) * plane_block_width + j] = color_order[color_idx];
Fangwen Fu's avatar
Fangwen Fu committed
252 253 254
    }
  }
  // Copy last column to extra columns.
Fangwen Fu's avatar
Fangwen Fu committed
255
  if (cols < plane_block_width) {
256
    for (int i = 0; i < plane_block_height; ++i) {
Fangwen Fu's avatar
Fangwen Fu committed
257 258 259
      memset(color_map + i * plane_block_width + cols,
             color_map[i * plane_block_width + cols - 1],
             (plane_block_width - cols));
Fangwen Fu's avatar
Fangwen Fu committed
260 261 262
    }
  }
#else
263 264
  for (int i = 0; i < rows; ++i) {
    for (int j = (i == 0 ? 1 : 0); j < cols; ++j) {
265
      const int color_ctx = av1_get_palette_color_index_context(
266
          color_map, plane_block_width, i, j, n, color_order, NULL);
267 268
      const int color_idx = aom_read_symbol(
          r, palette_cdf[n - PALETTE_MIN_SIZE][color_ctx], n, ACCT_STR);
hui su's avatar
hui su committed
269
      assert(color_idx >= 0 && color_idx < n);
270
      color_map[i * plane_block_width + j] = color_order[color_idx];
hui su's avatar
hui su committed
271
    }
272 273 274 275
    memset(color_map + i * plane_block_width + cols,
           color_map[i * plane_block_width + cols - 1],
           (plane_block_width - cols));  // Copy last column to extra columns.
  }
Fangwen Fu's avatar
Fangwen Fu committed
276
#endif  // CONFIG_PALETTE_THROUGHPUT
277
  // Copy last row to extra rows.
278
  for (int i = rows; i < plane_block_height; ++i) {
279 280
    memcpy(color_map + i * plane_block_width,
           color_map + (rows - 1) * plane_block_width, plane_block_width);
hui su's avatar
hui su committed
281 282
  }
}
283
#endif  // CONFIG_PALETTE
hui su's avatar
hui su committed
284

285
#if !CONFIG_PVQ || CONFIG_VAR_TX
286
int av1_decode_block_tokens(AV1_COMMON *cm, MACROBLOCKD *const xd, int plane,
287
                            const SCAN_ORDER *sc, int x, int y, TX_SIZE tx_size,
288
                            TX_TYPE tx_type, int16_t *max_scan_line,
289
                            aom_reader *r, int seg_id) {
Jingning Han's avatar
Jingning Han committed
290 291
  struct macroblockd_plane *const pd = &xd->plane[plane];
  const int16_t *const dequant = pd->seg_dequant[seg_id];
292 293
  const int ctx =
      get_entropy_context(tx_size, pd->above_context + x, pd->left_context + y);
294
#if CONFIG_NEW_QUANT
295
  const int ref = is_inter_block(&xd->mi[0]->mbmi);
296 297
  int dq =
      get_dq_profile_from_ctx(xd->qindex[seg_id], ctx, ref, pd->plane_type);
298 299
#endif  //  CONFIG_NEW_QUANT

300 301
  const int eob =
      decode_coefs(xd, pd->plane_type, pd->dqcoeff, tx_size, tx_type, dequant,
302
#if CONFIG_NEW_QUANT
303
                   pd->seg_dequant_nuq[seg_id][dq],
304
#endif  // CONFIG_NEW_QUANT
305 306
#if CONFIG_AOM_QM
                   pd->seg_iqmatrix[seg_id],
307
#endif  // CONFIG_AOM_QM
308
                   ctx, sc->scan, sc->neighbors, max_scan_line, r);
309
  av1_set_contexts(xd, pd, plane, tx_size, eob > 0, x, y);
310 311 312 313
#if CONFIG_ADAPT_SCAN
  if (xd->counts)
    av1_update_scan_count_facade(cm, xd->counts, tx_size, tx_type, pd->dqcoeff,
                                 eob);
314 315
#else
  (void)cm;
316
#endif
Jingning Han's avatar
Jingning Han committed
317 318
  return eob;
}
319
#endif  // !CONFIG_PVQ