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
    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
887
    {
Yaowu Xu's avatar
Yaowu Xu committed
888
      const int ctx = av1_get_pred_context_switchable_interp(xd);
889
890
891
892
      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
893
    }
894
#endif  // CONFIG_DUAL_FILTER
895
896
897
  }
}

hui su's avatar
hui su committed
898
#if CONFIG_PALETTE_DELTA_ENCODING
899
900
901
902
903
904
905
// 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;
906
  assert(colors[0] < (1 << bit_depth));
907
908
909
910
911
912
  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) {
913
    assert(colors[i] < (1 << bit_depth));
914
915
916
917
918
919
920
    const int delta = colors[i] - colors[i - 1];
    deltas[i - 1] = delta;
    assert(delta >= min_val);
    if (delta > max_delta) max_delta = delta;
  }
  const int min_bits = bit_depth - 3;
  int bits = AOMMAX(av1_ceil_log2(max_delta + 1 - min_val), min_bits);
921
  assert(bits <= bit_depth);
922
923
924
925
926
927
928
929
930
931
932
933
934
935
  int range = (1 << bit_depth) - colors[0] - min_val;
  aom_write_literal(w, bits - min_bits, 2);
  for (int i = 0; i < num - 1; ++i) {
    aom_write_literal(w, deltas[i] - min_val, bits);
    range -= deltas[i];
    bits = AOMMIN(bits, av1_ceil_log2(range));
  }
}

// Transmit luma palette color values. First signal if each color in the color
// cache is used. Those colors that are not in the cache are transmitted with
// delta encoding.
static void write_palette_colors_y(const MACROBLOCKD *const xd,
                                   const PALETTE_MODE_INFO *const pmi,
hui su's avatar
hui su committed
936
937
                                   int bit_depth, aom_writer *w) {
  const int n = pmi->palette_size[0];
938
  uint16_t color_cache[2 * PALETTE_MAX_SIZE];
939
  const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
940
941
942
943
944
945
946
947
948
949
  int out_cache_colors[PALETTE_MAX_SIZE];
  uint8_t cache_color_found[2 * PALETTE_MAX_SIZE];
  const int n_out_cache =
      av1_index_color_cache(color_cache, n_cache, pmi->palette_colors, n,
                            cache_color_found, out_cache_colors);
  int n_in_cache = 0;
  for (int i = 0; i < n_cache && n_in_cache < n; ++i) {
    const int found = cache_color_found[i];
    aom_write_bit(w, found);
    n_in_cache += found;
hui su's avatar
hui su committed
950
  }
951
952
  assert(n_in_cache + n_out_cache == n);
  delta_encode_palette_colors(out_cache_colors, n_out_cache, bit_depth, 1, w);
hui su's avatar
hui su committed
953
954
}

955
956
957
958
959
// Write chroma palette color values. U channel is handled similarly to the luma
// channel. For v channel, either use delta encoding or transmit raw values
// directly, whichever costs less.
static void write_palette_colors_uv(const MACROBLOCKD *const xd,
                                    const PALETTE_MODE_INFO *const pmi,
hui su's avatar
hui su committed
960
961
962
963
964
                                    int bit_depth, aom_writer *w) {
  const int n = pmi->palette_size[1];
  const uint16_t *colors_u = pmi->palette_colors + PALETTE_MAX_SIZE;
  const uint16_t *colors_v = pmi->palette_colors + 2 * PALETTE_MAX_SIZE;
  // U channel colors.
965
  uint16_t color_cache[2 * PALETTE_MAX_SIZE];