bitstream.c 176 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

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

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

85
static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data);
86

87
#if !CONFIG_OBU || CONFIG_EXT_TILE
88 89 90 91 92
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);
93
#endif
Yaowu Xu's avatar
Yaowu Xu committed
94 95
void av1_encode_token_init(void) {
  av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree);
96
  av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree);
97 98
}

Jingning Han's avatar
Jingning Han committed
99 100 101 102
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
103 104 105
#if CONFIG_INTRABC
  assert(!is_intrabc_block(&mi->mbmi));
#endif  // CONFIG_INTRABC
Hui Su's avatar
Hui Su committed
106
  aom_write_symbol(w, mode,
Jingning Han's avatar
Jingning Han committed
107 108 109 110
                   get_y_mode_cdf(frame_ctx, mi, above_mi, left_mi, block),
                   INTRA_MODES);
  (void)cm;
}
Jingning Han's avatar
Jingning Han committed
111

112
static void write_inter_mode(aom_writer *w, PREDICTION_MODE mode,
113
                             FRAME_CONTEXT *ec_ctx, const int16_t mode_ctx) {
114
  const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
Yue Chen's avatar
Yue Chen committed
115

116
  aom_write_symbol(w, mode != NEWMV, ec_ctx->newmv_cdf[newmv_ctx], 2);
117

Jingning Han's avatar
Jingning Han committed
118
  if (mode != NEWMV) {
119
    if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
Sarah Parker's avatar
Sarah Parker committed
120
      assert(mode == GLOBALMV);
121 122 123
      return;
    }

Sarah Parker's avatar
Sarah Parker committed
124 125 126
    const int16_t zeromv_ctx =
        (mode_ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
    aom_write_symbol(w, mode != GLOBALMV, ec_ctx->zeromv_cdf[zeromv_ctx], 2);
127

Sarah Parker's avatar
Sarah Parker committed
128
    if (mode != GLOBALMV) {
129 130
      int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;

131 132 133
      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;
134
      aom_write_symbol(w, mode != NEARESTMV, ec_ctx->refmv_cdf[refmv_ctx], 2);
135 136
    }
  }
Jingning Han's avatar
Jingning Han committed
137 138
}

139
static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
Yaowu Xu's avatar
Yaowu Xu committed
140 141
                          const MB_MODE_INFO_EXT *mbmi_ext, aom_writer *w) {
  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
142 143 144

  assert(mbmi->ref_mv_idx < 3);

145
  const int new_mv = mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV;
146
  if (new_mv) {
147 148 149 150
    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
151
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
152

153 154
        aom_write_symbol(w, mbmi->ref_mv_idx != idx, ec_ctx->drl_cdf[drl_ctx],
                         2);
155
        if (mbmi->ref_mv_idx == idx) return;
156
      }
157 158 159 160
    }
    return;
  }

David Barker's avatar
David Barker committed
161
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
162 163 164 165 166
    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
167
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
168 169
        aom_write_symbol(w, mbmi->ref_mv_idx != (idx - 1),
                         ec_ctx->drl_cdf[drl_ctx], 2);
170
        if (mbmi->ref_mv_idx == (idx - 1)) return;
171
      }
172
    }
173
    return;
174 175 176
  }
}

177 178
static void write_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                      aom_writer *w, PREDICTION_MODE mode,
179
                                      const int16_t mode_ctx) {
180 181 182 183 184
  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);
185
}
186

Yaowu Xu's avatar
Yaowu Xu committed
187
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
188
                                int max) {
Yaowu Xu's avatar
Yaowu Xu committed
189
  aom_wb_write_literal(wb, data, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
190 191
}

192
static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd,
193
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
194 195
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
196 197
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
198 199
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
200 201 202
  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);

203 204
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
205
                                   mbmi->sb_type, tx_size);
206

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

Jingning Han's avatar
Jingning Han committed
209
  if (depth == MAX_VARTX_DEPTH) {
210 211
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
212 213 214
    return;
  }

215 216 217
  const int write_txfm_partition =
      tx_size == mbmi->inter_tx_size[tx_row][tx_col];
  if (write_txfm_partition) {
218 219
    aom_write_symbol(w, 0, ec_ctx->txfm_partition_cdf[ctx], 2);

220 221
    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
222
    // TODO(yuec): set correct txfm partition update for qttx
223
  } else {
224
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
225 226
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
227

228
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
229

David Barker's avatar
David Barker committed
230
    if (sub_txs == TX_4X4) {
231 232
      txfm_partition_update(xd->above_txfm_context + blk_col,
                            xd->left_txfm_context + blk_row, sub_txs, tx_size);
233
      return;
234
    }
235

236 237 238 239 240 241 242 243
    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);
      }
