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

272 273
    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
274
    // TODO(yuec): set correct txfm partition update for qttx
275
  } else {
276
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
277 278
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
279

280 281 282
#if CONFIG_NEW_MULTISYMBOL
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
#else
Yaowu Xu's avatar
Yaowu Xu committed
283
    aom_write(w, 1, cm->fc->txfm_partition_prob[ctx]);
284
#endif
285

David Barker's avatar
David Barker committed
286
    if (sub_txs == TX_4X4) {
287 288
      txfm_partition_update(xd->above_txfm_context + blk_col,
                            xd->left_txfm_context + blk_row, sub_txs, tx_size);
289
      return;
290
    }
291

292 293 294 295 296 297 298 299
    assert(bsw > 0 && bsh > 0);
    for (int row = 0; row < tx_size_high_unit[tx_size]; row += bsh)
      for (int col = 0; col < tx_size_wide_unit[tx_size]; col += bsw) {
        int offsetr = blk_row + row;
        int offsetc = blk_col + col;
        write_tx_size_vartx(cm, xd, mbmi, sub_txs, depth + 1, offsetr, offsetc,
                            w);
      }
300 301
  }
}
302

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

Yaowu Xu's avatar
Yaowu Xu committed
313 314
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
315 316
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
317 318
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
319
  if (block_signals_txsize(bsize)) {
320
    const TX_SIZE tx_size = mbmi->tx_size;
321
    const int tx_size_ctx = get_tx_size_context(xd);
322
    const int32_t tx_size_cat = intra_tx_size_cat_lookup[bsize];
323
    const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
324 325 326 327 328 329 330
    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));
331
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
332

333
    aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx],
334
                     max_depths + 1);
Jingning Han's avatar
Jingning Han committed
335 336 337
  }
}

338
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
339
static void update_inter_mode_probs(AV1_COMMON *cm, aom_writer *w,
340 341
                                    FRAME_COUNTS *counts) {
  int i;
342
  const int probwt = cm->num_tg;
343
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
344 345
    av1_cond_prob_diff_update(w, &cm->fc->newmv_prob[i], counts->newmv_mode[i],
                              probwt);
Sarah Parker's avatar
Sarah Parker committed
346
  for (i = 0; i < GLOBALMV_MODE_CONTEXTS; ++i)
Yaowu Xu's avatar
Yaowu Xu committed
347
    av1_cond_prob_diff_update(w, &cm->fc->zeromv_prob[i],
348
                              counts->zeromv_mode[i], probwt);
349
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
350 351
    av1_cond_prob_diff_update(w, &cm->fc->refmv_prob[i], counts->refmv_mode[i],
                              probwt);
352
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
353 354
    av1_cond_prob_diff_update(w, &cm->fc->drl_prob[i], counts->drl_mode[i],
                              probwt);
355
}
356
#endif
357

Yaowu Xu's avatar
Yaowu Xu committed
358 359
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
360 361 362 363
  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
364
    const int ctx = av1_get_skip_context(xd);
365 366 367 368
#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
369
    aom_write(w, skip, cm->fc->skip_probs[ctx]);
370
#endif
Jingning Han's avatar
Jingning Han committed
371 372 373 374
    return skip;
  }
}

375 376 377
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)) {
378
    const int ctx = av1_get_intra_inter_context(xd);
379 380 381 382
#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
383
    aom_write(w, is_inter, cm->fc->intra_inter_prob[ctx]);
384 385 386 387
#endif
  }
}

388 389
static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd,
                              const MODE_INFO *mi, aom_writer *w) {
390
  const MB_MODE_INFO *mbmi = &mi->mbmi;
391

392
  MOTION_MODE last_motion_mode_allowed =
393
      motion_mode_allowed(0, cm->global_motion, xd, mi);
394 395 396
  switch (last_motion_mode_allowed) {
    case SIMPLE_TRANSLATION: break;
    case OBMC_CAUSAL:
397
#if CONFIG_NEW_MULTISYMBOL
398 399
      aom_write_symbol(w, mbmi->motion_mode == OBMC_CAUSAL,
                       xd->tile_ctx->obmc_cdf[mbmi->sb_type], 2);
400
#else
401 402
      aom_write(w, mbmi->motion_mode == OBMC_CAUSAL,
                cm->fc->obmc_prob[mbmi->sb_type]);
403
#endif
404 405 406 407 408
      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
409 410
  }
}
411

Thomas Davies's avatar
Thomas Davies committed
412 413
static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               int delta_qindex, aom_writer *w) {
414 415
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
Thomas Davies's avatar
Thomas Davies committed
416
  int rem_bits, thr;
417
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
Thomas Davies's avatar
Thomas Davies committed
418 419
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
420

Thomas Davies's avatar
Thomas Davies committed
421 422
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
423 424 425 426

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
427
    aom_write_literal(w, rem_bits - 1, 3);
428
    aom_write_literal(w, abs - thr, rem_bits);
429 430 431 432 433
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
434

Fangwen Fu's avatar
Fangwen Fu committed
435 436
#if CONFIG_EXT_DELTA_Q
static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
437 438 439
#if CONFIG_LOOPFILTER_LEVEL
                                int lf_id,
#endif
Fangwen Fu's avatar
Fangwen Fu committed
440 441 442 443 444 445 446 447
                                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;

448
#if CONFIG_LOOPFILTER_LEVEL
449 450 451 452 453 454 455 456
  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);
  }
