bitstream.c 207 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 17
#include "aom/aom_encoder.h"
#include "aom_dsp/aom_dsp_common.h"
18
#include "aom_dsp/binary_codes_writer.h"
19
#include "aom_dsp/bitwriter_buffer.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
#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

Angie Chiang's avatar
Angie Chiang committed
43 44 45
#if CONFIG_LV_MAP
#include "av1/encoder/encodetxb.h"
#endif  // CONFIG_LV_MAP
46 47 48 49
#include "av1/encoder/bitstream.h"
#include "av1/encoder/cost.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/mcomp.h"
Urvang Joshi's avatar
Urvang Joshi committed
50
#if CONFIG_PALETTE_DELTA_ENCODING
hui su's avatar
hui su committed
51
#include "av1/encoder/palette.h"
Urvang Joshi's avatar
Urvang Joshi committed
52
#endif  // CONFIG_PALETTE_DELTA_ENCODING
53 54 55
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
56 57 58
#if CONFIG_PVQ
#include "av1/encoder/pvq_encoder.h"
#endif
Jingning Han's avatar
Jingning Han committed
59

60
#define ENC_MISMATCH_DEBUG 0
61

62
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
63 64
static struct av1_token
    inter_singleref_comp_mode_encodings[INTER_SINGLEREF_COMP_MODES];
65
#endif  // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
66

Yaowu Xu's avatar
Yaowu Xu committed
67
static INLINE void write_uniform(aom_writer *w, int n, int v) {
68 69
  const int l = get_unsigned_bits(n);
  const int m = (1 << l) - n;
70
  if (l == 0) return;
hui su's avatar
hui su committed
71
  if (v < m) {
Yaowu Xu's avatar
Yaowu Xu committed
72
    aom_write_literal(w, v, l - 1);
hui su's avatar
hui su committed
73
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
74 75
    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
76 77
  }
}
Jingning Han's avatar
Jingning Han committed
78

79
#if CONFIG_EXT_INTRA
hui su's avatar
hui su committed
80
#if CONFIG_INTRA_INTERP
Yaowu Xu's avatar
Yaowu Xu committed
81
static struct av1_token intra_filter_encodings[INTRA_FILTERS];
hui su's avatar
hui su committed
82
#endif  // CONFIG_INTRA_INTERP
83
#endif  // CONFIG_EXT_INTRA
84
#if CONFIG_EXT_INTER
85
#if CONFIG_INTERINTRA
Yaowu Xu's avatar
Yaowu Xu committed
86
static struct av1_token interintra_mode_encodings[INTERINTRA_MODES];
87
#endif
88
#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
89
static struct av1_token compound_type_encodings[COMPOUND_TYPES];
90
#endif  // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
91
#endif  // CONFIG_EXT_INTER
92 93
#if CONFIG_LOOP_RESTORATION
static struct av1_token switchable_restore_encodings[RESTORE_SWITCHABLE_TYPES];
94 95 96 97
static void loop_restoration_write_sb_coeffs(const AV1_COMMON *const cm,
                                             MACROBLOCKD *xd,
                                             aom_writer *const w, int plane,
                                             int rtile_idx);
98
#endif  // CONFIG_LOOP_RESTORATION
99 100 101 102 103 104 105 106
#if CONFIG_OBU
static void write_uncompressed_header_obu(AV1_COMP *cpi,
                                          struct aom_write_bit_buffer *wb);
#else
static void write_uncompressed_header_frame(AV1_COMP *cpi,
                                            struct aom_write_bit_buffer *wb);
#endif

107
static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data);
108

109
#if !CONFIG_OBU || CONFIG_EXT_TILE
110 111 112 113 114
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);
115
#endif
Yaowu Xu's avatar
Yaowu Xu committed
116
void av1_encode_token_init(void) {
117
#if CONFIG_EXT_TX
Hui Su's avatar
Hui Su committed
118
  for (int s = 1; s < EXT_TX_SET_TYPES; ++s) {
Hui Su's avatar
Hui Su committed
119 120
    av1_indices_from_tree(av1_ext_tx_ind[s], av1_ext_tx_inv[s],
                          av1_ext_tx_tree[s]);
121
  }
122
#else
Hui Su's avatar
Hui Su committed
123 124 125 126
  /* 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. */
  av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, av1_ext_tx_tree);