244 245
  }
}
246

Yaowu Xu's avatar
Yaowu Xu committed
247 248
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
249 250
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
251 252
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
253
  if (block_signals_txsize(bsize)) {
254
    const TX_SIZE tx_size = mbmi->tx_size;
255
    const int tx_size_ctx = get_tx_size_context(xd);
256
    const int32_t tx_size_cat = intra_tx_size_cat_lookup[bsize];
257
    const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
258 259 260 261 262 263 264
    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));
265
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
266

267
    aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx],
268
                     max_depths + 1);
Jingning Han's avatar
Jingning Han committed
269 270 271
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
272 273
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
274 275 276 277
  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
278
    const int ctx = av1_get_skip_context(xd);
279 280
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, skip, ec_ctx->skip_cdfs[ctx], 2);
Jingning Han's avatar
Jingning Han committed
281 282 283 284
    return skip;
  }
}

Zoe Liu's avatar
Zoe Liu committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
#if CONFIG_EXT_SKIP
static int write_skip_mode(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                           int segment_id, const MODE_INFO *mi, aom_writer *w) {
  if (!cm->skip_mode_flag) return 0;
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 0;
  }
  const int skip_mode = mi->mbmi.skip_mode;
  if (!is_comp_ref_allowed(mi->mbmi.sb_type)) {
    assert(!skip_mode);
    return 0;
  }
  const int ctx = av1_get_skip_mode_context(xd);
  aom_write_symbol(w, skip_mode, xd->tile_ctx->skip_mode_cdfs[ctx], 2);
  return skip_mode;
}
#endif  // CONFIG_EXT_SKIP

303 304 305
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)) {
306
    const int ctx = av1_get_intra_inter_context(xd);
307 308 309 310 311
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, is_inter, ec_ctx->intra_inter_cdf[ctx], 2);
  }
}

312 313
static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd,
                              const MODE_INFO *mi, aom_writer *w) {
314
  const MB_MODE_INFO *mbmi = &mi->mbmi;
315

316
  MOTION_MODE last_motion_mode_allowed =
317
      motion_mode_allowed(0, cm->global_motion, xd, mi);
318 319 320 321 322 323 324 325 326 327
  switch (last_motion_mode_allowed) {
    case SIMPLE_TRANSLATION: break;
    case OBMC_CAUSAL:
      aom_write_symbol(w, mbmi->motion_mode == OBMC_CAUSAL,
                       xd->tile_ctx->obmc_cdf[mbmi->sb_type], 2);
      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
328 329
  }
}
330

Thomas Davies's avatar
Thomas Davies committed
331 332
static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               int delta_qindex, aom_writer *w) {
333 334
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
Thomas Davies's avatar
Thomas Davies committed
335
  int rem_bits, thr;
336
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
Thomas Davies's avatar
Thomas Davies committed
337 338
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
339

Thomas Davies's avatar
Thomas Davies committed
340 341
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
342 343 344 345

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
346
    aom_write_literal(w, rem_bits - 1, 3);
347
    aom_write_literal(w, abs - thr, rem_bits);
348 349 350 351 352
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
353

Fangwen Fu's avatar
Fangwen Fu committed
354 355
#if CONFIG_EXT_DELTA_Q
static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
356 357 358
#if CONFIG_LOOPFILTER_LEVEL
                                int lf_id,
#endif
Fangwen Fu's avatar
Fangwen Fu committed
359 360 361 362 363 364 365 366
                                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;

367
#if CONFIG_LOOPFILTER_LEVEL
368 369 370 371 372 373 374 375
  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);
  }
376
#else
Fangwen Fu's avatar
Fangwen Fu committed
377 378
  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);
379
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
380 381 382 383

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
384
    aom_write_literal(w, rem_bits - 1, 3);
Fangwen Fu's avatar
Fangwen Fu committed
385 386 387 388 389 390 391
    aom_write_literal(w, abs - thr, rem_bits);
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
#endif  // CONFIG_EXT_DELTA_Q
392

