vp9_detokenize.c 20 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 "vp9/common/vp9_blockd.h"
13
#include "vp9/decoder/vp9_onyxd_int.h"
John Koleszar's avatar
John Koleszar committed
14 15
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
16
#include "vp9/decoder/vp9_detokenize.h"
17
#include "vp9/common/vp9_seg_common.h"
18

John Koleszar's avatar
John Koleszar committed
19 20 21 22 23 24 25 26 27 28 29 30
#define EOB_CONTEXT_NODE            0
#define ZERO_CONTEXT_NODE           1
#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
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#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

56
static const vp9_prob cat6_prob[15] = {
57 58
  254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0
};
John Koleszar's avatar
John Koleszar committed
59

60
DECLARE_ALIGNED(16, extern const uint8_t, vp9_norm[256]);
61

Dmitry Kovalev's avatar
Dmitry Kovalev committed
62
static int16_t get_signed(BOOL_DECODER *br, int16_t value_to_sign) {
63
  return decode_bool(br, 128) ? -value_to_sign : value_to_sign;
Daniel Kang's avatar
Daniel Kang committed
64
}
John Koleszar's avatar
John Koleszar committed
65

Dmitry Kovalev's avatar
Dmitry Kovalev committed
66

67 68
#define INCREMENT_COUNT(token)               \
  do {                                       \
69 70
    coef_counts[type][ref][get_coef_band(scan, txfm_size, c)] \
               [pt][token]++;     \
71
    token_cache[c] = token; \
72 73
    pt = vp9_get_coef_context(scan, nb, pad, token_cache,     \
                              c, default_eob); \
74 75
  } while (0)

76
#if CONFIG_CODE_NONZEROCOUNT
77
#define WRITE_COEF_CONTINUE(val, token)                       \
Daniel Kang's avatar
Daniel Kang committed
78
  {                                                           \
Dmitry Kovalev's avatar
Dmitry Kovalev committed
79
    qcoeff_ptr[scan[c]] = get_signed(br, val);                \
80
    INCREMENT_COUNT(token);                                   \
John Koleszar's avatar
John Koleszar committed
81
    c++;                                                      \
Dmitry Kovalev's avatar
Dmitry Kovalev committed
82
    nzc++;                                                    \
John Koleszar's avatar
John Koleszar committed
83 84
    continue;                                                 \
  }
85
#else
Dmitry Kovalev's avatar
Dmitry Kovalev committed
86 87 88 89 90 91
#define WRITE_COEF_CONTINUE(val, token)                  \
  {                                                      \
    qcoeff_ptr[scan[c]] = get_signed(br, val);           \
    INCREMENT_COUNT(token);                              \
    c++;                                                 \
    continue;                                            \
92 93
  }
#endif  // CONFIG_CODE_NONZEROCOUNT
John Koleszar's avatar
John Koleszar committed
94

Daniel Kang's avatar
Daniel Kang committed
95 96
#define ADJUST_COEF(prob, bits_count)  \
  do {                                 \
97
    if (vp9_read(br, prob))            \
Dmitry Kovalev's avatar
Dmitry Kovalev committed
98
      val += 1 << bits_count;          \
John Koleszar's avatar
John Koleszar committed
99
  } while (0);
John Koleszar's avatar
John Koleszar committed
100

101
static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
102
                        BOOL_DECODER* const br, int block_idx,
