bitstream.c 184 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"
Jingning Han's avatar
Jingning Han committed
56

57
#define ENC_MISMATCH_DEBUG 0
58

59
#if CONFIG_COMPOUND_SINGLEREF
60 61
static struct av1_token
    inter_singleref_comp_mode_encodings[INTER_SINGLEREF_COMP_MODES];
62
#endif  // CONFIG_COMPOUND_SINGLEREF
63

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

Yaowu Xu's avatar
Yaowu Xu committed
76
static struct av1_token interintra_mode_encodings[INTERINTRA_MODES];
77
static struct av1_token compound_type_encodings[COMPOUND_TYPES];
78
#if CONFIG_LOOP_RESTORATION
79 80
static void loop_restoration_write_sb_coeffs(const AV1_COMMON *const cm,
                                             MACROBLOCKD *xd,
81 82
                                             const RestorationUnitInfo *rui,
                                             aom_writer *const w, int plane);
83
#endif  // CONFIG_LOOP_RESTORATION
84 85 86 87 88 89 90 91
#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

92
static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data);
93

94
#if !CONFIG_OBU || CONFIG_EXT_TILE
95 96 97 98 99
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);
100
#endif
Yaowu Xu's avatar
Yaowu Xu committed
101 102
void av1_encode_token_init(void) {
  av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree);
103 104 105 106
#if CONFIG_COMPOUND_SINGLEREF
  av1_tokens_from_tree(inter_singleref_comp_mode_encodings,
                       av1_inter_singleref_comp_mode_tree);
#endif  // CONFIG_COMPOUND_SINGLEREF
107
  av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree);
108 109
}

Jingning Han's avatar
Jingning Han committed
110 111 112 113
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
114 115 116
#if CONFIG_INTRABC
  assert(!is_intrabc_block(&mi->mbmi));
#endif  // CONFIG_INTRABC
Hui Su's avatar
Hui Su committed
117
  aom_write_symbol(w, mode,
Jingning Han's avatar
Jingning Han committed
118 119 120 121
                   get_y_mode_cdf(frame_ctx, mi, above_mi, left_mi, block),
                   INTRA_MODES);
  (void)cm;
}
Jingning Han's avatar
Jingning Han committed
122

123
static void write_inter_mode(aom_writer *w, PREDICTION_MODE mode,
124
                             FRAME_CONTEXT *ec_ctx, const int16_t mode_ctx) {
125
  const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
Yue Chen's avatar
Yue Chen committed
126

127 128 129 130 131
#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
132

Jingning Han's avatar
Jingning Han committed
133
  if (mode != NEWMV) {
134
    if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
Sarah Parker's avatar
Sarah Parker committed
135
      assert(mode == GLOBALMV);
136 137 138
      return;
    }

Sarah Parker's avatar
Sarah Parker committed
139 140
    const int16_t zeromv_ctx =
        (mode_ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
141
#if CONFIG_NEW_MULTISYMBOL
Sarah Parker's avatar
Sarah Parker committed
142
    aom_write_symbol(w, mode != GLOBALMV, ec_ctx->zeromv_cdf[zeromv_ctx], 2);
143
#else
Sarah Parker's avatar
Sarah Parker committed
144
    aom_write(w, mode != GLOBALMV, ec_ctx->zeromv_prob[zeromv_ctx]);
145
#endif
146

Sarah Parker's avatar
Sarah Parker committed
147
    if (mode != GLOBALMV) {
148 149
      int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;

150 151 152
      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;
153 154 155 156 157
#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
158 159
    }
  }
Jingning Han's avatar
Jingning Han committed
160 161
}

162
static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
Yaowu Xu's avatar
Yaowu Xu committed
163 164
                          const MB_MODE_INFO_EXT *mbmi_ext, aom_writer *w) {
  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
165 166 167

  assert(mbmi->ref_mv_idx < 3);

168
  const int new_mv =
169
#if CONFIG_COMPOUND_SINGLEREF
170 171 172 173
      mbmi->mode == SR_NEW_NEWMV ||
#endif
      mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV;
  if (new_mv) {
174 175 176 177
    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
178
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
179

180 181 182 183 184 185
#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
186
        if (mbmi->ref_mv_idx == idx) return;
187
      }
188 189 190 191
    }
    return;
  }

David Barker's avatar
David Barker committed
192
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
193 194 195 196 197
    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
