vp9_tokenize.c 20.8 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 13 14 15
 */


#include <math.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
16 17
#include "vp9/encoder/vp9_onyx_int.h"
#include "vp9/encoder/vp9_tokenize.h"
John Koleszar's avatar
John Koleszar committed
18 19
#include "vpx_mem/vpx_mem.h"

20 21 22
#include "vp9/common/vp9_pred_common.h"
#include "vp9/common/vp9_seg_common.h"
#include "vp9/common/vp9_entropy.h"
23

John Koleszar's avatar
John Koleszar committed
24
/* Global event counters used for accumulating statistics across several
25
   compressions, then generating vp9_context.c = initial stats. */
John Koleszar's avatar
John Koleszar committed
26 27

#ifdef ENTROPY_STATS
28 29 30
vp9_coeff_accum context_counters_4x4[BLOCK_TYPES];
vp9_coeff_accum context_counters_8x8[BLOCK_TYPES];
vp9_coeff_accum context_counters_16x16[BLOCK_TYPES];
31
vp9_coeff_accum context_counters_32x32[BLOCK_TYPES];
32

33 34 35
extern vp9_coeff_stats tree_update_hist_4x4[BLOCK_TYPES];
extern vp9_coeff_stats tree_update_hist_8x8[BLOCK_TYPES];
extern vp9_coeff_stats tree_update_hist_16x16[BLOCK_TYPES];
36
extern vp9_coeff_stats tree_update_hist_32x32[BLOCK_TYPES];
37 38
#endif  /* ENTROPY_STATS */

John Koleszar's avatar
John Koleszar committed
39
static TOKENVALUE dct_value_tokens[DCT_MAX_VALUE * 2];
40
const TOKENVALUE *vp9_dct_value_tokens_ptr;
John Koleszar's avatar
John Koleszar committed
41
static int dct_value_cost[DCT_MAX_VALUE * 2];
42
const int *vp9_dct_value_cost_ptr;
43

John Koleszar's avatar
John Koleszar committed
44
static void fill_value_tokens() {
John Koleszar's avatar
John Koleszar committed
45

John Koleszar's avatar
John Koleszar committed
46
  TOKENVALUE *const t = dct_value_tokens + DCT_MAX_VALUE;
47
  vp9_extra_bit *const e = vp9_extra_bits;
John Koleszar's avatar
John Koleszar committed
48

John Koleszar's avatar
John Koleszar committed
49 50
  int i = -DCT_MAX_VALUE;
  int sign = 1;
John Koleszar's avatar
John Koleszar committed
51

John Koleszar's avatar
John Koleszar committed
52 53 54
  do {
    if (!i)
      sign = 0;
John Koleszar's avatar
John Koleszar committed
55

John Koleszar's avatar
John Koleszar committed
56 57 58
    {
      const int a = sign ? -i : i;
      int eb = sign;
John Koleszar's avatar
John Koleszar committed
59

John Koleszar's avatar
John Koleszar committed
60 61
      if (a > 4) {
        int j = 4;
John Koleszar's avatar
John Koleszar committed
62

John Koleszar's avatar
John Koleszar committed
63
        while (++j < 11  &&  e[j].base_val <= a) {}
John Koleszar's avatar
John Koleszar committed
64

65
        t[i].token = --j;
John Koleszar's avatar
John Koleszar committed
66 67
        eb |= (a - e[j].base_val) << 1;
      } else
68
        t[i].token = a;
John Koleszar's avatar
John Koleszar committed
69

70
      t[i].extra = eb;
John Koleszar's avatar
John Koleszar committed
71
    }
John Koleszar's avatar
John Koleszar committed
72

John Koleszar's avatar
John Koleszar committed
73 74 75
    // initialize the cost for extra bits for all possible coefficient value.
    {
      int cost = 0;
76
      vp9_extra_bit *p = vp9_extra_bits + t[i].token;
John Koleszar's avatar
John Koleszar committed
77

John Koleszar's avatar
John Koleszar committed
78
      if (p->base_val) {
79
        const int extra = t[i].extra;
80
        const int length = p->len;
John Koleszar's avatar
John Koleszar committed
81

82 83
        if (length)
          cost += treed_cost(p->tree, p->prob, extra >> 1, length);
John Koleszar's avatar
John Koleszar committed
84

85
        cost += vp9_cost_bit(vp9_prob_half, extra & 1); /* sign */
John Koleszar's avatar
John Koleszar committed
86 87
        dct_value_cost[i + DCT_MAX_VALUE] = cost;
      }
John Koleszar's avatar
John Koleszar committed
88 89 90

    }

John Koleszar's avatar
John Koleszar committed
91 92
  } while (++i < DCT_MAX_VALUE);

93 94
  vp9_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE;
  vp9_dct_value_cost_ptr   = dct_value_cost + DCT_MAX_VALUE;
John Koleszar's avatar
John Koleszar committed
95
}
96

