bitstream.c 176 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4
5
6
7
8
9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10
11
12
13
 */

#include <assert.h>
#include <limits.h>
14
#include <stdio.h>
Jingning Han's avatar
Jingning Han committed
15

Yaowu Xu's avatar
Yaowu Xu committed
16
17
#include "aom/aom_encoder.h"
#include "aom_dsp/aom_dsp_common.h"
18
#include "aom_dsp/binary_codes_writer.h"
19
#include "aom_dsp/bitwriter_buffer.h"
Yaowu Xu's avatar
Yaowu Xu committed
20
#include "aom_mem/aom_mem.h"
21
22
#include "aom_ports/mem_ops.h"
#include "aom_ports/system_state.h"
23
#if CONFIG_BITSTREAM_DEBUG
24
#include "aom_util/debug_util.h"
25
#endif  // CONFIG_BITSTREAM_DEBUG
Jingning Han's avatar
Jingning Han committed
26

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

Angie Chiang's avatar
Angie Chiang committed
44
45
46
#if CONFIG_LV_MAP
#include "av1/encoder/encodetxb.h"
#endif  // CONFIG_LV_MAP
47
48
49
50
#include "av1/encoder/bitstream.h"
#include "av1/encoder/cost.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/mcomp.h"
Urvang Joshi's avatar
Urvang Joshi committed
51
#if CONFIG_PALETTE_DELTA_ENCODING
hui su's avatar
hui su committed
52
#include "av1/encoder/palette.h"
Urvang Joshi's avatar
Urvang Joshi committed
53
#endif  // CONFIG_PALETTE_DELTA_ENCODING
54
55
56
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
Jingning Han's avatar
Jingning Han committed
57

58
#define ENC_MISMATCH_DEBUG 0
59

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

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

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

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

Jingning Han's avatar
Jingning Han committed
106
107
108
109
static void write_intra_mode_kf(const AV1_COMMON *cm, FRAME_CONTEXT *frame_ctx,
                                const MODE_INFO *mi, const MODE_INFO *above_mi,
                                const MODE_INFO *left_mi, int block,
                                PREDICTION_MODE mode, aom_writer *w) {
Alex Converse's avatar
Alex Converse committed
110
111
112
#if CONFIG_INTRABC
  assert(!is_intrabc_block(&mi->mbmi));
#endif  // CONFIG_INTRABC
Hui Su's avatar
Hui Su committed
113
  aom_write_symbol(w, mode,
Jingning Han's avatar
Jingning Han committed
114
115
116
117
                   get_y_mode_cdf(frame_ctx, mi, above_mi, left_mi, block),
                   INTRA_MODES);
  (void)cm;
}
Jingning Han's avatar
Jingning Han committed
118

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

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

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

Sarah Parker's avatar
Sarah Parker committed
131
132
133
    const int16_t zeromv_ctx =
        (mode_ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
    aom_write_symbol(w, mode != GLOBALMV, ec_ctx->zeromv_cdf[zeromv_ctx], 2);
134

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

138
139
140
      if (mode_ctx & (1 << SKIP_NEARESTMV_OFFSET)) refmv_ctx = 6;
      if (mode_ctx & (1 << SKIP_NEARMV_OFFSET)) refmv_ctx = 7;
      if (mode_ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) refmv_ctx = 8;
141
      aom_write_symbol(w, mode != NEARESTMV, ec_ctx->refmv_cdf[refmv_ctx], 2);
142
143
    }
  }
Jingning Han's avatar
Jingning Han committed
144
145
}

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

  assert(mbmi->ref_mv_idx < 3);

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

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

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

186
187
static void write_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                      aom_writer *w, PREDICTION_MODE mode,
188
                                      const int16_t mode_ctx) {
189
190
191
192
193
  assert(is_inter_compound_mode(mode));
  (void)cm;
  aom_write_symbol(w, INTER_COMPOUND_OFFSET(mode),
                   xd->tile_ctx->inter_compound_mode_cdf[mode_ctx],
                   INTER_COMPOUND_MODES);
194
}
195

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