457
#else
Fangwen Fu's avatar
Fangwen Fu committed
458 459
  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);
460
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
461 462 463 464

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
465
    aom_write_literal(w, rem_bits - 1, 3);
Fangwen Fu's avatar
Fangwen Fu committed
466 467 468 469 470 471 472
    aom_write_literal(w, abs - thr, rem_bits);
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
#endif  // CONFIG_EXT_DELTA_Q
473

474
#if !CONFIG_NEW_MULTISYMBOL
Yaowu Xu's avatar
Yaowu Xu committed
475
static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
Jingning Han's avatar
Jingning Han committed
476 477
                              FRAME_COUNTS *counts) {
  int k;
478 479 480 481 482
  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
483
}
484
#endif
Jingning Han's avatar
Jingning Han committed
485

Sarah Parker's avatar
Sarah Parker committed
486 487
static void pack_map_tokens(aom_writer *w, const TOKENEXTRA **tp, int n,
                            int num) {
488
  const TOKENEXTRA *p = *tp;
489 490 491 492
  write_uniform(w, n, p->token);  // The first color index.
  ++p;
  --num;
  for (int i = 0; i < num; ++i) {
493
    aom_write_symbol(w, p->token, p->color_map_cdf, n);
hui su's avatar
hui su committed
494 495 496 497
    ++p;
  }
  *tp = p;
}
498

499
#if !CONFIG_LV_MAP
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
#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);
  }
}
526
#endif  // CONFIG_NEW_MULTISYMBOL
527

Yaowu Xu's avatar
Yaowu Xu committed
528
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
529
                           const TOKENEXTRA *const stop,
530
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
Sarah Parker's avatar
Sarah Parker committed
531 532 533
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                           TX_TYPE tx_type, int is_inter,
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
534
                           TOKEN_STATS *token_stats) {
535
  const TOKENEXTRA *p = *tp;
536
  int count = 0;
537
  const int seg_eob = tx_size_2d[tx_size];
Jingning Han's avatar
Jingning Han committed
538

Sarah Parker's avatar
Sarah Parker committed
539 540 541 542 543 544 545 546 547 548 549
#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
550
  while (p < stop && p->token != EOSB_TOKEN) {
551
    const int token = p->token;
Yaowu Xu's avatar
Yaowu Xu committed
552
    const int8_t eob_val = p->eob_val;
553
    if (token == BLOCK_Z_TOKEN) {
554
      aom_write_symbol(w, 0, *p->head_cdf, HEAD_TOKENS + 1);
555
      p++;
556
      break;
557 558
      continue;
    }
Yaowu Xu's avatar
Yaowu Xu committed
559 560

    const av1_extra_bit *const extra_bits = &av1_extra_bits[token];
561
    if (eob_val == LAST_EOB) {
562 563 564
      // Just code a flag indicating whether the value is >1 or 1.
      aom_write_bit(w, token != ONE_TOKEN);
    } else {
565
      int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - eob_val + p->first_val;
566
      aom_write_symbol(w, comb_symb, *p->head_cdf, HEAD_TOKENS + p->first_val);
567
    }
568
    if (token > ONE_TOKEN) {
569
      aom_write_symbol(w, token - TWO_TOKEN, *p->tail_cdf, TAIL_TOKENS);
Alex Converse's avatar
Alex Converse committed
570
    }
571 572 573 574

    if (extra_bits->base_val) {
      const int bit_string = p->extra;
      const int bit_string_length = extra_bits->len;  // Length of extra bits to
575
      const int is_cat6 = (extra_bits->base_val == CAT6_MIN_VAL);
576 577
      // be written excluding
      // the sign bit.
578
      int skip_bits = is_cat6
579 580 581
                          ? (int)sizeof(av1_cat6_prob) -
                                av1_get_cat6_extrabits_size(tx_size, bit_depth)
                          : 0;
582

583 584 585 586 587 588 589 590 591
      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
592 593 594 595 596 597

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

    ++count;
598
    if (eob_val == EARLY_EOB || count == seg_eob) break;
599 600 601 602
  }

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

605
#if CONFIG_LV_MAP
606
static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
607
                            const TOKENEXTRA **tp,
608 609
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
                            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
635 636
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, block, plane, tx_size,
                         tcoeff, eob, &txb_ctx);
637 638 639 640 641 642
#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];
643 644
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
645

646
    assert(bsw > 0 && bsh > 0);
647

648 649 650 651 652
    for (int r = 0; r < tx_size_high_unit[tx_size]; r += bsh) {
      for (int c = 0; c < tx_size_wide_unit[tx_size]; c += bsw) {
        const int offsetr = blk_row + r;
        const int offsetc = blk_col + c;
        const int step = bsh * bsw;
653

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

656 657 658 659 660
        pack_txb_tokens(w, cm, x, tp, tok_end, xd, mbmi, plane, plane_bsize,
                        bit_depth, block, offsetr, offsetc, sub_txs,
                        token_stats);
        block += step;
      }
661 662 663 664
    }
  }
}
#else  // CONFIG_LV_MAP
Yaowu Xu's avatar
Yaowu Xu committed
665
static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp,
Yushin Cho's avatar
Yushin Cho committed
666 667
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
Yaowu Xu's avatar
Yaowu Xu committed
668
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
669
                            int block, int blk_row, int blk_col,
