vp9_tokenize.c 18.9 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
struct tokenize_b_args {
  VP9_COMP *cpi;
  MACROBLOCKD *xd;
  TOKENEXTRA **tp;
  TX_SIZE tx_size;
  int dry_run;
};
static void tokenize_b(int plane, int block, BLOCK_SIZE_TYPE bsize,
                       int ss_txfrm_size, void *arg) {
  struct tokenize_b_args* const args = arg;
  VP9_COMP *cpi = args->cpi;
  MACROBLOCKD *xd = args->xd;
  TOKENEXTRA **tp = args->tp;
  PLANE_TYPE type = plane ? PLANE_TYPE_UV : PLANE_TYPE_Y_WITH_DC;
  TX_SIZE tx_size = ss_txfrm_size / 2;
  int dry_run = args->dry_run;

116
  MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
Daniel Kang's avatar
Daniel Kang committed
117
  int pt; /* near block/prev token context index */
118
  int c = 0, rc = 0;
Daniel Kang's avatar
Daniel Kang committed
119
  TOKENEXTRA *t = *tp;        /* store tokens starting here */
120
121
  const int eob = xd->plane[plane].eobs[block];
  const int16_t *qcoeff_ptr = BLOCK_OFFSET(xd->plane[plane].qcoeff, block, 16);
122
123
  const BLOCK_SIZE_TYPE sb_type = mbmi->sb_type;
  const int bwl = b_width_log2(sb_type);
124
125
  const int off = block >> (2 * tx_size);
  const int mod = bwl - tx_size - xd->plane[plane].subsampling_x;
126
127
  const int aoff = (off & ((1 << mod) - 1)) << tx_size;
  const int loff = (off >> mod) << tx_size;
128
129
  ENTROPY_CONTEXT *A = xd->plane[plane].above_context + aoff;
  ENTROPY_CONTEXT *L = xd->plane[plane].left_context + loff;
130
  int seg_eob, default_eob, pad;
131
  const int segment_id = mbmi->segment_id;
132
  const int *scan, *nb;
133
  vp9_coeff_count *counts;
134
  vp9_coeff_probs *coef_probs;
135
  const int ref = mbmi->ref_frame != INTRA_FRAME;
136
  ENTROPY_CONTEXT above_ec, left_ec;
137
  uint8_t token_cache[1024];
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  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
152

153
  assert((!type && !plane) || (type && plane));
154

155
156
  switch (tx_size) {
    default:
157
    case TX_4X4: {
158
      tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
John Koleszar's avatar
John Koleszar committed
159
          get_tx_type_4x4(xd, block) : DCT_DCT;
160
161
      above_ec = A[0] != 0;
      left_ec = L[0] != 0;
162
      seg_eob = 16;
163
      scan = get_scan_4x4(tx_type);
164
      counts = cpi->coef_counts_4x4;
165
166
167
168
169
      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
170
      break;
171
    }
172
    case TX_8X8: {
173
      const int sz = 1 + b_width_log2(sb_type);
John Koleszar's avatar
John Koleszar committed
174
      const int x = block & ((1 << sz) - 1), y = block - x;
175
176
      tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
          get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
177
178
      above_ec = (A[0] + A[1]) != 0;
      left_ec = (L[0] + L[1]) != 0;
179
      seg_eob = 64;
180
      scan = get_scan_8x8(tx_type);
181
      counts = cpi->coef_counts_8x8;
182
183
184
185
186
      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
187
      break;
188
189
    }
    case TX_16X16: {
190
      const int sz = 2 + b_width_log2(sb_type);
John Koleszar's avatar
John Koleszar committed
191
      const int x = block & ((1 << sz) - 1), y = block - x;
192
193
      tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
          get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
194
195
      above_ec = (A[0] + A[1] + A[2] + A[3]) != 0;
      left_ec = (L[0] + L[1] + L[2] + L[3]) != 0;
196
      seg_eob = 256;
197
      scan = get_scan_16x16(tx_type);
198
      counts = cpi->coef_counts_16x16;
199
200
201
202
203
      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
204
      break;
205
    }
206
    case TX_32X32:
207
208
      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;
209
210
211
      seg_eob = 1024;
      scan = vp9_default_zig_zag1d_32x32;
      counts = cpi->coef_counts_32x32;
212
213
214
215
216
      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
217
      break;
John Koleszar's avatar
John Koleszar committed
218
219
  }

220
  pt = combine_entropy_contexts(above_ec, left_ec);
221
222
  nb = vp9_get_coef_neighbors_handle(scan, &pad);
  default_eob = seg_eob;
Yaowu Xu's avatar
Yaowu Xu committed
223

Paul Wilkins's avatar
Paul Wilkins committed
224
225
  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))
    seg_eob = 0;