198
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
199 200 201 202 203 204
#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
205
        if (mbmi->ref_mv_idx == (idx - 1)) return;
206
      }
207
    }
208
    return;
209 210 211
  }
}

212 213
static void write_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                      aom_writer *w, PREDICTION_MODE mode,
214
                                      const int16_t mode_ctx) {
215 216 217 218 219
  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);
220
}
221 222

#if CONFIG_COMPOUND_SINGLEREF
223
static void write_inter_singleref_comp_mode(MACROBLOCKD *xd, aom_writer *w,
224 225 226
                                            PREDICTION_MODE mode,
                                            const int16_t mode_ctx) {
  assert(is_inter_singleref_comp_mode(mode));
227 228
  aom_cdf_prob *const inter_singleref_comp_cdf =
      xd->tile_ctx->inter_singleref_comp_mode_cdf[mode_ctx];
229

230 231
  aom_write_symbol(w, INTER_SINGLEREF_COMP_OFFSET(mode),
                   inter_singleref_comp_cdf, INTER_SINGLEREF_COMP_MODES);
232 233
}
#endif  // CONFIG_COMPOUND_SINGLEREF
234

Yaowu Xu's avatar
Yaowu Xu committed
235
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
236
                                int max) {
Yaowu Xu's avatar
Yaowu Xu committed
237
  aom_wb_write_literal(wb, data, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
238 239
}

240
static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd,
241
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
242 243
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
244 245 246 247
#if CONFIG_NEW_MULTISYMBOL
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
#endif
248 249
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
250 251 252
  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);

253 254
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
255
                                   mbmi->sb_type, tx_size);
256

257
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
258

Jingning Han's avatar
Jingning Han committed
259
  if (depth == MAX_VARTX_DEPTH) {
260 261
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
262 263 264
    return;
  }

265
  const int write_txfm_partition =
Yue Chen's avatar
Yue Chen committed
266
#if CONFIG_RECT_TX_EXT
267 268
      tx_size == mbmi->inter_tx_size[tx_row][tx_col] ||
      mbmi->tx_size == quarter_txsize_lookup[mbmi->sb_type];
Yue Chen's avatar
Yue Chen committed
269
#else
270
      tx_size == mbmi->inter_tx_size[tx_row][tx_col];
Yue Chen's avatar
Yue Chen committed
271
#endif
272
  if (write_txfm_partition) {
273 274 275
#if CONFIG_NEW_MULTISYMBOL
    aom_write_symbol(w, 0, ec_ctx->txfm_partition_cdf[ctx], 2);
#else
Yaowu Xu's avatar
Yaowu Xu committed
276
    aom_write(w, 0, cm->fc->txfm_partition_prob[ctx]);
277 278
#endif

279 280
    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
281
    // TODO(yuec): set correct txfm partition update for qttx
282
  } else {
283 284
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    const int bsl = tx_size_wide_unit[sub_txs];
285
    int i;
286

287 288 289
#if CONFIG_NEW_MULTISYMBOL
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
#else
Yaowu Xu's avatar
Yaowu Xu committed
290
    aom_write(w, 1, cm->fc->txfm_partition_prob[ctx]);
291
#endif
292

David Barker's avatar
David Barker committed
293
    if (sub_txs == TX_4X4) {
294 295
      txfm_partition_update(xd->above_txfm_context + blk_col,
                            xd->left_txfm_context + blk_row, sub_txs, tx_size);
296
      return;
297
    }
298 299 300

    assert(bsl > 0);
    for (i = 0; i < 4; ++i) {
301 302 303 304
      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);
305 306 307
    }
  }
}
308

309
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
310
static void update_txfm_partition_probs(AV1_COMMON *cm, aom_writer *w,
311
                                        FRAME_COUNTS *counts, int probwt) {
312 313
  int k;
  for (k = 0; k < TXFM_PARTITION_CONTEXTS; ++k)
Yaowu Xu's avatar
Yaowu Xu committed
314
    av1_cond_prob_diff_update(w, &cm->fc->txfm_partition_prob[k],
315
                              counts->txfm_partition[k], probwt);
316
}
317
#endif  // CONFIG_NEW_MULTISYMBOL
318

