bitstream.c 177 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4
5
6
7
8
9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10
11
12
13
 */

#include <assert.h>
#include <limits.h>
14
#include <stdio.h>
Jingning Han's avatar
Jingning Han committed
15

Yaowu Xu's avatar
Yaowu Xu committed
16
#include "aom/aom_encoder.h"
17
#include "aom_dsp/bitwriter_buffer.h"
Yaowu Xu's avatar
Yaowu Xu committed
18
19
#include "aom_dsp/aom_dsp_common.h"
#include "aom_mem/aom_mem.h"
20
21
#include "aom_ports/mem_ops.h"
#include "aom_ports/system_state.h"
22
#if CONFIG_BITSTREAM_DEBUG
23
#include "aom_util/debug_util.h"
24
#endif  // CONFIG_BITSTREAM_DEBUG
Jingning Han's avatar
Jingning Han committed
25

26
#if CONFIG_CDEF
27
28
#include "av1/common/clpf.h"
#include "av1/common/dering.h"
29
#endif  // CONFIG_CDEF
30
31
32
33
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
#include "av1/common/entropymv.h"
#include "av1/common/mvref_common.h"
34
#include "av1/common/odintrin.h"
35
36
#include "av1/common/pred_common.h"
#include "av1/common/reconinter.h"
hui su's avatar
hui su committed
37
38
39
#if CONFIG_EXT_INTRA
#include "av1/common/reconintra.h"
#endif  // CONFIG_EXT_INTRA
40
41
#include "av1/common/seg_common.h"
#include "av1/common/tile_common.h"
Jingning Han's avatar
Jingning Han committed
42

Alex Converse's avatar
Alex Converse committed
43
#if CONFIG_ANS
Alex Converse's avatar
Alex Converse committed
44
#include "aom_dsp/buf_ans.h"
Alex Converse's avatar
Alex Converse committed
45
#endif  // CONFIG_ANS
46
47
48
49
50
51
52
#include "av1/encoder/bitstream.h"
#include "av1/encoder/cost.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/mcomp.h"
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
53
54
55
#if CONFIG_PVQ
#include "av1/encoder/pvq_encoder.h"
#endif
Jingning Han's avatar
Jingning Han committed
56

57
58
static struct av1_token intra_mode_encodings[INTRA_MODES];
static struct av1_token switchable_interp_encodings[SWITCHABLE_FILTERS];
59
#if CONFIG_EXT_PARTITION_TYPES
Yaowu Xu's avatar
Yaowu Xu committed
60
static const struct av1_token ext_partition_encodings[EXT_PARTITION_TYPES] = {
61
62
63
  { 0, 1 },  { 4, 3 },  { 12, 4 }, { 7, 3 },
  { 10, 4 }, { 11, 4 }, { 26, 5 }, { 27, 5 }
};
64
#endif
65
static struct av1_token partition_encodings[PARTITION_TYPES];
66
#if !CONFIG_REF_MV
67
static struct av1_token inter_mode_encodings[INTER_MODES];
68
#endif
69
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
70
static const struct av1_token
71
72
73
74
    inter_compound_mode_encodings[INTER_COMPOUND_MODES] = {
      { 2, 2 },  { 50, 6 }, { 51, 6 }, { 24, 5 }, { 52, 6 },
      { 53, 6 }, { 54, 6 }, { 55, 6 }, { 0, 1 },  { 7, 3 }
    };
75
#endif  // CONFIG_EXT_INTER
76
#if CONFIG_PALETTE
77
static struct av1_token palette_size_encodings[PALETTE_MAX_SIZE - 1];
78
79
static struct av1_token palette_color_index_encodings[PALETTE_MAX_SIZE - 1]
                                                     [PALETTE_MAX_SIZE];
80
#endif  // CONFIG_PALETTE
81
#if !CONFIG_EC_MULTISYMBOL
Jingning Han's avatar
Jingning Han committed
82
static const struct av1_token tx_size_encodings[MAX_TX_DEPTH][TX_SIZES] = {
83
84
85
  { { 0, 1 }, { 1, 1 } },                      // Max tx_size is 8X8
  { { 0, 1 }, { 2, 2 }, { 3, 2 } },            // Max tx_size is 16X16
  { { 0, 1 }, { 2, 2 }, { 6, 3 }, { 7, 3 } },  // Max tx_size is 32X32
86
87
88
#if CONFIG_TX64X64
  { { 0, 1 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 15, 4 } },  // Max tx_size 64X64
#endif                                                     // CONFIG_TX64X64
89
};
90
#endif
91