201
static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd,
202
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
203
204
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
205
206
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
207
208
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
209
210
211
  const int max_blocks_high = max_block_high(xd, mbmi->sb_type, 0);
  const int max_blocks_wide = max_block_wide(xd, mbmi->sb_type, 0);

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

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

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

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

229
230
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
Yue Chen's avatar
Yue Chen committed
231
    // TODO(yuec): set correct txfm partition update for qttx
232
  } else {
233
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
234
235
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
236

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

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

245
246
247
248
249
250
251
252
    assert(bsw > 0 && bsh > 0);
    for (int row = 0; row < tx_size_high_unit[tx_size]; row += bsh)
      for (int col = 0; col < tx_size_wide_unit[tx_size]; col += bsw) {
        int offsetr = blk_row + row;
        int offsetc = blk_col + col;
        write_tx_size_vartx(cm, xd, mbmi, sub_txs, depth + 1, offsetr, offsetc,
                            w);
      }
253
254
  }
}
255

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

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

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

Yaowu Xu's avatar
Yaowu Xu committed
278
279
static int write_skip(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                      int segment_id, const MODE_INFO *mi, aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
280
281
282
283
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
Zoe Liu's avatar
Zoe Liu committed
284
    const int ctx = av1_get_skip_context(xd);
285
286
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, skip, ec_ctx->skip_cdfs[ctx], 2);
Jingning Han's avatar
Jingning Han committed
287
288
289
290
    return skip;
  }
}

Zoe Liu's avatar
Zoe Liu committed
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#if CONFIG_EXT_SKIP
static int write_skip_mode(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                           int segment_id, const MODE_INFO *mi, aom_writer *w) {
  if (!cm->skip_mode_flag) return 0;
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 0;
  }
  const int skip_mode = mi->mbmi.skip_mode;
  if (!is_comp_ref_allowed(mi->mbmi.sb_type)) {
    assert(!skip_mode);
    return 0;
  }
  const int ctx = av1_get_skip_mode_context(xd);
  aom_write_symbol(w, skip_mode, xd->tile_ctx->skip_mode_cdfs[ctx], 2);
  return skip_mode;
}
#endif  // CONFIG_EXT_SKIP

309
310
311
static void write_is_inter(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                           int segment_id, aom_writer *w, const int is_inter) {
  if (!segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
312
    const int ctx = av1_get_intra_inter_context(xd);
313
314
315
316
317
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, is_inter, ec_ctx->intra_inter_cdf[ctx], 2);
  }
}

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

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

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

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

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

Fangwen Fu's avatar
Fangwen Fu committed
373
374
#if CONFIG_EXT_DELTA_Q
static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd,
375
376
377
#if CONFIG_LOOPFILTER_LEVEL
                                int lf_id,
#endif
Fangwen Fu's avatar
Fangwen Fu committed
378
379
380
381
382
383
384
385
                                int delta_lflevel, aom_writer *w) {
  int sign = delta_lflevel < 0;
  int abs = sign ? -delta_lflevel : delta_lflevel;
  int rem_bits, thr;
  int smallval = abs < DELTA_LF_SMALL ? 1 : 0;
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;

386
#if CONFIG_LOOPFILTER_LEVEL
387
388
389
390
391
392
393
394
  if (cm->delta_lf_multi) {
    assert(lf_id >= 0 && lf_id < FRAME_LF_COUNT);
    aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL),
                     ec_ctx->delta_lf_multi_cdf[lf_id], DELTA_LF_PROBS + 1);
  } else {
    aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                     DELTA_LF_PROBS + 1);
  }
395
#else
Fangwen Fu's avatar
Fangwen Fu committed
396
397
  aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf,
                   DELTA_LF_PROBS + 1);
398
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
399
400
401
402

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

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

