vp9_detokenize.c 10.5 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9
10
 */

11
12
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
John Koleszar's avatar
John Koleszar committed
13

14
#include "vp9/common/vp9_blockd.h"
John Koleszar's avatar
John Koleszar committed
15
#include "vp9/common/vp9_common.h"
16
#include "vp9/common/vp9_seg_common.h"
17

18
19
20
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/decoder/vp9_onyxd_int.h"

21
22
23
24
#if CONFIG_BALANCED_COEFTREE
#define ZERO_CONTEXT_NODE           0
#define EOB_CONTEXT_NODE            1
#else
John Koleszar's avatar
John Koleszar committed
25
26
#define EOB_CONTEXT_NODE            0
#define ZERO_CONTEXT_NODE           1
27
#endif
28

John Koleszar's avatar
John Koleszar committed
29
30
31
32
33
34
35
36
37
38
#define ONE_CONTEXT_NODE            2
#define LOW_VAL_CONTEXT_NODE        3
#define TWO_CONTEXT_NODE            4
#define THREE_CONTEXT_NODE          5
#define HIGH_LOW_CONTEXT_NODE       6
#define CAT_ONE_CONTEXT_NODE        7
#define CAT_THREEFOUR_CONTEXT_NODE  8
#define CAT_THREE_CONTEXT_NODE      9
#define CAT_FIVE_CONTEXT_NODE       10

Scott LaVarnway's avatar
Scott LaVarnway committed
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#define CAT1_MIN_VAL    5
#define CAT2_MIN_VAL    7
#define CAT3_MIN_VAL   11
#define CAT4_MIN_VAL   19
#define CAT5_MIN_VAL   35
#define CAT6_MIN_VAL   67
#define CAT1_PROB0    159
#define CAT2_PROB0    145
#define CAT2_PROB1    165

#define CAT3_PROB0 140
#define CAT3_PROB1 148
#define CAT3_PROB2 173

#define CAT4_PROB0 135
#define CAT4_PROB1 140
#define CAT4_PROB2 155
#define CAT4_PROB3 176

#define CAT5_PROB0 130
#define CAT5_PROB1 134
#define CAT5_PROB2 141
#define CAT5_PROB3 157
#define CAT5_PROB4 180

64
static const vp9_prob cat6_prob[15] = {
65
66
  254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0
};
John Koleszar's avatar
John Koleszar committed
67

68
69
DECLARE_ALIGNED(16, extern const uint8_t,
                vp9_pt_energy_class[MAX_ENTROPY_TOKENS]);
70
71
72
73
74
75
#define INCREMENT_COUNT(token)               \
  do {                                       \
    coef_counts[type][ref][band][pt]         \
               [token >= TWO_TOKEN ?     \
                (token == DCT_EOB_TOKEN ? DCT_EOB_MODEL_TOKEN : TWO_TOKEN) : \
                token]++;     \
76
    token_cache[scan[c]] = vp9_pt_energy_class[token]; \
77
  } while (0)
78

Dmitry Kovalev's avatar
Dmitry Kovalev committed
79
80
#define WRITE_COEF_CONTINUE(val, token)                  \
  {                                                      \
81
82
    qcoeff_ptr[scan[c]] = vp9_read_and_apply_sign(r, val) * \
                            dq[c > 0] / (1 + (txfm_size == TX_32X32)); \
Dmitry Kovalev's avatar
Dmitry Kovalev committed
83
84
85
    INCREMENT_COUNT(token);                              \
    c++;                                                 \
    continue;                                            \
86
  }
John Koleszar's avatar
John Koleszar committed
87

Daniel Kang's avatar
Daniel Kang committed
88
89
#define ADJUST_COEF(prob, bits_count)  \
  do {                                 \
90
    if (vp9_read(r, prob))             \
Dmitry Kovalev's avatar
Dmitry Kovalev committed
91
      val += 1 << bits_count;          \
John Koleszar's avatar
John Koleszar committed
92
  } while (0);
John Koleszar's avatar
John Koleszar committed
93

94
static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd,
95
                        vp9_reader *r, int block_idx,
96
                        PLANE_TYPE type, int seg_eob, int16_t *qcoeff_ptr,