Yaowu Xu's avatar
Yaowu Xu committed
319 320
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
321 322
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
323 324
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
325
  if (block_signals_txsize(bsize)) {
326 327
    const TX_SIZE tx_size = mbmi->tx_size;
    const int is_inter = is_inter_block(mbmi);
328 329
    const int tx_size_ctx = get_tx_size_context(xd);
    const int32_t tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize]
330
                                         : intra_tx_size_cat_lookup[bsize];
331
    const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
332
    const int depth = tx_size_to_depth(coded_tx_size);
333
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
334

335
    aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx],
336
                     tx_size_cat + 2);
337
#if CONFIG_RECT_TX_EXT
338
    if (is_quarter_tx_allowed(xd, mbmi, is_inter) && tx_size != coded_tx_size)
339 340 341 342
#if CONFIG_NEW_MULTISYMBOL
      aom_write_symbol(w, tx_size == quarter_txsize_lookup[bsize],
                       cm->fc->quarter_tx_size_cdf, 2);
#else
343 344
      aom_write(w, tx_size == quarter_txsize_lookup[bsize],
                cm->fc->quarter_tx_size_prob);
345
#endif
Yue Chen's avatar
Yue Chen committed
346
#endif
Jingning Han's avatar
Jingning Han committed
347 348 349
  }
}

350
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
351
static void update_inter_mode_probs(AV1_COMMON *cm, aom_writer *w,
352 353
                                    FRAME_COUNTS *counts) {
  int i;
354
  const int probwt = cm->num_tg;
355
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
356 357
    av1_cond_prob_diff_update(w, &cm->fc->newmv_prob[i], counts->newmv_mode[i],
                              probwt);
Sarah Parker's avatar
Sarah Parker committed
358
  for (i = 0; i < GLOBALMV_MODE_CONTEXTS; ++i)
Yaowu Xu's avatar
Yaowu Xu committed
359
    av1_cond_prob_diff_update(w, &cm->fc->zeromv_prob[i],
360
                              counts->zeromv_mode[i], probwt);
361
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
362 363
    av1_cond_prob_diff_update(w, &cm->fc->refmv_prob[i], counts->refmv_mode[i],
                              probwt);
364
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
365 366
    av1_cond_prob_diff_update(w, &cm->fc->drl_prob[i], counts->drl_mode[i],
                              probwt);
367
}
368
#endif
369

Yaowu Xu's avatar
Yaowu Xu committed
370 371
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
372 373 374 375
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
Zoe Liu's avatar
Zoe Liu committed
376
    const int ctx = av1_get_skip_context(xd);
377 378 379 380
#if CONFIG_NEW_MULTISYMBOL
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, skip, ec_ctx->skip_cdfs[ctx], 2);
#else
Zoe Liu's avatar
Zoe Liu committed
381
    aom_write(w, skip, cm->fc->skip_probs[ctx]);
382
#endif
Jingning Han's avatar
Jingning Han committed
383 384 385 386
    return skip;
  }
}

387 388 389
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)) {
390
    const int ctx = av1_get_intra_inter_context(xd);
391 392 393 394
#if CONFIG_NEW_MULTISYMBOL
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, is_inter, ec_ctx->intra_inter_cdf[ctx], 2);
#else
395
    aom_write(w, is_inter, cm->fc->intra_inter_prob[ctx]);
396 397 398 399
#endif
  }
}

400 401
static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd,
                              const MODE_INFO *mi, aom_writer *w) {
402
  const MB_MODE_INFO *mbmi = &mi->mbmi;
403

404
  MOTION_MODE last_motion_mode_allowed =
405
      motion_mode_allowed(0, cm->global_motion, xd, mi);
406 407 408
  switch (last_motion_mode_allowed) {
    case SIMPLE_TRANSLATION: break;
    case OBMC_CAUSAL:
409
#if CONFIG_NEW_MULTISYMBOL
410 411
      aom_write_symbol(w, mbmi->motion_mode == OBMC_CAUSAL,
                       xd->tile_ctx->obmc_cdf[mbmi->sb_type], 2);
412
#else
413 414
      aom_write(w, mbmi->motion_mode == OBMC_CAUSAL,
                cm->fc->obmc_prob[mbmi->sb_type]);
415
#endif
416 417 418 419 420
      break;
    default:
      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
421 422
  }
}
423