670
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
671 672
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
673 674
  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
675
  TX_SIZE plane_tx_size;
676 677
  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
678 679 680 681
#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
682

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

685 686 687
  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
688

689
  if (tx_size == plane_tx_size) {
690 691
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);
Sarah Parker's avatar
Sarah Parker committed
692 693 694 695 696
    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);
697 698 699 700
#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
701
  } else {
702
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
703 704
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
705

706
    assert(bsw > 0 && bsh > 0);
707

708 709 710 711 712
    for (int r = 0; r < tx_size_high_unit[tx_size]; r += bsh) {
      for (int c = 0; c < tx_size_wide_unit[tx_size]; c += bsw) {
        const int offsetr = blk_row + r;
        const int offsetc = blk_col + c;
        const int step = bsh * bsw;
713

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

716 717 718 719
        pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                        block, offsetr, offsetc, sub_txs, token_stats);
        block += step;
      }
720 721 722
    }
  }
}
723
#endif  // CONFIG_LV_MAP
724

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 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
#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
798
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
799
                             struct segmentation_probs *segp, int segment_id) {
800 801 802
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
803 804
}

805 806
#if CONFIG_NEW_MULTISYMBOL
#define WRITE_REF_BIT(bname, pname) \
807
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
808 809
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
810 811 812
#else
#define WRITE_REF_BIT(bname, pname) \
  aom_write(w, bname, av1_get_pred_prob_##pname(cm, xd))
813 814
#define WRITE_REF_BIT2(bname, pname) \
  aom_write(w, bname, av1_get_pred_prob_##pname(cm, xd))
815 816
#endif

Jingning Han's avatar
Jingning Han committed
817
// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
818 819
static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                             aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
820 821 822 823 824 825 826 827 828
  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] ==
829
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
830
  }
Sarah Parker's avatar
Sarah Parker committed
831
#if CONFIG_SEGMENT_GLOBALMV
832
  else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP) ||
Sarah Parker's avatar
Sarah Parker committed
833
           segfeature_active(&cm->seg, segment_id, SEG_LVL_GLOBALMV))
834 835 836 837 838 839
#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
840 841 842 843
  } else {
    // does the feature use compound prediction or not
    // (if not specified at the frame/segment level)
    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
844
      if (is_comp_ref_allowed(mbmi->sb_type))
845 846 847
#if CONFIG_NEW_MULTISYMBOL
        aom_write_symbol(w, is_compound, av1_get_reference_mode_cdf(cm, xd), 2);
#else
848 849
        aom_write(w, is_compound, av1_get_reference_mode_prob(cm, xd));
#endif  // CONFIG_NEW_MULTISYMBOL
Jingning Han's avatar
Jingning Han committed
850
    } else {
851
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
852 853 854
    }

    if (is_compound) {
Zoe Liu's avatar
Zoe Liu committed
855 856 857 858
#if CONFIG_EXT_COMP_REFS
      const COMP_REFERENCE_TYPE comp_ref_type = has_uni_comp_refs(mbmi)
                                                    ? UNIDIR_COMP_REFERENCE
                                                    : BIDIR_COMP_REFERENCE;
859
#if CONFIG_NEW_MULTISYMBOL
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
860 861
      aom_write_symbol(w, comp_ref_type, av1_get_comp_reference_type_cdf(xd),
                       2);
862 863 864
#else
      aom_write(w, comp_ref_type, av1_get_comp_reference_type_prob(cm, xd));
#endif
Zoe Liu's avatar
Zoe Liu committed
865 866 867

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

Zoe Liu's avatar
Zoe Liu committed
870
        if (!bit) {
871
          assert(mbmi->ref_frame[0] == LAST_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
872 873 874 875 876 877
          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);
878 879 880
          }
        } else {
          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
Zoe Liu's avatar
Zoe Liu committed
881 882 883 884
        }

        return;
      }
885 886

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

889
      const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
890
                       mbmi->ref_frame[0] == LAST3_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
891
      WRITE_REF_BIT(bit, comp_ref_p);
892 893

      if (!bit) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
894 895
        const int bit1 = mbmi->ref_frame[0] == LAST_FRAME;
        WRITE_REF_BIT(bit1, comp_ref_p1);
896
      } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
897 898
        const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
        WRITE_REF_BIT(bit2, comp_ref_p2);
899 900
      }