bitstream.c 175 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
static struct av1_token compound_type_encodings[COMPOUND_TYPES];
74
#if CONFIG_LOOP_RESTORATION
75 76
static void loop_restoration_write_sb_coeffs(const AV1_COMMON *const cm,
                                             MACROBLOCKD *xd,
77 78
                                             const RestorationUnitInfo *rui,
                                             aom_writer *const w, int plane);
79
#endif  // CONFIG_LOOP_RESTORATION
80 81 82 83 84 85 86 87
#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

88
static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data);
89

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

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

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

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

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

Sarah Parker's avatar
Sarah Parker committed
127 128 129
    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);
130

Sarah Parker's avatar
Sarah Parker committed
131
    if (mode != GLOBALMV) {
132 133
      int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;

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

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

  assert(mbmi->ref_mv_idx < 3);

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

157 158
        aom_write_symbol(w, mbmi->ref_mv_idx != idx, ec_ctx->drl_cdf[drl_ctx],
                         2);
159
        if (mbmi->ref_mv_idx == idx) return;
160
      }
161 162 163 164
    }
    return;
  }

David Barker's avatar
David Barker committed
165
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
166 167 168
    int idx;
    // TODO(jingning): Temporary solution to compensate the NEARESTMV offset.
    for (idx = 1; idx < 3; ++idx) {
169 170
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1 ||
          CONFIG_OPT_REF_MV) {
171
        uint8_t drl_ctx =
Yaowu Xu's avatar
Yaowu Xu committed
172
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
173 174
        aom_write_symbol(w, mbmi->ref_mv_idx != (idx - 1),
                         ec_ctx->drl_cdf[drl_ctx], 2);
175
        if (mbmi->ref_mv_idx == (idx - 1)) return;
176
      }
177
    }
178
    return;
179 180 181
  }
}

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

Yaowu Xu's avatar
Yaowu Xu committed
192
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
193
                                int max) {
Yaowu Xu's avatar
Yaowu Xu committed
194
  aom_wb_write_literal(wb, data, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
195 196
}

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

208 209
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
210
                                   mbmi->sb_type, tx_size);
211

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

Jingning Han's avatar
Jingning Han committed
214
  if (depth == MAX_VARTX_DEPTH) {
215 216
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
217 218 219
    return;
  }

220 221 222
  const int write_txfm_partition =
      tx_size == mbmi->inter_tx_size[tx_row][tx_col];
  if (write_txfm_partition) {
223 224
    aom_write_symbol(w, 0, ec_ctx->txfm_partition_cdf[ctx], 2);

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

233
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
234

David Barker's avatar
David Barker committed
235
    if (sub_txs == TX_4X4) {
236 237
      txfm_partition_update(xd->above_txfm_context + blk_col,
                            xd->left_txfm_context + blk_row, sub_txs, tx_size);
238
      return;
239
    }
240

241 242 243 244 245 246 247 248
    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);
      }
249 250
  }
}
251

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

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

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

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

Zoe Liu's avatar
Zoe Liu committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
#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

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

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

318
  MOTION_MODE last_motion_mode_allowed =
319
      motion_mode_allowed(0, cm->global_motion, xd, mi);
320 321 322 323 324 325 326
  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:
327 328 329 330 331 332 333 334 335 336 337 338
#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
339 340 341
      aom_write_symbol(w, mbmi->motion_mode,
                       xd->tile_ctx->motion_mode_cdf[mbmi->sb_type],
                       MOTION_MODES);
342
#endif  // CONFIG_EXT_WARPED_MOTION
Yue Chen's avatar
Yue Chen committed
343 344
  }
}
345

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

Thomas Davies's avatar
Thomas Davies committed
355 356
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
357 358 359 360

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
361
    aom_write_literal(w, rem_bits - 1, 3);
362
    aom_write_literal(w, abs - thr, rem_bits);
363 364 365 366 367
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
368

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

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

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

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

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

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

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

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

477 478 479 480
      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);
481 482 483 484 485 486

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

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

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

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

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

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

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

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

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

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

574 575 576
  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
577

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

595
    assert(bsw > 0 && bsh > 0);
596

597 598 599 600 601
    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;
602

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

605 606 607 608
        pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                        block, offsetr, offsetc, sub_txs, token_stats);
        block += step;
      }
609 610 611
    }
  }
}
612
#endif  // CONFIG_LV_MAP
613

614 615 616 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
#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
682
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
683
                             struct segmentation_probs *segp, int segment_id) {
684 685 686
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
687 688
}

689
#define WRITE_REF_BIT(bname, pname) \
690
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
691 692
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
693

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

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

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

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

        return;
      }
754 755

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

758
      const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
759
                       mbmi->ref_frame[0] == LAST3_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
760
      WRITE_REF_BIT(bit, comp_ref_p);
761 762

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

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
770 771 772 773 774
      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
775 776
      }

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

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

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

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

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

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

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

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

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