detokenize.c 12.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
#if CONFIG_NEW_QUANT
                        dequant_val_type_nuq *dq_val,
Thomas Davies's avatar
Thomas Davies committed
107
#else
108
#if CONFIG_AOM_QM
109
                        qm_val_t *iqm[2][TX_SIZES_ALL],
110
#endif  // CONFIG_AOM_QM
Thomas Davies's avatar
Thomas Davies committed
111
#endif  // CONFIG_NEW_QUANT
112 113
                        int ctx, const int16_t *scan, const int16_t *nb,
                        int16_t *max_scan_line, aom_reader *r) {
114
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
115
  const int max_eob = tx_size_2d[tx_size];
Jingning Han's avatar
Jingning Han committed
116
  const int ref = is_inter_block(&xd->mi[0]->mbmi);
Thomas Davies's avatar
Thomas Davies committed
117
#if CONFIG_AOM_QM && !CONFIG_NEW_QUANT
118
  const qm_val_t *iqmatrix = iqm[!ref][tx_size];
119
#endif  // CONFIG_AOM_QM
120
  (void)tx_type;
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
  int v, token;
133
  int32_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
static void decode_color_map_tokens(Av1ColorMapParam *param, aom_reader *r) {
Fangwen Fu's avatar
Fangwen Fu committed
222
  uint8_t color_order[PALETTE_MAX_SIZE];
223 224 225 226 227 228 229
  const int n = param->n_colors;
  uint8_t *const color_map = param->color_map;
  MapCdf color_map_cdf = param->map_cdf;
  int plane_block_width = param->plane_width;
  int plane_block_height = param->plane_height;
  int rows = param->rows;
  int cols = param->cols;
Fangwen Fu's avatar
Fangwen Fu committed
230

231 232 233 234
  // The first color index.
  color_map[0] = av1_read_uniform(r, n);
  assert(color_map[0] < n);

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

277 278 279 280 281 282 283 284 285 286 287 288 289
static void get_palette_params(const MACROBLOCKD *const xd, int plane,
                               BLOCK_SIZE bsize, Av1ColorMapParam *params) {
  assert(plane == 0 || plane == 1);
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
  params->color_map = xd->plane[plane].color_index_map;
  params->map_cdf = plane ? xd->tile_ctx->palette_uv_color_index_cdf
                          : xd->tile_ctx->palette_y_color_index_cdf;
  params->n_colors = pmi->palette_size[plane];
  av1_get_block_dimensions(bsize, plane, xd, &params->plane_width,
                           &params->plane_height, &params->rows, &params->cols);
}

Sarah Parker's avatar
Sarah Parker committed
290 291 292
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
static void get_mrc_params(const MACROBLOCKD *const xd, TX_SIZE tx_size,
                           Av1ColorMapParam *params) {
293
  memset(params, 0, sizeof(*params));
Sarah Parker's avatar
Sarah Parker committed
294 295 296 297 298 299 300 301 302
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const int is_inter = is_inter_block(mbmi);
  params->color_map = xd->mrc_mask;
  params->map_cdf = is_inter ? xd->tile_ctx->mrc_mask_inter_cdf
                             : xd->tile_ctx->mrc_mask_intra_cdf;
  params->n_colors = 2;
  params->plane_width = tx_size_wide[tx_size];
  params->rows = tx_size_high[tx_size];
  params->cols = tx_size_wide[tx_size];
303
}
Sarah Parker's avatar
Sarah Parker committed
304
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
305 306 307 308 309 310 311 312 313 314 315 316

void av1_decode_palette_tokens(MACROBLOCKD *const xd, int plane,
                               aom_reader *r) {
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  assert(plane == 0 || plane == 1);
  assert(mbmi->sb_type >= BLOCK_8X8);
  Av1ColorMapParam color_map_params;
  memset(&color_map_params, 0, sizeof(color_map_params));
  get_palette_params(xd, plane, mbmi->sb_type, &color_map_params);
  decode_color_map_tokens(&color_map_params, r);
}

Sarah Parker's avatar
Sarah Parker committed
317 318 319
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
static void decode_mrc_tokens(MACROBLOCKD *const xd, TX_TYPE tx_size,
                              aom_reader *r) {
320
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
Sarah Parker's avatar
Sarah Parker committed
321 322 323 324
  const int is_inter = is_inter_block(mbmi);
  if ((is_inter && !SIGNAL_MRC_MASK_INTER) ||
      (!is_inter && !SIGNAL_MRC_MASK_INTRA))
    return;
325
  Av1ColorMapParam color_map_params;
Sarah Parker's avatar
Sarah Parker committed
326
  get_mrc_params(xd, tx_size, &color_map_params);
327 328
  decode_color_map_tokens(&color_map_params, r);
}
Sarah Parker's avatar
Sarah Parker committed
329
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
330

331
#if !CONFIG_PVQ || CONFIG_VAR_TX
332
int av1_decode_block_tokens(AV1_COMMON *cm, MACROBLOCKD *const xd, int plane,
333
                            const SCAN_ORDER *sc, int x, int y, TX_SIZE tx_size,
334
                            TX_TYPE tx_type, int16_t *max_scan_line,
335
                            aom_reader *r, int seg_id) {
Jingning Han's avatar
Jingning Han committed
336 337
  struct macroblockd_plane *const pd = &xd->plane[plane];
  const int16_t *const dequant = pd->seg_dequant[seg_id];
338 339
  const int ctx =
      get_entropy_context(tx_size, pd->above_context + x, pd->left_context + y);
340
#if CONFIG_NEW_QUANT
341
  const int ref = is_inter_block(&xd->mi[0]->mbmi);
342 343
  int dq =
      get_dq_profile_from_ctx(xd->qindex[seg_id], ctx, ref, pd->plane_type);
344 345
#endif  //  CONFIG_NEW_QUANT

Sarah Parker's avatar
Sarah Parker committed
346 347 348 349
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
  if (tx_type == MRC_DCT) decode_mrc_tokens(xd, tx_size, r);
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK

350 351
  const int eob =
      decode_coefs(xd, pd->plane_type, pd->dqcoeff, tx_size, tx_type, dequant,
352
#if CONFIG_NEW_QUANT
353
                   pd->seg_dequant_nuq[seg_id][dq],
Thomas Davies's avatar
Thomas Davies committed
354
#else
355 356
#if CONFIG_AOM_QM
                   pd->seg_iqmatrix[seg_id],
357
#endif  // CONFIG_AOM_QM
Thomas Davies's avatar
Thomas Davies committed
358
#endif  // CONFIG_NEW_QUANT
359
                   ctx, sc->scan, sc->neighbors, max_scan_line, r);
360
  av1_set_contexts(xd, pd, plane, tx_size, eob > 0, x, y);
361 362 363 364
#if CONFIG_ADAPT_SCAN
  if (xd->counts)
    av1_update_scan_count_facade(cm, xd->counts, tx_size, tx_type, pd->dqcoeff,
                                 eob);
365 366
#else
  (void)cm;
367
#endif
Jingning Han's avatar
Jingning Han committed
368 369
  return eob;
}
370
#endif  // !CONFIG_PVQ