92
#if CONFIG_EXT_INTRA || CONFIG_FILTER_INTRA || CONFIG_PALETTE
Yaowu Xu's avatar
Yaowu Xu committed
93
static INLINE void write_uniform(aom_writer *w, int n, int v) {
hui su's avatar
hui su committed
94
95
  int l = get_unsigned_bits(n);
  int m = (1 << l) - n;
96
  if (l == 0) return;
hui su's avatar
hui su committed
97
  if (v < m) {
Yaowu Xu's avatar
Yaowu Xu committed
98
    aom_write_literal(w, v, l - 1);
hui su's avatar
hui su committed
99
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
100
101
    aom_write_literal(w, m + ((v - m) >> 1), l - 1);
    aom_write_literal(w, (v - m) & 1, 1);
hui su's avatar
hui su committed
102
103
  }
}
104
#endif  // CONFIG_EXT_INTRA || CONFIG_FILTER_INTRA || CONFIG_PALETTE
Jingning Han's avatar
Jingning Han committed
105

106
#if CONFIG_EXT_TX
Yaowu Xu's avatar
Yaowu Xu committed
107
108
static struct av1_token ext_tx_inter_encodings[EXT_TX_SETS_INTER][TX_TYPES];
static struct av1_token ext_tx_intra_encodings[EXT_TX_SETS_INTRA][TX_TYPES];
109
#else
Yaowu Xu's avatar
Yaowu Xu committed
110
static struct av1_token ext_tx_encodings[TX_TYPES];
111
#endif  // CONFIG_EXT_TX
112
#if CONFIG_GLOBAL_MOTION
113
static struct av1_token global_motion_types_encodings[GLOBAL_TRANS_TYPES];
114
#endif  // CONFIG_GLOBAL_MOTION
115
#if CONFIG_EXT_INTRA
hui su's avatar
hui su committed
116
#if CONFIG_INTRA_INTERP
Yaowu Xu's avatar
Yaowu Xu committed
117
static struct av1_token intra_filter_encodings[INTRA_FILTERS];
hui su's avatar
hui su committed
118
#endif  // CONFIG_INTRA_INTERP
119
#endif  // CONFIG_EXT_INTRA
120
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
121
static struct av1_token interintra_mode_encodings[INTERINTRA_MODES];
122
static struct av1_token compound_type_encodings[COMPOUND_TYPES];
123
#endif  // CONFIG_EXT_INTER
Yue Chen's avatar
Yue Chen committed
124
125
126
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
static struct av1_token motion_mode_encodings[MOTION_MODES];
#endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
127
128
129
#if CONFIG_LOOP_RESTORATION
static struct av1_token switchable_restore_encodings[RESTORE_SWITCHABLE_TYPES];
#endif  // CONFIG_LOOP_RESTORATION
130
131
132
static void write_uncompressed_header(AV1_COMP *cpi,
                                      struct aom_write_bit_buffer *wb);
static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data);
133
134
135
136
137
static int remux_tiles(const AV1_COMMON *const cm, uint8_t *dst,
                       const uint32_t data_size, const uint32_t max_tile_size,
                       const uint32_t max_tile_col_size,
                       int *const tile_size_bytes,
                       int *const tile_col_size_bytes);
138

Yaowu Xu's avatar
Yaowu Xu committed
139
void av1_encode_token_init(void) {
140
#if CONFIG_EXT_TX || CONFIG_PALETTE
141
  int s;
142
143
#endif  // CONFIG_EXT_TX || CONFIG_PALETTE
#if CONFIG_EXT_TX
144
  for (s = 1; s < EXT_TX_SETS_INTER; ++s) {
Yaowu Xu's avatar
Yaowu Xu committed
145
    av1_tokens_from_tree(ext_tx_inter_encodings[s], av1_ext_tx_inter_tree[s]);
146
147
  }
  for (s = 1; s < EXT_TX_SETS_INTRA; ++s) {
Yaowu Xu's avatar
Yaowu Xu committed
148
    av1_tokens_from_tree(ext_tx_intra_encodings[s], av1_ext_tx_intra_tree[s]);
149
  }
150
#else
Yaowu Xu's avatar
Yaowu Xu committed
151
  av1_tokens_from_tree(ext_tx_encodings, av1_ext_tx_tree);
152
#endif  // CONFIG_EXT_TX
153
154
155
156
157
158
159
  av1_tokens_from_tree(intra_mode_encodings, av1_intra_mode_tree);
  av1_tokens_from_tree(switchable_interp_encodings, av1_switchable_interp_tree);
  av1_tokens_from_tree(partition_encodings, av1_partition_tree);
#if !CONFIG_REF_MV
  av1_tokens_from_tree(inter_mode_encodings, av1_inter_mode_tree);
#endif

160
161
162
#if CONFIG_PALETTE
  av1_tokens_from_tree(palette_size_encodings, av1_palette_size_tree);
  for (s = 0; s < PALETTE_MAX_SIZE - 1; ++s) {
163
164
    av1_tokens_from_tree(palette_color_index_encodings[s],
                         av1_palette_color_index_tree[s]);
165
166
167
  }
#endif  // CONFIG_PALETTE

168
#if CONFIG_EXT_INTRA
hui su's avatar
hui su committed
169
#if CONFIG_INTRA_INTERP
Yaowu Xu's avatar
Yaowu Xu committed
170
  av1_tokens_from_tree(intra_filter_encodings, av1_intra_filter_tree);
hui su's avatar
hui su committed
171
#endif  // CONFIG_INTRA_INTERP
172
#endif  // CONFIG_EXT_INTRA
173
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
174
  av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree);