Sarah Parker's avatar
Sarah Parker committed
393 394
static void pack_map_tokens(aom_writer *w, const TOKENEXTRA **tp, int n,
                            int num) {
395
  const TOKENEXTRA *p = *tp;
396 397 398 399
  write_uniform(w, n, p->token);  // The first color index.
  ++p;
  --num;
  for (int i = 0; i < num; ++i) {
400
    aom_write_symbol(w, p->token, p->color_map_cdf, n);
hui su's avatar
hui su committed
401 402 403 404
    ++p;
  }
  *tp = p;
}
405

406
#if !CONFIG_LV_MAP
407 408 409 410 411 412 413 414 415 416 417 418 419 420
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;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
421
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
422
                           const TOKENEXTRA *const stop,
423
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
Sarah Parker's avatar
Sarah Parker committed
424 425 426
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                           TX_TYPE tx_type, int is_inter,
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
427
                           TOKEN_STATS *token_stats) {
428
  const TOKENEXTRA *p = *tp;
429
  int count = 0;
430
  const int seg_eob = av1_get_max_eob(tx_size);
Jingning Han's avatar
Jingning Han committed
431

Sarah Parker's avatar
Sarah Parker committed
432 433 434 435 436 437 438 439 440 441 442
#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
443
  while (p < stop && p->token != EOSB_TOKEN) {
444
    const int token = p->token;
Yaowu Xu's avatar
Yaowu Xu committed
445
    const int8_t eob_val = p->eob_val;
446
    if (token == BLOCK_Z_TOKEN) {
447
      aom_write_symbol(w, 0, *p->head_cdf, HEAD_TOKENS + 1);
448
      p++;
449
      break;
450 451
      continue;
    }
Yaowu Xu's avatar
Yaowu Xu committed
452 453

    const av1_extra_bit *const extra_bits = &av1_extra_bits[token];
454
    if (eob_val == LAST_EOB) {
455 456 457
      // Just code a flag indicating whether the value is >1 or 1.
      aom_write_bit(w, token != ONE_TOKEN);
    } else {
458
      int comb_symb = 2 * AOMMIN(token, TWO_TOKEN) - eob_val + p->first_val;
459
      aom_write_symbol(w, comb_symb, *p->head_cdf, HEAD_TOKENS + p->first_val);
460
    }
461
    if (token > ONE_TOKEN) {
462
      aom_write_symbol(w, token - TWO_TOKEN, *p->tail_cdf, TAIL_TOKENS);
Alex Converse's avatar
Alex Converse committed
463
    }
464 465 466 467

    if (extra_bits->base_val) {
      const int bit_string = p->extra;
      const int bit_string_length = extra_bits->len;  // Length of extra bits to
468
      const int is_cat6 = (extra_bits->base_val == CAT6_MIN_VAL);
469 470
      // be written excluding
      // the sign bit.
471
      int skip_bits = is_cat6
472 473 474
                          ? (int)sizeof(av1_cat6_prob) -
                                av1_get_cat6_extrabits_size(tx_size, bit_depth)
                          : 0;
475

476 477 478 479
      assert(!(bit_string >> (bit_string_length - skip_bits + 1)));
      if (bit_string_length > 0)
        write_coeff_extra(extra_bits->cdf, bit_string >> 1,
                          bit_string_length - skip_bits, w);
480 481 482 483 484 485

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

    ++count;
486
    if (eob_val == EARLY_EOB || count == seg_eob) break;
487 488 489 490
  }

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

493
#if CONFIG_LV_MAP
494
static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
495
                            const TOKENEXTRA **tp,
496 497
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
                            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];

515 516 517 518 519
  if (tx_size == plane_tx_size
#if DISABLE_VARTX_FOR_CHROMA
      || pd->subsampling_x || pd->subsampling_y
#endif  // DISABLE_VARTX_FOR_CHROMA
      ) {
520 521 522 523 524 525 526
    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
527 528
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, block, plane, tx_size,
                         tcoeff, eob, &txb_ctx);
529 530 531 532 533 534
#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];
535 536
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
537

538
    assert(bsw > 0 && bsh > 0);
539

540 541 542 543 544
    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;
545

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

548 549 550 551 552
        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;
      }
553 554 555 556
    }
  }
}
#else  // CONFIG_LV_MAP
Yaowu Xu's avatar
Yaowu Xu committed
557
static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp,
Yushin Cho's avatar
Yushin Cho committed
558 559
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
Yaowu Xu's avatar
Yaowu Xu committed
560
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
561
                            int block, int blk_row, int blk_col,