97
98
                        TX_SIZE txfm_size, const int16_t *dq,
                        ENTROPY_CONTEXT *A, ENTROPY_CONTEXT *L) {
99
100
  FRAME_CONTEXT *const fc = &cm->fc;
  FRAME_COUNTS *const counts = &cm->counts;
101
  ENTROPY_CONTEXT above_ec, left_ec;
102
  int pt, c = 0;
Paul Wilkins's avatar
Paul Wilkins committed
103
  int band;
104
105
106
107
108
109
110
111
112
113
114
  vp9_prob (*coef_probs)[PREV_COEF_CONTEXTS][UNCONSTRAINED_NODES];
  vp9_prob coef_probs_full[COEF_BANDS][PREV_COEF_CONTEXTS][ENTROPY_NODES];
  uint8_t load_map[COEF_BANDS][PREV_COEF_CONTEXTS] = {
    {0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0},
  };

115
  vp9_prob *prob;
116
  vp9_coeff_count_model *coef_counts;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
117
  const int ref = xd->mode_info_context->mbmi.ref_frame[0] != INTRA_FRAME;
118
  const int16_t *scan, *nb;
119
  uint8_t token_cache[1024];
Paul Wilkins's avatar
Paul Wilkins committed
120
  const uint8_t * band_translate;
121
122
123
#if CONFIG_BALANCED_COEFTREE
  int skip_eob_node = 0;
#endif
Daniel Kang's avatar
Daniel Kang committed
124

125
  coef_probs  = fc->coef_probs[txfm_size][type][ref];
126
  coef_counts = counts->coef[txfm_size];
127
  switch (txfm_size) {
Daniel Kang's avatar
Daniel Kang committed
128
    default:
129
    case TX_4X4: {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
130
131
      const TX_TYPE tx_type = type == PLANE_TYPE_Y_WITH_DC ?
                                  get_tx_type_4x4(xd, block_idx) : DCT_DCT;
132
      scan = get_scan_4x4(tx_type);
133
134
      above_ec = A[0] != 0;
      left_ec = L[0] != 0;
Paul Wilkins's avatar
Paul Wilkins committed
135
      band_translate = vp9_coefband_trans_4x4;
Daniel Kang's avatar
Daniel Kang committed
136
      break;
137
    }
138
    case TX_8X8: {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
139
140
      const TX_TYPE tx_type = type == PLANE_TYPE_Y_WITH_DC ?
                                  get_tx_type_8x8(xd) : DCT_DCT;
141
      scan = get_scan_8x8(tx_type);
142
143
      above_ec = (A[0] + A[1]) != 0;
      left_ec = (L[0] + L[1]) != 0;
Paul Wilkins's avatar
Paul Wilkins committed
144
      band_translate = vp9_coefband_trans_8x8plus;
Daniel Kang's avatar
Daniel Kang committed
145
      break;
146
147
    }
    case TX_16X16: {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
148
149
      const TX_TYPE tx_type = type == PLANE_TYPE_Y_WITH_DC ?
                                  get_tx_type_16x16(xd) : DCT_DCT;
150
      scan = get_scan_16x16(tx_type);
151
152
      above_ec = (A[0] + A[1] + A[2] + A[3]) != 0;
      left_ec = (L[0] + L[1] + L[2] + L[3]) != 0;
Paul Wilkins's avatar
Paul Wilkins committed
153
      band_translate = vp9_coefband_trans_8x8plus;
Daniel Kang's avatar
Daniel Kang committed
154
      break;
155
    }
156
    case TX_32X32:
Paul Wilkins's avatar
Paul Wilkins committed
157
      scan = vp9_default_scan_32x32;
158
159
      above_ec = (A[0] + A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7]) != 0;
      left_ec = (L[0] + L[1] + L[2] + L[3] + L[4] + L[5] + L[6] + L[7]) != 0;
Paul Wilkins's avatar
Paul Wilkins committed
160
      band_translate = vp9_coefband_trans_8x8plus;
161
      break;
Daniel Kang's avatar
Daniel Kang committed
162
  }
John Koleszar's avatar
John Koleszar committed
163

164
  pt = combine_entropy_contexts(above_ec, left_ec);
165
  nb = vp9_get_coef_neighbors_handle(scan);
166

