bitstream.c 176 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_CLPF
27
#include "av1/common/clpf.h"
28
#endif
Yaowu Xu's avatar
Yaowu Xu committed
29
#if CONFIG_DERING
30
#include "av1/common/dering.h"
Yaowu Xu's avatar
Yaowu Xu committed
31
#endif  // CONFIG_DERING
32
33
34
35
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
#include "av1/common/entropymv.h"
#include "av1/common/mvref_common.h"
36
#include "av1/common/odintrin.h"
37
38
#include "av1/common/pred_common.h"
#include "av1/common/reconinter.h"
hui su's avatar
hui su committed
39
40
41
#if CONFIG_EXT_INTRA
#include "av1/common/reconintra.h"
#endif  // CONFIG_EXT_INTRA
42
43
#include "av1/common/seg_common.h"
#include "av1/common/tile_common.h"
Jingning Han's avatar
Jingning Han committed
44

Alex Converse's avatar
Alex Converse committed
45
#if CONFIG_ANS
Alex Converse's avatar
Alex Converse committed
46
#include "aom_dsp/buf_ans.h"
Alex Converse's avatar
Alex Converse committed
47
#endif  // CONFIG_ANS
48
49
50
51
52
53
54
#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"
55
56
57
#if CONFIG_PVQ
#include "av1/encoder/pvq_encoder.h"
#endif
Jingning Han's avatar
Jingning Han committed
58

59
60
static struct av1_token intra_mode_encodings[INTRA_MODES];
static struct av1_token switchable_interp_encodings[SWITCHABLE_FILTERS];
61
#if CONFIG_EXT_PARTITION_TYPES
Yaowu Xu's avatar
Yaowu Xu committed
62
static const struct av1_token ext_partition_encodings[EXT_PARTITION_TYPES] = {
63
64
65
  { 0, 1 },  { 4, 3 },  { 12, 4 }, { 7, 3 },
  { 10, 4 }, { 11, 4 }, { 26, 5 }, { 27, 5 }
};
66
#endif
67
static struct av1_token partition_encodings[PARTITION_TYPES];
68
#if !CONFIG_REF_MV
69
static struct av1_token inter_mode_encodings[INTER_MODES];
70
#endif
71
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
72
static const struct av1_token
73
74
75
76
    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 }
    };
77
#endif  // CONFIG_EXT_INTER
78
#if CONFIG_PALETTE
79
static struct av1_token palette_size_encodings[PALETTE_MAX_SIZE - 1];
80
81
static struct av1_token palette_color_index_encodings[PALETTE_MAX_SIZE - 1]
                                                     [PALETTE_MAX_SIZE];
82
#endif  // CONFIG_PALETTE
Jingning Han's avatar
Jingning Han committed
83
static const struct av1_token tx_size_encodings[MAX_TX_DEPTH][TX_SIZES] = {
84
85
86
  { { 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
87
88
89
#if CONFIG_TX64X64
  { { 0, 1 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 15, 4 } },  // Max tx_size 64X64
#endif                                                     // CONFIG_TX64X64
90
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
}

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

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

Yaowu Xu's avatar
Yaowu Xu committed
350
  av1_tree_probs_from_distribution(tree, branch_ct, counts);
Jingning Han's avatar
Jingning Han committed
351
  for (i = 0; i < n - 1; ++i)
352
    av1_cond_prob_diff_update(w, &probs[i], branch_ct[i], probwt);
Jingning Han's avatar
Jingning Han committed
353
}
354
#if CONFIG_EXT_INTER || CONFIG_EXT_TX || !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
355
356
static int prob_diff_update_savings(const aom_tree_index *tree,
                                    aom_prob probs[/*n - 1*/],
357
358
                                    const unsigned int counts[/*n - 1*/], int n,
                                    int probwt) {
359
360
361
362
363
364
  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
365
  av1_tree_probs_from_distribution(tree, branch_ct, counts);
366
  for (i = 0; i < n - 1; ++i) {
367
368
    savings +=
        av1_cond_prob_diff_update_savings(&probs[i], branch_ct[i], probwt);
369
370
371
  }
  return savings;
}
372
#endif  // CONFIG_EXT_INTER || CONFIG_EXT_TX || !CONFIG_EC_ADAPT
373

374
#if CONFIG_VAR_TX
Yaowu Xu's avatar
Yaowu Xu committed
375
static void write_tx_size_vartx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
376
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
377
378
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
379
380
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
381
382
383
  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);

384
  int ctx = txfm_partition_context(xd->above_txfm_context + tx_col,
385
386
                                   xd->left_txfm_context + tx_row,
                                   mbmi->sb_type, tx_size);
387

388
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
389

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

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

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

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

    assert(bsl > 0);
    for (i = 0; i < 4; ++i) {
415
416
417
418
      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);
419
420
421
    }
  }
}
422

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

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

Yaowu Xu's avatar
Yaowu Xu committed
459
460
    av1_write_token(w, av1_tx_size_tree[tx_size_cat],
                    cm->fc->tx_size_probs[tx_size_cat][tx_size_ctx],
461
                    &tx_size_encodings[tx_size_cat][depth]);
Jingning Han's avatar
Jingning Han committed
462
463
464
  }
}

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