Thomas Davies's avatar
Thomas Davies committed
424 425
static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               int delta_qindex, aom_writer *w) {
426 427
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
Thomas Davies's avatar
Thomas Davies committed
428
  int rem_bits, thr;
429
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
Thomas Davies's avatar
Thomas Davies committed
430 431
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
432

Thomas Davies's avatar
Thomas Davies committed
433 434
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
435 436 437 438

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
439
    aom_write_literal(w, rem_bits - 1, 3);
440
    aom_write_literal(w, abs - thr, rem_bits);
441 442 443 444 445
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
446

Fangwen Fu's avatar
Fangwen Fu committed
447 448
#if CONFIG_EXT_DELTA_Q
static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
449 450 451
#if CONFIG_LOOPFILTER_LEVEL
                                int lf_id,
#endif
Fangwen Fu's avatar
Fangwen Fu committed
452 453 454 455 456 457 458 459
                                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;

460
#if CONFIG_LOOPFILTER_LEVEL
461 462 463 464 465 466 467 468
  if (cm->delta_lf_multi) {
    assert(lf_id >= 0 && lf_id < FRAME_LF_COUNT);
    aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL),
                     ec_ctx->delta_lf_multi_cdf[lf_id], DELTA_LF_PROBS + 1);
  } else {
    aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                     DELTA_LF_PROBS + 1);
  }
469
#else
Fangwen Fu's avatar
Fangwen Fu committed
470 471
  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);
472
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
473 474 475 476

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
477
    aom_write_literal(w, rem_bits - 1, 3);
Fangwen Fu's avatar
Fangwen Fu committed
478 479 480 481 482 483 484
    aom_write_literal(w, abs - thr, rem_bits);
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
#endif  // CONFIG_EXT_DELTA_Q
485

486
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
487
static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
488 489
                              FRAME_COUNTS *counts) {
  int k;
490 491 492 493 494
  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
495
}
496
#endif
Jingning Han's avatar
Jingning Han committed
497

Sarah Parker's avatar
Sarah Parker committed
498 499
static void pack_map_tokens(aom_writer *w, const TOKENEXTRA **tp, int n,
                            int num) {
500
  const TOKENEXTRA *p = *tp;
501 502 503 504
  write_uniform(w, n, p->token);  // The first color index.
  ++p;
  --num;
  for (int i = 0; i < num; ++i) {
505
    aom_write_symbol(w, p->token, p->color_map_cdf, n);
hui su's avatar
hui su committed
506 507 508 509
    ++p;
  }
  *tp = p;
}
510

511
#if !CONFIG_LV_MAP
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
#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);
  }
}
538
#endif  // CONFIG_NEW_MULTISYMBOL
539

Yaowu Xu's avatar
Yaowu Xu committed
540
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
541
                           const TOKENEXTRA *const stop,
542
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
Sarah Parker's avatar
Sarah Parker committed
543 544 545
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                           TX_TYPE tx_type, int is_inter,
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
546
                           TOKEN_STATS *token_stats) {
547
  const TOKENEXTRA *p = *tp;
548
  int count = 0;
549
  const int seg_eob = tx_size_2d[tx_size];
Jingning Han's avatar
Jingning Han committed
550

Sarah Parker's avatar
Sarah Parker committed
551 552 553 554 555 556 557 558 559 560 561
#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
562
  while (p < stop && p->token != EOSB_TOKEN) {
563
    const int token = p->token;
Yaowu Xu's avatar
Yaowu Xu committed
564
    const int8_t eob_val = p->eob_val;
565
    if (token == BLOCK_Z_TOKEN) {
566
      aom_write_symbol(w, 0, *p->head_cdf, HEAD_TOKENS + 1);
567
      p++;
568
      break;
569 570
      continue;
    }
Yaowu Xu's avatar
Yaowu Xu committed
571 572

    const av1_extra_bit *const extra_bits = &av1_extra_bits[token];
573
    if (eob_val == LAST_EOB) {
574 575 576
      // Just code a flag indicating whether the value is >1 or 1.
      aom_write_bit(w, token != ONE_TOKEN);
    } else {
577
      int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - eob_val + p->first_val;
578
      aom_write_symbol(w, comb_symb, *p->head_cdf, HEAD_TOKENS + p->first_val);
579
    }
580
    if (token > ONE_TOKEN) {
581
      aom_write_symbol(w, token - TWO_TOKEN, *p->tail_cdf, TAIL_TOKENS);
Alex Converse's avatar
Alex Converse committed
582
    }
583 584 585 586

    if (extra_bits->base_val) {
      const int bit_string = p->extra;
      const int bit_string_length = extra_bits->len;  // Length of extra bits to
587
      const int is_cat6 = (extra_bits->base_val == CAT6_MIN_VAL);
588 589
      // be written excluding
      // the sign bit.
590
      int skip_bits = is_cat6
591 592 593
                          ? (int)sizeof(av1_cat6_prob) -
                                av1_get_cat6_extrabits_size(tx_size, bit_depth)
                          : 0;
594

595 596 597 598 599 600 601 602 603
      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
604 605 606 607 608 609

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

    ++count;
610
    if (eob_val == EARLY_EOB || count == seg_eob) break;
611 612 613 614
  }

  *tp = p;
}
Angie Chiang's avatar
Angie Chiang committed
615
#endif  // !CONFIG_LV_MAP
616

617
#if CONFIG_LV_MAP
618
static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
619
                            const TOKENEXTRA **tp,
620 621
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
                            int block, int blk_row, int blk_col,
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
  TX_SIZE plane_tx_size;
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);

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

  plane_tx_size =
      plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
            : mbmi->inter_tx_size[tx_row][tx_col];

  if (tx_size == plane_tx_size) {
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);

    tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
    uint16_t eob = x->mbmi_ext->eobs[plane][block];
    TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
                        x->mbmi_ext->dc_sign_ctx[plane][block] };