175
  av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree);
176
#endif  // CONFIG_EXT_INTER
Yue Chen's avatar
Yue Chen committed
177
178
179
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
  av1_tokens_from_tree(motion_mode_encodings, av1_motion_mode_tree);
#endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
180
#if CONFIG_GLOBAL_MOTION
Yaowu Xu's avatar
Yaowu Xu committed
181
182
  av1_tokens_from_tree(global_motion_types_encodings,
                       av1_global_motion_types_tree);
183
#endif  // CONFIG_GLOBAL_MOTION
184
185
186
187
#if CONFIG_LOOP_RESTORATION
  av1_tokens_from_tree(switchable_restore_encodings,
                       av1_switchable_restore_tree);
#endif  // CONFIG_LOOP_RESTORATION
188

189
#if CONFIG_EC_MULTISYMBOL
190
  /* This hack is necessary when CONFIG_DUAL_FILTER is enabled because the five
191
192
193
194
      SWITCHABLE_FILTERS are not consecutive, e.g., 0, 1, 2, 3, 4, when doing
      an in-order traversal of the av1_switchable_interp_tree structure. */
  av1_indices_from_tree(av1_switchable_interp_ind, av1_switchable_interp_inv,
                        SWITCHABLE_FILTERS, av1_switchable_interp_tree);
195
196
197
/* This hack is necessary because the four TX_TYPES are not consecutive,
    e.g., 0, 1, 2, 3, when doing an in-order traversal of the av1_ext_tx_tree
    structure. */
David Barker's avatar
David Barker committed
198
#if !CONFIG_EXT_TX
199
200
  av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, TX_TYPES,
                        av1_ext_tx_tree);
David Barker's avatar
David Barker committed
201
#endif
202
203
  av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv, INTRA_MODES,
                        av1_intra_mode_tree);
204
205
  av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv, INTER_MODES,
                        av1_inter_mode_tree);
206
#endif
207
208
}

209
#if !CONFIG_EC_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
210
211
212
static void write_intra_mode(aom_writer *w, PREDICTION_MODE mode,
                             const aom_prob *probs) {
  av1_write_token(w, av1_intra_mode_tree, probs, &intra_mode_encodings[mode]);
Jingning Han's avatar
Jingning Han committed
213
}
214
#endif
Jingning Han's avatar
Jingning Han committed
215

216
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
217
218
219
220
static void write_interintra_mode(aom_writer *w, INTERINTRA_MODE mode,
                                  const aom_prob *probs) {
  av1_write_token(w, av1_interintra_mode_tree, probs,
                  &interintra_mode_encodings[mode]);
221
222
223
}
#endif  // CONFIG_EXT_INTER

224
225
static void write_inter_mode(aom_writer *w, PREDICTION_MODE mode,
                             FRAME_CONTEXT *ec_ctx,
Yue Chen's avatar
Yue Chen committed
226
227
228
#if CONFIG_REF_MV && CONFIG_EXT_INTER
                             int is_compound,
#endif  // CONFIG_REF_MV && CONFIG_EXT_INTER
229
                             const int16_t mode_ctx) {
230
#if CONFIG_REF_MV
231
  const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
232
  const aom_prob newmv_prob = ec_ctx->newmv_prob[newmv_ctx];
Yue Chen's avatar
Yue Chen committed
233
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
234
  aom_write(w, mode != NEWMV && mode != NEWFROMNEARMV, newmv_prob);
Yue Chen's avatar
Yue Chen committed
235
236

  if (!is_compound && (mode == NEWMV || mode == NEWFROMNEARMV))
237
    aom_write(w, mode == NEWFROMNEARMV, ec_ctx->new2mv_prob);
Yue Chen's avatar
Yue Chen committed
238
239
240

  if (mode != NEWMV && mode != NEWFROMNEARMV) {
#else
Yaowu Xu's avatar
Yaowu Xu committed
241
  aom_write(w, mode != NEWMV, newmv_prob);
242
243

  if (mode != NEWMV) {
Yue Chen's avatar
Yue Chen committed
244
#endif  // CONFIG_EXT_INTER
245
    const int16_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
246
    const aom_prob zeromv_prob = ec_ctx->zeromv_prob[zeromv_ctx];
247
248
249
250
251
252

    if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
      assert(mode == ZEROMV);
      return;
    }

Yaowu Xu's avatar
Yaowu Xu committed
253
    aom_write(w, mode != ZEROMV, zeromv_prob);
254
255

    if (mode != ZEROMV) {
256
      int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
Yaowu Xu's avatar
Yaowu Xu committed
257
      aom_prob refmv_prob;
258

259
260
261
      if (mode_ctx & (1 << SKIP_NEARESTMV_OFFSET)) refmv_ctx = 6;
      if (mode_ctx & (1 << SKIP_NEARMV_OFFSET)) refmv_ctx = 7;
      if (mode_ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) refmv_ctx = 8;
262

263
      refmv_prob = ec_ctx->refmv_prob[refmv_ctx];
Yaowu Xu's avatar
Yaowu Xu committed
264
      aom_write(w, mode != NEARESTMV, refmv_prob);
265
266
267
    }
  }
#else
Jingning Han's avatar
Jingning Han committed
268
  assert(is_inter_mode(mode));
269
#if CONFIG_EC_MULTISYMBOL
270
  aom_write_symbol(w, av1_inter_mode_ind[INTER_OFFSET(mode)],
271
                   ec_ctx->inter_mode_cdf[mode_ctx], INTER_MODES);
272
273
#else
  {
274
    const aom_prob *const inter_probs = ec_ctx->inter_mode_probs[mode_ctx];
275
276
277
278
    av1_write_token(w, av1_inter_mode_tree, inter_probs,
                    &inter_mode_encodings[INTER_OFFSET(mode)]);
  }
#endif
279
#endif
Jingning Han's avatar
Jingning Han committed
280
281
}

