bitstream.c 178 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
#include "aom_dsp/aom_dsp_common.h"
19
#include "aom_dsp/binary_codes_writer.h"
Yaowu Xu's avatar
Yaowu Xu committed
20
#include "aom_mem/aom_mem.h"
21 22
#include "aom_ports/mem_ops.h"
#include "aom_ports/system_state.h"
23
#if CONFIG_BITSTREAM_DEBUG
24
#include "aom_util/debug_util.h"
25
#endif  // CONFIG_BITSTREAM_DEBUG
Jingning Han's avatar
Jingning Han committed
26

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

Alex Converse's avatar
Alex Converse committed
44
#if CONFIG_ANS
Alex Converse's avatar
Alex Converse committed
45
#include "aom_dsp/buf_ans.h"
Alex Converse's avatar
Alex Converse committed
46
#endif  // CONFIG_ANS
Angie Chiang's avatar
Angie Chiang committed
47 48 49
#if CONFIG_LV_MAP
#include "av1/encoder/encodetxb.h"
#endif  // CONFIG_LV_MAP
50 51 52 53
#include "av1/encoder/bitstream.h"
#include "av1/encoder/cost.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/mcomp.h"
hui su's avatar
hui su committed
54 55 56
#if CONFIG_PALETTE && CONFIG_PALETTE_DELTA_ENCODING
#include "av1/encoder/palette.h"
#endif  // CONFIG_PALETTE && CONFIG_PALETTE_DELTA_ENCODING
57 58 59
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
60 61 62
#if CONFIG_PVQ
#include "av1/encoder/pvq_encoder.h"
#endif
Jingning Han's avatar
Jingning Han committed
63

64 65 66
static struct av1_token intra_mode_encodings[INTRA_MODES];
static struct av1_token switchable_interp_encodings[SWITCHABLE_FILTERS];
static struct av1_token partition_encodings[PARTITION_TYPES];
67
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
68
static const struct av1_token
69
    inter_compound_mode_encodings[INTER_COMPOUND_MODES] = {
70 71
      { 2, 2 },  { 12, 4 }, { 52, 6 }, { 53, 6 },
      { 54, 6 }, { 55, 6 }, { 0, 1 },  { 7, 3 }
72
    };
73
#endif  // CONFIG_EXT_INTER
74
#if CONFIG_PALETTE
75 76 77
static struct av1_token palette_size_encodings[PALETTE_SIZES];
static struct av1_token palette_color_index_encodings[PALETTE_SIZES]
                                                     [PALETTE_COLORS];
78
#endif  // CONFIG_PALETTE
79

80
#if CONFIG_EXT_INTRA || CONFIG_FILTER_INTRA || CONFIG_PALETTE
Yaowu Xu's avatar
Yaowu Xu committed
81
static INLINE void write_uniform(aom_writer *w, int n, int v) {
82 83
  const int l = get_unsigned_bits(n);
  const int m = (1 << l) - n;
84
  if (l == 0) return;
hui su's avatar
hui su committed
85
  if (v < m) {
Yaowu Xu's avatar
Yaowu Xu committed
86
    aom_write_literal(w, v, l - 1);
hui su's avatar
hui su committed
87
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
88 89
    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
90 91
  }
}
92
#endif  // CONFIG_EXT_INTRA || CONFIG_FILTER_INTRA || CONFIG_PALETTE
Jingning Han's avatar
Jingning Han committed
93

94
#if CONFIG_EXT_TX
Yaowu Xu's avatar
Yaowu Xu committed
95 96
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];
97
#else
Yaowu Xu's avatar
Yaowu Xu committed
98
static struct av1_token ext_tx_encodings[TX_TYPES];
99
#endif  // CONFIG_EXT_TX
100
#if CONFIG_GLOBAL_MOTION
101
static struct av1_token global_motion_types_encodings[GLOBAL_TRANS_TYPES];
102
#endif  // CONFIG_GLOBAL_MOTION
103
#if CONFIG_EXT_INTRA
hui su's avatar
hui su committed
104
#if CONFIG_INTRA_INTERP
Yaowu Xu's avatar
Yaowu Xu committed
105
static struct av1_token intra_filter_encodings[INTRA_FILTERS];
hui su's avatar
hui su committed
106
#endif  // CONFIG_INTRA_INTERP
107
#endif  // CONFIG_EXT_INTRA
108
#if CONFIG_EXT_INTER
109
#if CONFIG_INTERINTRA
Yaowu Xu's avatar
Yaowu Xu committed
110
static struct av1_token interintra_mode_encodings[INTERINTRA_MODES];
111
#endif
112
#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
113
static struct av1_token compound_type_encodings[COMPOUND_TYPES];
114
#endif  // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
115
#endif  // CONFIG_EXT_INTER
Yue Chen's avatar
Yue Chen committed
116 117 118
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
static struct av1_token motion_mode_encodings[MOTION_MODES];
#endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
119 120 121
#if CONFIG_LOOP_RESTORATION
static struct av1_token switchable_restore_encodings[RESTORE_SWITCHABLE_TYPES];
#endif  // CONFIG_LOOP_RESTORATION
122 123 124
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);
125 126 127 128 129
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);
130