97 98
extern const int *vp9_get_coef_neighbors_handle(const int *scan, int *pad);

99
static void tokenize_b(VP9_COMP *cpi,
100
                       MACROBLOCKD *xd,
Yaowu Xu's avatar
Yaowu Xu committed
101
                       const int ib,
102 103 104
                       TOKENEXTRA **tp,
                       PLANE_TYPE type,
                       TX_SIZE tx_size,
John Koleszar's avatar
John Koleszar committed
105
                       int y_blocks,
106
                       int dry_run) {
107
  MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
Daniel Kang's avatar
Daniel Kang committed
108
  int pt; /* near block/prev token context index */
109
  int c = 0, rc = 0;
Daniel Kang's avatar
Daniel Kang committed
110
  TOKENEXTRA *t = *tp;        /* store tokens starting here */
John Koleszar's avatar
John Koleszar committed
111
  const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, ib);
112 113 114 115 116 117 118 119
  const BLOCK_SIZE_TYPE sb_type = mbmi->sb_type;
  const int bwl = b_width_log2(sb_type);
  const int off = pb_idx.block >> (2 * tx_size);
  const int mod = bwl - tx_size - xd->plane[pb_idx.plane].subsampling_x;
  const int aoff = (off & ((1 << mod) - 1)) << tx_size;
  const int loff = (off >> mod) << tx_size;
  ENTROPY_CONTEXT *A = xd->plane[pb_idx.plane].above_context + aoff;
  ENTROPY_CONTEXT *L = xd->plane[pb_idx.plane].left_context + loff;
John Koleszar's avatar
John Koleszar committed
120
  const int eob = xd->plane[pb_idx.plane].eobs[pb_idx.block];
121 122
  const int16_t *qcoeff_ptr = BLOCK_OFFSET(xd->plane[pb_idx.plane].qcoeff,
                                           pb_idx.block, 16);
123
  int seg_eob, default_eob, pad;
124
  const int segment_id = mbmi->segment_id;
125
  const int *scan, *nb;
126
  vp9_coeff_count *counts;
127
  vp9_coeff_probs *coef_probs;
128
  const int ref = mbmi->ref_frame != INTRA_FRAME;
129
  ENTROPY_CONTEXT above_ec, left_ec;
130
  uint8_t token_cache[1024];
131 132 133 134 135 136 137 138 139 140 141 142 143 144
  TX_TYPE tx_type = DCT_DCT;
#if CONFIG_CODE_ZEROGROUP
  int last_nz_pos[3] = {-1, -1, -1};  // Encoder only
  int is_eoo_list[3] = {0, 0, 0};
  int is_last_zero[3] = {0, 0, 0};
  int is_eoo_negative[3] = {0, 0, 0};
  int o;
  vp9_zpc_probs *zpc_probs;
  vp9_zpc_count *zpc_count;
  uint8_t token_cache_full[1024];
#endif
#if CONFIG_CODE_ZEROGROUP
  vpx_memset(token_cache, UNKNOWN_TOKEN, sizeof(token_cache));
#endif
145

John Koleszar's avatar
John Koleszar committed
146
  assert((!type && !pb_idx.plane) || (type && pb_idx.plane));
147