282
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
283
284
285
static void write_drl_idx(const AV1_COMMON *cm, const MB_MODE_INFO *mbmi,
                          const MB_MODE_INFO_EXT *mbmi_ext, aom_writer *w) {
  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
286
287
288

  assert(mbmi->ref_mv_idx < 3);

289
290
291
292
293
  if (mbmi->mode == NEWMV) {
    int idx;
    for (idx = 0; idx < 2; ++idx) {
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
        uint8_t drl_ctx =
Yaowu Xu's avatar
Yaowu Xu committed
294
295
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
        aom_prob drl_prob = cm->fc->drl_prob[drl_ctx];
296

Yaowu Xu's avatar
Yaowu Xu committed
297
        aom_write(w, mbmi->ref_mv_idx != idx, drl_prob);
298
        if (mbmi->ref_mv_idx == idx) return;
299
      }
300
301
302
303
    }
    return;
  }

304
305
306
307
308
309
  if (mbmi->mode == NEARMV) {
    int idx;
    // TODO(jingning): Temporary solution to compensate the NEARESTMV offset.
    for (idx = 1; idx < 3; ++idx) {
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
        uint8_t drl_ctx =
Yaowu Xu's avatar
Yaowu Xu committed
310
311
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
        aom_prob drl_prob = cm->fc->drl_prob[drl_ctx];
312

Yaowu Xu's avatar
Yaowu Xu committed
313
        aom_write(w, mbmi->ref_mv_idx != (idx - 1), drl_prob);
314
        if (mbmi->ref_mv_idx == (idx - 1)) return;
315
      }
316
    }
317
    return;
318
319
320
321
  }
}
#endif