Yaowu Xu's avatar
Yaowu Xu committed
131
void av1_encode_token_init(void) {
132
#if CONFIG_EXT_TX || CONFIG_PALETTE
133
  int s;
134 135
#endif  // CONFIG_EXT_TX || CONFIG_PALETTE
#if CONFIG_EXT_TX
136
  for (s = 1; s < EXT_TX_SETS_INTER; ++s) {
Yaowu Xu's avatar
Yaowu Xu committed
137
    av1_tokens_from_tree(ext_tx_inter_encodings[s], av1_ext_tx_inter_tree[s]);
138 139
  }
  for (s = 1; s < EXT_TX_SETS_INTRA; ++s) {
Yaowu Xu's avatar
Yaowu Xu committed
140
    av1_tokens_from_tree(ext_tx_intra_encodings[s], av1_ext_tx_intra_tree[s]);
141
  }
142
#else
Yaowu Xu's avatar
Yaowu Xu committed
143
  av1_tokens_from_tree(ext_tx_encodings, av1_ext_tx_tree);
144
#endif  // CONFIG_EXT_TX
145 146 147 148
  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);

149 150
#if CONFIG_PALETTE
  av1_tokens_from_tree(palette_size_encodings, av1_palette_size_tree);
151
  for (s = 0; s < PALETTE_SIZES; ++s) {
152 153
    av1_tokens_from_tree(palette_color_index_encodings[s],
                         av1_palette_color_index_tree[s]);
154 155 156
  }
#endif  // CONFIG_PALETTE

157
#if CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP
Yaowu Xu's avatar
Yaowu Xu committed
158
  av1_tokens_from_tree(intra_filter_encodings, av1_intra_filter_tree);
159
#endif  // CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP
160
#if CONFIG_EXT_INTER
161
#if CONFIG_INTERINTRA
Yaowu Xu's avatar
Yaowu Xu committed
162
  av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree);
163
#endif  // CONFIG_INTERINTRA
164
#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
165
  av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree);
166
#endif  // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
167
#endif  // CONFIG_EXT_INTER
Yue Chen's avatar
Yue Chen committed
168 169 170
#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
171
#if CONFIG_GLOBAL_MOTION
Yaowu Xu's avatar
Yaowu Xu committed
172 173
  av1_tokens_from_tree(global_motion_types_encodings,
                       av1_global_motion_types_tree);
174
#endif  // CONFIG_GLOBAL_MOTION
175 176 177 178
#if CONFIG_LOOP_RESTORATION
  av1_tokens_from_tree(switchable_restore_encodings,
                       av1_switchable_restore_tree);
#endif  // CONFIG_LOOP_RESTORATION
179

180
  /* This hack is necessary when CONFIG_DUAL_FILTER is enabled because the five
181 182 183
      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,
Jingning Han's avatar
Jingning Han committed
184
                        av1_switchable_interp_tree);
185 186 187
/* 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. */
188 189 190
#if CONFIG_EXT_TX
  for (s = 1; s < EXT_TX_SETS_INTRA; ++s)
    av1_indices_from_tree(av1_ext_tx_intra_ind[s], av1_ext_tx_intra_inv[s],
Jingning Han's avatar
Jingning Han committed
191
                          av1_ext_tx_intra_tree[s]);
192 193
  for (s = 1; s < EXT_TX_SETS_INTER; ++s)
    av1_indices_from_tree(av1_ext_tx_inter_ind[s], av1_ext_tx_inter_inv[s],
Jingning Han's avatar
Jingning Han committed
194
                          av1_ext_tx_inter_tree[s]);