425
#if !CONFIG_LV_MAP
426
427
428
429
430
431
432
433
434
435
436
437
438
439
static INLINE void write_coeff_extra(const aom_cdf_prob *const *cdf, int val,
                                     int n, aom_writer *w) {
  // Code the extra bits from LSB to MSB in groups of 4
  int i = 0;
  int count = 0;
  while (count < n) {
    const int size = AOMMIN(n - count, 4);
    const int mask = (1 << size) - 1;
    aom_write_cdf(w, val & mask, cdf[i++], 1 << size);
    val >>= size;
    count += size;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
440
static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp,
441
                           const TOKENEXTRA *const stop,
442
443
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
                           TOKEN_STATS *token_stats) {
444
  const TOKENEXTRA *p = *tp;
445
  int count = 0;
446
  const int seg_eob = av1_get_max_eob(tx_size);
Jingning Han's avatar
Jingning Han committed
447
448

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

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

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

481
482
483
484
      assert(!(bit_string >> (bit_string_length - skip_bits + 1)));
      if (bit_string_length > 0)
        write_coeff_extra(extra_bits->cdf, bit_string >> 1,
                          bit_string_length - skip_bits, w);
485
486
487
488
489
490

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

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

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

498
#if CONFIG_LV_MAP
499
static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
500
                            const TOKENEXTRA **tp,
501
502
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
                            int block, int blk_row, int blk_col,
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
  TX_SIZE plane_tx_size;
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);

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

  plane_tx_size =
      plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
            : mbmi->inter_tx_size[tx_row][tx_col];

520
521
522
523
524
  if (tx_size == plane_tx_size
#if DISABLE_VARTX_FOR_CHROMA
      || pd->subsampling_x || pd->subsampling_y
#endif  // DISABLE_VARTX_FOR_CHROMA
      ) {
525
526
527
528
529
530
531
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);

    tran_low_t *tcoeff = BLOCK_OFFSET(x->mbmi_ext->tcoeff[plane], block);
    uint16_t eob = x->mbmi_ext->eobs[plane][block];
    TXB_CTX txb_ctx = { x->mbmi_ext->txb_skip_ctx[plane][block],
                        x->mbmi_ext->dc_sign_ctx[plane][block] };
Jingning Han's avatar
Jingning Han committed
532
533
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, block, plane, tx_size,
                         tcoeff, eob, &txb_ctx);
534
535
536
537
538
539
#if CONFIG_RD_DEBUG
    token_stats->txb_coeff_cost_map[blk_row][blk_col] = tmp_token_stats.cost;
    token_stats->cost += tmp_token_stats.cost;