103 104
                        PLANE_TYPE type, int seg_eob, int16_t *qcoeff_ptr,
                        TX_SIZE txfm_size) {
105 106
  ENTROPY_CONTEXT* const A0 = (ENTROPY_CONTEXT *) xd->above_context;
  ENTROPY_CONTEXT* const L0 = (ENTROPY_CONTEXT *) xd->left_context;
107 108
  int aidx, lidx;
  ENTROPY_CONTEXT above_ec, left_ec;
John Koleszar's avatar
John Koleszar committed
109
  FRAME_CONTEXT *const fc = &dx->common.fc;
110
  int pt, c = 0, pad, default_eob;
111 112 113
  vp9_coeff_probs *coef_probs;
  vp9_prob *prob;
  vp9_coeff_count *coef_counts;
114
  const int ref = xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME;
115 116 117 118
#if CONFIG_CODE_NONZEROCOUNT
  uint16_t nzc = 0;
  uint16_t nzc_expected = xd->mode_info_context->mbmi.nzcs[block_idx];
#endif
119 120
  const int *scan, *nb;
  uint8_t token_cache[1024];
Daniel Kang's avatar
Daniel Kang committed
121

122 123 124 125 126 127 128 129 130 131 132
  if (xd->mode_info_context->mbmi.sb_type == BLOCK_SIZE_SB64X64) {
    aidx = vp9_block2above_sb64[txfm_size][block_idx];
    lidx = vp9_block2left_sb64[txfm_size][block_idx];
  } else if (xd->mode_info_context->mbmi.sb_type == BLOCK_SIZE_SB32X32) {
    aidx = vp9_block2above_sb[txfm_size][block_idx];
    lidx = vp9_block2left_sb[txfm_size][block_idx];
  } else {
    aidx = vp9_block2above[txfm_size][block_idx];
    lidx = vp9_block2left[txfm_size][block_idx];
  }

133
  switch (txfm_size) {
Daniel Kang's avatar
Daniel Kang committed
134
    default:
135
    case TX_4X4: {
136 137
      const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
                              get_tx_type_4x4(xd, block_idx) : DCT_DCT;
138 139 140 141 142 143 144 145 146 147 148
      switch (tx_type) {
        default:
          scan = vp9_default_zig_zag1d_4x4;
          break;
        case ADST_DCT:
          scan = vp9_row_scan_4x4;
          break;
        case DCT_ADST:
          scan = vp9_col_scan_4x4;
          break;
      }
149 150
      above_ec = A0[aidx] != 0;
      left_ec = L0[lidx] != 0;
151 152
      coef_probs  = fc->coef_probs_4x4;
      coef_counts = fc->coef_counts_4x4;
153
      default_eob = 16;
Daniel Kang's avatar
Daniel Kang committed
154
      break;
155
    }
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
    case TX_8X8: {
      const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type;
      const int sz = 3 + sb_type, x = block_idx & ((1 << sz) - 1);
      const int y = block_idx - x;
      const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
                              get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
      switch (tx_type) {
        default:
          scan = vp9_default_zig_zag1d_8x8;
          break;
        case ADST_DCT:
          scan = vp9_row_scan_8x8;
          break;
        case DCT_ADST:
          scan = vp9_col_scan_8x8;
          break;
      }
173 174
      coef_probs  = fc->coef_probs_8x8;
      coef_counts = fc->coef_counts_8x8;
175 176
      above_ec = (A0[aidx] + A0[aidx + 1]) != 0;
      left_ec  = (L0[lidx] + L0[lidx + 1]) != 0;
177
      default_eob = 64;
Daniel Kang's avatar
Daniel Kang committed
178
      break;
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    }
    case TX_16X16: {
      const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type;
      const int sz = 4 + sb_type, x = block_idx & ((1 << sz) - 1);
      const int y = block_idx - x;
      const TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
                              get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
      switch (tx_type) {
        default:
          scan = vp9_default_zig_zag1d_16x16;
          break;
        case ADST_DCT:
          scan = vp9_row_scan_16x16;
          break;
        case DCT_ADST:
          scan = vp9_col_scan_16x16;
          break;
      }
197 198
      coef_probs  = fc->coef_probs_16x16;
      coef_counts = fc->coef_counts_16x16;
199 200 201 202 203
      if (type == PLANE_TYPE_UV) {
        ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
        ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
        above_ec = (A0[aidx] + A0[aidx + 1] + A1[aidx] + A1[aidx + 1]) != 0;
        left_ec  = (L0[lidx] + L0[lidx + 1] + L1[lidx] + L1[lidx + 1]) != 0;
204
      } else {
205 206 207
        above_ec = (A0[aidx] + A0[aidx + 1] + A0[aidx + 2] + A0[aidx + 3]) != 0;
        left_ec  = (L0[lidx] + L0[lidx + 1] + L0[lidx + 2] + L0[lidx + 3]) != 0;
      }
208
      default_eob = 256;
Daniel Kang's avatar
Daniel Kang committed
209
      break;
210
    }
211
    case TX_32X32:
212
      scan = vp9_default_zig_zag1d_32x32;
213 214
      coef_probs = fc->coef_probs_32x32;
      coef_counts = fc->coef_counts_32x32;
215 216 217 218 219 220 221 222 223 224 225
      if (type == PLANE_TYPE_UV) {
        ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
        ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
        ENTROPY_CONTEXT *A2 = (ENTROPY_CONTEXT *) (xd->above_context + 2);
        ENTROPY_CONTEXT *L2 = (ENTROPY_CONTEXT *) (xd->left_context + 2);
        ENTROPY_CONTEXT *A3 = (ENTROPY_CONTEXT *) (xd->above_context + 3);
        ENTROPY_CONTEXT *L3 = (ENTROPY_CONTEXT *) (xd->left_context + 3);
        above_ec = (A0[aidx] + A0[aidx + 1] + A1[aidx] + A1[aidx + 1] +
                    A2[aidx] + A2[aidx + 1] + A3[aidx] + A3[aidx + 1]) != 0;
        left_ec  = (L0[lidx] + L0[lidx + 1] + L1[lidx] + L1[lidx + 1] +
                    L2[lidx] + L2[lidx + 1] + L3[lidx] + L3[lidx + 1]) != 0;
226
      } else {
227 228 229 230 231 232 233
        ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
        ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
        above_ec = (A0[aidx] + A0[aidx + 1] + A0[aidx + 2] + A0[aidx + 3] +
                    A1[aidx] + A1[aidx + 1] + A1[aidx + 2] + A1[aidx + 3]) != 0;
        left_ec  = (L0[lidx] + L0[lidx + 1] + L0[lidx + 2] + L0[lidx + 3] +
                    L1[lidx] + L1[lidx + 1] + L1[lidx + 2] + L1[lidx + 3]) != 0;
      }
234
      default_eob = 1024;
235
      break;
Daniel Kang's avatar
Daniel Kang committed
236
  }
John Koleszar's avatar
John Koleszar committed
237

238
  VP9_COMBINEENTROPYCONTEXTS(pt, above_ec, left_ec);
239 240
  nb = vp9_get_coef_neighbors_handle(scan, &pad);

John Koleszar's avatar
John Koleszar committed
241 242 243
  while (1) {
    int val;
    const uint8_t *cat6 = cat6_prob;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
244 245 246

    if (c >= seg_eob)
      break;
247 248 249 250
#if CONFIG_CODE_NONZEROCOUNT
    if (nzc == nzc_expected)
      break;
#endif
251
    prob = coef_probs[type][ref][get_coef_band(scan, txfm_size, c)][pt];
252
#if CONFIG_CODE_NONZEROCOUNT == 0
253
    fc->eob_branch_counts[txfm_size][type][ref]
254
                         [get_coef_band(scan, txfm_size, c)][pt]++;
255
    if (!vp9_read(br, prob[EOB_CONTEXT_NODE]))
John Koleszar's avatar
John Koleszar committed
256
      break;
257
#endif
Daniel Kang's avatar
Daniel Kang committed
258
SKIP_START:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
259 260
    if (c >= seg_eob)
      break;
261 262 263 264 265 266
#if CONFIG_CODE_NONZEROCOUNT
    if (nzc == nzc_expected)
      break;
    // decode zero node only if there are zeros left
    if (seg_eob - nzc_expected - c + nzc > 0)
#endif
267
    if (!vp9_read(br, prob[ZERO_CONTEXT_NODE])) {
268
      INCREMENT_COUNT(ZERO_TOKEN);
John Koleszar's avatar
John Koleszar committed
269
      ++c;
270
      prob = coef_probs[type][ref][get_coef_band(scan, txfm_size, c)][pt];
John Koleszar's avatar
John Koleszar committed
271 272 273
      goto SKIP_START;
    }
    // ONE_CONTEXT_NODE_0_
274
    if (!vp9_read(br, prob[ONE_CONTEXT_NODE])) {
275
      WRITE_COEF_CONTINUE(1, ONE_TOKEN);
John Koleszar's avatar
John Koleszar committed
276 277
    }
    // LOW_VAL_CONTEXT_NODE_0_
278 279
    if (!vp9_read(br, prob[LOW_VAL_CONTEXT_NODE])) {
      if (!vp9_read(br, prob[TWO_CONTEXT_NODE])) {
280
        WRITE_COEF_CONTINUE(2, TWO_TOKEN);
John Koleszar's avatar
John Koleszar committed
281
      }
282
      if (!vp9_read(br, prob[THREE_CONTEXT_NODE])) {
283
        WRITE_COEF_CONTINUE(3, THREE_TOKEN);
John Koleszar's avatar
John Koleszar committed
284
      }
285
      WRITE_COEF_CONTINUE(4, FOUR_TOKEN);
John Koleszar's avatar
John Koleszar committed
286 287
    }
    // HIGH_LOW_CONTEXT_NODE_0_
288 289
    if (!vp9_read(br, prob[HIGH_LOW_CONTEXT_NODE])) {
      if (!vp9_read(br, prob[CAT_ONE_CONTEXT_NODE])) {
John Koleszar's avatar
John Koleszar committed
290 291
        val = CAT1_MIN_VAL;
        ADJUST_COEF(CAT1_PROB0, 0);
292
        WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY1);
John Koleszar's avatar
John Koleszar committed
293 294 295 296
      }
      val = CAT2_MIN_VAL;
      ADJUST_COEF(CAT2_PROB1, 1);
      ADJUST_COEF(CAT2_PROB0, 0);
297
      WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY2);
Daniel Kang's avatar
Daniel Kang committed
298
    }