195
#else
Jingning Han's avatar
Jingning Han committed
196
  av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, av1_ext_tx_tree);
David Barker's avatar
David Barker committed
197
#endif
Jingning Han's avatar
Jingning Han committed
198
  av1_indices_from_tree(av1_intra_mode_ind, av1_intra_mode_inv,
199
                        av1_intra_mode_tree);
Jingning Han's avatar
Jingning Han committed
200
  av1_indices_from_tree(av1_inter_mode_ind, av1_inter_mode_inv,
201
                        av1_inter_mode_tree);
202 203
}

Jingning Han's avatar
Jingning Han committed
204 205 206 207
static void write_intra_mode_kf(const AV1_COMMON *cm, FRAME_CONTEXT *frame_ctx,
                                const MODE_INFO *mi, const MODE_INFO *above_mi,
                                const MODE_INFO *left_mi, int block,
                                PREDICTION_MODE mode, aom_writer *w) {
Alex Converse's avatar
Alex Converse committed
208 209 210
#if CONFIG_INTRABC
  assert(!is_intrabc_block(&mi->mbmi));
#endif  // CONFIG_INTRABC
Jingning Han's avatar
Jingning Han committed
211 212 213 214 215
  aom_write_symbol(w, av1_intra_mode_ind[mode],
                   get_y_mode_cdf(frame_ctx, mi, above_mi, left_mi, block),
                   INTRA_MODES);
  (void)cm;
}
Jingning Han's avatar
Jingning Han committed
216

217
#if CONFIG_EXT_INTER && CONFIG_INTERINTRA
Yaowu Xu's avatar
Yaowu Xu committed
218 219 220 221
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]);
222
}
223
#endif  // CONFIG_EXT_INTER && CONFIG_INTERINTRA
224

225
static void write_inter_mode(aom_writer *w, PREDICTION_MODE mode,
226
                             FRAME_CONTEXT *ec_ctx, const int16_t mode_ctx) {
227
  const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
228
  const aom_prob newmv_prob = ec_ctx->newmv_prob[newmv_ctx];
Yue Chen's avatar
Yue Chen committed
229

Jingning Han's avatar
Jingning Han committed
230
  aom_write(w, mode != NEWMV, newmv_prob);
231

Jingning Han's avatar
Jingning Han committed
232
  if (mode != NEWMV) {
233
    const int16_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
234
    const aom_prob zeromv_prob = ec_ctx->zeromv_prob[zeromv_ctx];
235 236 237 238 239 240

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

Yaowu Xu's avatar
Yaowu Xu committed
241
    aom_write(w, mode != ZEROMV, zeromv_prob);
242 243

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

247 248 249
      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;
250

251
      refmv_prob = ec_ctx->refmv_prob[refmv_ctx];
Yaowu Xu's avatar
Yaowu Xu committed
252
      aom_write(w, mode != NEARESTMV, refmv_prob);
253 254
    }
  }
Jingning Han's avatar
Jingning Han committed
255 256
}

Yaowu Xu's avatar
Yaowu Xu committed
257 258 259
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);
260 261 262

  assert(mbmi->ref_mv_idx < 3);

263 264 265
#if CONFIG_EXT_INTER
  if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
#else
266
  if (mbmi->mode == NEWMV) {
267
#endif
268 269 270 271
    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
272 273
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
        aom_prob drl_prob = cm->fc->drl_prob[drl_ctx];
274

Yaowu Xu's avatar
Yaowu Xu committed
275
        aom_write(w, mbmi->ref_mv_idx != idx, drl_prob);
276
        if (mbmi->ref_mv_idx == idx) return;
277
      }
278 279 280 281
    }
    return;
  }

David Barker's avatar
David Barker committed
282
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
283 284 285 286 287
    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
288 289
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
        aom_prob drl_prob = cm->fc->drl_prob[drl_ctx];
290

Yaowu Xu's avatar
Yaowu Xu committed
291
        aom_write(w, mbmi->ref_mv_idx != (idx - 1), drl_prob);
292
        if (mbmi->ref_mv_idx == (idx - 1)) return;
293
      }
294
    }
295
    return;
296 297 298
  }
}