148 149
  switch (tx_size) {
    default:
150
    case TX_4X4: {
151 152
      tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
          get_tx_type_4x4(xd, ib) : DCT_DCT;
153 154
      above_ec = A[0] != 0;
      left_ec = L[0] != 0;
155
      seg_eob = 16;
156
      scan = get_scan_4x4(tx_type);
157
      counts = cpi->coef_counts_4x4;
158 159 160 161 162
      coef_probs = cpi->common.fc.coef_probs_4x4;
#if CONFIG_CODE_ZEROGROUP
      zpc_count = &cpi->common.fc.zpc_counts_4x4;
      zpc_probs = &cpi->common.fc.zpc_probs_4x4;
#endif
163
      break;
164
    }
165
    case TX_8X8: {
166
      const int sz = 1 + b_width_log2(sb_type);
167
      const int x = ib & ((1 << sz) - 1), y = ib - x;
168 169
      tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
          get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
170 171
      above_ec = (A[0] + A[1]) != 0;
      left_ec = (L[0] + L[1]) != 0;
172
      seg_eob = 64;
173
      scan = get_scan_8x8(tx_type);
174
      counts = cpi->coef_counts_8x8;
175 176 177 178 179
      coef_probs = cpi->common.fc.coef_probs_8x8;
#if CONFIG_CODE_ZEROGROUP
      zpc_count = &cpi->common.fc.zpc_counts_8x8;
      zpc_probs = &cpi->common.fc.zpc_probs_8x8;
#endif
180
      break;
181 182
    }
    case TX_16X16: {
183
      const int sz = 2 + b_width_log2(sb_type);
184
      const int x = ib & ((1 << sz) - 1), y = ib - x;
185 186
      tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
          get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
187 188
      above_ec = (A[0] + A[1] + A[2] + A[3]) != 0;
      left_ec = (L[0] + L[1] + L[2] + L[3]) != 0;
189
      seg_eob = 256;
190
      scan = get_scan_16x16(tx_type);
191
      counts = cpi->coef_counts_16x16;
192 193 194 195 196
      coef_probs = cpi->common.fc.coef_probs_16x16;
#if CONFIG_CODE_ZEROGROUP
      zpc_count = &cpi->common.fc.zpc_counts_16x16;
      zpc_probs = &cpi->common.fc.zpc_probs_16x16;
#endif
197
      break;
198
    }
199
    case TX_32X32:
200 201
      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;
202 203 204
      seg_eob = 1024;
      scan = vp9_default_zig_zag1d_32x32;
      counts = cpi->coef_counts_32x32;
205 206 207 208 209
      coef_probs = cpi->common.fc.coef_probs_32x32;
#if CONFIG_CODE_ZEROGROUP
      zpc_count = &cpi->common.fc.zpc_counts_32x32;
      zpc_probs = &cpi->common.fc.zpc_probs_32x32;
#endif
210
      break;
John Koleszar's avatar
John Koleszar committed
211 212
  }

213
  pt = combine_entropy_contexts(above_ec, left_ec);
214 215
  nb = vp9_get_coef_neighbors_handle(scan, &pad);
  default_eob = seg_eob;
Yaowu Xu's avatar
Yaowu Xu committed
216

Paul Wilkins's avatar
Paul Wilkins committed
217 218
  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))
    seg_eob = 0;
John Koleszar's avatar
John Koleszar committed
219

220 221 222 223 224 225 226 227 228 229 230 231
#if CONFIG_CODE_ZEROGROUP
  vpx_memset(token_cache_full, ZERO_TOKEN, sizeof(token_cache_full));
  for (c = 0; c < eob; ++c) {
    rc = scan[c];
    token_cache_full[rc] = vp9_dct_value_tokens_ptr[qcoeff_ptr[rc]].token;
    o = vp9_get_orientation(rc, tx_size);
    if (qcoeff_ptr[rc] != 0) {
      last_nz_pos[o] = c;
    }
  }
#endif
  c = 0;
232
  do {
233
    const int band = get_coef_band(scan, tx_size, c);
234
    int token;
235
    int v = 0;
236 237 238
    rc = scan[c];
    if (c)
      pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob);