John Koleszar's avatar
John Koleszar committed
167
168
169
  while (1) {
    int val;
    const uint8_t *cat6 = cat6_prob;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
170
171
    if (c >= seg_eob)
      break;
172
    if (c)
173
      pt = get_coef_context(nb, token_cache, c);
Paul Wilkins's avatar
Paul Wilkins committed
174
    band = get_coef_band(band_translate, c);
175
    prob = coef_probs[band][pt];
176
#if !CONFIG_BALANCED_COEFTREE
177
    counts->eob_branch[txfm_size][type][ref][band][pt]++;
178
179
    if (!vp9_read(r, prob[EOB_CONTEXT_NODE]))
      break;
180

Daniel Kang's avatar
Daniel Kang committed
181
SKIP_START:
182
#endif
Dmitry Kovalev's avatar
Dmitry Kovalev committed
183
184
    if (c >= seg_eob)
      break;
185
    if (c)
186
      pt = get_coef_context(nb, token_cache, c);
Paul Wilkins's avatar
Paul Wilkins committed
187
    band = get_coef_band(band_translate, c);
188
    prob = coef_probs[band][pt];
Paul Wilkins's avatar
Paul Wilkins committed
189

190
    if (!vp9_read(r, prob[ZERO_CONTEXT_NODE])) {
191
      INCREMENT_COUNT(ZERO_TOKEN);
John Koleszar's avatar
John Koleszar committed
192
      ++c;
193
194
195
196
#if CONFIG_BALANCED_COEFTREE
      skip_eob_node = 1;
      continue;
#else
John Koleszar's avatar
John Koleszar committed
197
      goto SKIP_START;
198
#endif
John Koleszar's avatar
John Koleszar committed
199
    }
200
201
202
203
204
205
206
207
208
#if CONFIG_BALANCED_COEFTREE
    if (!skip_eob_node) {
      fc->eob_branch_counts[txfm_size][type][ref][band][pt]++;
      if (!vp9_read(r, prob[EOB_CONTEXT_NODE]))
        break;
    }
    skip_eob_node = 0;
#endif

John Koleszar's avatar
John Koleszar committed
209
    // ONE_CONTEXT_NODE_0_
210
    if (!vp9_read(r, prob[ONE_CONTEXT_NODE])) {
211
      WRITE_COEF_CONTINUE(1, ONE_TOKEN);
John Koleszar's avatar
John Koleszar committed
212
    }
213
214
    // Load full probabilities if not already loaded
    if (!load_map[band][pt]) {
215
      vp9_model_to_full_probs(coef_probs[band][pt],
216
217
218
219
                              coef_probs_full[band][pt]);
      load_map[band][pt] = 1;
    }
    prob = coef_probs_full[band][pt];
John Koleszar's avatar
John Koleszar committed
220
    // LOW_VAL_CONTEXT_NODE_0_
221
222
    if (!vp9_read(r, prob[LOW_VAL_CONTEXT_NODE])) {
      if (!vp9_read(r, prob[TWO_CONTEXT_NODE])) {
223
        WRITE_COEF_CONTINUE(2, TWO_TOKEN);
John Koleszar's avatar
John Koleszar committed
224
      }
225
      if (!vp9_read(r, prob[THREE_CONTEXT_NODE])) {
226
        WRITE_COEF_CONTINUE(3, THREE_TOKEN);
John Koleszar's avatar
John Koleszar committed
227
      }
228
      WRITE_COEF_CONTINUE(4, FOUR_TOKEN);
John Koleszar's avatar
John Koleszar committed
229
230
    }
    // HIGH_LOW_CONTEXT_NODE_0_
231
232
    if (!vp9_read(r, prob[HIGH_LOW_CONTEXT_NODE])) {
      if (!vp9_read(r, prob[CAT_ONE_CONTEXT_NODE])) {
John Koleszar's avatar
John Koleszar committed
233
234
        val = CAT1_MIN_VAL;
        ADJUST_COEF(CAT1_PROB0, 0);
235
        WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY1);
John Koleszar's avatar
John Koleszar committed
236
237
238
239
      }
      val = CAT2_MIN_VAL;
      ADJUST_COEF(CAT2_PROB1, 1);
      ADJUST_COEF(CAT2_PROB0, 0);
240
      WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY2);
Daniel Kang's avatar
Daniel Kang committed
241
    }
John Koleszar's avatar
John Koleszar committed
242
    // CAT_THREEFOUR_CONTEXT_NODE_0_
243
244
    if (!vp9_read(r, prob[CAT_THREEFOUR_CONTEXT_NODE])) {
      if (!vp9_read(r, prob[CAT_THREE_CONTEXT_NODE])) {
John Koleszar's avatar
John Koleszar committed
245
246
247
248
        val = CAT3_MIN_VAL;
        ADJUST_COEF(CAT3_PROB2, 2);
        ADJUST_COEF(CAT3_PROB1, 1);
        ADJUST_COEF(CAT3_PROB0, 0);
249
        WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY3);
John Koleszar's avatar
John Koleszar committed
250
251
252
253
254
255
      }
      val = CAT4_MIN_VAL;
      ADJUST_COEF(CAT4_PROB3, 3);
      ADJUST_COEF(CAT4_PROB2, 2);
      ADJUST_COEF(CAT4_PROB1, 1);
      ADJUST_COEF(CAT4_PROB0, 0);