493
#if CONFIG_EXT_INTER
494
495
static void update_inter_compound_mode_probs(AV1_COMMON *cm, int probwt,
                                             aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
496
497
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
498
499
500
501
  int i;
  int savings = 0;
  int do_update = 0;
  for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
502
    savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
503
        av1_inter_compound_mode_tree, cm->fc->inter_compound_mode_probs[i],
504
        cm->counts.inter_compound_mode[i], INTER_COMPOUND_MODES, probwt);
505
506
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
507
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
508
509
  if (do_update) {
    for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
510
      prob_diff_update(
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, w);
513
514
515
516
517
    }
  }
}
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
518
519
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
520
521
522
523
  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
524
    aom_write(w, skip, av1_get_skip_prob(cm, xd));
Jingning Han's avatar
Jingning Han committed
525
526
527
528
    return skip;
  }
}

Yue Chen's avatar
Yue Chen committed
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
#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

550
#if CONFIG_DELTA_Q
551
552
static void write_delta_qindex(const AV1_COMMON *cm, int delta_qindex,
                               aom_writer *w) {
553
554
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
555
556
557
558
559
560
561
562
563
564
565
566
567
568
  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);
569
570
571
572
573
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
574
575
576
577

static void update_delta_q_probs(AV1_COMMON *cm, aom_writer *w,
                                 FRAME_COUNTS *counts) {
  int k;
578
579
580
581
582
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
583
  for (k = 0; k < DELTA_Q_CONTEXTS; ++k) {
584
585
    av1_cond_prob_diff_update(w, &cm->fc->delta_q_prob[k], counts->delta_q[k],
                              probwt);
586
587
  }
}
588
589
#endif

Yaowu Xu's avatar
Yaowu Xu committed
590
static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
591
592
                              FRAME_COUNTS *counts) {
  int k;
593
594
595
596
597
598
599
600
601
#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
602
603
}

604
#if !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
605
static void update_switchable_interp_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
606
607
                                           FRAME_COUNTS *counts) {
  int j;
608
  for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; ++j) {
609
610
611
612
613
614
615
616
#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);
617
  }
Jingning Han's avatar
Jingning Han committed
618
}
619
#endif
Jingning Han's avatar
Jingning Han committed
620

621
#if CONFIG_EXT_TX
Yaowu Xu's avatar
Yaowu Xu committed
622
623
624
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);
625
  int i, j;
626
  int s;
627
628
629
630
631
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
632
633
634
635
  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) {
636
      if (!use_inter_ext_tx_for_txsize[s][i]) continue;
637
      savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
638
          av1_ext_tx_inter_tree[s], cm->fc->inter_ext_tx_prob[s][i],
639
          cm->counts.inter_ext_tx[s][i], num_ext_tx_set_inter[s], probwt);
640
641
    }
    do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
642
    aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
643
644
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
645
        if (!use_inter_ext_tx_for_txsize[s][i]) continue;
646
        prob_diff_update(
Yaowu Xu's avatar
Yaowu Xu committed
647
            av1_ext_tx_inter_tree[s], cm->fc->inter_ext_tx_prob[s][i],
648
            cm->counts.inter_ext_tx[s][i], num_ext_tx_set_inter[s], probwt, w);
649
      }
650
651
    }
  }
652

653
654
655
656
  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) {
657
      if (!use_intra_ext_tx_for_txsize[s][i]) continue;
658
      for (j = 0; j < INTRA_MODES; ++j)
659
        savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
660
            av1_ext_tx_intra_tree[s], cm->fc->intra_ext_tx_prob[s][i][j],
661
            cm->counts.intra_ext_tx[s][i][j], num_ext_tx_set_intra[s], probwt);
662
663
    }
    do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
664
    aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
665
666
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
667
        if (!use_intra_ext_tx_for_txsize[s][i]) continue;
668
        for (j = 0; j < INTRA_MODES; ++j)
669
670
671
672
          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);
673
674
      }
    }
675
  }
676
}
Debargha Mukherjee's avatar
Debargha Mukherjee committed
677

678
#else
679
#if !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
680
681
682
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);
683
684
685
686
  int i, j;

  int savings = 0;
  int do_update = 0;
687
688
689
690
691
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
692
693
694
  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
695
          av1_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
696
          cm->counts.intra_ext_tx[i][j], TX_TYPES, probwt);
697
698
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
699
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
700
701
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
702
      for (j = 0; j < TX_TYPES; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
703
        prob_diff_update(av1_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
704
                         cm->counts.intra_ext_tx[i][j], TX_TYPES, probwt, w);
705
      }
706
707
    }
  }
708

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

732
  for (i = 0; i < num; ++i) {
733
734
    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
735
736
737
738
739
    ++p;
  }

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

768
#if CONFIG_NEW_TOKENSET
Yaowu Xu's avatar
Yaowu Xu committed
769
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
770
                           const TOKENEXTRA *const stop,
771
772
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
                           TOKEN_STATS *token_stats) {
773
  const TOKENEXTRA *p = *tp;
774
775
#if CONFIG_VAR_TX
  int count = 0;
776
  const int seg_eob = tx_size_2d[tx_size];
777
#endif
Alex Converse's avatar
Alex Converse committed
778
779
780
781
782
783
784
785
786
#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
787
788

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

793
794
795
796
797
798
    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
799

800
801
802
803
    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
804
    }
805
806
807
808

    if (extra_bits->base_val) {
      const int bit_string = p->extra;
      const int bit_string_length = extra_bits->len;  // Length of extra bits to
809
810
      // be written excluding
      // the sign bit.
811
812
813
814
815
816
817
818
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
      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
845
#else
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861