299
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
300
static void write_inter_compound_mode(AV1_COMMON *cm, aom_writer *w,
301 302
                                      PREDICTION_MODE mode,
                                      const int16_t mode_ctx) {
Yaowu Xu's avatar
Yaowu Xu committed
303
  const aom_prob *const inter_compound_probs =
304
      cm->fc->inter_compound_mode_probs[mode_ctx];
305 306

  assert(is_inter_compound_mode(mode));
Yaowu Xu's avatar
Yaowu Xu committed
307 308
  av1_write_token(w, av1_inter_compound_mode_tree, inter_compound_probs,
                  &inter_compound_mode_encodings[INTER_COMPOUND_OFFSET(mode)]);
309 310 311
}
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
312
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
313
                                int max) {
Yaowu Xu's avatar
Yaowu Xu committed
314
  aom_wb_write_literal(wb, data, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
315 316
}

317 318
#if !CONFIG_EC_ADAPT || \
    (CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION || CONFIG_EXT_INTER)
Yaowu Xu's avatar
Yaowu Xu committed
319 320
static void prob_diff_update(const aom_tree_index *tree,
                             aom_prob probs[/*n - 1*/],
321
                             const unsigned int counts[/*n - 1*/], int n,
322
                             int probwt, aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
323 324 325 326 327 328
  int i;
  unsigned int branch_ct[32][2];

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

Yaowu Xu's avatar
Yaowu Xu committed
329
  av1_tree_probs_from_distribution(tree, branch_ct, counts);
Jingning Han's avatar
Jingning Han committed
330
  for (i = 0; i < n - 1; ++i)
331
    av1_cond_prob_diff_update(w, &probs[i], branch_ct[i], probwt);
Jingning Han's avatar
Jingning Han committed
332
}
333 334
#endif

335
#if CONFIG_EXT_INTER || !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
336 337
static int prob_diff_update_savings(const aom_tree_index *tree,
                                    aom_prob probs[/*n - 1*/],
338 339
                                    const unsigned int counts[/*n - 1*/], int n,
                                    int probwt) {
340 341 342 343 344 345
  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
346
  av1_tree_probs_from_distribution(tree, branch_ct, counts);
347
  for (i = 0; i < n - 1; ++i) {
348 349
    savings +=
        av1_cond_prob_diff_update_savings(&probs[i], branch_ct[i], probwt);
350 351 352
  }
  return savings;
}
353
#endif  // CONFIG_EXT_INTER || !CONFIG_EC_ADAPT
354

355
#if CONFIG_VAR_TX
Yaowu Xu's avatar
Yaowu Xu committed
356
static void write_tx_size_vartx(const AV1_COMMON *cm, const MACROBLOCKD *xd,
357
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
358 359
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
360 361
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
362 363 364
  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);

365
  int ctx = txfm_partition_context(xd->above_txfm_context + tx_col,
366 367
                                   xd->left_txfm_context + tx_row,
                                   mbmi->sb_type, tx_size);
368

369
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
370

Jingning Han's avatar
Jingning Han committed
371
  if (depth == MAX_VARTX_DEPTH) {
372
    txfm_partition_update(xd->above_txfm_context + tx_col,
373
                          xd->left_txfm_context + tx_row, tx_size, tx_size);
374 375 376
    return;
  }

377
  if (tx_size == mbmi->inter_tx_size[tx_row][tx_col]) {
Yaowu Xu's avatar
Yaowu Xu committed
378
    aom_write(w, 0, cm->fc->txfm_partition_prob[ctx]);
379
    txfm_partition_update(xd->above_txfm_context + tx_col,
380
                          xd->left_txfm_context + tx_row, tx_size, tx_size);
381
  } else {
382 383
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    const int bsl = tx_size_wide_unit[sub_txs];
384
    int i;
385

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

388
    if (tx_size == TX_8X8) {
389
      txfm_partition_update(xd->above_txfm_context + tx_col,
390
                            xd->left_txfm_context + tx_row, sub_txs, tx_size);
391
      return;
392
    }
393 394 395

    assert(bsl > 0);
    for (i = 0; i < 4; ++i) {
396 397 398 399
      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);
400 401 402
    }
  }
}
403

Yaowu Xu's avatar
Yaowu Xu committed
404
static void update_txfm_partition_probs(AV1_COMMON *cm, aom_writer *w,
405
                                        FRAME_COUNTS *counts, int probwt) {
406 407
  int k;
  for (k = 0; k < TXFM_PARTITION_CONTEXTS; ++k)
Yaowu Xu's avatar
Yaowu Xu committed
408
    av1_cond_prob_diff_update(w, &cm->fc->txfm_partition_prob[k],
409
                              counts->txfm_partition[k], probwt);
410
}
411 412
#endif

