detokenize.c 11.7 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

20
21
#define ACCT_STR __func__

22
#if !CONFIG_PVQ || CONFIG_VAR_TX
23
24
25
26
#include "av1/common/common.h"
#include "av1/common/entropy.h"
#include "av1/common/idct.h"
#include "av1/decoder/detokenize.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) {
Jingning Han's avatar
Jingning Han committed
113
  FRAME_COUNTS *counts = xd->counts;
114
115
116
117
118
#if CONFIG_EC_ADAPT
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
#else
  FRAME_CONTEXT *const ec_ctx = xd->fc;
#endif
119
  const int max_eob = tx_size_2d[tx_size];
Jingning Han's avatar
Jingning Han committed
120
  const int ref = is_inter_block(&xd->mi[0]->mbmi);
121
122
#if CONFIG_AOM_QM
  const qm_val_t *iqmatrix = iqm[!ref][tx_size];
123
124
#else
  (void)tx_type;
125
#endif  // CONFIG_AOM_QM
Jingning Han's avatar
Jingning Han committed
126
  int band, c = 0;
127
  const int tx_size_ctx = txsize_sqr_map[tx_size];
128
  aom_cdf_prob(*coef_head_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
129
      ec_ctx->coef_head_cdfs[tx_size_ctx][type][ref];
130
  aom_cdf_prob(*coef_tail_cdfs)[COEFF_CONTEXTS][CDF_SIZE(ENTROPY_TOKENS)] =
131
132
      ec_ctx->coef_tail_cdfs[tx_size_ctx][type][ref];
  int val = 0;
133

134
#if !CONFIG_EC_ADAPT
135
  unsigned int *blockz_count;
136
137
  unsigned int(*coef_counts)[COEFF_CONTEXTS][UNCONSTRAINED_NODES + 1] = NULL;
  unsigned int(*eob_branch_count)[COEFF_CONTEXTS] = NULL;
138
#endif
139
  uint8_t token_cache[MAX_TX_SQUARE];
Jingning Han's avatar
Jingning Han committed
140
  const uint8_t *band_translate = get_band_translate(tx_size);
141
  int dq_shift;
Jingning Han's avatar
Jingning Han committed
142
143
  int v, token;
  int16_t dqv = dq[0];
144
145
146
#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
147
148

  if (counts) {
149
#if !CONFIG_EC_ADAPT
150
151
    coef_counts = counts->coef[tx_size_ctx][type][ref];
    eob_branch_count = counts->eob_branch[tx_size_ctx][type][ref];
152
153
    blockz_count = counts->blockz_count[tx_size_ctx][type][ref][ctx];
#endif
Jingning Han's avatar
Jingning Han committed
154
155
  }

156
  dq_shift = av1_get_tx_scale(tx_size);
157

158
159
  band = *band_translate++;

160
  int more_data = 1;
161
  while (more_data) {
162
    int comb_token;
163
    int last_pos = (c + 1 == max_eob);
164
    int first_pos = (c == 0);
Jingning Han's avatar
Jingning Han committed
165

166
167
168
169
#if CONFIG_NEW_QUANT
    dqv_val = &dq_val[band][0];
#endif  // CONFIG_NEW_QUANT

170
    comb_token = last_pos ? 2 * aom_read_bit(r, ACCT_STR) + 2
171
                          : aom_read_symbol(r, coef_head_cdfs[band][ctx],
172
173
174
                                            HEAD_TOKENS + first_pos, ACCT_STR) +
                                !first_pos;
    if (first_pos) {
175
#if !CONFIG_EC_ADAPT
176
      if (counts) ++blockz_count[comb_token != 0];
177
#endif
178
179
180
      if (comb_token == 0) return 0;
    }
    token = comb_token >> 1;
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

    while (!token) {
      *max_scan_line = AOMMAX(*max_scan_line, scan[c]);
      token_cache[scan[c]] = 0;
#if !CONFIG_EC_ADAPT
      if (counts && !last_pos) {
        ++coef_counts[band][ctx][ZERO_TOKEN];
      }
#endif
      ++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;
    }

204
205
    more_data = comb_token & 1;
#if !CONFIG_EC_ADAPT
206
    if (counts && !last_pos) {
207
      ++coef_counts[band][ctx][token];
208
209
      ++eob_branch_count[band][ctx];
      if (!more_data) ++coef_counts[band][ctx][EOB_MODEL_TOKEN];
210
    }
211
#endif
212

213
    if (token > ONE_TOKEN)
214
215
      token +=
          aom_read_symbol(r, coef_tail_cdfs[band][ctx], TAIL_TOKENS, ACCT_STR);
216
#if CONFIG_NEW_QUANT
217
    dqv_val = &dq_val[band][0];
218
#endif  // CONFIG_NEW_QUANT
219
220

    *max_scan_line = AOMMAX(*max_scan_line, scan[c]);
221
    token_cache[scan[c]] = av1_pt_energy_class[token];
222

223
    val = token_to_value(r, token, tx_size, xd->bd);
224
225
226
227
228
229

#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
230
231
232
233
    // Apply quant matrix only for 2D transforms
    if (IS_2D_TRANSFORM(tx_type))
      dqv = ((iqmatrix[scan[c]] * (int)dqv) + (1 << (AOM_QM_BITS - 1))) >>
            AOM_QM_BITS;
234
235
236
#endif
    v = (val * dqv) >> dq_shift;
#endif
237

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

240
    dqcoeff[scan[c]] = v;
241

242
    ++c;
243
244
    more_data &= (c < max_eob);
    if (!more_data) break;
245
246
    dqv = dq[1];
    ctx = get_coef_context(nb, token_cache, c);
247
    band = *band_translate++;
Jingning Han's avatar
Jingning Han committed
248
249
250
251
  }

  return c;
}
252
#endif  // !CONFIG_PVQ
Jingning Han's avatar
Jingning Han committed
253