Jingning Han's avatar
Jingning Han committed
647 648
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, block, plane, tx_size,
                         tcoeff, eob, &txb_ctx);
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
#if CONFIG_RD_DEBUG
    token_stats->txb_coeff_cost_map[blk_row][blk_col] = tmp_token_stats.cost;
    token_stats->cost += tmp_token_stats.cost;
#endif
  } else {
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
    const int bsl = tx_size_wide_unit[sub_txs];
    int i;

    assert(bsl > 0);

    for (i = 0; i < 4; ++i) {
      const int offsetr = blk_row + (i >> 1) * bsl;
      const int offsetc = blk_col + (i & 0x01) * bsl;
      const int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];

      if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;

667 668
      pack_txb_tokens(w, cm, x, tp, tok_end, xd, mbmi, plane, plane_bsize,
                      bit_depth, block, offsetr, offsetc, sub_txs, token_stats);
669 670 671 672 673
      block += step;
    }
  }
}
#else  // CONFIG_LV_MAP
Yaowu Xu's avatar
Yaowu Xu committed
674
static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp,
Yushin Cho's avatar
Yushin Cho committed
675 676
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
Yaowu Xu's avatar
Yaowu Xu committed
677
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
678
                            int block, int blk_row, int blk_col,
679
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
680 681
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
682 683
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
Debargha Mukherjee's avatar
Debargha Mukherjee committed
684
  TX_SIZE plane_tx_size;
685 686
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Sarah Parker's avatar
Sarah Parker committed
687 688 689 690
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
  TX_TYPE tx_type = av1_get_tx_type(plane ? PLANE_TYPE_UV : PLANE_TYPE_Y, xd,
                                    blk_row, blk_col, block, tx_size);
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
691

692
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
693

694 695 696
  plane_tx_size =
      plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
            : mbmi->inter_tx_size[tx_row][tx_col];
Debargha Mukherjee's avatar
Debargha Mukherjee committed
697

698
  if (tx_size == plane_tx_size) {
699 700
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);
Sarah Parker's avatar
Sarah Parker committed
701 702 703 704 705
    pack_mb_tokens(w, tp, tok_end, bit_depth, tx_size,
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                   tx_type, is_inter_block(mbmi),
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                   &tmp_token_stats);
706 707 708 709
#if CONFIG_RD_DEBUG
    token_stats->txb_coeff_cost_map[blk_row][blk_col] = tmp_token_stats.cost;
    token_stats->cost += tmp_token_stats.cost;