John Koleszar's avatar
John Koleszar committed
226

227
228
229
230
231
232
233
234
235
236
237
238
#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;
239
  do {
240
    const int band = get_coef_band(scan, tx_size, c);
241
    int token;
242
    int v = 0;
243
244
245
    rc = scan[c];
    if (c)
      pt = vp9_get_coef_context(scan, nb, pad, token_cache, c, default_eob);
246
    if (c < eob) {
247
      v = qcoeff_ptr[rc];
248
249
      assert(-DCT_MAX_VALUE <= v  &&  v < DCT_MAX_VALUE);

250
251
      t->extra = vp9_dct_value_tokens_ptr[v].extra;
      token    = vp9_dct_value_tokens_ptr[v].token;
252
    } else {
253
      token = DCT_EOB_TOKEN;
254
    }
John Koleszar's avatar
John Koleszar committed
255

256
    t->token = token;
257
258
    t->context_tree = coef_probs[type][ref][band][pt];
      t->skip_eob_node = (c > 0) && (token_cache[scan[c - 1]] == 0);
259
    assert(vp9_coef_encodings[t->token].len - t->skip_eob_node > 0);
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#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
274
    if (!dry_run) {
275
      ++counts[type][ref][band][pt][token];
276
277
      if (!t->skip_eob_node)
        ++cpi->common.fc.eob_branch_counts[tx_size][type][ref][band][pt];
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
341
342
343
344
345
346
347
    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
348
    ++t;
349
  } while (c < eob && ++c < seg_eob);
350
351

  *tp = t;
352
353
  for (pt = 0; pt < (1 << tx_size); pt++) {
    A[pt] = L[pt] = c > 0;
Yaowu Xu's avatar
Yaowu Xu committed
354
  }
John Koleszar's avatar
John Koleszar committed
355
356
}

357
358
359
360
361
struct is_skippable_args {
  MACROBLOCKD *xd;
  int *skippable;
};
static void is_skippable(int plane, int block,
362
                         BLOCK_SIZE_TYPE bsize, int ss_txfrm_size, void *argv) {
363
364
  struct is_skippable_args *args = argv;
  args->skippable[0] &= (!args->xd->plane[plane].eobs[block]);
Deb Mukherjee's avatar
Deb Mukherjee committed
365
366
}

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

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

382
383
384
int vp9_sbuv_is_skippable(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  int result = 1;
  struct is_skippable_args args = {xd, &result};
385
  foreach_transformed_block_uv(xd, bsize, is_skippable, &args);
386
  return result;
387
388
}

389
390
391
void vp9_tokenize_sb(VP9_COMP *cpi,
                     MACROBLOCKD *xd,
                     TOKENEXTRA **t,
392
                     int dry_run, BLOCK_SIZE_TYPE bsize) {
393
394
395
396
397
  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
398
  const int skip_inc = !vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
399
  const TX_SIZE txfm_size = mbmi->txfm_size;
400
401
402
  struct tokenize_b_args arg = {
    cpi, xd, t, txfm_size, dry_run
  };
403

404
  mbmi->mb_skip_coeff = vp9_sb_is_skippable(xd, bsize);
405
406
407
408

  if (mbmi->mb_skip_coeff) {
    if (!dry_run)
      cpi->skip_true_count[mb_skip_context] += skip_inc;
409
    vp9_reset_sb_tokens_context(xd, bsize);
410
411
412
413
414
415
416
417
    if (dry_run)
      *t = t_backup;
    return;
  }

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

418
  foreach_transformed_block(xd, bsize, tokenize_b, &arg);
419

420
421
422
423
  if (dry_run)
    *t = t_backup;
}