John Koleszar's avatar
John Koleszar committed
299
    // CAT_THREEFOUR_CONTEXT_NODE_0_
300 301
    if (!vp9_read(br, prob[CAT_THREEFOUR_CONTEXT_NODE])) {
      if (!vp9_read(br, prob[CAT_THREE_CONTEXT_NODE])) {
John Koleszar's avatar
John Koleszar committed
302 303 304 305
        val = CAT3_MIN_VAL;
        ADJUST_COEF(CAT3_PROB2, 2);
        ADJUST_COEF(CAT3_PROB1, 1);
        ADJUST_COEF(CAT3_PROB0, 0);
306
        WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY3);
John Koleszar's avatar
John Koleszar committed
307 308 309 310 311 312
      }
      val = CAT4_MIN_VAL;
      ADJUST_COEF(CAT4_PROB3, 3);
      ADJUST_COEF(CAT4_PROB2, 2);
      ADJUST_COEF(CAT4_PROB1, 1);
      ADJUST_COEF(CAT4_PROB0, 0);
313
      WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY4);
John Koleszar's avatar
John Koleszar committed
314 315
    }
    // CAT_FIVE_CONTEXT_NODE_0_:
316
    if (!vp9_read(br, prob[CAT_FIVE_CONTEXT_NODE])) {
John Koleszar's avatar
John Koleszar committed
317 318 319 320 321 322
      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);