322
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
323
static void write_inter_compound_mode(AV1_COMMON *cm, aom_writer *w,
324
325
                                      PREDICTION_MODE mode,
                                      const int16_t mode_ctx) {
Yaowu Xu's avatar
Yaowu Xu committed
326
  const aom_prob *const inter_compound_probs =
327
      cm->fc->inter_compound_mode_probs[mode_ctx];
328
329

  assert(is_inter_compound_mode(mode));
Yaowu Xu's avatar
Yaowu Xu committed
330
331
  av1_write_token(w, av1_inter_compound_mode_tree, inter_compound_probs,
                  &inter_compound_mode_encodings[INTER_COMPOUND_OFFSET(mode)]);
332
333
334
}
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
335
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
336
                                int max) {
Yaowu Xu's avatar
Yaowu Xu committed
337
  aom_wb_write_literal(wb, data, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
338
339
}

340
#if !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
341
342
static void prob_diff_update(const aom_tree_index *tree,
                             aom_prob probs[/*n - 1*/],
343
                             const unsigned int counts[/*n - 1*/], int n,
344
                             int probwt, aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
345
346
347
348
349
350
  int i;
  unsigned int branch_ct[32][2];

  // Assuming max number of probabilities <= 32
  assert(n <= 32);

Yaowu Xu's avatar
Yaowu Xu committed
351
  av1_tree_probs_from_distribution(tree, branch_ct, counts);
Jingning Han's avatar
Jingning Han committed
352
  for (i = 0; i < n - 1; ++i)
353
    av1_cond_prob_diff_update(w, &probs[i], branch_ct[i], probwt);
Jingning Han's avatar
Jingning Han committed
354
}
355
356
#endif

357
#if CONFIG_EXT_INTER || CONFIG_EXT_TX || !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
358
359
static int prob_diff_update_savings(const aom_tree_index *tree,
                                    aom_prob probs[/*n - 1*/],
360
361
                                    const unsigned int counts[/*n - 1*/], int n,
                                    int probwt) {
362
363
364
365
366
367
  int i;
  unsigned int branch_ct[32][2];
  int savings = 0;

  // Assuming max number of probabilities <= 32
  assert(n <= 32);
Yaowu Xu's avatar
Yaowu Xu committed
368
  av1_tree_probs_from_distribution(tree, branch_ct, counts);
369
  for (i = 0; i < n - 1; ++i) {
370
371
    savings +=
        av1_cond_prob_diff_update_savings(&probs[i], branch_ct[i], probwt);
372
373
374
  }
  return savings;
}
375
#endif  // CONFIG_EXT_INTER || CONFIG_EXT_TX || !CONFIG_EC_ADAPT
376

377
#if CONFIG_VAR_TX
Yaowu Xu's avatar
Yaowu Xu committed
378
static void write_tx_size_vartx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
379
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
380
381
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
382
383
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
384
385
386
  const int max_blocks_high = max_block_high(xd, mbmi->sb_type, 0);
  const int max_blocks_wide = max_block_wide(xd, mbmi->sb_type, 0);

387
  int ctx = txfm_partition_context(xd->above_txfm_context + tx_col,
388
389
                                   xd->left_txfm_context + tx_row,
                                   mbmi->sb_type, tx_size);
390

391
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
392

Jingning Han's avatar
Jingning Han committed
393
  if (depth == MAX_VARTX_DEPTH) {
394
    txfm_partition_update(xd->above_txfm_context + tx_col,
395
                          xd->left_txfm_context + tx_row, tx_size, tx_size);
396
397
398
    return;
  }

399
  if (tx_size == mbmi->inter_tx_size[tx_row][tx_col]) {
Yaowu Xu's avatar
Yaowu Xu committed
400
    aom_write(w, 0, cm->fc->txfm_partition_prob[ctx]);
401
    txfm_partition_update(xd->above_txfm_context + tx_col,
402
                          xd->left_txfm_context + tx_row, tx_size, tx_size);
403
  } else {
404
405
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    const int bsl = tx_size_wide_unit[sub_txs];
406
    int i;
407

Yaowu Xu's avatar
Yaowu Xu committed
408
    aom_write(w, 1, cm->fc->txfm_partition_prob[ctx]);
409

410
    if (tx_size == TX_8X8) {
411
      txfm_partition_update(xd->above_txfm_context + tx_col,
412
                            xd->left_txfm_context + tx_row, sub_txs, tx_size);
413
      return;
414
    }
415
416
417

    assert(bsl > 0);
    for (i = 0; i < 4; ++i) {
418
419
420
421
      int offsetr = blk_row + (i >> 1) * bsl;
      int offsetc = blk_col + (i & 0x01) * bsl;
      write_tx_size_vartx(cm, xd, mbmi, sub_txs, depth + 1, offsetr, offsetc,
                          w);
422
423
424
    }
  }
}
425

Yaowu Xu's avatar
Yaowu Xu committed
426
static void update_txfm_partition_probs(AV1_COMMON *cm, aom_writer *w,
427
                                        FRAME_COUNTS *counts, int probwt) {
428
429
  int k;
  for (k = 0; k < TXFM_PARTITION_CONTEXTS; ++k)
Yaowu Xu's avatar
Yaowu Xu committed
430
    av1_cond_prob_diff_update(w, &cm->fc->txfm_partition_prob[k],
431
                              counts->txfm_partition[k], probwt);
432
}
433
434
#endif

Yaowu Xu's avatar
Yaowu Xu committed
435
436
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
437
438
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
439
440
// For sub8x8 blocks the tx_size symbol does not need to be sent
#if CONFIG_CB4X4 && (CONFIG_VAR_TX || CONFIG_RECT_TX)
441
#if CONFIG_RECT_TX
442
  if (bsize > BLOCK_4X4) {
443
444
445
#else
  if (bsize >= BLOCK_8X8 || (bsize > BLOCK_4X4 && is_inter_block(mbmi))) {
#endif  // CONFIG_RECT_TX
446
#else
447
  if (bsize >= BLOCK_8X8) {
448
#endif
449
450
451
452
453
454
    const TX_SIZE tx_size = mbmi->tx_size;
    const int is_inter = is_inter_block(mbmi);
    const int tx_size_ctx = get_tx_size_context(xd);
    const int tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize]
                                     : intra_tx_size_cat_lookup[bsize];
    const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
455
    const int depth = tx_size_to_depth(coded_tx_size);
456
#if CONFIG_EXT_TX && CONFIG_RECT_TX
457
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
458
459
460
461
    assert(
        IMPLIES(is_rect_tx(tx_size), tx_size == max_txsize_rect_lookup[bsize]));
#endif  // CONFIG_EXT_TX && CONFIG_RECT_TX

462
463
464
465
#if CONFIG_EC_MULTISYMBOL
    aom_write_symbol(w, depth, cm->fc->tx_size_cdf[tx_size_cat][tx_size_ctx],
                     tx_size_cat + 2);
#else
Yaowu Xu's avatar
Yaowu Xu committed
466
467
    av1_write_token(w, av1_tx_size_tree[tx_size_cat],
                    cm->fc->tx_size_probs[tx_size_cat][tx_size_ctx],
468
                    &tx_size_encodings[tx_size_cat][depth]);
469
#endif
Jingning Han's avatar
Jingning Han committed
470
471
472
  }
}