562
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
563 564
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
565 566
  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
567
  TX_SIZE plane_tx_size;
568 569
  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
570 571 572 573
#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
574

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

577 578 579
  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
580

581 582 583 584 585
  if (tx_size == plane_tx_size
#if DISABLE_VARTX_FOR_CHROMA
      || pd->subsampling_x || pd->subsampling_y
#endif  // DISABLE_VARTX_FOR_CHROMA
      ) {
586 587
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);
Sarah Parker's avatar
Sarah Parker committed
588 589 590 591 592
    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);
593 594 595 596
#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
597
  } else {
598
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
599 600
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
601

602
    assert(bsw > 0 && bsh > 0);
603

604 605 606 607 608
    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;
609

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

612 613 614 615
        pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                        block, offsetr, offsetc, sub_txs, token_stats);
        block += step;
      }
616 617 618
    }
  }
}
619
#endif  // CONFIG_LV_MAP
620

621 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 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
#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);

  aom_cdf_prob *pred_cdf = segp->q_seg_cdf[cdf_num];
  aom_write_symbol(w, coded_id, pred_cdf, 8);

  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
689
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
690
                             struct segmentation_probs *segp, int segment_id) {
691 692 693
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
694 695
}

696
#define WRITE_REF_BIT(bname, pname) \
697
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
698 699
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
700

Jingning Han's avatar
Jingning Han committed
701
// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
702 703
static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                             aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
704 705 706 707 708 709 710 711 712
  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] ==
713
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
714
  }
Sarah Parker's avatar
Sarah Parker committed
715
#if CONFIG_SEGMENT_GLOBALMV
716
  else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP) ||
Sarah Parker's avatar
Sarah Parker committed
717
           segfeature_active(&cm->seg, segment_id, SEG_LVL_GLOBALMV))
718 719 720 721 722 723
#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
724 725 726 727
  } else {
    // does the feature use compound prediction or not
    // (if not specified at the frame/segment level)
    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
728
      if (is_comp_ref_allowed(mbmi->sb_type))
729
        aom_write_symbol(w, is_compound, av1_get_reference_mode_cdf(cm, xd), 2);
Jingning Han's avatar
Jingning Han committed
730
    } else {
731
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
732 733 734
    }

    if (is_compound) {
Zoe Liu's avatar
Zoe Liu committed
735 736 737 738
#if CONFIG_EXT_COMP_REFS
      const COMP_REFERENCE_TYPE comp_ref_type = has_uni_comp_refs(mbmi)
                                                    ? UNIDIR_COMP_REFERENCE
                                                    : BIDIR_COMP_REFERENCE;
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
739 740
      aom_write_symbol(w, comp_ref_type, av1_get_comp_reference_type_cdf(xd),
                       2);
Zoe Liu's avatar
Zoe Liu committed
741 742 743

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

Zoe Liu's avatar
Zoe Liu committed
746
        if (!bit) {
747
          assert(mbmi->ref_frame[0] == LAST_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
748 749 750 751 752 753
          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);
754 755 756
          }
        } else {
          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
Zoe Liu's avatar
Zoe Liu committed
757 758 759 760
        }

        return;
      }
761 762

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

765
      const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
766
                       mbmi->ref_frame[0] == LAST3_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
767
      WRITE_REF_BIT(bit, comp_ref_p);
768 769

      if (!bit) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
770 771
        const int bit1 = mbmi->ref_frame[0] == LAST_FRAME;
        WRITE_REF_BIT(bit1, comp_ref_p1);
772
      } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
773 774
        const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
        WRITE_REF_BIT(bit2, comp_ref_p2);
775 776
      }

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
777 778 779 780 781
      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
782 783
      }

Jingning Han's avatar
Jingning Han committed
784
    } else {
Zoe Liu's avatar
Zoe Liu committed
785 786
      const int bit0 = (mbmi->ref_frame[0] <= ALTREF_FRAME &&
                        mbmi->ref_frame[0] >= BWDREF_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
787
      WRITE_REF_BIT(bit0, single_ref_p1);
788 789

      if (bit0) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
790 791 792 793 794
        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
795
        }
796 797
      } else {
        const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
798
                          mbmi->ref_frame[0] == GOLDEN_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
799
        WRITE_REF_BIT(bit2, single_ref_p3);
800 801

        if (!bit2) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
802 803
          const int bit3 = mbmi->ref_frame[0] != LAST_FRAME;
          WRITE_REF_BIT(bit3, single_ref_p4);
804
        } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
