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"
hui su's avatar
hui su committed
51
#include "av1/encoder/palette.h"
52
53
54
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
Jingning Han's avatar
Jingning Han committed
55

56
#define ENC_MISMATCH_DEBUG 0
57

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

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

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

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

107
108
109
110
static void write_intra_mode_kf(FRAME_CONTEXT *frame_ctx, const MODE_INFO *mi,
                                const MODE_INFO *above_mi,
                                const MODE_INFO *left_mi, PREDICTION_MODE mode,
                                aom_writer *w) {
Alex Converse's avatar
Alex Converse committed
111
112
113
#if CONFIG_INTRABC
  assert(!is_intrabc_block(&mi->mbmi));
#endif  // CONFIG_INTRABC
114
115
  (void)mi;
  aom_write_symbol(w, mode, get_y_mode_cdf(frame_ctx, above_mi, left_mi),
Jingning Han's avatar
Jingning Han committed
116
117
                   INTRA_MODES);
}
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) {
Sarah Parker's avatar
Sarah Parker committed
126
127
128
    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);
129

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

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

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

  assert(mbmi->ref_mv_idx < 3);

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

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

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

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

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

200
201
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
202
                                   mbmi->sb_type, tx_size);
203

204
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
205

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

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

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

225
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
226

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

233
234
235
236
237
238
239
240
    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);
      }
241
242
  }
}
243

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

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

261
    aom_write_symbol(w, depth, ec_ctx->tx_size_cdf[tx_size_cat][tx_size_ctx],
262
                     max_depths + 1);
Jingning Han's avatar
Jingning Han committed
263
264
265
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
266
267
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
268
269
270
271
  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
272
    const int ctx = av1_get_skip_context(xd);
273
274
    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
275
276
277
278
    return skip;
  }
}

Zoe Liu's avatar
Zoe Liu committed
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#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

297
298
299
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)) {
300
    const int ctx = av1_get_intra_inter_context(xd);
301
302
303
304
305
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, is_inter, ec_ctx->intra_inter_cdf[ctx], 2);
  }
}

306
307
static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd,
                              const MODE_INFO *mi, aom_writer *w) {
308
  const MB_MODE_INFO *mbmi = &mi->mbmi;
309

310
  MOTION_MODE last_motion_mode_allowed =
Luc Trudeau's avatar
Luc Trudeau committed
311
      motion_mode_allowed(cm->global_motion, xd, mi);
312
313
314
315
316
317
318
  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:
319
320
321
322
323
324
325
326
327
328
329
330
#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
331
332
333
      aom_write_symbol(w, mbmi->motion_mode,
                       xd->tile_ctx->motion_mode_cdf[mbmi->sb_type],
                       MOTION_MODES);
334
#endif  // CONFIG_EXT_WARPED_MOTION
Yue Chen's avatar
Yue Chen committed
335
336
  }
}
337

Thomas Davies's avatar
Thomas Davies committed
338
339
static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               int delta_qindex, aom_writer *w) {
340
341
  int sign = delta_qindex < 0;
  int abs = sign ? -delta_qindex : delta_qindex;
Thomas Davies's avatar
Thomas Davies committed
342
  int rem_bits, thr;
343
  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
Thomas Davies's avatar
Thomas Davies committed
344
345
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
346

Thomas Davies's avatar
Thomas Davies committed
347
348
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
349
350
351
352

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
353
    aom_write_literal(w, rem_bits - 1, 3);
354
    aom_write_literal(w, abs - thr, rem_bits);
355
356
357
358
359
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
360

Fangwen Fu's avatar
Fangwen Fu committed
361
362
#if CONFIG_EXT_DELTA_Q
static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
363
364
365
#if CONFIG_LOOPFILTER_LEVEL
                                int lf_id,
#endif
Fangwen Fu's avatar
Fangwen Fu committed
366
367
368
369
370
371
372
373
                                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;

374
#if CONFIG_LOOPFILTER_LEVEL
375
376
377
378
379
380
381
382
  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);
  }
383
#else
Fangwen Fu's avatar
Fangwen Fu committed
384
385
  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);
386
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
387
388
389
390

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
391
    aom_write_literal(w, rem_bits - 1, 3);