239
    if (c < eob) {
240
      v = qcoeff_ptr[rc];
241 242
      assert(-DCT_MAX_VALUE <= v  &&  v < DCT_MAX_VALUE);

243 244
      t->extra = vp9_dct_value_tokens_ptr[v].extra;
      token    = vp9_dct_value_tokens_ptr[v].token;
245
    } else {
246
      token = DCT_EOB_TOKEN;
247
    }
John Koleszar's avatar
John Koleszar committed
248

249
    t->token = token;
250 251
    t->context_tree = coef_probs[type][ref][band][pt];
      t->skip_eob_node = (c > 0) && (token_cache[scan[c - 1]] == 0);
252
    assert(vp9_coef_encodings[t->token].len - t->skip_eob_node > 0);
253 254 255 256 257 258 259 260 261 262 263 264 265 266
#if CONFIG_CODE_ZEROGROUP
    o = vp9_get_orientation(rc, tx_size);
    t->skip_coef_val = (token_cache[rc] == ZERO_TOKEN || is_eoo_list[o]);
    if (t->skip_coef_val) {
      assert(v == 0);
    }
    // No need to transmit any token
    if (t->skip_eob_node && t->skip_coef_val) {
      assert(token == ZERO_TOKEN);
      is_last_zero[o] = 1;
      token_cache[scan[c]] = ZERO_TOKEN;
      continue;
    }
#endif
267
    if (!dry_run) {
268
      ++counts[type][ref][band][pt][token];
269 270
      if (!t->skip_eob_node)
        ++cpi->common.fc.eob_branch_counts[tx_size][type][ref][band][pt];
271
    }
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
    token_cache[scan[c]] = token;
#if CONFIG_CODE_ZEROGROUP
    if (token == ZERO_TOKEN && !t->skip_coef_val) {
      int eoo = 0, use_eoo;
#if USE_ZPC_EOORIENT == 1
      use_eoo = vp9_use_eoo(c, seg_eob, scan, tx_size,
                            is_last_zero, is_eoo_list);
#else
      use_eoo = 0;
#endif
      if (use_eoo) {
        eoo = vp9_is_eoo(c, eob, scan, tx_size, qcoeff_ptr, last_nz_pos);
        if (eoo && is_eoo_negative[o]) eoo = 0;
        if (eoo) {
          int c_;
          int savings = 0;
          int zsaved = 0;
          savings =
              vp9_cost_bit((*zpc_probs)[ref]
                           [coef_to_zpc_band(band)]
                           [coef_to_zpc_ptok(pt)][0], 1) -
              vp9_cost_bit((*zpc_probs)[ref]
                           [coef_to_zpc_band(band)]
                           [coef_to_zpc_ptok(pt)][0], 0);
          for (c_ = c + 1; c_ < eob; ++c_) {
            if (o == vp9_get_orientation(scan[c_], tx_size)) {
              int pt_ = vp9_get_coef_context(scan, nb, pad, token_cache_full,
                                             c_, default_eob);
              int band_ = get_coef_band(scan, tx_size, c_);
              assert(token_cache_full[scan[c_]] == ZERO_TOKEN);
              if (!c_ || token_cache_full[scan[c_ - 1]])
                savings +=
                    vp9_cost_bit(coef_probs[type][ref][band_][pt_][0], 1);
              savings += vp9_cost_bit(coef_probs[type][ref][band_][pt_][1], 0);
              zsaved++;
            }
          }
          /*
          if (!dry_run)
            if (savings > 0)
              printf("savings %d zsaved %d (%d, %d)\n",
                     savings, zsaved, tx_size, band);
                     */
          if (savings < 0) {
            eoo = 0;
            is_eoo_negative[o] = 1;
          }
        }
      }
      if (use_eoo) {
        t++;
        t->skip_eob_node = t->skip_coef_val = 0;
        // transmit the eoo symbol
        t->token = !eoo ? ZPC_ISOLATED : ZPC_EOORIENT;
        t->context_tree = &((*zpc_probs)[ref]
                            [coef_to_zpc_band(band)]
                            [coef_to_zpc_ptok(pt)][0]);
        if (!dry_run)
          (*zpc_count)[ref]
              [coef_to_zpc_band(band)]
              [coef_to_zpc_ptok(pt)][0][!eoo]++;
        if (eoo) {
          assert(is_eoo_list[o] == 0);
          is_eoo_list[o] = 1;
        }
      }
    }
    is_last_zero[o] = (token == ZERO_TOKEN);