805 806
          const int bit4 = mbmi->ref_frame[0] != LAST3_FRAME;
          WRITE_REF_BIT(bit4, single_ref_p5);
807 808
        }
      }
Jingning Han's avatar
Jingning Han committed
809 810 811 812
    }
  }
}

813
#if CONFIG_FILTER_INTRA
814
static void write_filter_intra_mode_info(const MACROBLOCKD *xd,
815 816
                                         const MB_MODE_INFO *const mbmi,
                                         aom_writer *w) {
817 818
  if (mbmi->mode == DC_PRED && mbmi->palette_mode_info.palette_size[0] == 0 &&
      av1_filter_intra_allowed_txsize(mbmi->tx_size)) {
819 820
    aom_write_symbol(w, mbmi->filter_intra_mode_info.use_filter_intra_mode[0],
                     xd->tile_ctx->filter_intra_cdfs[mbmi->tx_size], 2);
821 822 823
    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];
824 825
      aom_write_symbol(w, mode, xd->tile_ctx->filter_intra_mode_cdf[0],
                       FILTER_INTRA_MODES);
hui su's avatar
hui su committed
826 827 828
    }
  }
}
829
#endif  // CONFIG_FILTER_INTRA
830

831
#if CONFIG_EXT_INTRA
Joe Young's avatar
Joe Young committed
832 833
static void write_intra_angle_info(const MACROBLOCKD *xd,
                                   FRAME_CONTEXT *const ec_ctx, aom_writer *w) {
834 835
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
836
  if (!av1_use_angle_delta(bsize)) return;
837

hui su's avatar
hui su committed
838
  if (av1_is_directional_mode(mbmi->mode, bsize)) {
Joe Young's avatar
Joe Young committed
839 840 841 842 843 844
#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
845 846
    write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                  MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
Joe Young's avatar
Joe Young committed
847
#endif  // CONFIG_EXT_INTRA_MOD
848 849
  }

Luc Trudeau's avatar
Luc Trudeau committed
850
  if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize)) {
Joe Young's avatar
Joe Young committed
851 852 853 854 855
#if CONFIG_EXT_INTRA_MOD
    aom_write_symbol(w, mbmi->angle_delta[1] + MAX_ANGLE_DELTA,
                     ec_ctx->angle_delta_cdf[mbmi->uv_mode - V_PRED],
                     2 * MAX_ANGLE_DELTA + 1);
#else
hui su's avatar
hui su committed
856 857
    write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                  MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
Joe Young's avatar
Joe Young committed
858
#endif
859 860
  }
}
hui su's avatar
hui su committed
861 862
#endif  // CONFIG_EXT_INTRA

Angie Chiang's avatar
Angie Chiang committed
863 864
static void write_mb_interp_filter(AV1_COMP *cpi, const MACROBLOCKD *xd,
                                   aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
865
  AV1_COMMON *const cm = &cpi->common;
866
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
867
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
868

869
  if (!av1_is_interp_needed(xd)) {
870 871 872
    assert(mbmi->interp_filters ==
           av1_broadcast_interp_filter(
               av1_unswitchable_filter(cm->interp_filter)));
873 874
    return;
  }
875
  if (cm->interp_filter == SWITCHABLE) {
876
#if CONFIG_DUAL_FILTER
877
    int dir;
878
    for (dir = 0; dir < 2; ++dir) {
879
      if (has_subpel_mv_component(xd->mi[0], xd, dir) ||
880
          (mbmi->ref_frame[1] > INTRA_FRAME &&
881
           has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
Yaowu Xu's avatar
Yaowu Xu committed
882
        const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
883 884 885
        InterpFilter filter =
            av1_extract_interp_filter(mbmi->interp_filters, dir);
        aom_write_symbol(w, filter, ec_ctx->switchable_interp_cdf[ctx],
886
                         SWITCHABLE_FILTERS);
887
        ++cpi->interp_filter_selected[0][filter];
888
      } else {
889 890
        assert(av1_extract_interp_filter(mbmi->interp_filters, dir) ==
               EIGHTTAP_REGULAR);
891 892 893
      }
    }
#else
Geza Lore's avatar
Geza Lore committed
894
    {
Yaowu Xu's avatar
Yaowu Xu committed
895
      const int ctx = av1_get_pred_context_switchable_interp(xd);