Yaowu Xu's avatar
Yaowu Xu committed
413 414
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
415 416
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
417 418 419 420 421 422
#if CONFIG_EC_ADAPT
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
#else
  FRAME_CONTEXT *ec_ctx = cm->fc;
#endif
423
// For sub8x8 blocks the tx_size symbol does not need to be sent
424
#if CONFIG_CB4X4 && (CONFIG_VAR_TX || CONFIG_EXT_TX) && CONFIG_RECT_TX
425 426
  if (bsize > BLOCK_4X4) {
#else
427
  if (bsize >= BLOCK_8X8) {
428
#endif
429 430 431 432 433 434
    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];
435
    const int depth = tx_size_to_depth(coded_tx_size);
436
#if CONFIG_EXT_TX && CONFIG_RECT_TX
437
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
438 439
#endif  // CONFIG_EXT_TX && CONFIG_RECT_TX

440
    aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx],
441
                     tx_size_cat + 2);
442 443 444 445 446
#if CONFIG_EXT_TX && CONFIG_RECT_TX && CONFIG_RECT_TX_EXT
    if (is_quarter_tx_allowed(xd, mbmi, is_inter) && tx_size != coded_tx_size)
      aom_write(w, tx_size == quarter_txsize_lookup[bsize],
                cm->fc->quarter_tx_size_prob);
#endif  // CONFIG_EXT_TX && CONFIG_RECT_TX && CONFIG_RECT_TX_EXT
Jingning Han's avatar
Jingning Han committed
447 448 449
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
450
static void update_inter_mode_probs(AV1_COMMON *cm, aom_writer *w,
451 452
                                    FRAME_COUNTS *counts) {
  int i;
453 454 455 456 457
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
458
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
459 460
    av1_cond_prob_diff_update(w, &cm->fc->newmv_prob[i], counts->newmv_mode[i],
                              probwt);
461
  for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
Yaowu Xu's avatar
Yaowu Xu committed
462
    av1_cond_prob_diff_update(w, &cm->fc->zeromv_prob[i],
463
                              counts->zeromv_mode[i], probwt);
464
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
465 466
    av1_cond_prob_diff_update(w, &cm->fc->refmv_prob[i], counts->refmv_mode[i],
                              probwt);
467
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
468 469
    av1_cond_prob_diff_update(w, &cm->fc->drl_prob[i], counts->drl_mode[i],
                              probwt);
470 471
}

472
#if CONFIG_EXT_INTER
473 474
static void update_inter_compound_mode_probs(AV1_COMMON *cm, int probwt,
                                             aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
475 476
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
477 478 479 480
  int i;
  int savings = 0;
  int do_update = 0;
  for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
481
    savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
482
        av1_inter_compound_mode_tree, cm->fc->inter_compound_mode_probs[i],
483
        cm->counts.inter_compound_mode[i], INTER_COMPOUND_MODES, probwt);
484 485
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
486
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
487 488
  if (do_update) {
    for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
489
      prob_diff_update(
Yaowu Xu's avatar
Yaowu Xu committed
490
          av1_inter_compound_mode_tree, cm->fc->inter_compound_mode_probs[i],
491
          cm->counts.inter_compound_mode[i], INTER_COMPOUND_MODES, probwt, w);
492 493 494 495 496
    }
  }
}
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
497 498
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
499 500 501 502
  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
503
    aom_write(w, skip, av1_get_skip_prob(cm, xd));
Jingning Han's avatar
Jingning Han committed
504 505 506 507
    return skip;
  }
}

Yue Chen's avatar
Yue Chen committed
508
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
509
static void write_motion_mode(const AV1_COMMON *cm, const MODE_INFO *mi,
Yue Chen's avatar
Yue Chen committed
510
                              aom_writer *w) {
511 512 513 514 515 516
  const MB_MODE_INFO *mbmi = &mi->mbmi;
  MOTION_MODE last_motion_mode_allowed = motion_mode_allowed(
#if CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
      0, cm->global_motion,
#endif  // CONFIG_GLOBAL_MOTION && SEPARATE_GLOBAL_MOTION
      mi);
Yue Chen's avatar
Yue Chen committed
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533

  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

534
#if CONFIG_DELTA_Q
Thomas Davies's avatar
Thomas Davies committed
535 536
static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               int delta_qindex, aom_writer *w) {
537 538
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
Thomas Davies's avatar
Thomas Davies committed
539
  int rem_bits, thr;
540
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
Thomas Davies's avatar
Thomas Davies committed
541 542 543 544 545 546 547
#if CONFIG_EC_ADAPT
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
#else
  FRAME_CONTEXT *ec_ctx = cm->fc;
  (void)xd;
#endif
548

Thomas Davies's avatar
Thomas Davies committed
549 550
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
551 552 553 554 555 556

  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);