#endif
710
  } else {
Yue Chen's avatar
Yue Chen committed
711 712 713 714
#if CONFIG_RECT_TX_EXT
    int is_qttx = plane_tx_size == quarter_txsize_lookup[plane_bsize];
    const TX_SIZE sub_txs = is_qttx ? plane_tx_size : sub_tx_size_map[tx_size];
#else
715
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
Yue Chen's avatar
Yue Chen committed
716
#endif
717
    const int bsl = tx_size_wide_unit[sub_txs];
718 719 720 721 722
    int i;

    assert(bsl > 0);

    for (i = 0; i < 4; ++i) {
Yue Chen's avatar
Yue Chen committed
723 724 725 726 727 728 729 730 731
#if CONFIG_RECT_TX_EXT
      int is_wide_tx = tx_size_wide_unit[sub_txs] > tx_size_high_unit[sub_txs];
      const int offsetr =
          is_qttx ? (is_wide_tx ? i * tx_size_high_unit[sub_txs] : 0)
                  : blk_row + (i >> 1) * bsl;
      const int offsetc =
          is_qttx ? (is_wide_tx ? 0 : i * tx_size_wide_unit[sub_txs])
                  : blk_col + (i & 0x01) * bsl;
#else
732 733
      const int offsetr = blk_row + (i >> 1) * bsl;
      const int offsetc = blk_col + (i & 0x01) * bsl;
Yue Chen's avatar
Yue Chen committed
734
#endif
735
      const int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
736

737
      if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
738

Yushin Cho's avatar
Yushin Cho committed
739 740
      pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                      block, offsetr, offsetc, sub_txs, token_stats);
741
      block += step;
742 743 744
    }
  }
}
745
#endif  // CONFIG_LV_MAP
746

747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
#if CONFIG_Q_SEGMENTATION
static int neg_interleave(int x, int ref, int max) {
  const int diff = x - ref;
  if (!ref) return x;
  if (ref >= (max - 1)) return -diff;
  if (2 * ref < max) {
    if (abs(diff) <= ref) {
      if (diff > 0)
        return (diff << 1) - 1;
      else
        return ((-diff) << 1);
    }
    return x;
  } else {
    if (abs(diff) < (max - ref)) {
      if (diff > 0)
        return (diff << 1) - 1;
      else
        return ((-diff) << 1);
    }
    return (max - x) - 1;
  }
}

static void write_q_segment_id(const AV1_COMMON *cm, int skip,
                               const MB_MODE_INFO *const mbmi, aom_writer *w,
                               const struct segmentation *seg,
                               struct segmentation_probs *segp,
                               BLOCK_SIZE bsize, int mi_row, int mi_col) {
  int prev_ul = 0; /* Top left segment_id */
  int prev_l = 0;  /* Current left segment_id */
  int prev_u = 0;  /* Current top segment_id */

  if (!seg->q_lvls) return;

  MODE_INFO *const mi = cm->mi + mi_row * cm->mi_stride + mi_col;
  int tinfo = mi->mbmi.boundary_info;
  int above = (!(tinfo & TILE_ABOVE_BOUNDARY)) && ((mi_row - 1) >= 0);
  int left = (!(tinfo & TILE_LEFT_BOUNDARY)) && ((mi_col - 1) >= 0);

  if (above && left)
    prev_ul =
        get_segment_id(cm, cm->q_seg_map, BLOCK_4X4, mi_row - 1, mi_col - 1);

  if (above)
    prev_u = get_segment_id(cm, cm->q_seg_map, BLOCK_4X4, mi_row - 1, mi_col);

  if (left)
    prev_l = get_segment_id(cm, cm->q_seg_map, BLOCK_4X4, mi_row, mi_col - 1);

  int cdf_num = pick_q_seg_cdf(prev_ul, prev_u, prev_l);
  int pred = pick_q_seg_pred(prev_ul, prev_u, prev_l);

  if (skip) {
    set_q_segment_id(cm, cm->q_seg_map, mbmi->sb_type, mi_row, mi_col, pred);
    return;
  }

  int coded_id = neg_interleave(mbmi->q_segment_id, pred, seg->q_lvls);

#if CONFIG_NEW_MULTISYMBOL
  aom_cdf_prob *pred_cdf = segp->q_seg_cdf[cdf_num];
  aom_write_symbol(w, coded_id, pred_cdf, 8);
#else
  aom_prob pred_cdf = segp->q_seg_cdf[cdf_num];
  aom_write(w, coded_id, pred_prob);
#endif

  set_q_segment_id(cm, cm->q_seg_map, bsize, mi_row, mi_col,
                   mbmi->q_segment_id);
}
#endif