#endif
341
    ++t;
342
  } while (c < eob && ++c < seg_eob);
343 344

  *tp = t;
345 346
  for (pt = 0; pt < (1 << tx_size); pt++) {
    A[pt] = L[pt] = c > 0;
Yaowu Xu's avatar
Yaowu Xu committed
347
  }
John Koleszar's avatar
John Koleszar committed
348 349
}

350 351 352 353 354
struct is_skippable_args {
  MACROBLOCKD *xd;
  int *skippable;
};
static void is_skippable(int plane, int block,
355
                         BLOCK_SIZE_TYPE bsize, int ss_txfrm_size, void *argv) {
356 357
  struct is_skippable_args *args = argv;
  args->skippable[0] &= (!args->xd->plane[plane].eobs[block]);
Deb Mukherjee's avatar
Deb Mukherjee committed
358 359
}

360 361 362
int vp9_sb_is_skippable(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  int result = 1;
  struct is_skippable_args args = {xd, &result};
363
  foreach_transformed_block(xd, bsize, is_skippable, &args);
364
  return result;
365 366
}

367 368 369
int vp9_sby_is_skippable(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  int result = 1;
  struct is_skippable_args args = {xd, &result};
370
  foreach_transformed_block_in_plane(xd, bsize, 0, 0, is_skippable, &args);
371
  return result;
372 373
}

374 375 376
int vp9_sbuv_is_skippable(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  int result = 1;
  struct is_skippable_args args = {xd, &result};
377
  foreach_transformed_block_uv(xd, bsize, is_skippable, &args);
378
  return result;
379 380
}

381 382 383
void vp9_tokenize_sb(VP9_COMP *cpi,
                     MACROBLOCKD *xd,
                     TOKENEXTRA **t,
384
                     int dry_run, BLOCK_SIZE_TYPE bsize) {
385
  const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
386 387 388 389 390
  VP9_COMMON * const cm = &cpi->common;
  MB_MODE_INFO * const mbmi = &xd->mode_info_context->mbmi;
  TOKENEXTRA *t_backup = *t;
  const int mb_skip_context = vp9_get_pred_context(cm, xd, PRED_MBSKIP);
  const int segment_id = mbmi->segment_id;
Paul Wilkins's avatar
Paul Wilkins committed
391
  const int skip_inc = !vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
392
  const TX_SIZE txfm_size = mbmi->txfm_size;
393
  TX_SIZE uv_txfm_size = get_uv_tx_size(xd);
394
  int b;
395
  const int n_y = (1 << (bwl + bhl)), n_uv = (n_y * 3) >> 1;
396

397
  mbmi->mb_skip_coeff = vp9_sb_is_skippable(xd, bsize);
398 399 400 401

  if (mbmi->mb_skip_coeff) {
    if (!dry_run)
      cpi->skip_true_count[mb_skip_context] += skip_inc;
402
    vp9_reset_sb_tokens_context(xd, bsize);
403 404 405 406 407 408 409 410
    if (dry_run)
      *t = t_backup;
    return;
  }

  if (!dry_run)
    cpi->skip_false_count[mb_skip_context] += skip_inc;

411
  switch (txfm_size) {
412
    case TX_32X32:
413
      for (b = 0; b < n_y; b += 64)
414
        tokenize_b(cpi, xd, b, t, PLANE_TYPE_Y_WITH_DC,
415 416 417 418 419 420 421 422 423 424 425 426
                   TX_32X32, n_y, dry_run);
      if (uv_txfm_size == TX_32X32) {
        assert(bsize == BLOCK_SIZE_SB64X64);
        tokenize_b(cpi, xd, 256, t, PLANE_TYPE_UV,
                   TX_32X32, n_y, dry_run);
        tokenize_b(cpi, xd, 320, t, PLANE_TYPE_UV,
                   TX_32X32, n_y, dry_run);
      } else {
        for (; b < n_uv; b += 16)
          tokenize_b(cpi, xd, b, t, PLANE_TYPE_UV,
                     TX_16X16, n_y, dry_run);
      }
427 428
      break;
    case TX_16X16:
429
      for (b = 0; b < n_y; b += 16)
430
        tokenize_b(cpi, xd, b, t, PLANE_TYPE_Y_WITH_DC,
431 432 433 434 435 436 437 438 439 440
                   TX_16X16, n_y, dry_run);
      if (uv_txfm_size == TX_16X16) {
        for (; b < n_uv; b += 16)
          tokenize_b(cpi, xd, b, t, PLANE_TYPE_UV,
                     TX_16X16, n_y, dry_run);
      } else {
        for (; b < n_uv; b += 4)
          tokenize_b(cpi, xd, b, t, PLANE_TYPE_UV,
                     TX_8X8, n_y, dry_run);
      }
441 442
      break;
    case TX_8X8:
443
      for (b = 0; b < n_y; b += 4)
444
        tokenize_b(cpi, xd, b, t, PLANE_TYPE_Y_WITH_DC,
445
                   TX_8X8, n_y, dry_run);
446 447 448 449 450 451 452 453 454
      if (uv_txfm_size == TX_8X8) {
        for (; b < n_uv; b += 4)
          tokenize_b(cpi, xd, b, t, PLANE_TYPE_UV,
                     TX_8X8, n_y, dry_run);
      } else {
        for (; b < n_uv; ++b)
          tokenize_b(cpi, xd, b, t, PLANE_TYPE_UV,
                     TX_4X4, n_y, dry_run);
      }
455 456
      break;
    case TX_4X4:
457
      for (b = 0; b < n_y; b++)
458
        tokenize_b(cpi, xd, b, t, PLANE_TYPE_Y_WITH_DC,
459 460
                   TX_4X4, n_y, dry_run);
      for (; b < n_uv; b++)
461
        tokenize_b(cpi, xd, b, t, PLANE_TYPE_UV,
462
                   TX_4X4, n_y, dry_run);
463 464
      break;
    default: assert(0);
465
  }
466

467 468 469 470
  if (dry_run)
    *t = t_backup;
}