557 558 559 560 561
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
562

Thomas Davies's avatar
Thomas Davies committed
563
#if !CONFIG_EC_ADAPT
564 565 566
static void update_delta_q_probs(AV1_COMMON *cm, aom_writer *w,
                                 FRAME_COUNTS *counts) {
  int k;
567 568 569 570 571
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
Fangwen Fu's avatar
Fangwen Fu committed
572 573 574
#if CONFIG_EXT_DELTA_Q
  if (!cm->delta_q_present_flag) return;
#endif  // CONFIG_EXT_DELTA_Q
575
  for (k = 0; k < DELTA_Q_PROBS; ++k) {
576 577
    av1_cond_prob_diff_update(w, &cm->fc->delta_q_prob[k], counts->delta_q[k],
                              probwt);
578 579
  }
}
Thomas Davies's avatar
Thomas Davies committed
580
#endif  // CONFIG_EC_ADAPT
Fangwen Fu's avatar
Fangwen Fu committed
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627

#if CONFIG_EXT_DELTA_Q
static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                int delta_lflevel, aom_writer *w) {
  int sign = delta_lflevel < 0;
  int abs = sign ? -delta_lflevel : delta_lflevel;
  int rem_bits, thr;
  int smallval = abs < DELTA_LF_SMALL ? 1 : 0;
#if CONFIG_EC_ADAPT
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
#else
  FRAME_CONTEXT *ec_ctx = cm->fc;
  (void)xd;
#endif

  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);

  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);
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}

#if !CONFIG_EC_ADAPT
static void update_delta_lf_probs(AV1_COMMON *cm, aom_writer *w,
                                  FRAME_COUNTS *counts) {
  int k;
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
  if (!cm->delta_lf_present_flag) return;
  for (k = 0; k < DELTA_LF_PROBS; ++k) {
    av1_cond_prob_diff_update(w, &cm->fc->delta_lf_prob[k], counts->delta_lf[k],
                              probwt);
  }
}
#endif  // CONFIG_EC_ADAPT
#endif  // CONFIG_EXT_DELTA_Q
Thomas Davies's avatar
Thomas Davies committed
628
#endif  // CONFIG_DELTA_Q
629

Yaowu Xu's avatar
Yaowu Xu committed
630
static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
631 632
                              FRAME_COUNTS *counts) {
  int k;
633 634 635 636 637 638 639 640 641
#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
642 643
}

644
#if !CONFIG_EC_ADAPT
Yaowu Xu's avatar
Yaowu Xu committed
645
static void update_switchable_interp_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
646 647
                                           FRAME_COUNTS *counts) {
  int j;
648
  for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; ++j) {
649 650 651 652 653 654 655 656
#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);
657
  }
Jingning Han's avatar
Jingning Han committed
658
}
659
#endif
Jingning Han's avatar
Jingning Han committed
660

661
#if !CONFIG_EC_ADAPT
662
#if CONFIG_EXT_TX
Yaowu Xu's avatar
Yaowu Xu committed
663 664 665
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);
666
  int i, j;
667
  int s;
668 669 670 671 672
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
673 674 675 676
  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) {
677
      if (!use_inter_ext_tx_for_txsize[s][i]) continue;
678
      savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
679
          av1_ext_tx_inter_tree[s], cm->fc->inter_ext_tx_prob[s][i],
680 681
          cm->counts.inter_ext_tx[s][i],
          num_ext_tx_set[ext_tx_set_type_inter[s]], probwt);
682 683
    }
    do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
684
    aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
685 686
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
687
        if (!use_inter_ext_tx_for_txsize[s][i]) continue;