Yaowu Xu's avatar
Yaowu Xu committed
820
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
821
                             struct segmentation_probs *segp, int segment_id) {
822 823 824
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
825 826
}

827 828
#if CONFIG_NEW_MULTISYMBOL
#define WRITE_REF_BIT(bname, pname) \
829
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
830 831
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
832 833 834
#else
#define WRITE_REF_BIT(bname, pname) \
  aom_write(w, bname, av1_get_pred_prob_##pname(cm, xd))
835 836
#define WRITE_REF_BIT2(bname, pname) \
  aom_write(w, bname, av1_get_pred_prob_##pname(cm, xd))
837 838
#endif

Jingning Han's avatar
Jingning Han committed
839
// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
840 841
static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                             aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
842 843 844 845 846 847 848 849 850
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const int is_compound = has_second_ref(mbmi);
  const int segment_id = mbmi->segment_id;

  // If segment level coding of this signal is disabled...
  // or the segment allows multiple reference frame options
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
    assert(!is_compound);
    assert(mbmi->ref_frame[0] ==
851
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
852
  }
Sarah Parker's avatar
Sarah Parker committed
853
#if CONFIG_SEGMENT_GLOBALMV
854
  else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP) ||
Sarah Parker's avatar
Sarah Parker committed
855
           segfeature_active(&cm->seg, segment_id, SEG_LVL_GLOBALMV))
856 857 858 859 860 861
#else
  else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP))
#endif
  {
    assert(!is_compound);
    assert(mbmi->ref_frame[0] == LAST_FRAME);
Jingning Han's avatar
Jingning Han committed
862 863 864 865
  } else {
    // does the feature use compound prediction or not
    // (if not specified at the frame/segment level)
    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
866
      if (is_comp_ref_allowed(mbmi->sb_type))
867 868 869
#if CONFIG_NEW_MULTISYMBOL
        aom_write_symbol(w, is_compound, av1_get_reference_mode_cdf(cm, xd), 2);
#else
870 871
        aom_write(w, is_compound, av1_get_reference_mode_prob(cm, xd));
#endif  // CONFIG_NEW_MULTISYMBOL
Jingning Han's avatar
Jingning Han committed
872
    } else {
873
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
874 875 876
    }

    if (is_compound) {
Zoe Liu's avatar
Zoe Liu committed
877 878 879 880
#if CONFIG_EXT_COMP_REFS
      const COMP_REFERENCE_TYPE comp_ref_type = has_uni_comp_refs(mbmi)
                                                    ? UNIDIR_COMP_REFERENCE
                                                    : BIDIR_COMP_REFERENCE;
881
#if CONFIG_NEW_MULTISYMBOL
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
882 883
      aom_write_symbol(w, comp_ref_type, av1_get_comp_reference_type_cdf(xd),
                       2);
884 885 886
#else
      aom_write(w, comp_ref_type, av1_get_comp_reference_type_prob(cm, xd));
#endif
Zoe Liu's avatar
Zoe Liu committed
887 888 889

      if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
        const int bit = mbmi->ref_frame[0] == BWDREF_FRAME;
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
890
        WRITE_REF_BIT2(bit, uni_comp_ref_p);
891

Zoe Liu's avatar
Zoe Liu committed
892
        if (!bit) {
893
          assert(mbmi->ref_frame[0] == LAST_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
894 895 896 897 898 899
          const int bit1 = mbmi->ref_frame[1] == LAST3_FRAME ||
                           mbmi->ref_frame[1] == GOLDEN_FRAME;
          WRITE_REF_BIT2(bit1, uni_comp_ref_p1);
          if (bit1) {
            const int bit2 = mbmi->ref_frame[1] == GOLDEN_FRAME;
            WRITE_REF_BIT2(bit2, uni_comp_ref_p2);
900 901 902
          }
        } else {
          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
Zoe Liu's avatar
Zoe Liu committed
903 904 905 906
        }

        return;
      }
907 908

      assert(comp_ref_type == BIDIR_COMP_REFERENCE);
Zoe Liu's avatar
Zoe Liu committed
909 910
#endif  // CONFIG_EXT_COMP_REFS

911
      const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
912
                       mbmi->ref_frame[0] == LAST3_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
913
      WRITE_REF_BIT(bit, comp_ref_p);
914 915

      if (!bit) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
916 917
        const int bit1 = mbmi->ref_frame[0] == LAST_FRAME;
        WRITE_REF_BIT(bit1, comp_ref_p1);
918
      } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