John Koleszar's avatar
John Koleszar committed
424
#ifdef ENTROPY_STATS
John Koleszar's avatar
John Koleszar committed
425
426
427
void init_context_counters(void) {
  FILE *f = fopen("context.bin", "rb");
  if (!f) {
428
    vpx_memset(context_counters_4x4, 0, sizeof(context_counters_4x4));
John Koleszar's avatar
John Koleszar committed
429
    vpx_memset(context_counters_8x8, 0, sizeof(context_counters_8x8));
Daniel Kang's avatar
Daniel Kang committed
430
    vpx_memset(context_counters_16x16, 0, sizeof(context_counters_16x16));
431
    vpx_memset(context_counters_32x32, 0, sizeof(context_counters_32x32));
John Koleszar's avatar
John Koleszar committed
432
  } else {
433
    fread(context_counters_4x4, sizeof(context_counters_4x4), 1, f);
John Koleszar's avatar
John Koleszar committed
434
    fread(context_counters_8x8, sizeof(context_counters_8x8), 1, f);
Daniel Kang's avatar
Daniel Kang committed
435
    fread(context_counters_16x16, sizeof(context_counters_16x16), 1, f);
436
    fread(context_counters_32x32, sizeof(context_counters_32x32), 1, f);
John Koleszar's avatar
John Koleszar committed
437
438
439
440
441
    fclose(f);
  }

  f = fopen("treeupdate.bin", "rb");
  if (!f) {
442
    vpx_memset(tree_update_hist_4x4, 0, sizeof(tree_update_hist_4x4));
John Koleszar's avatar
John Koleszar committed
443
    vpx_memset(tree_update_hist_8x8, 0, sizeof(tree_update_hist_8x8));
Daniel Kang's avatar
Daniel Kang committed
444
    vpx_memset(tree_update_hist_16x16, 0, sizeof(tree_update_hist_16x16));
445
    vpx_memset(tree_update_hist_32x32, 0, sizeof(tree_update_hist_32x32));
John Koleszar's avatar
John Koleszar committed
446
  } else {
447
    fread(tree_update_hist_4x4, sizeof(tree_update_hist_4x4), 1, f);
John Koleszar's avatar
John Koleszar committed
448
    fread(tree_update_hist_8x8, sizeof(tree_update_hist_8x8), 1, f);
Daniel Kang's avatar
Daniel Kang committed
449
    fread(tree_update_hist_16x16, sizeof(tree_update_hist_16x16), 1, f);
450
    fread(tree_update_hist_32x32, sizeof(tree_update_hist_32x32), 1, f);
John Koleszar's avatar
John Koleszar committed
451
452
    fclose(f);
  }
John Koleszar's avatar
John Koleszar committed
453
454
}

455
456
static void print_counter(FILE *f, vp9_coeff_accum *context_counters,
                          int block_types, const char *header) {
457
  int type, ref, band, pt, t;
John Koleszar's avatar
John Koleszar committed
458

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

461
#define Comma(X) (X ? "," : "")
John Koleszar's avatar
John Koleszar committed
462
463
  type = 0;
  do {
464
    ref = 0;
John Koleszar's avatar
John Koleszar committed
465
466
    fprintf(f, "%s\n  { /* block Type %d */", Comma(type), type);
    do {
467
468
      fprintf(f, "%s\n    { /* %s */", Comma(type), ref ? "Inter" : "Intra");
      band = 0;
John Koleszar's avatar
John Koleszar committed
469
      do {
470
471
        fprintf(f, "%s\n      { /* Coeff Band %d */", Comma(band), band);
        pt = 0;
John Koleszar's avatar
John Koleszar committed
472
        do {
473
474
475
476
477
478
479
480
481
          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);
482
          } while (++t < 1 + MAX_ENTROPY_TOKENS);
483
484
485
486
          fprintf(f, "}");
        } while (++pt < PREV_COEF_CONTEXTS);
        fprintf(f, "\n      }");
      } while (++band < COEF_BANDS);
John Koleszar's avatar
John Koleszar committed
487
      fprintf(f, "\n    }");
488
    } while (++ref < REF_TYPES);
John Koleszar's avatar
John Koleszar committed
489
    fprintf(f, "\n  }");
490
  } while (++type < block_types);
Daniel Kang's avatar
Daniel Kang committed
491
  fprintf(f, "\n};\n");
