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

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

58
#define ENC_MISMATCH_DEBUG 0
59

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

Yaowu Xu's avatar
Yaowu Xu committed
72
static struct av1_token interintra_mode_encodings[INTERINTRA_MODES];
73 74 75
#if CONFIG_JNT_COMP
static struct av1_token compound_type_encodings[COMPOUND_TYPES - 1];
#else
76
static struct av1_token compound_type_encodings[COMPOUND_TYPES];
77
#endif  // CONFIG_JNT_COMP
78
#if CONFIG_LOOP_RESTORATION
79 80
static void loop_restoration_write_sb_coeffs(const AV1_COMMON *const cm,
                                             MACROBLOCKD *xd,
81 82
                                             const RestorationUnitInfo *rui,
                                             aom_writer *const w, int plane);
83
#endif  // CONFIG_LOOP_RESTORATION
84 85 86 87 88 89 90 91
#if CONFIG_OBU
static void write_uncompressed_header_obu(AV1_COMP *cpi,
                                          struct aom_write_bit_buffer *wb);
#else
static void write_uncompressed_header_frame(AV1_COMP *cpi,
                                            struct aom_write_bit_buffer *wb);
#endif

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

94
#if !CONFIG_OBU || CONFIG_EXT_TILE
95 96 97 98 99
static int remux_tiles(const AV1_COMMON *const cm, uint8_t *dst,
                       const uint32_t data_size, const uint32_t max_tile_size,
                       const uint32_t max_tile_col_size,
                       int *const tile_size_bytes,
                       int *const tile_col_size_bytes);
100
#endif
Yaowu Xu's avatar
Yaowu Xu committed
101 102
void av1_encode_token_init(void) {
  av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree);
103
  av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree);
104 105
}

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

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

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

Jingning Han's avatar
Jingning Han committed
125
  if (mode != NEWMV) {
126
    if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
Sarah Parker's avatar
Sarah Parker committed
127
      assert(mode == GLOBALMV);
128 129 130
      return;
    }

Sarah Parker's avatar
Sarah Parker committed
131 132 133
    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);
134

Sarah Parker's avatar
Sarah Parker committed
135
    if (mode != GLOBALMV) {
136 137
      int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;

138 139 140
      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;
141
      aom_write_symbol(w, mode != NEARESTMV, ec_ctx->refmv_cdf[refmv_ctx], 2);
142 143
    }
  }
Jingning Han's avatar
Jingning Han committed
144 145
}

146
static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi,
Yaowu Xu's avatar
Yaowu Xu committed
147 148
                          const MB_MODE_INFO_EXT *mbmi_ext, aom_writer *w) {
  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
149 150 151

  assert(mbmi->ref_mv_idx < 3);

152
  const int new_mv = mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV;
153
  if (new_mv) {
154 155
    int idx;
    for (idx = 0; idx < 2; ++idx) {
156 157
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1 ||
          CONFIG_OPT_REF_MV) {
158
        uint8_t drl_ctx =
Yaowu Xu's avatar
Yaowu Xu committed
159
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
160

161 162
        aom_write_symbol(w, mbmi->ref_mv_idx != idx, ec_ctx->drl_cdf[drl_ctx],
                         2);
163
        if (mbmi->ref_mv_idx == idx) return;
164
      }
165 166 167 168
    }
    return;
  }

David Barker's avatar
David Barker committed
169
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
170 171 172
    int idx;
    // TODO(jingning): Temporary solution to compensate the NEARESTMV offset.
    for (idx = 1; idx < 3; ++idx) {
173 174
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1 ||
          CONFIG_OPT_REF_MV) {
175
        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
        aom_write_symbol(w, mbmi->ref_mv_idx != (idx - 1),
                         ec_ctx->drl_cdf[drl_ctx], 2);
179
        if (mbmi->ref_mv_idx == (idx - 1)) return;
180
      }
181
    }
182
    return;
183 184 185
  }
}

186 187
static void write_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                      aom_writer *w, PREDICTION_MODE mode,
188
                                      const int16_t mode_ctx) {
189 190 191 192 193
  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);