John Koleszar's avatar
John Koleszar committed
471
#ifdef ENTROPY_STATS
John Koleszar's avatar
John Koleszar committed
472 473 474
void init_context_counters(void) {
  FILE *f = fopen("context.bin", "rb");
  if (!f) {
475
    vpx_memset(context_counters_4x4, 0, sizeof(context_counters_4x4));
John Koleszar's avatar
John Koleszar committed
476
    vpx_memset(context_counters_8x8, 0, sizeof(context_counters_8x8));
Daniel Kang's avatar
Daniel Kang committed
477
    vpx_memset(context_counters_16x16, 0, sizeof(context_counters_16x16));
478
    vpx_memset(context_counters_32x32, 0, sizeof(context_counters_32x32));
John Koleszar's avatar
John Koleszar committed
479
  } else {
480
    fread(context_counters_4x4, sizeof(context_counters_4x4), 1, f);
John Koleszar's avatar
John Koleszar committed
481
    fread(context_counters_8x8, sizeof(context_counters_8x8), 1, f);
Daniel Kang's avatar
Daniel Kang committed
482
    fread(context_counters_16x16, sizeof(context_counters_16x16), 1, f);
483
    fread(context_counters_32x32, sizeof(context_counters_32x32), 1, f);
John Koleszar's avatar
John Koleszar committed
484 485 486 487 488
    fclose(f);
  }

  f = fopen("treeupdate.bin", "rb");
  if (!f) {
489
    vpx_memset(tree_update_hist_4x4, 0, sizeof(tree_update_hist_4x4));
John Koleszar's avatar
John Koleszar committed
490
    vpx_memset(tree_update_hist_8x8, 0, sizeof(tree_update_hist_8x8));
Daniel Kang's avatar
Daniel Kang committed
491
    vpx_memset(tree_update_hist_16x16, 0, sizeof(tree_update_hist_16x16));
492
    vpx_memset(tree_update_hist_32x32, 0, sizeof(tree_update_hist_32x32));
John Koleszar's avatar
John Koleszar committed
493
  } else {
494
    fread(tree_update_hist_4x4, sizeof(tree_update_hist_4x4), 1, f);
John Koleszar's avatar
John Koleszar committed
495
    fread(tree_update_hist_8x8, sizeof(tree_update_hist_8x8), 1, f);
Daniel Kang's avatar
Daniel Kang committed
496
    fread(tree_update_hist_16x16, sizeof(tree_update_hist_16x16), 1, f);
497
    fread(tree_update_hist_32x32, sizeof(tree_update_hist_32x32), 1, f);
John Koleszar's avatar
John Koleszar committed
498 499
    fclose(f);
  }
John Koleszar's avatar
John Koleszar committed
500 501
}