323
      WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY5);
John Koleszar's avatar
John Koleszar committed
324 325 326
    }
    val = 0;
    while (*cat6) {
327
      val = (val << 1) | vp9_read(br, *cat6++);
John Koleszar's avatar
John Koleszar committed
328 329
    }
    val += CAT6_MIN_VAL;
330
    WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY6);
John Koleszar's avatar
John Koleszar committed
331
  }
Jingning Han's avatar
Jingning Han committed
332

333
#if CONFIG_CODE_NONZEROCOUNT == 0
334
  if (c < seg_eob)
335 336
    coef_counts[type][ref][get_coef_band(scan, txfm_size, c)]
               [pt][DCT_EOB_TOKEN]++;
337
#endif
338

Dmitry Kovalev's avatar
Dmitry Kovalev committed
339
  A0[aidx] = L0[lidx] = c > 0;
340
  if (txfm_size >= TX_8X8) {
341 342 343 344 345
    A0[aidx + 1] = L0[lidx + 1] = A0[aidx];
    if (txfm_size >= TX_16X16) {
      if (type == PLANE_TYPE_UV) {
        ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
        ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
346
        A1[aidx] = A1[aidx + 1] = L1[lidx] = L1[lidx + 1] = A0[aidx];
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
        if (txfm_size >= TX_32X32) {
          ENTROPY_CONTEXT *A2 = (ENTROPY_CONTEXT *) (xd->above_context + 2);
          ENTROPY_CONTEXT *L2 = (ENTROPY_CONTEXT *) (xd->left_context + 2);
          ENTROPY_CONTEXT *A3 = (ENTROPY_CONTEXT *) (xd->above_context + 3);
          ENTROPY_CONTEXT *L3 = (ENTROPY_CONTEXT *) (xd->left_context + 3);
          A2[aidx] = A2[aidx + 1] = A3[aidx] = A3[aidx + 1] = A0[aidx];
          L2[lidx] = L2[lidx + 1] = L3[lidx] = L3[lidx + 1] = A0[aidx];
        }
      } else {
        A0[aidx + 2] = A0[aidx + 3] = L0[lidx + 2] = L0[lidx + 3] = A0[aidx];
        if (txfm_size >= TX_32X32) {
          ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
          ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
          A1[aidx] = A1[aidx + 1] = A1[aidx + 2] = A1[aidx + 3] = A0[aidx];
          L1[lidx] = L1[lidx + 1] = L1[lidx + 2] = L1[lidx + 3] = A0[aidx];
        }
      }
    }
  }