127
#endif  // CONFIG_EXT_TX
128

129
#if CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP
Yaowu Xu's avatar
Yaowu Xu committed
130
  av1_tokens_from_tree(intra_filter_encodings, av1_intra_filter_tree);
131
#endif  // CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP
132
#if CONFIG_EXT_INTER
133
#if CONFIG_INTERINTRA
Yaowu Xu's avatar
Yaowu Xu committed
134
  av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree);
135
#endif  // CONFIG_INTERINTRA
136 137 138 139
#if CONFIG_COMPOUND_SINGLEREF
  av1_tokens_from_tree(inter_singleref_comp_mode_encodings,
                       av1_inter_singleref_comp_mode_tree);
#endif  // CONFIG_COMPOUND_SINGLEREF
140
#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
141
  av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree);
142
#endif  // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
143
#endif  // CONFIG_EXT_INTER
144 145 146 147
#if CONFIG_LOOP_RESTORATION
  av1_tokens_from_tree(switchable_restore_encodings,
                       av1_switchable_restore_tree);
#endif  // CONFIG_LOOP_RESTORATION
148

149
  /* This hack is necessary when CONFIG_DUAL_FILTER is enabled because the five
150 151 152
      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
153
                        av1_switchable_interp_tree);
154 155
}

Jingning Han's avatar
Jingning Han committed
156 157 158 159
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
160 161 162
#if CONFIG_INTRABC
  assert(!is_intrabc_block(&mi->mbmi));
#endif  // CONFIG_INTRABC
Jingning Han's avatar
Jingning Han committed
163 164 165 166 167
  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
168

169
static void write_inter_mode(aom_writer *w, PREDICTION_MODE mode,
170
                             FRAME_CONTEXT *ec_ctx, const int16_t mode_ctx) {
171
  const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
Yue Chen's avatar
Yue Chen committed
172

173 174 175 176 177
#if CONFIG_NEW_MULTISYMBOL
  aom_write_symbol(w, mode != NEWMV, ec_ctx->newmv_cdf[newmv_ctx], 2);
#else
  aom_write(w, mode != NEWMV, ec_ctx->newmv_prob[newmv_ctx]);
#endif
178

Jingning Han's avatar
Jingning Han committed
179
  if (mode != NEWMV) {
180 181 182 183 184
    if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
      assert(mode == ZEROMV);
      return;
    }

185 186 187 188 189 190
    const int16_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
#if CONFIG_NEW_MULTISYMBOL
    aom_write_symbol(w, mode != ZEROMV, ec_ctx->zeromv_cdf[zeromv_ctx], 2);
#else
    aom_write(w, mode != ZEROMV, ec_ctx->zeromv_prob[zeromv_ctx]);
#endif
191 192

    if (mode != ZEROMV) {
193 194
      int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;

195 196 197
      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;
198 199 200 201 202
#if CONFIG_NEW_MULTISYMBOL
      aom_write_symbol(w, mode != NEARESTMV, ec_ctx->refmv_cdf[refmv_ctx], 2);
#else
      aom_write(w, mode != NEARESTMV, ec_ctx->refmv_prob[refmv_ctx]);
#endif
203 204
    }
  }
Jingning Han's avatar
Jingning Han committed
205 206
}

207
static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
Yaowu Xu's avatar
Yaowu Xu committed
208 209
                          const MB_MODE_INFO_EXT *mbmi_ext, aom_writer *w) {
  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
210 211 212

  assert(mbmi->ref_mv_idx < 3);

213
#if CONFIG_EXT_INTER
214 215 216 217
#if CONFIG_COMPOUND_SINGLEREF
  if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV ||
      mbmi->mode == SR_NEW_NEWMV) {
#else   // !CONFIG_COMPOUND_SINGLEREF
218
  if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
219 220
#endif  // CONFIG_COMPOUND_SINGLEREF
#else   // !CONFIG_EXT_INTER
221
  if (mbmi->mode == NEWMV) {
222
#endif  // CONFIG_EXT_INTER
223 224 225 226
    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
227
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
228

229 230 231 232 233 234
#if CONFIG_NEW_MULTISYMBOL
        aom_write_symbol(w, mbmi->ref_mv_idx != idx, ec_ctx->drl_cdf[drl_ctx],
                         2);
#else
        aom_write(w, mbmi->ref_mv_idx != idx, ec_ctx->drl_prob[drl_ctx]);
#endif
235
        if (mbmi->ref_mv_idx == idx) return;
236
      }
237 238 239 240
    }
    return;
  }

David Barker's avatar
David Barker committed
241
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
242 243 244 245 246
    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
247
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
248 249 250 251 252 253
#if CONFIG_NEW_MULTISYMBOL
        aom_write_symbol(w, mbmi->ref_mv_idx != (idx - 1),
                         ec_ctx->drl_cdf[drl_ctx], 2);
#else
        aom_write(w, mbmi->ref_mv_idx != (idx - 1), ec_ctx->drl_prob[drl_ctx]);
#endif
254
        if (mbmi->ref_mv_idx == (idx - 1)) return;
255
      }
256
    }
257
    return;
258 259 260
  }
}

261
#if CONFIG_EXT_INTER
262 263
static void write_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                      aom_writer *w, PREDICTION_MODE mode,
264
                                      const int16_t mode_ctx) {
265 266 267 268 269
  assert(is_inter_compound_mode(mode));
  (void)cm;
  aom_write_symbol(w, INTER_COMPOUND_OFFSET(mode),
                   xd->tile_ctx->inter_compound_mode_cdf[mode_ctx],
                   INTER_COMPOUND_MODES);
270
}
271 272

#if CONFIG_COMPOUND_SINGLEREF
273
static void write_inter_singleref_comp_mode(MACROBLOCKD *xd, aom_writer *w,
274 275 276
                                            PREDICTION_MODE mode,
                                            const int16_t mode_ctx) {
  assert(is_inter_singleref_comp_mode(mode));
277 278
  aom_cdf_prob *const inter_singleref_comp_cdf =
      xd->tile_ctx->inter_singleref_comp_mode_cdf[mode_ctx];
279

280 281
  aom_write_symbol(w, INTER_SINGLEREF_COMP_OFFSET(mode),
                   inter_singleref_comp_cdf, INTER_SINGLEREF_COMP_MODES);
282 283
}
#endif  // CONFIG_COMPOUND_SINGLEREF
284 285
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
286
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
287
                                int max) {
Yaowu Xu's avatar
Yaowu Xu committed
288
  aom_wb_write_literal(wb, data, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
289 290
}

291
#if CONFIG_VAR_TX
292
static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd,
293
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
294 295
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
296 297 298 299
#if CONFIG_NEW_MULTISYMBOL
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
#endif
300 301
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
302 303 304
  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);

305 306
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
307
                                   mbmi->sb_type, tx_size);
308

309
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
310

Jingning Han's avatar
Jingning Han committed
311
  if (depth == MAX_VARTX_DEPTH) {
312 313
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
314 315 316
    return;
  }

Yue Chen's avatar
Yue Chen committed
317 318 319 320
#if CONFIG_RECT_TX_EXT
  if (tx_size == mbmi->inter_tx_size[tx_row][tx_col] ||
      mbmi->tx_size == quarter_txsize_lookup[mbmi->sb_type]) {
#else
321
  if (tx_size == mbmi->inter_tx_size[tx_row][tx_col]) {
Yue Chen's avatar
Yue Chen committed
322
#endif
323 324 325
#if CONFIG_NEW_MULTISYMBOL
    aom_write_symbol(w, 0, ec_ctx->txfm_partition_cdf[ctx], 2);
#else
Yaowu Xu's avatar
Yaowu Xu committed
326
    aom_write(w, 0, cm->fc->txfm_partition_prob[ctx]);
327 328
#endif

329 330
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
Yue Chen's avatar
Yue Chen committed
331
    // TODO(yuec): set correct txfm partition update for qttx
332
  } else {
333 334
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    const int bsl = tx_size_wide_unit[sub_txs];
335
    int i;
336

337 338 339
#if CONFIG_NEW_MULTISYMBOL
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
#else
Yaowu Xu's avatar
Yaowu Xu committed
340
    aom_write(w, 1, cm->fc->txfm_partition_prob[ctx]);
341
#endif
342

David Barker's avatar
David Barker committed
343
    if (sub_txs == TX_4X4) {
344 345
      txfm_partition_update(xd->above_txfm_context + blk_col,
                            xd->left_txfm_context + blk_row, sub_txs, tx_size);
346
      return;
347
    }
348 349 350

    assert(bsl > 0);
    for (i = 0; i < 4; ++i) {
351 352 353 354
      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);
355 356 357
    }
  }
}
358

359
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
360
static void update_txfm_partition_probs(AV1_COMMON *cm, aom_writer *w,
361
                                        FRAME_COUNTS *counts, int probwt) {
362 363
  int k;
  for (k = 0; k < TXFM_PARTITION_CONTEXTS; ++k)
Yaowu Xu's avatar
Yaowu Xu committed
364
    av1_cond_prob_diff_update(w, &cm->fc->txfm_partition_prob[k],
365
                              counts->txfm_partition[k], probwt);
366
}
367
#endif  // CONFIG_NEW_MULTISYMBOL
David Barker's avatar
David Barker committed
368
#endif  // CONFIG_VAR_TX
369

Yaowu Xu's avatar
Yaowu Xu committed
370 371
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
372 373
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
374 375
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
376
// For sub8x8 blocks the tx_size symbol does not need to be sent
377
#if CONFIG_CB4X4 && (CONFIG_VAR_TX || CONFIG_EXT_TX) && CONFIG_RECT_TX
378 379
  if (bsize > BLOCK_4X4) {
#else
380
  if (bsize >= BLOCK_8X8) {
381
#endif
382 383 384 385 386 387
    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];
388
    const int depth = tx_size_to_depth(coded_tx_size);
389
#if CONFIG_EXT_TX && CONFIG_RECT_TX
390
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
391 392
#endif  // CONFIG_EXT_TX && CONFIG_RECT_TX

393
    aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx],
394
                     tx_size_cat + 2);
Yue Chen's avatar
Yue Chen committed
395
#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX)
396 397 398
    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);
Yue Chen's avatar
Yue Chen committed
399
#endif
Jingning Han's avatar
Jingning Han committed
400 401 402
  }
}

403
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
404
static void update_inter_mode_probs(AV1_COMMON *cm, aom_writer *w,
405 406
                                    FRAME_COUNTS *counts) {
  int i;
407
  const int probwt = cm->num_tg;
408
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
409 410
    av1_cond_prob_diff_update(w, &cm->fc->newmv_prob[i], counts->newmv_mode[i],
                              probwt);
411
  for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
Yaowu Xu's avatar
Yaowu Xu committed
412
    av1_cond_prob_diff_update(w, &cm->fc->zeromv_prob[i],
413
                              counts->zeromv_mode[i], probwt);
414
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
415 416
    av1_cond_prob_diff_update(w, &cm->fc->refmv_prob[i], counts->refmv_mode[i],
                              probwt);
417
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
418 419
    av1_cond_prob_diff_update(w, &cm->fc->drl_prob[i], counts->drl_mode[i],
                              probwt);
420
}
421
#endif
422

Yaowu Xu's avatar
Yaowu Xu committed
423 424
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
425 426 427 428
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
429 430 431 432 433
#if CONFIG_NEW_MULTISYMBOL
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    const int ctx = av1_get_skip_context(xd);
    aom_write_symbol(w, skip, ec_ctx->skip_cdfs[ctx], 2);
#else
Yaowu Xu's avatar
Yaowu Xu committed
434
    aom_write(w, skip, av1_get_skip_prob(cm, xd));
435
#endif
Jingning Han's avatar
Jingning Han committed
436 437 438 439
    return skip;
  }
}

440 441 442 443 444 445 446 447 448 449 450 451 452
static void write_is_inter(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                           int segment_id, aom_writer *w, const int is_inter) {
  if (!segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
#if CONFIG_NEW_MULTISYMBOL
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    const int ctx = av1_get_intra_inter_context(xd);
    aom_write_symbol(w, is_inter, ec_ctx->intra_inter_cdf[ctx], 2);
#else
    aom_write(w, is_inter, av1_get_intra_inter_prob(cm, xd));
#endif
  }
}

Yue Chen's avatar
Yue Chen committed
453
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
454 455
static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd,
                              const MODE_INFO *mi, aom_writer *w) {
456
  const MB_MODE_INFO *mbmi = &mi->mbmi;
457

458 459 460 461 462 463
#if !CONFIG_GLOBAL_MOTION
  // The cm parameter is only used with global_motion or with
  // motion_var and warped_motion. In other cases, explicitly ignore
  // it to avoid a compiler warning.
  (void)cm;
#endif
464
  MOTION_MODE last_motion_mode_allowed = motion_mode_allowed(
465
#if CONFIG_GLOBAL_MOTION
466
      0, cm->global_motion,
467
#endif  // CONFIG_GLOBAL_MOTION
468 469 470
#if CONFIG_WARPED_MOTION
      xd,
#endif
471
      mi);
Yue Chen's avatar
Yue Chen committed
472 473
  if (last_motion_mode_allowed == SIMPLE_TRANSLATION) return;
#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
474 475 476 477 478 479 480 481 482 483
#if CONFIG_NCOBMC_ADAPT_WEIGHT
  if (last_motion_mode_allowed == NCOBMC_ADAPT_WEIGHT) {
    aom_write_symbol(w, mbmi->motion_mode,
                     xd->tile_ctx->ncobmc_cdf[mbmi->sb_type],
                     OBMC_FAMILY_MODES);
  } else if (last_motion_mode_allowed == OBMC_CAUSAL) {
    aom_write_symbol(w, mbmi->motion_mode == OBMC_CAUSAL,
                     xd->tile_ctx->obmc_cdf[mbmi->sb_type], 2);
  } else {
#else
Yue Chen's avatar
Yue Chen committed
484
  if (last_motion_mode_allowed == OBMC_CAUSAL) {
485 486 487 488
#if CONFIG_NEW_MULTISYMBOL
    aom_write_symbol(w, mbmi->motion_mode == OBMC_CAUSAL,
                     xd->tile_ctx->obmc_cdf[mbmi->sb_type], 2);
#else
Yue Chen's avatar
Yue Chen committed
489 490
    aom_write(w, mbmi->motion_mode == OBMC_CAUSAL,
              cm->fc->obmc_prob[mbmi->sb_type]);
491
#endif
Yue Chen's avatar
Yue Chen committed
492
  } else {
493
#endif  // CONFIG_NCOBMC_ADAPT_WEIGHT
Yue Chen's avatar
Yue Chen committed
494
#endif  // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
Thomas Davies's avatar
Thomas Davies committed
495 496 497
    aom_write_symbol(w, mbmi->motion_mode,
                     xd->tile_ctx->motion_mode_cdf[mbmi->sb_type],
                     MOTION_MODES);
Yue Chen's avatar
Yue Chen committed
498 499 500 501
#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
  }
#endif  // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
}
502 503

#if CONFIG_NCOBMC_ADAPT_WEIGHT
504
static void write_ncobmc_mode(MACROBLOCKD *xd, const MODE_INFO *mi,
505 506 507
                              aom_writer *w) {
  const MB_MODE_INFO *mbmi = &mi->mbmi;
  ADAPT_OVERLAP_BLOCK ao_block = adapt_overlap_block_lookup[mbmi->sb_type];
508
  if (mbmi->motion_mode != NCOBMC_ADAPT_WEIGHT) return;
509

510 511
  aom_write_symbol(w, mbmi->ncobmc_mode[0],
                   xd->tile_ctx->ncobmc_mode_cdf[ao_block], MAX_NCOBMC_MODES);
512
  if (mi_size_wide[mbmi->sb_type] != mi_size_high[mbmi->sb_type]) {
513 514
    aom_write_symbol(w, mbmi->ncobmc_mode[1],
                     xd->tile_ctx->ncobmc_mode_cdf[ao_block], MAX_NCOBMC_MODES);
515 516 517
  }
}
#endif
Yue Chen's avatar
Yue Chen committed
518 519
#endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION

520
#if CONFIG_DELTA_Q
Thomas Davies's avatar
Thomas Davies committed
521 522
static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               int delta_qindex, aom_writer *w) {
523 524
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
Thomas Davies's avatar
Thomas Davies committed
525
  int rem_bits, thr;
526
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
Thomas Davies's avatar
Thomas Davies committed
527 528
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
529

Thomas Davies's avatar
Thomas Davies committed
530 531
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
532 533 534 535

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
536
    aom_write_literal(w, rem_bits - 1, 3);
537
    aom_write_literal(w, abs - thr, rem_bits);
538 539 540 541 542
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
543

Fangwen Fu's avatar
Fangwen Fu committed
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
#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;
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;

  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;
560
    aom_write_literal(w, rem_bits - 1, 3);
Fangwen Fu's avatar
Fangwen Fu committed
561 562 563 564 565 566 567
    aom_write_literal(w, abs - thr, rem_bits);
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
#endif  // CONFIG_EXT_DELTA_Q
Thomas Davies's avatar
Thomas Davies committed
568
#endif  // CONFIG_DELTA_Q
569

570
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
571
static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
572 573
                              FRAME_COUNTS *counts) {
  int k;
574 575 576 577 578
  const int probwt = cm->num_tg;
  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
579
}
580
#endif
Jingning Han's avatar
Jingning Han committed
581

Sarah Parker's avatar
Sarah Parker committed
582 583
static void pack_map_tokens(aom_writer *w, const TOKENEXTRA **tp, int n,
                            int num) {
584
  const TOKENEXTRA *p = *tp;
585 586 587 588
  write_uniform(w, n, p->token);  // The first color index.
  ++p;
  --num;
  for (int i = 0; i < num; ++i) {
589
    aom_write_symbol(w, p->token, p->color_map_cdf, n);
hui su's avatar
hui su committed
590 591 592 593
    ++p;
  }
  *tp = p;
}
594

595
#if !CONFIG_PVQ
596
#if CONFIG_SUPERTX
597
static void update_supertx_probs(AV1_COMMON *cm, int probwt, aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
598 599
  const int savings_thresh = av1_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             av1_cost_zero(GROUP_DIFF_UPDATE_PROB);
600 601 602 603
  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
604
    for (j = TX_8X8; j < TX_SIZES; ++j) {
605 606
      savings += av1_cond_prob_diff_update_savings(
          &cm->fc->supertx_prob[i][j], cm->counts.supertx[i][j], probwt);
607 608 609
    }
  }
  do_update = savings > savings_thresh;
Yaowu Xu's avatar
Yaowu Xu committed
610
  aom_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
611 612
  if (do_update) {
    for (i = 0; i < PARTITION_SUPERTX_CONTEXTS; ++i) {
Jingning Han's avatar
Jingning Han committed
613
      for (j = TX_8X8; j < TX_SIZES; ++j) {
Yaowu Xu's avatar
Yaowu Xu committed
614
        av1_cond_prob_diff_update(w, &cm->fc->supertx_prob[i][j],
615
                                  cm->counts.supertx[i][j], probwt);
616 617 618 619 620 621
      }
    }
  }
}
#endif  // CONFIG_SUPERTX

622
#if !CONFIG_LV_MAP
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
#if CONFIG_NEW_MULTISYMBOL
static INLINE void write_coeff_extra(const aom_cdf_prob *const *cdf, int val,
                                     int n, aom_writer *w) {
  // Code the extra bits from LSB to MSB in groups of 4
  int i = 0;
  int count = 0;
  while (count < n) {
    const int size = AOMMIN(n - count, 4);
    const int mask = (1 << size) - 1;
    aom_write_cdf(w, val & mask, cdf[i++], 1 << size);
    val >>= size;
    count += size;
  }
}
#else
static INLINE void write_coeff_extra(const aom_prob *pb, int value,
                                     int num_bits, int skip_bits, aom_writer *w,
                                     TOKEN_STATS *token_stats) {
  // Code the extra bits from MSB to LSB 1 bit at a time
  int index;
  for (index = skip_bits; index < num_bits; ++index) {
    const int shift = num_bits - index - 1;
    const int bb = (value >> shift) & 1;
    aom_write_record(w, bb, pb[index], token_stats);
  }
}
649
#endif  // CONFIG_NEW_MULTISYMBOL
650

Yaowu Xu's avatar
Yaowu Xu committed
651
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
652
                           const TOKENEXTRA *const stop,
653
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
Sarah Parker's avatar
Sarah Parker committed
654 655 656
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                           TX_TYPE tx_type, int is_inter,
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
657
                           TOKEN_STATS *token_stats) {
658
  const TOKENEXTRA *p = *tp;
Fangwen Fu's avatar
Fangwen Fu committed
659
#if CONFIG_VAR_TX
660
  int count = 0;
661
  const int seg_eob = tx_size_2d[tx_size];
662
#endif
Jingning Han's avatar
Jingning Han committed
663

Sarah Parker's avatar
Sarah Parker committed
664 665 666 667 668 669 670 671 672 673 674
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
  if (tx_type == MRC_DCT && ((is_inter && SIGNAL_MRC_MASK_INTER) ||
                             (!is_inter && SIGNAL_MRC_MASK_INTRA))) {
    int rows = tx_size_high[tx_size];
    int cols = tx_size_wide[tx_size];
    assert(tx_size == TX_32X32);
    assert(p < stop);
    pack_map_tokens(w, &p, 2, rows * cols);
  }
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK

Jingning Han's avatar
Jingning Han committed
675
  while (p < stop && p->token != EOSB_TOKEN) {
676
    const int token = p->token;
677
    const int eob_val = p->eob_val;
678
    if (token == BLOCK_Z_TOKEN) {
679
      aom_write_symbol(w, 0, *p->head_cdf, HEAD_TOKENS + 1);
680
      p++;
681 682 683
#if CONFIG_VAR_TX
      break;
#endif
684 685
      continue;
    }
Yaowu Xu's avatar
Yaowu Xu committed
686 687

    const av1_extra_bit *const extra_bits = &av1_extra_bits[token];
688
    if (eob_val == LAST_EOB) {
689 690 691
      // Just code a flag indicating whether the value is >1 or 1.
      aom_write_bit(w, token != ONE_TOKEN);
    } else {
692
      int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - eob_val + p->first_val;
693
      aom_write_symbol(w, comb_symb, *p->head_cdf, HEAD_TOKENS + p->first_val);
694
    }
695
    if (token > ONE_TOKEN) {
696
      aom_write_symbol(w, token - TWO_TOKEN, *p->tail_cdf, TAIL_TOKENS);
Alex Converse's avatar
Alex Converse committed
697
    }
698 699 700 701

    if (extra_bits->base_val) {
      const int bit_string = p->extra;
      const int bit_string_length = extra_bits->len;  // Length of extra bits to
702
      const int is_cat6 = (extra_bits->base_val == CAT6_MIN_VAL);
703 704
      // be written excluding
      // the sign bit.
705
      int skip_bits = is_cat6
706 707 708
                          ? (int)sizeof(av1_cat6_prob) -
                                av1_get_cat6_extrabits_size(tx_size, bit_depth)
                          : 0;
709

710 711 712 713 714 715 716 717 718
      assert(!(bit_string >> (bit_string_length - skip_bits + 1)));
      if (bit_string_length > 0)
#if CONFIG_NEW_MULTISYMBOL
        write_coeff_extra(extra_bits->cdf, bit_string >> 1,
                          bit_string_length - skip_bits, w);
#else
        write_coeff_extra(extra_bits->prob, bit_string >> 1, bit_string_length,
                          skip_bits, w, token_stats);
#endif
719 720 721 722 723

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

Fangwen Fu's avatar
Fangwen Fu committed
724
#if CONFIG_VAR_TX
725
    ++count;
726
    if (eob_val == EARLY_EOB || count == seg_eob) break;
727 728 729 730 731
#endif
  }

  *tp = p;
}
Angie Chiang's avatar
Angie Chiang committed
732
#endif  // !CONFIG_LV_MAP
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
#else   // !CONFIG_PVQ
static PVQ_INFO *get_pvq_block(PVQ_QUEUE *pvq_q) {
  PVQ_INFO *pvq;

  assert(pvq_q->curr_pos <= pvq_q->last_pos);
  assert(pvq_q->curr_pos < pvq_q->buf_len);

  pvq = pvq_q->buf + pvq_q->curr_pos;
  ++pvq_q->curr_pos;

  return pvq;
}

static void pack_pvq_tokens(aom_writer *w, MACROBLOCK *const x,
                            MACROBLOCKD *const xd, int plane, BLOCK_SIZE bsize,
                            const TX_SIZE tx_size) {
  PVQ_INFO *pvq;
  int idx, idy;
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  od_adapt_ctx *adapt;
  int max_blocks_wide;
  int max_blocks_high;
  int step = (1 << tx_size);
756 757

#if CONFIG_CHROMA_SUB8X8
758
  const BLOCK_SIZE plane_bsize =
759 760 761 762 763 764 765
      AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
#elif CONFIG_CB4X4
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
#else
  const BLOCK_SIZE plane_bsize =
      get_plane_block_size(AOMMAX(BLOCK_8X8, bsize), pd);
#endif
766

767
  adapt = x->daala_enc.state.adapt;
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785

  max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
  max_blocks_high = max_block_high(xd, plane_bsize, plane);

  for (idy = 0; idy < max_blocks_high; idy += step) {
    for (idx = 0; idx < max_blocks_wide; idx += step) {
      const int is_keyframe = 0;
      const int encode_flip = 0;
      const int flip = 0;
      int i;
      const int has_dc_skip = 1;
      int *exg = &adapt->pvq.pvq_exg[plane][tx_size][0];
      int *ext = adapt->pvq.pvq_ext + tx_size * PVQ_MAX_PARTITIONS;
      generic_encoder *model = adapt->pvq.pvq_param_model;

      pvq = get_pvq_block(x->pvq_q);

      // encode block skip info
786 787
      aom_write_symbol(w, pvq->ac_dc_coded,
                       adapt->skip_cdf[2 * tx_size + (plane != 0)], 4);
788 789 790 791 792 793 794 795

      // AC coeffs coded?
      if (pvq->ac_dc_coded & AC_CODED) {
        assert(pvq->bs == tx_size);
        for (i = 0; i < pvq->nb_bands; i++) {
          if (i == 0 ||
              (!pvq->skip_rest && !(pvq->skip_dir & (1 << ((i - 1) % 3))))) {
            pvq_encode_partition(
796 797
                w, pvq->qg[i], pvq->theta[i], pvq->y + pvq->off[i],
                pvq->size[i], pvq->k[i], model, adapt, exg + i, ext + i,
798 799 800 801 802 803
                (plane != 0) * OD_TXSIZES * PVQ_MAX_PARTITIONS +
                    pvq->bs * PVQ_MAX_PARTITIONS + i,
                is_keyframe, i == 0 && (i < pvq->nb_bands - 1), pvq->skip_rest,
                encode_flip, flip);
          }
          if (i == 0 && !pvq->skip_rest && pvq->bs > 0) {
804
            aom_write_symbol(
805 806 807
                w, pvq->skip_dir,
                &adapt->pvq
                     .pvq_skip_dir_cdf[(plane != 0) + 2 * (pvq->bs - 1)][0],
808
                7);
809 810 811 812 813 814
          }
        }
      }
      // Encode residue of DC coeff, if exist.
      if (!has_dc_skip || (pvq->ac_dc_coded & DC_CODED)) {
        generic_encode(w, &adapt->model_dc[plane],
815
                       abs(pvq->dq_dc_residue) - has_dc_skip,
816 817 818 819 820 821 822 823
                       &adapt->ex_dc[plane][pvq->bs][0], 2);
      }
      if ((pvq->ac_dc_coded & DC_CODED)) {
        aom_write_bit(w, pvq->dq_dc_residue < 0);
      }
    }
  }  // for (idy = 0;
}