473
#if CONFIG_REF_MV
Yaowu Xu's avatar
Yaowu Xu committed
474
static void update_inter_mode_probs(AV1_COMMON *cm, aom_writer *w,
475
476
                                    FRAME_COUNTS *counts) {
  int i;
477
478
479
480
481
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
482
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
483
484
    av1_cond_prob_diff_update(w, &cm->fc->newmv_prob[i], counts->newmv_mode[i],
                              probwt);
485
  for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
Yaowu Xu's avatar
Yaowu Xu committed
486
    av1_cond_prob_diff_update(w, &cm->fc->zeromv_prob[i],
487
                              counts->zeromv_mode[i], probwt);
488
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
489
490
    av1_cond_prob_diff_update(w, &cm->fc->refmv_prob[i], counts->refmv_mode[i],
                              probwt);
491
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
492
493
    av1_cond_prob_diff_update(w, &cm->fc->drl_prob[i], counts->drl_mode[i],
                              probwt);
Yue Chen's avatar
Yue Chen committed
494
#if CONFIG_EXT_INTER
495
496
  av1_cond_prob_diff_update(w, &cm->fc->new2mv_prob, counts->new2mv_mode,
                            probwt);
Yue Chen's avatar
Yue Chen committed
497
#endif  // CONFIG_EXT_INTER
498
499
500
}
#endif

501
#if CONFIG_EXT_INTER
502
503
static void update_inter_compound_mode_probs(AV1_COMMON *cm, int probwt,
                                             aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
504
505
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
506
507
508
509
  int i;
  int savings = 0;
  int do_update = 0;
  for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
510
    savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
511
        av1_inter_compound_mode_tree, cm->fc->inter_compound_mode_probs[i],
512
        cm->counts.inter_compound_mode[i], INTER_COMPOUND_MODES, probwt);
513
514
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
515
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
516
517
  if (do_update) {
    for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
518
      prob_diff_update(
Yaowu Xu's avatar
Yaowu Xu committed
519
          av1_inter_compound_mode_tree, cm->fc->inter_compound_mode_probs[i],
520
          cm->counts.inter_compound_mode[i], INTER_COMPOUND_MODES, probwt, w);
521
522
523
524
525
    }
  }
}
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
526
527
static int write_skip(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                      int segment_id, const MODE_INFO *mi, aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
528
529
530
531
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
Yaowu Xu's avatar
Yaowu Xu committed
532
    aom_write(w, skip, av1_get_skip_prob(cm, xd));
Jingning Han's avatar
Jingning Han committed
533
534
535
536
    return skip;
  }
}

Yue Chen's avatar
Yue Chen committed
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
static void write_motion_mode(const AV1_COMMON *cm, const MB_MODE_INFO *mbmi,
                              aom_writer *w) {
  MOTION_MODE last_motion_mode_allowed = motion_mode_allowed(mbmi);

  if (last_motion_mode_allowed == SIMPLE_TRANSLATION) return;
#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
  if (last_motion_mode_allowed == OBMC_CAUSAL) {
    aom_write(w, mbmi->motion_mode == OBMC_CAUSAL,
              cm->fc->obmc_prob[mbmi->sb_type]);
  } else {
#endif  // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
    av1_write_token(w, av1_motion_mode_tree,
                    cm->fc->motion_mode_prob[mbmi->sb_type],
                    &motion_mode_encodings[mbmi->motion_mode]);
#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
  }
#endif  // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
}
#endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION

558
#if CONFIG_DELTA_Q
559
560
static void write_delta_qindex(const AV1_COMMON *cm, int delta_qindex,
                               aom_writer *w) {
561
562
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  int rem_bits, thr, i = 0;
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;

  while (i < DELTA_Q_SMALL && i <= abs) {
    int bit = (i < abs);
    aom_write(w, bit, cm->fc->delta_q_prob[i]);
    i++;
  }

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
    aom_write_literal(w, rem_bits, 3);
    aom_write_literal(w, abs - thr, rem_bits);
577
578
579
580
581
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
582
583
584
585

static void update_delta_q_probs(AV1_COMMON *cm, aom_writer *w,
                                 FRAME_COUNTS *counts) {
  int k;
586
587
588
589
590
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
591
  for (k = 0; k < DELTA_Q_CONTEXTS; ++k) {
592
593
    av1_cond_prob_diff_update(w, &cm->fc->delta_q_prob[k], counts->delta_q[k],
                              probwt);
594
595
  }
}
596
597
#endif

Yaowu Xu's avatar
Yaowu Xu committed
598
static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
599
600
                              FRAME_COUNTS *counts) {
  int k;
601
602
603
604
605
606
607
608
609
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
  for (k = 0; k < SKIP_CONTEXTS; ++k) {
    av1_cond_prob_diff_update(w, &cm->fc->skip_probs[k], counts->skip[k],
                              probwt);
  }
Jingning Han's avatar
Jingning Han committed
610
611
}