256
      WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY4);
John Koleszar's avatar
John Koleszar committed
257
258
    }
    // CAT_FIVE_CONTEXT_NODE_0_:
259
    if (!vp9_read(r, prob[CAT_FIVE_CONTEXT_NODE])) {
John Koleszar's avatar
John Koleszar committed
260
261
262
263
264
265
      val = CAT5_MIN_VAL;
      ADJUST_COEF(CAT5_PROB4, 4);
      ADJUST_COEF(CAT5_PROB3, 3);
      ADJUST_COEF(CAT5_PROB2, 2);
      ADJUST_COEF(CAT5_PROB1, 1);
      ADJUST_COEF(CAT5_PROB0, 0);
266
      WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY5);
John Koleszar's avatar
John Koleszar committed
267
268
269
    }
    val = 0;
    while (*cat6) {
270
      val = (val << 1) | vp9_read(r, *cat6++);
John Koleszar's avatar
John Koleszar committed
271
272
    }
    val += CAT6_MIN_VAL;
273
    WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY6);
John Koleszar's avatar
John Koleszar committed
274
  }
Jingning Han's avatar
Jingning Han committed
275

276
  if (c < seg_eob)
277
    coef_counts[type][ref][band][pt][DCT_EOB_MODEL_TOKEN]++;
278

279

John Koleszar's avatar
John Koleszar committed
280
  return c;
Daniel Kang's avatar
Daniel Kang committed
281
}
John Koleszar's avatar
John Koleszar committed
282

283
284
static int get_eob(struct segmentation *seg, int segment_id, int eob_max) {
  return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
285
286
}

John Koleszar's avatar
John Koleszar committed
287
288
struct decode_block_args {
  VP9D_COMP *pbi;
289
  vp9_reader *r;
John Koleszar's avatar
John Koleszar committed
290
291
  int *eobtotal;
};
292

John Koleszar's avatar
John Koleszar committed
293
static void decode_block(int plane, int block,
294
                         BLOCK_SIZE_TYPE bsize,
John Koleszar's avatar
John Koleszar committed
295
296
297
                         int ss_txfrm_size,
                         void *argv) {
  const struct decode_block_args* const arg = argv;
John Koleszar's avatar
John Koleszar committed
298
  const int bw = b_width_log2(bsize);
299
300

  // find the maximum eob for this transform size, adjusted by segment
301
302
303
  MACROBLOCKD *xd = &arg->pbi->mb;
  struct macroblockd_plane* pd = &xd->plane[plane];
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
John Koleszar's avatar
John Koleszar committed
304
  const TX_SIZE ss_tx_size = ss_txfrm_size / 2;
305
  const int seg_eob = get_eob(&xd->seg, segment_id, 16 << ss_txfrm_size);
306
  const int off = block >> ss_txfrm_size;
307
  const int mod = bw - ss_tx_size - pd->subsampling_x;
308
309
  const int aoff = (off & ((1 << mod) - 1)) << ss_tx_size;
  const int loff = (off >> mod) << ss_tx_size;
310
311
312

  ENTROPY_CONTEXT *A = pd->above_context + aoff;
  ENTROPY_CONTEXT *L = pd->left_context + loff;
313
  const int eob = decode_coefs(&arg->pbi->common, xd, arg->r, block,
314
315
316
                               pd->plane_type, seg_eob,
                               BLOCK_OFFSET(pd->qcoeff, block, 16),
                               ss_tx_size, pd->dequant, A, L);
317

318
319
320
  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
    set_contexts_on_border(xd, bsize, plane, ss_tx_size, eob, aoff, loff, A, L);
  } else {
321
322
    int pt;
    for (pt = 0; pt < (1 << ss_tx_size); pt++)
323
324
      A[pt] = L[pt] = eob > 0;
  }
325
326
  pd->eobs[block] = eob;
  *arg->eobtotal += eob;
327
328
}

329
int vp9_decode_tokens(VP9D_COMP *pbi, vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
John Koleszar's avatar
John Koleszar committed
330
  int eobtotal = 0;
331
332
  struct decode_block_args args = {pbi, r, &eobtotal};
  foreach_transformed_block(&pbi->mb, bsize, decode_block, &args);
John Koleszar's avatar
John Koleszar committed
333
  return eobtotal;
334
}