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
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
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