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

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

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

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

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

58
#define ENC_MISMATCH_DEBUG 0
59

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

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

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

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

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

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

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

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

Sarah Parker's avatar
Sarah Parker committed
127
128
129
    const int16_t zeromv_ctx =
        (mode_ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
    aom_write_symbol(w, mode != GLOBALMV, ec_ctx->zeromv_cdf[zeromv_ctx], 2);
130

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

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

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

  assert(mbmi->ref_mv_idx < 3);

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

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

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

180
181
static void write_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                      aom_writer *w, PREDICTION_MODE mode,
182
                                      const int16_t mode_ctx) {
183
184
185
186
187
  assert(is_inter_compound_mode(mode));
  (void)cm;
  aom_write_symbol(w, INTER_COMPOUND_OFFSET(mode),
                   xd->tile_ctx->inter_compound_mode_cdf[mode_ctx],
                   INTER_COMPOUND_MODES);
188
}
189

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

195
static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd,
196
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
197
198
                                int depth, int blk_row, int blk_col,
                                aom_writer *w) {
199
200
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
201
202
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
203
204
205
  const int max_blocks_high = max_block_high(xd, mbmi->sb_type, 0);
  const int max_blocks_wide = max_block_wide(xd, mbmi->sb_type, 0);

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

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

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

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

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

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

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

239
240
241
242
243
244
245
246
    assert(bsw > 0 && bsh > 0);
    for (int row = 0; row < tx_size_high_unit[tx_size]; row += bsh)
      for (int col = 0; col < tx_size_wide_unit[tx_size]; col += bsw) {
        int offsetr = blk_row + row;
        int offsetc = blk_col + col;
        write_tx_size_vartx(cm, xd, mbmi, sub_txs, depth + 1, offsetr, offsetc,
                            w);
      }
247
248
  }
}
249

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

    assert(coded_tx_size <= tx_size_cat + 1);
    assert(depth >= 0 && depth <= max_depths);

    assert(!is_inter_block(mbmi));
268
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
269

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

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

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

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

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

319
  MOTION_MODE last_motion_mode_allowed =
320
      motion_mode_allowed(0, cm->global_motion, xd, mi);
321
322
323
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:
      aom_write_symbol(w, mbmi->motion_mode,
                       xd->tile_ctx->motion_mode_cdf[mbmi->sb_type],
                       MOTION_MODES);
Yue Chen's avatar
Yue Chen committed
331
332
  }
}
333

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

Thomas Davies's avatar
Thomas Davies committed
343
344
  aom_write_symbol(w, AOMMIN(abs, DELTA_Q_SMALL), ec_ctx->delta_q_cdf,
                   DELTA_Q_PROBS + 1);
345
346
347
348

  if (!smallval) {
    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
    thr = (1 << rem_bits) + 1;
349
    aom_write_literal(w, rem_bits - 1, 3);
350
    aom_write_literal(w, abs - thr, rem_bits);
351
352
353
354
355
  }
  if (abs > 0) {
    aom_write_bit(w, sign);
  }
}
356

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

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

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

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

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

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

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

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

465
466
467
468
      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);
469
470
471
472
473
474

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

    ++count;
475
    if (eob_val == EARLY_EOB || count == seg_eob) break;
476
477
478
479
  }

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

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

504
505
506
507
508
  if (tx_size == plane_tx_size
#if DISABLE_VARTX_FOR_CHROMA
      || pd->subsampling_x || pd->subsampling_y
#endif  // DISABLE_VARTX_FOR_CHROMA
      ) {
509
510
511
512
513
514
515
    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
516
517
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, block, plane, tx_size,
                         tcoeff, eob, &txb_ctx);
518
519
520
521
522
523
#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];
524
525
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
526

527
    assert(bsw > 0 && bsh > 0);
528

529
530
531
532
533
    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;
534

535
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
536

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

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

562
563
564
  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
565

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

583
    assert(bsw > 0 && bsh > 0);
584

585
586
587
588
589
    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;
590

591
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
592

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

602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
#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
670
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
671
                             struct segmentation_probs *segp, int segment_id) {
672
673
674
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
675
676
}

677
#define WRITE_REF_BIT(bname, pname) \
678
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
679
680
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
681

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

    if (is_compound) {
Zoe Liu's avatar
Zoe Liu committed
716
717
718
719
#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
720
721
      aom_write_symbol(w, comp_ref_type, av1_get_comp_reference_type_cdf(xd),
                       2);
Zoe Liu's avatar
Zoe Liu committed
722
723
724

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

Zoe Liu's avatar
Zoe Liu committed
727
        if (!bit) {
728
          assert(mbmi->ref_frame[0] == LAST_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
729
730
731
732
733
734
          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);
735
736
737
          }
        } else {
          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
Zoe Liu's avatar
Zoe Liu committed
738
739
740
741
        }

        return;
      }
742
743

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

746
      const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
747
                       mbmi->ref_frame[0] == LAST3_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
748
      WRITE_REF_BIT(bit, comp_ref_p);