194
}
195

Yaowu Xu's avatar
Yaowu Xu committed
196
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
197
                                int max) {
Yaowu Xu's avatar
Yaowu Xu committed
198
  aom_wb_write_literal(wb, data, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
199 200
}

201
static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd,
202
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
203 204
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
205 206
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
207 208
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
209 210 211
  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);

212 213
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
214
                                   mbmi->sb_type, tx_size);
215

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

Jingning Han's avatar
Jingning Han committed
218
  if (depth == MAX_VARTX_DEPTH) {
219 220
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
221 222 223
    return;
  }

224 225 226
  const int write_txfm_partition =
      tx_size == mbmi->inter_tx_size[tx_row][tx_col];
  if (write_txfm_partition) {
227 228
    aom_write_symbol(w, 0, ec_ctx->txfm_partition_cdf[ctx], 2);

229 230
    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
231
    // TODO(yuec): set correct txfm partition update for qttx
232
  } else {
233
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
234 235
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
236

237
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
238

David Barker's avatar
David Barker committed
239
    if (sub_txs == TX_4X4) {
240 241
      txfm_partition_update(xd->above_txfm_context + blk_col,
                            xd->left_txfm_context + blk_row, sub_txs, tx_size);
242
      return;
243
    }
244

245 246 247 248 249 250 251 252
    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);
      }
253 254
  }
}
255

Yaowu Xu's avatar
Yaowu Xu committed
256 257
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
258 259
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
260 261
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
262
  if (block_signals_txsize(bsize)) {
263
    const TX_SIZE tx_size = mbmi->tx_size;
264
    const int tx_size_ctx = get_tx_size_context(xd);
265
    const int32_t tx_size_cat = intra_tx_size_cat_lookup[bsize];
266 267
    const int depth = tx_size_to_depth(tx_size, bsize);
    const int max_depths = bsize_to_max_depth(bsize);
268 269 270

    assert(depth >= 0 && depth <= max_depths);
    assert(!is_inter_block(mbmi));
271
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
272

273
    aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx],
274
                     max_depths + 1);
Jingning Han's avatar
Jingning Han committed
275 276 277
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
278 279
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
280 281 282 283
  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
284
    const int ctx = av1_get_skip_context(xd);
285 286
    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
287 288 289 290
    return skip;
  }
}

Zoe Liu's avatar
Zoe Liu committed
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
#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

309 310 311
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)) {
312
    const int ctx = av1_get_intra_inter_context(xd);
313 314 315 316 317
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, is_inter, ec_ctx->intra_inter_cdf[ctx], 2);
  }
}

318 319
static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd,
                              const MODE_INFO *mi, aom_writer *w) {
320
  const MB_MODE_INFO *mbmi = &mi->mbmi;
321

322
  MOTION_MODE last_motion_mode_allowed =
323
      motion_mode_allowed(0, cm->global_motion, xd, mi);
324 325 326 327 328 329 330
  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:
331 332 333 334 335 336 337 338 339 340 341 342
#if CONFIG_EXT_WARPED_MOTION
    {
      int wm_ctx = 0;
      if (mbmi->wm_ctx != -1) {
        wm_ctx = 1;
        if (mbmi->mode == NEARESTMV) wm_ctx = 2;
      }
      aom_write_symbol(w, mbmi->motion_mode,
                       xd->tile_ctx->motion_mode_cdf[wm_ctx][mbmi->sb_type],
                       MOTION_MODES);
    }
#else
343 344 345
      aom_write_symbol(w, mbmi->motion_mode,
                       xd->tile_ctx->motion_mode_cdf[mbmi->sb_type],
                       MOTION_MODES);
346
#endif  // CONFIG_EXT_WARPED_MOTION
Yue Chen's avatar
Yue Chen committed
347 348
  }
}
349