502 503
static void print_counter(FILE *f, vp9_coeff_accum *context_counters,
                          int block_types, const char *header) {
504
  int type, ref, band, pt, t;
John Koleszar's avatar
John Koleszar committed
505

506
  fprintf(f, "static const vp9_coeff_count %s = {\n", header);
John Koleszar's avatar
John Koleszar committed
507

508
#define Comma(X) (X ? "," : "")
John Koleszar's avatar
John Koleszar committed
509 510
  type = 0;
  do {
511
    ref = 0;
John Koleszar's avatar
John Koleszar committed
512 513
    fprintf(f, "%s\n  { /* block Type %d */", Comma(type), type);
    do {
514 515
      fprintf(f, "%s\n    { /* %s */", Comma(type), ref ? "Inter" : "Intra");
      band = 0;
John Koleszar's avatar
John Koleszar committed
516
      do {
517 518
        fprintf(f, "%s\n      { /* Coeff Band %d */", Comma(band), band);
        pt = 0;
John Koleszar's avatar
John Koleszar committed
519
        do {
520 521 522 523 524 525 526 527 528
          fprintf(f, "%s\n        {", Comma(pt));

          t = 0;
          do {
            const int64_t x = context_counters[type][ref][band][pt][t];
            const int y = (int) x;

            assert(x == (int64_t) y);  /* no overflow handling yet */
            fprintf(f, "%s %d", Comma(t), y);
529
          } while (++t < 1 + MAX_ENTROPY_TOKENS);
530 531 532 533
          fprintf(f, "}");
        } while (++pt < PREV_COEF_CONTEXTS);
        fprintf(f, "\n      }");
      } while (++band < COEF_BANDS);
John Koleszar's avatar
John Koleszar committed
534
      fprintf(f, "\n    }");
535
    } while (++ref < REF_TYPES);
John Koleszar's avatar
John Koleszar committed
536
    fprintf(f, "\n  }");
537
  } while (++type < block_types);
Daniel Kang's avatar
Daniel Kang committed
538
  fprintf(f, "\n};\n");
539
}
540

541 542
static void print_probs(FILE *f, vp9_coeff_accum *context_counters,
                        int block_types, const char *header) {
543
  int type, ref, band, pt, t;
Daniel Kang's avatar
Daniel Kang committed
544

545
  fprintf(f, "static const vp9_coeff_probs %s = {", header);
546

John Koleszar's avatar
John Koleszar committed
547
  type = 0;
548
#define Newline(x, spaces) (x ? " " : "\n" spaces)
John Koleszar's avatar
John Koleszar committed
549
  do {
550 551
    fprintf(f, "%s%s{ /* block Type %d */",
            Comma(type), Newline(type, "  "), type);
552
    ref = 0;
John Koleszar's avatar
John Koleszar committed
553
    do {
554 555 556
      fprintf(f, "%s%s{ /* %s */",
              Comma(band), Newline(band, "    "), ref ? "Inter" : "Intra");
      band = 0;
John Koleszar's avatar
John Koleszar committed
557
      do {
558 559 560
        fprintf(f, "%s%s{ /* Coeff Band %d */",
                Comma(band), Newline(band, "      "), band);
        pt = 0;
John Koleszar's avatar
John Koleszar committed
561
        do {
562
          unsigned int branch_ct[ENTROPY_NODES][2];
563
          unsigned int coef_counts[MAX_ENTROPY_TOKENS + 1];
564 565
          vp9_prob coef_probs[ENTROPY_NODES];

566 567 568
          if (pt >= 3 && band == 0)
            break;
          for (t = 0; t < MAX_ENTROPY_TOKENS + 1; ++t)
569
            coef_counts[t] = context_counters[type][ref][band][pt][t];
570 571
          vp9_tree_probs_from_distribution(vp9_coef_tree, coef_probs,
                                           branch_ct, coef_counts, 0);
572 573
          branch_ct[0][1] = coef_counts[MAX_ENTROPY_TOKENS] - branch_ct[0][0];
          coef_probs[0] = get_binary_prob(branch_ct[0][0], branch_ct[0][1]);
574 575 576 577 578 579 580 581 582 583 584
          fprintf(f, "%s\n      {", Comma(pt));

          t = 0;
          do {
            fprintf(f, "%s %3d", Comma(t), coef_probs[t]);
          } while (++t < ENTROPY_NODES);

          fprintf(f, " }");
        } while (++pt < PREV_COEF_CONTEXTS);
        fprintf(f, "\n      }");
      } while (++band < COEF_BANDS);
John Koleszar's avatar
John Koleszar committed
585
      fprintf(f, "\n    }");
586
    } while (++ref < REF_TYPES);
John Koleszar's avatar
John Koleszar committed
587
    fprintf(f, "\n  }");
588
  } while (++type < block_types);
John Koleszar's avatar
John Koleszar committed
589
  fprintf(f, "\n};\n");
590
}
591