#endif
  } else {
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
540
541
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
542

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

545
546
547
548
549
    for (int r = 0; r < tx_size_high_unit[tx_size]; r += bsh) {
      for (int c = 0; c < tx_size_wide_unit[tx_size]; c += bsw) {
        const int offsetr = blk_row + r;
        const int offsetc = blk_col + c;
        const int step = bsh * bsw;
550

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

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

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

578
579
580
  plane_tx_size =
      plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
            : mbmi->inter_tx_size[tx_row][tx_col];
Debargha Mukherjee's avatar
Debargha Mukherjee committed
581

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

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

601
602
603
604
605
    for (int r = 0; r < tx_size_high_unit[tx_size]; r += bsh) {
      for (int c = 0; c < tx_size_wide_unit[tx_size]; c += bsw) {
        const int offsetr = blk_row + r;
        const int offsetc = blk_col + c;
        const int step = bsh * bsw;
606

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

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

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
#if CONFIG_Q_SEGMENTATION
static int neg_interleave(int x, int ref, int max) {
  const int diff = x - ref;
  if (!ref) return x;
  if (ref >= (max - 1)) return -diff;
  if (2 * ref < max) {
    if (abs(diff) <= ref) {
      if (diff > 0)
        return (diff << 1) - 1;
      else
        return ((-diff) << 1);
    }
    return x;
  } else {
    if (abs(diff) < (max - ref)) {
      if (diff > 0)
        return (diff << 1) - 1;
      else
        return ((-diff) << 1);
    }
    return (max - x) - 1;
  }
}

static void write_q_segment_id(const AV1_COMMON *cm, int skip,
                               const MB_MODE_INFO *const mbmi, aom_writer *w,
                               const struct segmentation *seg,
                               struct segmentation_probs *segp,
                               BLOCK_SIZE bsize, int mi_row, int mi_col) {
  int prev_ul = 0; /* Top left segment_id */
  int prev_l = 0;  /* Current left segment_id */
  int prev_u = 0;  /* Current top segment_id */

  if (!seg->q_lvls) return;

  MODE_INFO *const mi = cm->mi + mi_row * cm->mi_stride + mi_col;
  int tinfo = mi->mbmi.boundary_info;
  int above = (!(tinfo & TILE_ABOVE_BOUNDARY)) && ((mi_row - 1) >= 0);
  int left = (!(tinfo & TILE_LEFT_BOUNDARY)) && ((mi_col - 1) >= 0);

  if (above && left)
    prev_ul =
        get_segment_id(cm, cm->q_seg_map, BLOCK_4X4, mi_row - 1, mi_col - 1);

  if (above)
    prev_u = get_segment_id(cm, cm->q_seg_map, BLOCK_4X4, mi_row - 1, mi_col);

  if (left)
    prev_l = get_segment_id(cm, cm->q_seg_map, BLOCK_4X4, mi_row, mi_col - 1);

  int cdf_num = pick_q_seg_cdf(prev_ul, prev_u, prev_l);
  int pred = pick_q_seg_pred(prev_ul, prev_u, prev_l);

  if (skip) {
    set_q_segment_id(cm, cm->q_seg_map, mbmi->sb_type, mi_row, mi_col, pred);
    return;
  }

  int coded_id = neg_interleave(mbmi->q_segment_id, pred, seg->q_lvls);

  aom_cdf_prob *pred_cdf = segp->q_seg_cdf[cdf_num];
  aom_write_symbol(w, coded_id, pred_cdf, 8);

  set_q_segment_id(cm, cm->q_seg_map, bsize, mi_row, mi_col,
                   mbmi->q_segment_id);
}
#endif

Yaowu Xu's avatar
Yaowu Xu committed
686
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
687
                             struct segmentation_probs *segp, int segment_id) {
688
689
690
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
691
692
}

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

Jingning Han's avatar
Jingning Han committed
698
// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
699
700
static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                             aom_writer *w) {
Jingning Han's avatar
Jingning Han committed
701
702
703
704
705
706
707
708
709
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const int is_compound = has_second_ref(mbmi);
  const int segment_id = mbmi->segment_id;

  // If segment level coding of this signal is disabled...
  // or the segment allows multiple reference frame options
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
    assert(!is_compound);
    assert(mbmi->ref_frame[0] ==
710
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
711
  }
Sarah Parker's avatar
Sarah Parker committed
712
#if CONFIG_SEGMENT_GLOBALMV
713
  else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP) ||
Sarah Parker's avatar
Sarah Parker committed
714
           segfeature_active(&cm->seg, segment_id, SEG_LVL_GLOBALMV))
715
716
717
718
719
720
#else
  else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP))