612
#if !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
613
static void update_switchable_interp_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
614
615
                                           FRAME_COUNTS *counts) {
  int j;
616
  for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; ++j) {
617
618
619
620
621
622
623
624
#if CONFIG_TILE_GROUPS
    const int probwt = cm->num_tg;
#else
    const int probwt = 1;
#endif
    prob_diff_update(
        av1_switchable_interp_tree, cm->fc->switchable_interp_prob[j],
        counts->switchable_interp[j], SWITCHABLE_FILTERS, probwt, w);
625
  }
Jingning Han's avatar
Jingning Han committed
626
}
627
#endif
Jingning Han's avatar
Jingning Han committed
628

629
#if CONFIG_EXT_TX
Yaowu Xu's avatar
Yaowu Xu committed
630
631
632
static void update_ext_tx_probs(AV1_COMMON *cm, aom_writer *w) {
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
633
  int i, j;
634
  int s;
635
636
637
638
639
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
640
641
642
643
  for (s = 1; s < EXT_TX_SETS_INTER; ++s) {
    int savings = 0;
    int do_update = 0;
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
644
      if (!use_inter_ext_tx_for_txsize[s][i]) continue;
645
      savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
646
          av1_ext_tx_inter_tree[s], cm->fc->inter_ext_tx_prob[s][i],
647
          cm->counts.inter_ext_tx[s][i], num_ext_tx_set_inter[s], probwt);
648
649
    }
    do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
650
    aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
651
652
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
653
        if (!use_inter_ext_tx_for_txsize[s][i]) continue;
654
        prob_diff_update(
Yaowu Xu's avatar
Yaowu Xu committed
655
            av1_ext_tx_inter_tree[s], cm->fc->inter_ext_tx_prob[s][i],
656
            cm->counts.inter_ext_tx[s][i], num_ext_tx_set_inter[s], probwt, w);
657
      }
658
659
    }
  }
660

661
662
663
664
  for (s = 1; s < EXT_TX_SETS_INTRA; ++s) {
    int savings = 0;
    int do_update = 0;
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
665
      if (!use_intra_ext_tx_for_txsize[s][i]) continue;
666
      for (j = 0; j < INTRA_MODES; ++j)
667
        savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
668
            av1_ext_tx_intra_tree[s], cm->fc->intra_ext_tx_prob[s][i][j],
669
            cm->counts.intra_ext_tx[s][i][j], num_ext_tx_set_intra[s], probwt);
670
671
    }
    do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
672
    aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
673
674
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
675
        if (!use_intra_ext_tx_for_txsize[s][i]) continue;
676
        for (j = 0; j < INTRA_MODES; ++j)
677
678
679
680
          prob_diff_update(av1_ext_tx_intra_tree[s],
                           cm->fc->intra_ext_tx_prob[s][i][j],
                           cm->counts.intra_ext_tx[s][i][j],
                           num_ext_tx_set_intra[s], probwt, w);
681
682
      }
    }
683
  }
684
}
Debargha Mukherjee's avatar
Debargha Mukherjee committed
685

686
#else
687
#if !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
688
689
690
static void update_ext_tx_probs(AV1_COMMON *cm, aom_writer *w) {
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
691
692
693
694
  int i, j;

  int savings = 0;
  int do_update = 0;
695
696
697
698
699
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
700
701
702
  for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
    for (j = 0; j < TX_TYPES; ++j)
      savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
703
          av1_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
704
          cm->counts.intra_ext_tx[i][j], TX_TYPES, probwt);
705
706
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
707
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
708
709
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
710
      for (j = 0; j < TX_TYPES; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
711
        prob_diff_update(av1_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
712
                         cm->counts.intra_ext_tx[i][j], TX_TYPES, probwt, w);
713
      }
714
715
    }
  }
716

717
718
  savings = 0;
  for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
719
    savings +=
Yaowu Xu's avatar
Yaowu Xu committed
720
        prob_diff_update_savings(av1_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
721
                                 cm->counts.inter_ext_tx[i], TX_TYPES, probwt);
722
723
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
724
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
725
726
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
Yaowu Xu's avatar
Yaowu Xu committed
727
      prob_diff_update(av1_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
728
                       cm->counts.inter_ext_tx[i], TX_TYPES, probwt, w);