Fangwen Fu's avatar
Fangwen Fu committed
392
393
394
395
396
397
398
    aom_write_literal(w, abs - thr, rem_bits);
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
#endif  // CONFIG_EXT_DELTA_Q
399

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

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

  while (p < stop && p->token != EOSB_TOKEN) {
437
    const int token = p->token;
Yaowu Xu's avatar
Yaowu Xu committed
438
    const int8_t eob_val = p->eob_val;
439
    if (token == BLOCK_Z_TOKEN) {
440
      aom_write_symbol(w, 0, *p->head_cdf, HEAD_TOKENS + 1);
441
      p++;
442
      break;
443
444
      continue;
    }
Yaowu Xu's avatar
Yaowu Xu committed
445
446

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

    if (extra_bits->base_val) {
      const int bit_string = p->extra;
      const int bit_string_length = extra_bits->len;  // Length of extra bits to
461
      const int is_cat6 = (extra_bits->base_val == CAT6_MIN_VAL);
462
463
      // be written excluding
      // the sign bit.
464
      int skip_bits = is_cat6
465
466
467
                          ? (int)sizeof(av1_cat6_prob) -
                                av1_get_cat6_extrabits_size(tx_size, bit_depth)
                          : 0;
468

469
470
471
472
      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);
473
474
475
476
477
478

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

    ++count;
479
    if (eob_val == EARLY_EOB || count == seg_eob) break;
480
481
482
483
  }

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

486
#if CONFIG_LV_MAP
487
static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
488
                            const TOKENEXTRA **tp,
489
490
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
491
492
493
494
495
496
497
498
499
500
501
502
                            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);
  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;

503
504
  const TX_SIZE plane_tx_size =
      plane ? av1_get_uv_tx_size_vartx(mbmi, pd, bsize, tx_row, tx_col)
505
506
            : mbmi->inter_tx_size[tx_row][tx_col];

507
508
  if (tx_size == plane_tx_size
#if DISABLE_VARTX_FOR_CHROMA
509
      || plane
510
511
#endif  // DISABLE_VARTX_FOR_CHROMA
      ) {
512
513
514
515
516
517
518
    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] };
Luc Trudeau's avatar
Luc Trudeau committed
519
520
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, plane, tx_size, tcoeff,
                         eob, &txb_ctx);
521
522
523
524
525
#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 {
526
    const TX_SIZE sub_txs = sub_tx_size_map[1][tx_size];
527
528
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
529

530
    assert(bsw > 0 && bsh > 0);
531

532
533
534
535
536
    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;
537

538
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
539

540
541
542
543
544
        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;
      }
545
546
547
548
    }
  }
}
#else  // CONFIG_LV_MAP
Yaowu Xu's avatar
Yaowu Xu committed
549
static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp,
Yushin Cho's avatar
Yushin Cho committed
550
551
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
Yaowu Xu's avatar
Yaowu Xu committed
552
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
553
                            int block, int blk_row, int blk_col,
554
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
555
556
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
557
558
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
559
560
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
561

562
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
563

564
565
  const TX_SIZE plane_tx_size =
      plane ? av1_get_uv_tx_size_vartx(mbmi, pd, bsize, tx_row, tx_col)
566
            : mbmi->inter_tx_size[tx_row][tx_col];
Debargha Mukherjee's avatar
Debargha Mukherjee committed
567

568
569
  if (tx_size == plane_tx_size
#if DISABLE_VARTX_FOR_CHROMA
570
      || plane
571
572
#endif  // DISABLE_VARTX_FOR_CHROMA
      ) {
573
574
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
575
    pack_mb_tokens(w, tp, tok_end, bit_depth, tx_size, &tmp_token_stats);
576
577
578
579
#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
580
  } else {
581
    const TX_SIZE sub_txs = sub_tx_size_map[1][tx_size];
582
583
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
584

585
    assert(bsw > 0 && bsh > 0);
586

587
588
589
590
591
    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;
592

593
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
594

595
596
597
598
        pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                        block, offsetr, offsetc, sub_txs, token_stats);
        block += step;
      }
599
600
601
    }
  }
}
602
#endif  // CONFIG_LV_MAP
603