749
750

      if (!bit) {
751
        const int bit1 = mbmi->ref_frame[0] == LAST2_FRAME;
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
752
        WRITE_REF_BIT(bit1, comp_ref_p1);
753
      } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
754
755
        const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
        WRITE_REF_BIT(bit2, comp_ref_p2);
756
757
      }

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
758
759
760
761
762
      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
763
764
      }

Jingning Han's avatar
Jingning Han committed
765
    } else {
Zoe Liu's avatar
Zoe Liu committed
766
767
      const int bit0 = (mbmi->ref_frame[0] <= ALTREF_FRAME &&
                        mbmi->ref_frame[0] >= BWDREF_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
768
      WRITE_REF_BIT(bit0, single_ref_p1);
769
770

      if (bit0) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
771
772
773
774
775
        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
776
        }
777
778
      } else {
        const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
779
                          mbmi->ref_frame[0] == GOLDEN_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
780
        WRITE_REF_BIT(bit2, single_ref_p3);
781
782

        if (!bit2) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
783
784
          const int bit3 = mbmi->ref_frame[0] != LAST_FRAME;
          WRITE_REF_BIT(bit3, single_ref_p4);
785
        } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
786
787
          const int bit4 = mbmi->ref_frame[0] != LAST3_FRAME;
          WRITE_REF_BIT(bit4, single_ref_p5);
788
789
        }
      }
Jingning Han's avatar
Jingning Han committed
790
791
792
793
    }
  }
}

794
#if CONFIG_FILTER_INTRA
795
static void write_filter_intra_mode_info(const MACROBLOCKD *xd,
796
797
                                         const MB_MODE_INFO *const mbmi,
                                         aom_writer *w) {
798
799
  if (mbmi->mode == DC_PRED && mbmi->palette_mode_info.palette_size[0] == 0 &&
      av1_filter_intra_allowed_txsize(mbmi->tx_size)) {
800
801
    aom_write_symbol(w, mbmi->filter_intra_mode_info.use_filter_intra_mode[0],
                     xd->tile_ctx->filter_intra_cdfs[mbmi->tx_size], 2);
802
803
804
    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];
805
806
      aom_write_symbol(w, mode, xd->tile_ctx->filter_intra_mode_cdf[0],
                       FILTER_INTRA_MODES);
hui su's avatar
hui su committed
807
808
809
    }
  }
}
810
#endif  // CONFIG_FILTER_INTRA
811

812
#if CONFIG_EXT_INTRA
Joe Young's avatar
Joe Young committed
813
814
static void write_intra_angle_info(const MACROBLOCKD *xd,
                                   FRAME_CONTEXT *const ec_ctx, aom_writer *w) {
815
816
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
817
  if (!av1_use_angle_delta(bsize)) return;
818

hui su's avatar
hui su committed
819
  if (av1_is_directional_mode(mbmi->mode, bsize)) {
Joe Young's avatar
Joe Young committed
820
821
822
823
824
825
#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
826
827
    write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                  MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
Joe Young's avatar
Joe Young committed
828
#endif  // CONFIG_EXT_INTRA_MOD
829
830
  }

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

Angie Chiang's avatar
Angie Chiang committed
844
845
static void write_mb_interp_filter(AV1_COMP *cpi, const MACROBLOCKD *xd,
                                   aom_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
846
  AV1_COMMON *const cm = &cpi->common;
847
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
848
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
849

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

hui su's avatar
hui su committed
886
#if CONFIG_PALETTE_DELTA_ENCODING
887
888
889
890
891
892
893
// 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;
894
  assert(colors[0] < (1 << bit_depth));
895
896
897
898
899
900
  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) {
901
    assert(colors[i] < (1 << bit_depth));
902
903
904
905
906
907
908
    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);
909
  assert(bits <= bit_depth);
910
911
912
913
914
915
916
917
918
919
920
921
922
923
  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
924
925
                                   int bit_depth, aom_writer *w) {
  const int n = pmi->palette_size[0];
926
  uint16_t color_cache[2 * PALETTE_MAX_SIZE];
927
  const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
928
929
930
931
932
933
934
935
936
937
  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
938
  }
939
940
  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
941
942
}

943
944
945
946
947
// 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
948
949
950
951
952
                                    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.
953
  uint16_t color_cache[2 * PALETTE_MAX_SIZE];
954
  const int n_cache = av1_get_palette_cache(xd, 1, color_cache);
955
956
957
958
959
960
961
962
963
  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, colors_u, 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
964
  }
965
966
967
  delta_encode_palette_colors(out_cache_colors, n_out_cache, bit_depth, 0, w);

  // V channel colors. Don't use color cache as the colors are not sorted.
hui su's avatar
hui su committed
968
969
970
971
972
973
974
975
  const int max_val = 1 << bit_depth;
  int zero_count = 0, min_bits_v = 0;
  int bits_v =
      av1_get_palette_delta_bits_v(pmi, bit_depth, &zero_count, &min_bits_v);