bitstream.c 185 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
#include "av1/common/cdef.h"
28
29
30
31
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
#include "av1/common/entropymv.h"
#include "av1/common/mvref_common.h"
32
#include "av1/common/odintrin.h"
33
34
#include "av1/common/pred_common.h"
#include "av1/common/reconinter.h"
hui su's avatar
hui su committed
35
36
37
#if CONFIG_EXT_INTRA
#include "av1/common/reconintra.h"
#endif  // CONFIG_EXT_INTRA
38
39
#include "av1/common/seg_common.h"
#include "av1/common/tile_common.h"
Jingning Han's avatar
Jingning Han committed
40

Angie Chiang's avatar
Angie Chiang committed
41
42
43
#if CONFIG_LV_MAP
#include "av1/encoder/encodetxb.h"
#endif  // CONFIG_LV_MAP
44
45
46
47
#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
48
#if CONFIG_PALETTE_DELTA_ENCODING
hui su's avatar
hui su committed
49
#include "av1/encoder/palette.h"
Urvang Joshi's avatar
Urvang Joshi committed
50
#endif  // CONFIG_PALETTE_DELTA_ENCODING
51
52
53
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
Jingning Han's avatar
Jingning Han committed
54

55
#define ENC_MISMATCH_DEBUG 0
56

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

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

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

90
static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data);
91

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

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

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

125
126
127
128
129
#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
130

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

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

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

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

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

  assert(mbmi->ref_mv_idx < 3);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    assert(coded_tx_size <= tx_size_cat + 1);
    assert(depth >= 0 && depth <= max_depths);

    assert(!is_inter_block(mbmi));
335
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
336

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

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

Yaowu Xu's avatar
Yaowu Xu committed
372
373
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
374
375
376
377
  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
378
    const int ctx = av1_get_skip_context(xd);
379
380
381
382
#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
383
    aom_write(w, skip, cm->fc->skip_probs[ctx]);
384
#endif
Jingning Han's avatar
Jingning Han committed
385
386
387
388
    return skip;
  }
}

389
390
391
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)) {
392
    const int ctx = av1_get_intra_inter_context(xd);
393
394
395
396
#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
397
    aom_write(w, is_inter, cm->fc->intra_inter_prob[ctx]);
398
399
400
401
#endif
  }
}

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

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

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

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

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

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

462
#if CONFIG_LOOPFILTER_LEVEL
463
464
465
466
467
468
469
470
  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);
  }
471
#else
Fangwen Fu's avatar
Fangwen Fu committed
472
473
  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);
474
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
475
476
477
478

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

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

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

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

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

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

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

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

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

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

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

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

619
#if CONFIG_LV_MAP
620
static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
621
                            const TOKENEXTRA **tp,
622
623
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
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
                            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
649
650
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, block, plane, tx_size,
                         tcoeff, eob, &txb_ctx);
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
#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;

669
670
      pack_txb_tokens(w, cm, x, tp, tok_end, xd, mbmi, plane, plane_bsize,
                      bit_depth, block, offsetr, offsetc, sub_txs, token_stats);
671
672
673
674
675
      block += step;
    }
  }
}
#else  // CONFIG_LV_MAP
Yaowu Xu's avatar
Yaowu Xu committed
676
static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp,
Yushin Cho's avatar
Yushin Cho committed
677
678
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
Yaowu Xu's avatar
Yaowu Xu committed
679
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
680
                            int block, int blk_row, int blk_col,
681
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
682
683
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
684
685
  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
686
  TX_SIZE plane_tx_size;
687
688
  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
689
690
691
692
#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
693

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

696
697
698
  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
699

700
  if (tx_size == plane_tx_size) {
701
702
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);
Sarah Parker's avatar
Sarah Parker committed
703
704
705
706
707
    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);
708
709
710
711
#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
712
  } else {
Yue Chen's avatar
Yue Chen committed
713
714
715
716
#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
717
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
Yue Chen's avatar
Yue Chen committed
718
#endif
719
    const int bsl = tx_size_wide_unit[sub_txs];
720
721
722
723
724
    int i;

    assert(bsl > 0);

    for (i = 0; i < 4; ++i) {
Yue Chen's avatar
Yue Chen committed
725
726
727
728
729
730
731
732
733
#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
734
735
      const int offsetr = blk_row + (i >> 1) * bsl;
      const int offsetc = blk_col + (i & 0x01) * bsl;
Yue Chen's avatar
Yue Chen committed
736
#endif
737
      const int step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
738

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

Yushin Cho's avatar
Yushin Cho committed
741
742
      pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                      block, offsetr, offsetc, sub_txs, token_stats);
743
      block += step;
744
745
746
    }
  }
}
747
#endif  // CONFIG_LV_MAP
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
820
821
#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
822
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
823
                             struct segmentation_probs *segp, int segment_id) {
824
825
826
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
827
828
}

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

Jingning Han's avatar
Jingning Han committed
841
// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
842
843
static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                             aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
844
845
846
847
848
849
850
851
852
  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] ==
853
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
854
  }
Sarah Parker's avatar
Sarah Parker committed
855
#if CONFIG_SEGMENT_GLOBALMV
856
  else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP) ||
Sarah Parker's avatar
Sarah Parker committed
857
           segfeature_active(&cm->seg, segment_id, SEG_LVL_GLOBALMV))
858
859
860
861
862
863
#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
864
865
866
867
  } else {
    // does the feature use compound prediction or not
    // (if not specified at the frame/segment level)
    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
868
      if (is_comp_ref_allowed(mbmi->sb_type))
869
870
871
#if CONFIG_NEW_MULTISYMBOL
        aom_write_symbol(w, is_compound, av1_get_reference_mode_cdf(cm, xd), 2);
#else
872
873
        aom_write(w, is_compound, av1_get_reference_mode_prob(cm, xd));
#endif  // CONFIG_NEW_MULTISYMBOL
Jingning Han's avatar
Jingning Han committed
874
    } else {
875
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
876
877
878
    }

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

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

Zoe Liu's avatar
Zoe Liu committed
894
        if (!bit) {
895
          assert(mbmi->ref_frame[0] == LAST_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
896
897
898
899
900
901
          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);
902
903
904
          }
        } else {
          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
Zoe Liu's avatar
Zoe Liu committed
905
906
907
908
        }

        return;
      }
909
910

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

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

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

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
925
926
927
928
929
      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
930
931
      }

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

      if (bit0) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
938
939
940
941
942
        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
943
        }
944
945
      } else {
        const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
946
                          mbmi->ref_frame[0] == GOLDEN_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
947
        WRITE_REF_BIT(bit2, single_ref_p3);
Zoe Liu's avatar