604
#if CONFIG_SPATIAL_SEGMENTATION
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
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;
  }
}

628
629
630
631
632
static void write_segment_id(AV1_COMP *cpi, const MB_MODE_INFO *const mbmi,
                             aom_writer *w, const struct segmentation *seg,
                             struct segmentation_probs *segp, int mi_row,
                             int mi_col, int skip) {
  AV1_COMMON *const cm = &cpi->common;
633
634
635
636
  int prev_ul = 0; /* Top left segment_id */
  int prev_l = 0;  /* Current left segment_id */
  int prev_u = 0;  /* Current top segment_id */

637
  if (!seg->enabled || !seg->update_map) return;
638
639
640
641
642
643
644

  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)
645
646
    prev_ul = get_segment_id(cm, cm->current_frame_seg_map, BLOCK_4X4,
                             mi_row - 1, mi_col - 1);
647
648

  if (above)
649
650
    prev_u = get_segment_id(cm, cm->current_frame_seg_map, BLOCK_4X4,
                            mi_row - 1, mi_col - 0);
651
652

  if (left)
653
654
    prev_l = get_segment_id(cm, cm->current_frame_seg_map, BLOCK_4X4,
                            mi_row - 0, mi_col - 1);
655

656
657
  int cdf_num = pick_spatial_seg_cdf(prev_ul, prev_u, prev_l);
  int pred = pick_spatial_seg_pred(prev_ul, prev_u, prev_l);
658
659

  if (skip) {
660
661
662
663
664
665
    set_spatial_segment_id(cm, cm->current_frame_seg_map, mbmi->sb_type, mi_row,
                           mi_col, pred);
    set_spatial_segment_id(cm, cpi->segmentation_map, mbmi->sb_type, mi_row,
                           mi_col, pred);
    /* mbmi is read only but we need to update segment_id */
    ((MB_MODE_INFO *)mbmi)->segment_id = pred;
666
667
668
    return;
  }

669
670
  int coded_id =
      neg_interleave(mbmi->segment_id, pred, cm->last_active_segid + 1);
671

672
  aom_cdf_prob *pred_cdf = segp->spatial_pred_seg_cdf[cdf_num];
673
674
  aom_write_symbol(w, coded_id, pred_cdf, 8);

675
676
  set_spatial_segment_id(cm, cm->current_frame_seg_map, mbmi->sb_type, mi_row,
                         mi_col, mbmi->segment_id);
677
}
678
#else
Yaowu Xu's avatar
Yaowu Xu committed
679
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
680
                             struct segmentation_probs *segp, int segment_id) {
681
682
683
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
684
}
685
#endif
Jingning Han's avatar
Jingning Han committed
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
    aom_write_symbol(w, mbmi->filter_intra_mode_info.use_filter_intra,
811
                     xd->tile_ctx->filter_intra_cdfs[mbmi->tx_size], 2);
812
    if (mbmi->filter_intra_mode_info.use_filter_intra) {
813
      const FILTER_INTRA_MODE mode =
814
          mbmi->filter_intra_mode_info.filter_intra_mode;
815
      aom_write_symbol(w, mode, xd->tile_ctx->filter_intra_mode_cdf,
816
                       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];
Geza Lore's avatar
Geza Lore committed
891
    }
892
#endif  // CONFIG_DUAL_FILTER
893
894
895
  }
}

896
897
898
899
900
901
902
// Transmit color values with delta encoding. Write the first value as
// literal, and the deltas between each value and the previous one. "min_val" is
// the smallest possible value of the deltas.
static void delta_encode_palette_colors(const int *colors, int num,
                                        int bit_depth, int min_val,
                                        aom_writer *w) {
  if (num <= 0) return;
903
  assert(colors[0] < (1 << bit_depth));
904
905
906
907
908
909
  aom_write_literal(w, colors[0], bit_depth);
  if (num == 1) return;
  int max_delta = 0;
  int deltas[PALETTE_MAX_SIZE];
  memset(deltas, 0, sizeof(deltas));
  for (int i = 1; i < num; ++i) {
910
    assert(colors[i] < (1 << bit_depth));
911
912
913
914