254
#if CONFIG_PALETTE
Fangwen Fu's avatar
Fangwen Fu committed
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
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];
  int i, j;
  uint8_t *const color_map = xd->plane[plane].color_index_map;
  const aom_prob(
      *const prob)[PALETTE_COLOR_INDEX_CONTEXTS][PALETTE_COLORS - 1] =
      plane ? av1_default_palette_uv_color_index_prob
            : av1_default_palette_y_color_index_prob;
  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);

Fangwen Fu's avatar
Fangwen Fu committed
272
273
274
275
#if CONFIG_PALETTE_THROUGHPUT
  // Run wavefront on the palette map index decoding.
  for (i = 1; i < rows + cols - 1; ++i) {
    for (j = AOMMIN(i, cols - 1); j >= AOMMAX(0, i - rows + 1); --j) {
Fangwen Fu's avatar
Fangwen Fu committed
276
      const int color_ctx = av1_get_palette_color_index_context(
Fangwen Fu's avatar
Fangwen Fu committed
277
          color_map, plane_block_width, (i - j), j, n, color_order, NULL);
Fangwen Fu's avatar
Fangwen Fu committed
278
279
280
281
      const int color_idx =
          aom_read_tree(r, av1_palette_color_index_tree[n - 2],
                        prob[n - 2][color_ctx], ACCT_STR);
      assert(color_idx >= 0 && color_idx < n);
Fangwen Fu's avatar
Fangwen Fu committed
282
      color_map[(i - j) * plane_block_width + j] = color_order[color_idx];
Fangwen Fu's avatar
Fangwen Fu committed
283
284
285
    }
  }
  // Copy last column to extra columns.
Fangwen Fu's avatar
Fangwen Fu committed
286
287
288
289
290
  if (cols < plane_block_width) {
    for (i = 0; i < plane_block_height; ++i) {
      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
291
292
293
    }
  }
#else
hui su's avatar
hui su committed
294
295
  for (i = 0; i < rows; ++i) {
    for (j = (i == 0 ? 1 : 0); j < cols; ++j) {
296
      const int color_ctx = av1_get_palette_color_index_context(
297
          color_map, plane_block_width, i, j, n, color_order, NULL);
298
      const int color_idx =
299
300
          aom_read_tree(r, av1_palette_color_index_tree[n - PALETTE_MIN_SIZE],
                        prob[n - PALETTE_MIN_SIZE][color_ctx], ACCT_STR);
hui su's avatar
hui su committed
301
      assert(color_idx >= 0 && color_idx < n);
302
      color_map[i * plane_block_width + j] = color_order[color_idx];
hui su's avatar
hui su committed
303
    }
304
305
306
307
    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
308
#endif  // CONFIG_PALETTE_THROUGHPUT
309
310
311
312
  // Copy last row to extra rows.
  for (i = rows; i < plane_block_height; ++i) {
    memcpy(color_map + i * plane_block_width,
           color_map + (rows - 1) * plane_block_width, plane_block_width);
hui su's avatar
hui su committed
313
314
  }
}
315
#endif  // CONFIG_PALETTE
hui su's avatar
hui su committed
316

317
#if !CONFIG_PVQ || CONFIG_VAR_TX
318
int av1_decode_block_tokens(AV1_COMMON *cm, MACROBLOCKD *const xd, int plane,
319
                            const SCAN_ORDER *sc, int x, int y, TX_SIZE tx_size,
320
                            TX_TYPE tx_type, int16_t *max_scan_line,
321
                            aom_reader *r, int seg_id) {
Jingning Han's avatar
Jingning Han committed
322
323
  struct macroblockd_plane *const pd = &xd->plane[plane];
  const int16_t *const dequant = pd->seg_dequant[seg_id];
324
325
  const int ctx =
      get_entropy_context(tx_size, pd->above_context + x, pd->left_context + y);
326
#if CONFIG_NEW_QUANT
327
  const int ref = is_inter_block(&xd->mi[0]->mbmi);
328
329
  int dq =
      get_dq_profile_from_ctx(xd->qindex[seg_id], ctx, ref, pd->plane_type);
330
331
#endif  //  CONFIG_NEW_QUANT

332
333
  const int eob =
      decode_coefs(xd, pd->plane_type, pd->dqcoeff, tx_size, tx_type, dequant,
334
#if CONFIG_NEW_QUANT
335
                   pd->seg_dequant_nuq[seg_id][dq],
336
#endif  // CONFIG_NEW_QUANT
337
338
#if CONFIG_AOM_QM
                   pd->seg_iqmatrix[seg_id],
339
#endif  // CONFIG_AOM_QM
340
                   ctx, sc->scan, sc->neighbors, max_scan_line, r);
341
  av1_set_contexts(xd, pd, plane, tx_size, eob > 0, x, y);
342
343
344
345
#if CONFIG_ADAPT_SCAN
  if (xd->counts)
    av1_update_scan_count_facade(cm, xd->counts, tx_size, tx_type, pd->dqcoeff,
                                 eob);
346
347
#else
  (void)cm;
348
#endif
Jingning Han's avatar
Jingning Han committed
349
350
  return eob;
}
351
#endif  // !CONFIG_PVQ