bitstream.c 173 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 152 153
    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
154
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
155

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

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

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

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

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

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

210
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
211

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

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

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

231
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
232

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

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

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

    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
  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:
325 326 327 328 329 330 331 332 333 334 335 336
#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
337 338 339
      aom_write_symbol(w, mbmi->motion_mode,
                       xd->tile_ctx->motion_mode_cdf[mbmi->sb_type],
                       MOTION_MODES);
340
#endif  // CONFIG_EXT_WARPED_MOTION
Yue Chen's avatar
Yue Chen committed
341 342
  }
}
343

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

570
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
571

572 573 574
  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
575

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

593
    assert(bsw > 0 && bsh > 0);
594

595 596 597 598 599
    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;
600

601
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
602

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

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

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

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

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

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

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

        return;
      }
752 753

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

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

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

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

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

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

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

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

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

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

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

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

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