492
}
493

494
495
static void print_probs(FILE *f, vp9_coeff_accum *context_counters,
                        int block_types, const char *header) {
496
  int type, ref, band, pt, t;
Daniel Kang's avatar
Daniel Kang committed
497

498
  fprintf(f, "static const vp9_coeff_probs %s = {", header);
499

John Koleszar's avatar
John Koleszar committed
500
  type = 0;
501
#define Newline(x, spaces) (x ? " " : "\n" spaces)
John Koleszar's avatar
John Koleszar committed
502
  do {
503
504
    fprintf(f, "%s%s{ /* block Type %d */",
            Comma(type), Newline(type, "  "), type);
505
    ref = 0;
John Koleszar's avatar
John Koleszar committed
506
    do {
507
508
509
      fprintf(f, "%s%s{ /* %s */",
              Comma(band), Newline(band, "    "), ref ? "Inter" : "Intra");
      band = 0;
John Koleszar's avatar
John Koleszar committed
510
      do {
511
512
513
        fprintf(f, "%s%s{ /* Coeff Band %d */",
                Comma(band), Newline(band, "      "), band);
        pt = 0;
John Koleszar's avatar
John Koleszar committed
514
        do {
515
          unsigned int branch_ct[ENTROPY_NODES][2];
516
          unsigned int coef_counts[MAX_ENTROPY_TOKENS + 1];
517
518
          vp9_prob coef_probs[ENTROPY_NODES];

519
520
521
          if (pt >= 3 && band == 0)
            break;
          for (t = 0; t < MAX_ENTROPY_TOKENS + 1; ++t)
522
            coef_counts[t] = context_counters[type][ref][band][pt][t];
523
524
          vp9_tree_probs_from_distribution(vp9_coef_tree, coef_probs,
                                           branch_ct, coef_counts, 0);
525
526
          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]);
527
528
529
530
531
532
533
534
535
536
537
          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
538
      fprintf(f, "\n    }");
539
    } while (++ref < REF_TYPES);
John Koleszar's avatar
John Koleszar committed
540
    fprintf(f, "\n  }");
541
  } while (++type < block_types);
John Koleszar's avatar
John Koleszar committed
542
  fprintf(f, "\n};\n");
543
}
544

545
546
void print_context_counters() {
  FILE *f = fopen("vp9_context.c", "w");
547

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

551
  /* print counts */
552
  print_counter(f, context_counters_4x4, BLOCK_TYPES,
553
                "vp9_default_coef_counts_4x4[BLOCK_TYPES]");
554
  print_counter(f, context_counters_8x8, BLOCK_TYPES,
555
                "vp9_default_coef_counts_8x8[BLOCK_TYPES]");
556
  print_counter(f, context_counters_16x16, BLOCK_TYPES,
557
558
559
                "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
560

561
  /* print coefficient probabilities */
562
  print_probs(f, context_counters_4x4, BLOCK_TYPES,
563
              "default_coef_probs_4x4[BLOCK_TYPES]");
564
  print_probs(f, context_counters_8x8, BLOCK_TYPES,
565
              "default_coef_probs_8x8[BLOCK_TYPES]");
566
  print_probs(f, context_counters_16x16, BLOCK_TYPES,
567
568
569
              "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
570

John Koleszar's avatar
John Koleszar committed
571
572
573
  fclose(f);

  f = fopen("context.bin", "wb");
574
  fwrite(context_counters_4x4, sizeof(context_counters_4x4), 1, f);
John Koleszar's avatar
John Koleszar committed
575
  fwrite(context_counters_8x8, sizeof(context_counters_8x8), 1, f);
Daniel Kang's avatar
Daniel Kang committed
576
  fwrite(context_counters_16x16, sizeof(context_counters_16x16), 1, f);
577
  fwrite(context_counters_32x32, sizeof(context_counters_32x32), 1, f);
John Koleszar's avatar
John Koleszar committed
578
  fclose(f);
John Koleszar's avatar
John Koleszar committed
579
580
581
}
#endif

582
void vp9_tokenize_initialize() {
John Koleszar's avatar
John Koleszar committed
583
  fill_value_tokens();
John Koleszar's avatar
John Koleszar committed
584
}