919 920
        const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
        WRITE_REF_BIT(bit2, comp_ref_p2);
921 922
      }

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
923 924 925 926 927
      const int bit_bwd = mbmi->ref_frame[1] == ALTREF_FRAME;
      WRITE_REF_BIT(bit_bwd, comp_bwdref_p);

      if (!bit_bwd) {
        WRITE_REF_BIT(mbmi->ref_frame[1] == ALTREF2_FRAME, comp_bwdref_p1);
Zoe Liu's avatar
Zoe Liu committed
928 929
      }

Jingning Han's avatar
Jingning Han committed
930
    } else {
Zoe Liu's avatar
Zoe Liu committed
931 932
      const int bit0 = (mbmi->ref_frame[0] <= ALTREF_FRAME &&
                        mbmi->ref_frame[0] >= BWDREF_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
933
      WRITE_REF_BIT(bit0, single_ref_p1);
934 935

      if (bit0) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
936 937 938 939 940
        const int bit1 = mbmi->ref_frame[0] == ALTREF_FRAME;
        WRITE_REF_BIT(bit1, single_ref_p2);

        if (!bit1) {
          WRITE_REF_BIT(mbmi->ref_frame[0] == ALTREF2_FRAME, single_ref_p6);
Zoe Liu's avatar
Zoe Liu committed
941
        }
942 943
      } else {
        const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
944
                          mbmi->ref_frame[0] == GOLDEN_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
945
        WRITE_REF_BIT(bit2, single_ref_p3);
946 947

        if (!bit2) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
948 949
          const int bit3 = mbmi->ref_frame[0] != LAST_FRAME;
          WRITE_REF_BIT(bit3, single_ref_p4);
950
        } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
951 952
          const int bit4 = mbmi->ref_frame[0] != LAST3_FRAME;
          WRITE_REF_BIT(bit4, single_ref_p5);
953 954
        }
      }
Jingning Han's avatar
Jingning Han committed
955 956 957 958
    }
  }
}

959 960
#if CONFIG_FILTER_INTRA
static void write_filter_intra_mode_info(const AV1_COMMON *const cm,
961
                                         const MACROBLOCKD *xd,
962 963
                                         const MB_MODE_INFO *const mbmi,
                                         aom_writer *w) {
964 965
  if (mbmi->mode == DC_PRED && mbmi->palette_mode_info.palette_size[0] == 0 &&
      av1_filter_intra_allowed_txsize(mbmi->tx_size)) {
966 967 968 969 970
    aom_write(w, mbmi->filter_intra_mode_info.use_filter_intra_mode[0],
              cm->fc->filter_intra_probs[0]);
    if (mbmi->filter_intra_mode_info.use_filter_intra_mode[0]) {
      const FILTER_INTRA_MODE mode =
          mbmi->filter_intra_mode_info.filter_intra_mode[0];
971 972
      aom_write_symbol(w, mode, xd->tile_ctx->filter_intra_mode_cdf[0],
                       FILTER_INTRA_MODES);
hui su's avatar
hui su committed
973 974 975
    }
  }
}
976
#endif  // CONFIG_FILTER_INTRA
977

978
#if CONFIG_EXT_INTRA
Joe Young's avatar
Joe Young committed
979 980
static void write_intra_angle_info(const MACROBLOCKD *xd,
                                   FRAME_CONTEXT *const ec_ctx, aom_writer *w) {
981 982
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
983
  if (!av1_use_angle_delta(bsize)) return;
984

hui su's avatar
hui su committed
985
  if (av1_is_directional_mode(mbmi->mode, bsize)) {
Joe Young's avatar
Joe Young committed
986 987 988 989 990 991
#if CONFIG_EXT_INTRA_MOD
    aom_write_symbol(w, mbmi->angle_delta[0] + MAX_ANGLE_DELTA,
                     ec_ctx->angle_delta_cdf[mbmi->mode - V_PRED],
                     2 * MAX_ANGLE_DELTA + 1);
#else
    (void)ec_ctx;
hui su's avatar
hui su committed
992 993
    write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                  MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
Joe Young's avatar
Joe Young committed
994
#endif  // CONFIG_EXT_INTRA_MOD
995 996
  }