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
#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
                        const 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
120
#else
  (void)tx_type;
121
#endif  // CONFIG_AOM_QM
Jingning Han's avatar
Jingning Han committed
122
  int band, c = 0;
123
  const int tx_size_ctx = txsize_sqr_map[tx_size];
124
  aom_cdf_prob(*coef_head_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
125
      ec_ctx->coef_head_cdfs[tx_size_ctx][type][ref];
126
  aom_cdf_prob(*coef_tail_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
127
128
      ec_ctx->coef_tail_cdfs[tx_size_ctx][type][ref];
  int val = 0;
129

130
  uint8_t token_cache[MAX_TX_SQUARE];
Jingning Han's avatar
Jingning Han committed
131
  const uint8_t *band_translate = get_band_translate(tx_size);
132
  int dq_shift;
Jingning Han's avatar
Jingning Han committed
133
134
  int v, token;
  int16_t dqv = dq[0];
135
136
137
#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
138

139
  dq_shift = av1_get_tx_scale(tx_size);
140

141
142
  band = *band_translate++;

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

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

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

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

179
    more_data = comb_token & 1;
180

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

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

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

#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
198
    // Apply quant matrix only for 2D transforms
199
    if (IS_2D_TRANSFORM(tx_type) && iqmatrix != NULL)
200
201
      dqv = ((iqmatrix[scan[c]] * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >>
            AOM_QM_BITS;
202
203
204
#endif
    v = (val * dqv) >> dq_shift;
#endif
205

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

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

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

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

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
  int plane_block_width, plane_block_height, rows, cols;
234
  assert(mbmi->sb_type >= BLOCK_8X8);
Fangwen Fu's avatar
Fangwen Fu committed
235
236
237
238
  av1_get_block_dimensions(mbmi->sb_type, plane, xd, &plane_block_width,
                           &plane_block_height, &rows, &cols);
  assert(plane == 0 || plane == 1);

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

Fangwen Fu's avatar
Fangwen Fu committed
243
244
#if CONFIG_PALETTE_THROUGHPUT
  // Run wavefront on the palette map index decoding.
245
246
  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
247
      const int color_ctx = av1_get_palette_color_index_context(
Fangwen Fu's avatar
Fangwen Fu committed
248
          color_map, plane_block_width, (i - j), j, n, color_order, NULL);
249
250
      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
251
      assert(color_idx >= 0 && color_idx < n);
Fangwen Fu's avatar
Fangwen Fu committed
252
      color_map[(i - j) * plane_block_width + j] = color_order[color_idx];
Fangwen Fu's avatar
Fangwen Fu committed
253
254
255
    }
  }
  // Copy last column to extra columns.
Fangwen Fu's avatar
Fangwen Fu committed
256
  if (cols < plane_block_width) {
257
    for (int i = 0; i < rows; ++i) {
Fangwen Fu's avatar
Fangwen Fu committed
258
259
260
      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
261
262
263
    }
  }
#else
264
265
  for (int i = 0; i < rows; ++i) {
    for (int j = (i == 0 ? 1 : 0); j < cols; ++j) {
266
      const int color_ctx = av1_get_palette_color_index_context(
267
          color_map, plane_block_width, i, j, n, color_order, NULL);
268
269
      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
270
      assert(color_idx >= 0 && color_idx < n);
271
      color_map[i * plane_block_width + j] = color_order[color_idx];
hui su's avatar
hui su committed
272
    }
273
274
275
276
    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
277
#endif  // CONFIG_PALETTE_THROUGHPUT
278
  // Copy last row to extra rows.
279
  for (int i = rows; i < plane_block_height; ++i) {
280
281
    memcpy(color_map + i * plane_block_width,
           color_map + (rows - 1) * plane_block_width, plane_block_width);
hui su's avatar
hui su committed
282
283
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],
Thomas Davies's avatar
Thomas Davies committed
304
#else
305
306
#if CONFIG_AOM_QM
                   pd->seg_iqmatrix[seg_id],
307
#endif  // CONFIG_AOM_QM
Thomas Davies's avatar
Thomas Davies committed
308
#endif  // CONFIG_NEW_QUANT
309
                   ctx, sc->scan, sc->neighbors, max_scan_line, r);
310
  av1_set_contexts(xd, pd, plane, tx_size, eob > 0, x, y);
311
312
313
314
#if CONFIG_ADAPT_SCAN
  if (xd->counts)
    av1_update_scan_count_facade(cm, xd->counts, tx_size, tx_type, pd->dqcoeff,
                                 eob);
315
316
#else
  (void)cm;
317
#endif
Jingning Han's avatar
Jingning Han committed
318
319
  return eob;
}
320
#endif  // !CONFIG_PVQ