John Koleszar's avatar
John Koleszar committed
366
  return c;
Daniel Kang's avatar
Daniel Kang committed
367
}
John Koleszar's avatar
John Koleszar committed
368

369
static int get_eob(MACROBLOCKD* const xd, int segment_id, int eob_max) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
370
  return vp9_get_segdata(xd, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
371 372
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
static INLINE int decode_sb(VP9D_COMP* const pbi,
                            MACROBLOCKD* const xd,
                            BOOL_DECODER* const bc,
                            int offset, int count, int inc,
                            int eob_max, TX_SIZE tx_size) {
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
  const int seg_eob = get_eob(xd, segment_id, eob_max);
  int i, eobtotal = 0;

  // luma blocks
  for (i = 0; i < offset; i += inc) {
    const int c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC, seg_eob,
                               xd->qcoeff + i * 16, tx_size);
    xd->eobs[i] = c;
    eobtotal += c;
  }

  // chroma blocks
  for (i = offset; i < count; i += inc) {
    const int c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
                               xd->qcoeff + i * 16, tx_size);
    xd->eobs[i] = c;
    eobtotal += c;
  }

  return eobtotal;
}

401 402 403
int vp9_decode_sb_tokens(VP9D_COMP* const pbi,
                         MACROBLOCKD* const xd,
                         BOOL_DECODER* const bc) {
404
  switch (xd->mode_info_context->mbmi.txfm_size) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
405 406 407 408 409
    case TX_32X32: {
      // 32x32 luma block
      const int segment_id = xd->mode_info_context->mbmi.segment_id;
      int i, eobtotal = 0, seg_eob;
      int c = decode_coefs(pbi, xd, bc, 0, PLANE_TYPE_Y_WITH_DC,
410
                       get_eob(xd, segment_id, 1024), xd->qcoeff, TX_32X32);
411 412 413 414 415 416
      xd->eobs[0] = c;
      eobtotal += c;

      // 16x16 chroma blocks
      seg_eob = get_eob(xd, segment_id, 256);
      for (i = 64; i < 96; i += 16) {
417 418
        c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
                         xd->qcoeff + i * 16, TX_16X16);
419 420 421
        xd->eobs[i] = c;
        eobtotal += c;
      }
Dmitry Kovalev's avatar
Dmitry Kovalev committed
422 423
      return eobtotal;
    }