#endif
  {
    assert(!is_compound);
    assert(mbmi->ref_frame[0] == LAST_FRAME);
Jingning Han's avatar
Jingning Han committed
721
722
723
724
  } else {
    // does the feature use compound prediction or not
    // (if not specified at the frame/segment level)
    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
725
      if (is_comp_ref_allowed(mbmi->sb_type))
726
        aom_write_symbol(w, is_compound, av1_get_reference_mode_cdf(cm, xd), 2);
Jingning Han's avatar
Jingning Han committed
727
    } else {
728
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
729
730
731
    }

    if (is_compound) {
Zoe Liu's avatar
Zoe Liu committed
732
733
734
735
#if CONFIG_EXT_COMP_REFS
      const COMP_REFERENCE_TYPE comp_ref_type = has_uni_comp_refs(mbmi)
                                                    ? UNIDIR_COMP_REFERENCE
                                                    : BIDIR_COMP_REFERENCE;
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
736
737
      aom_write_symbol(w, comp_ref_type, av1_get_comp_reference_type_cdf(xd),
                       2);
Zoe Liu's avatar
Zoe Liu committed
738
739
740

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

Zoe Liu's avatar
Zoe Liu committed
743
        if (!bit) {
744
          assert(mbmi->ref_frame[0] == LAST_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
745
746
747
748
749
750
          const int bit1 = mbmi->ref_frame[1] == LAST3_FRAME ||
                           mbmi->ref_frame[1] == GOLDEN_FRAME;
          WRITE_REF_BIT2(bit1, uni_comp_ref_p1);
          if (bit1) {
            const int bit2 = mbmi->ref_frame[1] == GOLDEN_FRAME;
            WRITE_REF_BIT2(bit2, uni_comp_ref_p2);
751
752
753
          }
        } else {
          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
Zoe Liu's avatar
Zoe Liu committed
754
755
756
757
        }

        return;
      }
758
759

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

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

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

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
774
775
776
777
778
      const int bit_bwd = mbmi->ref_frame[1] == ALTREF_FRAME;
      WRITE_REF_BIT(bit_bwd, comp_bwdref_p);

      if (!bit_bwd) {
        WRITE_REF_BIT(mbmi->ref_frame[1] == ALTREF2_FRAME, comp_bwdref_p1);
Zoe Liu's avatar
Zoe Liu committed
779
780
      }

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

      if (bit0) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
787
788
789
790
791
        const int bit1 = mbmi->ref_frame[0] == ALTREF_FRAME;
        WRITE_REF_BIT(bit1, single_ref_p2);

        if (!bit1) {
          WRITE_REF_BIT(mbmi->ref_frame[0] == ALTREF2_FRAME, single_ref_p6);
Zoe Liu's avatar
Zoe Liu committed
792
        }
793
794
      } else {
        const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
795
                          mbmi->ref_frame[0] == GOLDEN_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
796
        WRITE_REF_BIT(bit2, single_ref_p3);
797
798

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

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

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

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

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

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

866
  if (!av1_is_interp_needed(xd)) {
867
868
869
    assert(mbmi->interp_filters ==
           av1_broadcast_interp_filter(
               av1_unswitchable_filter(cm->interp_filter)));
870
871
    return;
  }
872
  if (cm->interp_filter == SWITCHABLE) {
873
#if CONFIG_DUAL_FILTER
874
    int dir;
875
    for (dir = 0; dir < 2; ++dir) {
876
      if (has_subpel_mv_component(xd->mi[0], xd, dir) ||
877
          (mbmi->ref_frame[1] > INTRA_FRAME &&
878
           has_subpel_mv_component(xd->mi[0], xd, dir + 2))) {
Yaowu Xu's avatar
Yaowu Xu committed
879
        const int ctx = av1_get_pred_context_switchable_interp(xd, dir);
880
881
882
        InterpFilter filter =
            av1_extract_interp_filter(mbmi->interp_filters, dir);
        aom_write_symbol(w, filter, ec_ctx->switchable_interp_cdf[ctx],
883
                         SWITCHABLE_FILTERS);
884
        ++cpi->interp_filter_selected[0][filter];
885
      } else {
886
887
        assert(av1_extract_interp_filter(mbmi->interp_filters, dir) ==
               EIGHTTAP_REGULAR);
888
889
890
      }
    }
#else
Geza Lore's avatar
Geza Lore committed
891
    {
Yaowu Xu's avatar
Yaowu Xu committed
892
      const int ctx = av1_get_pred_context_switchable_interp(xd);
893
894
895
896
      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
897
    }
898
#endif  // CONFIG_DUAL_FILTER
899
900
901
  }
}

hui su's avatar
hui su committed
902
#if CONFIG_PALETTE_DELTA_ENCODING
903
904
905
906
907
908
909
// 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;
910
  assert(colors[0] < (1 << bit_depth));
911
912
913
914
915
916
  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) {
917
    assert(colors[i] < (1 << bit_depth));
918
919
920
921
922
923
924
    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);
925
  assert(bits <= bit_depth);
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  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
940
941
                                   int bit_depth, aom_writer *w) {
  const int n = pmi->palette_size[0];
942
  uint16_t color_cache[2 * PALETTE_MAX_SIZE];
943
  const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
944
945
946
947
948
949
950
951
952
953
  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
954
  }
955
956
  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
957
958
}

959
960
961
962
963
// 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
964
965
966
967
968
                                    int bit_depth, aom_writer *w) {
  const int n = pmi->palette_size[