592 593
void print_context_counters() {
  FILE *f = fopen("vp9_context.c", "w");
594

595 596
  fprintf(f, "#include \"vp9_entropy.h\"\n");
  fprintf(f, "\n/* *** GENERATED FILE: DO NOT EDIT *** */\n\n");
John Koleszar's avatar
John Koleszar committed
597

598
  /* print counts */
599
  print_counter(f, context_counters_4x4, BLOCK_TYPES,
600
                "vp9_default_coef_counts_4x4[BLOCK_TYPES]");
601
  print_counter(f, context_counters_8x8, BLOCK_TYPES,
602
                "vp9_default_coef_counts_8x8[BLOCK_TYPES]");
603
  print_counter(f, context_counters_16x16, BLOCK_TYPES,
604 605 606
                "vp9_default_coef_counts_16x16[BLOCK_TYPES]");
  print_counter(f, context_counters_32x32, BLOCK_TYPES,
                "vp9_default_coef_counts_32x32[BLOCK_TYPES]");
Daniel Kang's avatar
Daniel Kang committed
607

608
  /* print coefficient probabilities */
609
  print_probs(f, context_counters_4x4, BLOCK_TYPES,
610
              "default_coef_probs_4x4[BLOCK_TYPES]");
611
  print_probs(f, context_counters_8x8, BLOCK_TYPES,
612
              "default_coef_probs_8x8[BLOCK_TYPES]");
613
  print_probs(f, context_counters_16x16, BLOCK_TYPES,
614 615 616
              "default_coef_probs_16x16[BLOCK_TYPES]");
  print_probs(f, context_counters_32x32, BLOCK_TYPES,
              "default_coef_probs_32x32[BLOCK_TYPES]");
Daniel Kang's avatar
Daniel Kang committed
617

John Koleszar's avatar
John Koleszar committed
618 619 620
  fclose(f);

  f = fopen("context.bin", "wb");
621
  fwrite(context_counters_4x4, sizeof(context_counters_4x4), 1, f);
John Koleszar's avatar
John Koleszar committed
622
  fwrite(context_counters_8x8, sizeof(context_counters_8x8), 1, f);
Daniel Kang's avatar
Daniel Kang committed
623
  fwrite(context_counters_16x16, sizeof(context_counters_16x16), 1, f);
624
  fwrite(context_counters_32x32, sizeof(context_counters_32x32), 1, f);
John Koleszar's avatar
John Koleszar committed
625
  fclose(f);
John Koleszar's avatar
John Koleszar committed
626 627 628
}
#endif

629
void vp9_tokenize_initialize() {
John Koleszar's avatar
John Koleszar committed
630
  fill_value_tokens();
John Koleszar's avatar
John Koleszar committed
631
}