424
    case TX_16X16:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
425
      return decode_sb(pbi, xd, bc, 64, 96, 16, 16 * 16, TX_16X16);
426
    case TX_8X8:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
427
      return decode_sb(pbi, xd, bc, 64, 96, 4, 8 * 8, TX_8X8);
428
    case TX_4X4:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
429 430 431 432
      return decode_sb(pbi, xd, bc, 64, 96, 1, 4 * 4, TX_4X4);
    default:
      assert(0);
      return 0;
433 434 435 436 437 438 439 440
  }
}

int vp9_decode_sb64_tokens(VP9D_COMP* const pbi,
                           MACROBLOCKD* const xd,
                           BOOL_DECODER* const bc) {
  switch (xd->mode_info_context->mbmi.txfm_size) {
    case TX_32X32:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
441
      return decode_sb(pbi, xd, bc, 256, 384, 64, 32 * 32, TX_32X32);
442
    case TX_16X16:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
443
      return decode_sb(pbi, xd, bc, 256, 384, 16, 16 * 16, TX_16X16);
444
    case TX_8X8:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
445
      return decode_sb(pbi, xd, bc, 256, 384, 4, 8 * 8, TX_8X8);
446
    case TX_4X4:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
447 448 449 450
      return decode_sb(pbi, xd, bc, 256, 384, 1, 4 * 4, TX_4X4);
    default:
      assert(0);
      return 0;
451 452
  }
}
453

454 455 456
static int vp9_decode_mb_tokens_16x16(VP9D_COMP* const pbi,
                                      MACROBLOCKD* const xd,
                                      BOOL_DECODER* const bc) {
Daniel Kang's avatar
Daniel Kang committed
457
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
458
  int i, eobtotal = 0, seg_eob;
Yaowu Xu's avatar
Yaowu Xu committed
459

460
  // Luma block
Dmitry Kovalev's avatar
Dmitry Kovalev committed
461
  int c = decode_coefs(pbi, xd, bc, 0, PLANE_TYPE_Y_WITH_DC,
462
                       get_eob(xd, segment_id, 256), xd->qcoeff, TX_16X16);
463
  xd->eobs[0] = c;
464
  eobtotal += c;
Daniel Kang's avatar
Daniel Kang committed
465 466

  // 8x8 chroma blocks
467
  seg_eob = get_eob(xd, segment_id, 64);
Daniel Kang's avatar
Daniel Kang committed
468
  for (i = 16; i < 24; i += 4) {
469
    c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV,
470
                     seg_eob, xd->block[i].qcoeff, TX_8X8);
471
    xd->eobs[i] = c;
Daniel Kang's avatar
Daniel Kang committed
472 473 474 475 476
    eobtotal += c;
  }
  return eobtotal;
}

477 478 479
static int vp9_decode_mb_tokens_8x8(VP9D_COMP* const pbi,
                                    MACROBLOCKD* const xd,
                                    BOOL_DECODER* const bc) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
480
  int i, eobtotal = 0;
John Koleszar's avatar
John Koleszar committed
481
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
482

483
  // luma blocks
Dmitry Kovalev's avatar
Dmitry Kovalev committed
484
  int seg_eob = get_eob(xd, segment_id, 64);
485
  for (i = 0; i < 16; i += 4) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
486 487
    const int c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
                               seg_eob, xd->block[i].qcoeff, TX_8X8);
488
    xd->eobs[i] = c;
John Koleszar's avatar
John Koleszar committed
489 490 491
    eobtotal += c;
  }

492 493 494 495
  // chroma blocks
  if (xd->mode_info_context->mbmi.mode == I8X8_PRED ||
      xd->mode_info_context->mbmi.mode == SPLITMV) {
    // use 4x4 transform for U, V components in I8X8/splitmv prediction mode
496
    seg_eob = get_eob(xd, segment_id, 16);
497
    for (i = 16; i < 24; i++) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
498 499
      const int c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV,
                                 seg_eob, xd->block[i].qcoeff, TX_4X4);