Thomas Davies's avatar
Thomas Davies committed
350 351
static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               int delta_qindex, aom_writer *w) {
352 353
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
Thomas Davies's avatar
Thomas Davies committed
354
  int rem_bits, thr;
355
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
Thomas Davies's avatar
Thomas Davies committed
356 357
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
358

Thomas Davies's avatar
Thomas Davies committed
359 360
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
361 362 363 364

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
365
    aom_write_literal(w, rem_bits - 1, 3);
366
    aom_write_literal(w, abs - thr, rem_bits);
367 368 369 370 371
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
372

Fangwen Fu's avatar
Fangwen Fu committed
373 374
#if CONFIG_EXT_DELTA_Q
static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
375 376 377
#if CONFIG_LOOPFILTER_LEVEL
                                int lf_id,
#endif
Fangwen Fu's avatar
Fangwen Fu committed
378 379 380 381 382 383 384 385
                                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;

386
#if CONFIG_LOOPFILTER_LEVEL
387 388 389 390 391 392 393 394
  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);
  }
395
#else
Fangwen Fu's avatar
Fangwen Fu committed
396 397
  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);
398
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
399 400 401 402

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
403
    aom_write_literal(w, rem_bits - 1, 3);
Fangwen Fu's avatar
Fangwen Fu committed
404 405 406 407 408 409 410
    aom_write_literal(w, abs - thr, rem_bits);
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
#endif  // CONFIG_EXT_DELTA_Q
411

Sarah Parker's avatar
Sarah Parker committed
412 413
static void pack_map_tokens(aom_writer *w, const TOKENEXTRA **tp, int n,
                            int num) {
414
  const TOKENEXTRA *p = *tp;
415 416 417 418
  write_uniform(w, n, p->token);  // The first color index.
  ++p;
  --num;
  for (int i = 0; i < num; ++i) {
419
    aom_write_symbol(w, p->token, p->color_map_cdf, n);
hui su's avatar
hui su committed
420 421 422 423
    ++p;
  }
  *tp = p;
}
424

425
#if !CONFIG_LV_MAP
426 427 428 429 430 431 432 433 434 435 436 437 438 439
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
440
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
441
                           const TOKENEXTRA *const stop,
442 443
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
                           TOKEN_STATS *token_stats) {
444
  const TOKENEXTRA *p = *tp;
445
  int count = 0;
446
  const int seg_eob = av1_get_max_eob(tx_size);
Jingning Han's avatar
Jingning Han committed
447 448

  while (p < stop && p->token != EOSB_TOKEN) {
449
    const int token = p->token;
Yaowu Xu's avatar
Yaowu Xu committed
450
    const int8_t eob_val = p->eob_val;
451
    if (token == BLOCK_Z_TOKEN) {
452
      aom_write_symbol(w, 0, *p->head_cdf, HEAD_TOKENS + 1);
453
      p++;
454
      break;
455 456
      continue;
    }
Yaowu Xu's avatar
Yaowu Xu committed
457 458

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

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

481 482 483 484
      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);
485 486 487 488 489 490

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

    ++count;
491
    if (eob_val == EARLY_EOB || count == seg_eob) break;
492 493 494 495
  }

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

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

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

543
    assert(bsw > 0 && bsh > 0);
544

545 546 547 548 549
    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;
550

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

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

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

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

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

599
    assert(bsw > 0 && bsh > 0);
600

601 602 603 604 605
    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;
606

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

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

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

693
#define WRITE_REF_BIT(bname, pname) \
694
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
695 696
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
697

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

    if (is_compound) {
Zoe Liu's avatar
Zoe Liu committed
732 733 734 735
#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
736 737
      aom_write_symbol(w, comp_ref_type, av1_get_comp_reference_type_cdf(xd),
                       2);
Zoe Liu's avatar
Zoe Liu committed
738 739 740

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

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

        return;
      }
758 759

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

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

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

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
774 775 776 777 778
      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
779 780
      }

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

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

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

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

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

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

Luc Trudeau's avatar
Luc Trudeau committed
847
  if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize)) {
Joe Young's avatar
Joe Young committed
848 849 850 851 852
#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
853 854
    write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                  MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
Joe Young's avatar
Joe Young committed
855
#endif
856 857
  }
}
hui su's avatar
hui su committed
858 859
#endif  // CONFIG_EXT_INTRA

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

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