688 689 690 691
        prob_diff_update(av1_ext_tx_inter_tree[s],
                         cm->fc->inter_ext_tx_prob[s][i],
                         cm->counts.inter_ext_tx[s][i],
                         num_ext_tx_set[ext_tx_set_type_inter[s]], probwt, w);
692
      }
693 694
    }
  }
695

696 697 698 699
  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) {
700
      if (!use_intra_ext_tx_for_txsize[s][i]) continue;
701
      for (j = 0; j < INTRA_MODES; ++j)
702
        savings += prob_diff_update_savings(
Yaowu Xu's avatar
Yaowu Xu committed
703
            av1_ext_tx_intra_tree[s], cm->fc->intra_ext_tx_prob[s][i][j],
704 705
            cm->counts.intra_ext_tx[s][i][j],
            num_ext_tx_set[ext_tx_set_type_intra[s]], probwt);
706 707
    }
    do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
708
    aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
709 710
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
711
        if (!use_intra_ext_tx_for_txsize[s][i]) continue;
712
        for (j = 0; j < INTRA_MODES; ++j)
713 714 715
          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],
716
                           num_ext_tx_set[ext_tx_set_type_intra[s]], probwt, w);
717 718
      }
    }
719
  }
720
}
Debargha Mukherjee's avatar
Debargha Mukherjee committed
721

722
#else
Yaowu Xu's avatar
Yaowu Xu committed
723 724 725
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);
726 727 728 729
  int i, j;

  int savings = 0;
  int do_update = 0;
730 731 732 733 734
#if CONFIG_TILE_GROUPS
  const int probwt = cm->num_tg;
#else
  const int probwt = 1;
#endif
735 736 737
  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
738
          av1_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
739
          cm->counts.intra_ext_tx[i][j], TX_TYPES, probwt);
740 741
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
742
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
743 744
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
745
      for (j = 0; j < TX_TYPES; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
746
        prob_diff_update(av1_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
747
                         cm->counts.intra_ext_tx[i][j], TX_TYPES, probwt, w);
748
      }
749 750
    }
  }
751

752 753
  savings = 0;
  for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
754
    savings +=
Yaowu Xu's avatar
Yaowu Xu committed
755
        prob_diff_update_savings(av1_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
756
                                 cm->counts.inter_ext_tx[i], TX_TYPES, probwt);
757 758
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
759
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
760 761
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
Yaowu Xu's avatar
Yaowu Xu committed
762
      prob_diff_update(av1_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
763
                       cm->counts.inter_ext_tx[i], TX_TYPES, probwt, w);
764 765 766
    }
  }
}
767
#endif  // CONFIG_EXT_TX
768
#endif  // !CONFIG_EC_ADAPT
769
#if CONFIG_PALETTE
Yaowu Xu's avatar
Yaowu Xu committed
770
static void pack_palette_tokens(aom_writer *w, const TOKENEXTRA **tp, int n,
771
                                int num) {
hui su's avatar
hui su committed
772
  int i;
773
  const TOKENEXTRA *p = *tp;
hui su's avatar
hui su committed
774

775
  for (i = 0; i < num; ++i) {
776 777 778
    av1_write_token(
        w, av1_palette_color_index_tree[n - PALETTE_MIN_SIZE], p->context_tree,
        &palette_color_index_encodings[n - PALETTE_MIN_SIZE][p->token]);
hui su's avatar
hui su committed
779 780 781 782 783
    ++p;
  }

  *tp = p;
}
784
#endif  // CONFIG_PALETTE
785

786
#if !CONFIG_PVQ
787
#if CONFIG_SUPERTX
788
static void update_supertx_probs(AV1_COMMON *cm, int probwt, aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
789 790
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
791 792 793 794
  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
795
    for (j = TX_8X8; j < TX_SIZES; ++j) {
796 797
      savings += av1_cond_prob_diff_update_savings(
          &cm->fc->supertx_prob[i][j], cm->counts.supertx[i][j], probwt);
798 799 800
    }
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
801
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
802 803
  if (do_update) {
    for (i = 0; i < PARTITION_SUPERTX_CONTEXTS; ++i) {
Jingning Han's avatar
Jingning Han committed
804
      for (j = TX_8X8; j < TX_SIZES; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
805
        av1_cond_prob_diff_update(w, &cm->fc->supertx_prob[i][j],
806
                                  cm->counts.supertx[i][j], probwt);
807 808 809 810 811 812
      }
    }
  }
}
#endif  // CONFIG_SUPERTX

813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 <