500
      xd->eobs[i] = c;
501 502 503 504
      eobtotal += c;
    }
  } else {
    for (i = 16; i < 24; i += 4) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
505 506
      const int c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV,
                                 seg_eob, xd->block[i].qcoeff, TX_8X8);
507
      xd->eobs[i] = c;
508 509 510 511
      eobtotal += c;
    }
  }

John Koleszar's avatar
John Koleszar committed
512
  return eobtotal;
513 514
}

515 516
static int decode_coefs_4x4(VP9D_COMP *dx, MACROBLOCKD *xd,
                            BOOL_DECODER* const bc,
517
                            PLANE_TYPE type, int i, int seg_eob) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
518 519
  const int c = decode_coefs(dx, xd, bc, i, type, seg_eob,
                             xd->block[i].qcoeff, TX_4X4);
520
  xd->eobs[i] = c;
521 522 523 524 525 526 527 528 529
  return c;
}

int vp9_decode_coefs_4x4(VP9D_COMP *dx, MACROBLOCKD *xd,
                         BOOL_DECODER* const bc,
                         PLANE_TYPE type, int i) {
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
  const int seg_eob = get_eob(xd, segment_id, 16);

530
  return decode_coefs_4x4(dx, xd, bc, type, i, seg_eob);
531 532 533 534 535 536
}

static int decode_mb_tokens_4x4_uv(VP9D_COMP* const dx,
                                   MACROBLOCKD* const xd,
                                   BOOL_DECODER* const bc,
                                   int seg_eob) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
537
  int i, eobtotal = 0;
538

539
  // chroma blocks
Dmitry Kovalev's avatar
Dmitry Kovalev committed
540
  for (i = 16; i < 24; i++)
541
    eobtotal += decode_coefs_4x4(dx, xd, bc, PLANE_TYPE_UV, i, seg_eob);
542 543 544 545

  return eobtotal;
}

546 547 548 549 550 551 552 553 554
int vp9_decode_mb_tokens_4x4_uv(VP9D_COMP* const dx,
                                MACROBLOCKD* const xd,
                                BOOL_DECODER* const bc) {
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
  const int seg_eob = get_eob(xd, segment_id, 16);

  return decode_mb_tokens_4x4_uv(dx, xd, bc, seg_eob);
}

555 556 557
static int vp9_decode_mb_tokens_4x4(VP9D_COMP* const dx,
                                    MACROBLOCKD* const xd,
                                    BOOL_DECODER* const bc) {
558
  int i, eobtotal = 0;
559 560
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
  const int seg_eob = get_eob(xd, segment_id, 16);
John Koleszar's avatar
John Koleszar committed
561

562
  // luma blocks
Dmitry Kovalev's avatar
Dmitry Kovalev committed
563
  for (i = 0; i < 16; ++i)
564
    eobtotal += decode_coefs_4x4(dx, xd, bc, PLANE_TYPE_Y_WITH_DC, i, seg_eob);
565

566 567 568 569
  // chroma blocks
  eobtotal += decode_mb_tokens_4x4_uv(dx, xd, bc, seg_eob);

  return eobtotal;
John Koleszar's avatar
John Koleszar committed
570
}
571 572 573 574 575

int vp9_decode_mb_tokens(VP9D_COMP* const dx,
                         MACROBLOCKD* const xd,
                         BOOL_DECODER* const bc) {
  const TX_SIZE tx_size = xd->mode_info_context->mbmi.txfm_size;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
576 577 578 579 580 581 582 583
  switch (tx_size) {
    case TX_16X16:
      return vp9_decode_mb_tokens_16x16(dx, xd, bc);
    case TX_8X8:
      return vp9_decode_mb_tokens_8x8(dx, xd, bc);
    default:
      assert(tx_size == TX_4X4);
      return vp9_decode_mb_tokens_4x4(dx, xd, bc);
584 585
  }
}