729
730
731
    }
  }
}
732
#endif  // CONFIG_EXT_TX
733
#endif
734
#if CONFIG_PALETTE
Yaowu Xu's avatar
Yaowu Xu committed
735
static void pack_palette_tokens(aom_writer *w, const TOKENEXTRA **tp, int n,
736
                                int num) {
hui su's avatar
hui su committed
737
  int i;
738
  const TOKENEXTRA *p = *tp;
hui su's avatar
hui su committed
739

740
  for (i = 0; i < num; ++i) {
741
742
    av1_write_token(w, av1_palette_color_index_tree[n - 2], p->context_tree,
                    &palette_color_index_encodings[n - 2][p->token]);
hui su's avatar
hui su committed
743
744
745
746
747
    ++p;
  }

  *tp = p;
}
748
#endif  // CONFIG_PALETTE
749
#if !CONFIG_PVQ
750
#if CONFIG_SUPERTX
751
static void update_supertx_probs(AV1_COMMON *cm, int probwt, aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
752
753
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
754
755
756
757
  int i, j;
  int savings = 0;
  int do_update = 0;
  for (i = 0; i < PARTITION_SUPERTX_CONTEXTS; ++i) {
Jingning Han's avatar
Jingning Han committed
758
    for (j = TX_8X8; j < TX_SIZES; ++j) {
759
760
      savings += av1_cond_prob_diff_update_savings(
          &cm->fc->supertx_prob[i][j], cm->counts.supertx[i][j], probwt);
761
762
763
    }
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
764
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
765
766
  if (do_update) {
    for (i = 0; i < PARTITION_SUPERTX_CONTEXTS; ++i) {
Jingning Han's avatar
Jingning Han committed
767
      for (j = TX_8X8; j < TX_SIZES; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
768
        av1_cond_prob_diff_update(w, &cm->fc->supertx_prob[i][j],
769
                                  cm->counts.supertx[i][j], probwt);
770
771
772
773
774
775
      }
    }
  }
}
#endif  // CONFIG_SUPERTX

776
#if CONFIG_NEW_TOKENSET
Yaowu Xu's avatar
Yaowu Xu committed
777
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
778
                           const TOKENEXTRA *const stop,
779
780
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
                           TOKEN_STATS *token_stats) {
781
  const TOKENEXTRA *p = *tp;
782
783
#if CONFIG_VAR_TX
  int count = 0;
784
  const int seg_eob = tx_size_2d[tx_size];
785
#endif
Alex Converse's avatar
Alex Converse committed
786
787
788
789
790
791
792
793
794
#if CONFIG_AOM_HIGHBITDEPTH
  const av1_extra_bit *const extra_bits_table =
      (bit_depth == AOM_BITS_12)
          ? av1_extra_bits_high12
          : (bit_depth == AOM_BITS_10) ? av1_extra_bits_high10 : av1_extra_bits;
#else
  const av1_extra_bit *const extra_bits_table = av1_extra_bits;
  (void)bit_depth;
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
795
796

  while (p < stop && p->token != EOSB_TOKEN) {
797
798
    const int token = p->token;
    aom_tree_index index = 0;
Alex Converse's avatar
Alex Converse committed
799
    const av1_extra_bit *const extra_bits = &extra_bits_table[token];
Jingning Han's avatar
Jingning Han committed
800

801
802
803
804
805
806
    if (token == BLOCK_Z_TOKEN) {
      aom_write_symbol(w, 0, *p->head_cdf, 6);
      p++;
      continue;
    }
    int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - p->is_eob + 1;
Alex Converse's avatar
Alex Converse committed
807

808
809
810
811
    aom_write_symbol(w, comb_symb, *p->head_cdf, 6);
    if (token > ONE_TOKEN) {
      aom_write_symbol(w, token - TWO_TOKEN, *p->tail_cdf,
                       CATEGORY6_TOKEN + 1 - 2);
Alex Converse's avatar
Alex Converse committed
812
    }
813
814
815
816

    if (extra_bits->base_val) {
      const int bit_string = p->extra;
      const int bit_string_length = extra_bits->len;  // Length of extra bits to
817
818
      // be written excluding
      // the sign bit.
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
      int skip_bits = (extra_bits->base_val == CAT6_MIN_VAL)
                          ? TX_SIZES - 1 - txsize_sqr_up_map[tx_size]
                          : 0;

      if (bit_string_length > 0) {
        const unsigned char *pb = extra_bits->prob;
        const int value = bit_string >> 1;
        const int num_bits = bit_string_length;  // number of bits in value
        assert(num_bits > 0);

        for (index = 0; index < num_bits; ++index) {
          const int shift = num_bits - index - 1;
          const int bb = (value >> shift) & 1;
          if (skip_bits) {
            --skip_bits;
            assert(!bb);
          } else {
            aom_write_record(w, bb, pb[index], token_stats);
          }
        }
      }

      aom_write_bit_record(w, bit_string & 1, token_stats);
    }
    ++p;

#if CONFIG_VAR_TX
    ++count;
    if (token == EOB_TOKEN || count == seg_eob) break;
#endif
  }

  *tp = p;
}
Alex Converse's avatar
Alex Converse committed
853
#else
854
855
856
857
858
859
860
861