bitstream.c 174 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"
28
29
30
31
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
#include "av1/common/entropymv.h"
#include "av1/common/mvref_common.h"
32
#include "av1/common/odintrin.h"
33
34
#include "av1/common/pred_common.h"
#include "av1/common/reconinter.h"
hui su's avatar
hui su committed
35
36
37
#if CONFIG_EXT_INTRA
#include "av1/common/reconintra.h"
#endif  // CONFIG_EXT_INTRA
38
39
#include "av1/common/seg_common.h"
#include "av1/common/tile_common.h"
Jingning Han's avatar
Jingning Han committed
40

Angie Chiang's avatar
Angie Chiang committed
41
42
43
#if CONFIG_LV_MAP
#include "av1/encoder/encodetxb.h"
#endif  // CONFIG_LV_MAP
44
45
46
47
#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
48
#if CONFIG_PALETTE_DELTA_ENCODING
hui su's avatar
hui su committed
49
#include "av1/encoder/palette.h"
Urvang Joshi's avatar
Urvang Joshi committed
50
#endif  // CONFIG_PALETTE_DELTA_ENCODING
51
52
53
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
Jingning Han's avatar
Jingning Han committed
54

55
#define ENC_MISMATCH_DEBUG 0
56

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

Yaowu Xu's avatar
Yaowu Xu committed
69
static struct av1_token interintra_mode_encodings[INTERINTRA_MODES];
70
static struct av1_token compound_type_encodings[COMPOUND_TYPES];
71
#if CONFIG_LOOP_RESTORATION
72
73
static void loop_restoration_write_sb_coeffs(const AV1_COMMON *const cm,
                                             MACROBLOCKD *xd,
74
75
                                             const RestorationUnitInfo *rui,
                                             aom_writer *const w, int plane);
76
#endif  // CONFIG_LOOP_RESTORATION
77
78
79
80
81
82
83
84
#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

85
static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data);
86

87
#if !CONFIG_OBU || CONFIG_EXT_TILE
88
89
90
91
92
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);
93
#endif
Yaowu Xu's avatar
Yaowu Xu committed
94
95
void av1_encode_token_init(void) {
  av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree);
96
  av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree);
97
98
}

Jingning Han's avatar
Jingning Han committed
99
100
101
102
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
103
104
105
#if CONFIG_INTRABC
  assert(!is_intrabc_block(&mi->mbmi));
#endif  // CONFIG_INTRABC
Hui Su's avatar
Hui Su committed
106
  aom_write_symbol(w, mode,
Jingning Han's avatar
Jingning Han committed
107
108
109
110
                   get_y_mode_cdf(frame_ctx, mi, above_mi, left_mi, block),
                   INTRA_MODES);
  (void)cm;
}
Jingning Han's avatar
Jingning Han committed
111

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

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

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

Sarah Parker's avatar
Sarah Parker committed
124
125
126
    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);
127

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

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

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

  assert(mbmi->ref_mv_idx < 3);

145
  const int new_mv = mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV;
146
  if (new_mv) {
147
148
149
150
    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
151
            av1_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
152

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

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

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

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

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

203
204
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
205
                                   mbmi->sb_type, tx_size);
206

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

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

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

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

228
    aom_write_symbol(w, 1, ec_ctx->txfm_partition_cdf[ctx], 2);
229

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

236
237
238
239
240
241
242
243
    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);
      }
244
245
  }
}
246

Yaowu Xu's avatar
Yaowu Xu committed
247
248
static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                                   aom_writer *w) {
249
250
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
251
252
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
253
  if (block_signals_txsize(bsize)) {
254
    const TX_SIZE tx_size = mbmi->tx_size;
255
    const int tx_size_ctx = get_tx_size_context(xd);
256
    const int32_t tx_size_cat = intra_tx_size_cat_lookup[bsize];
257
    const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];
258
259
260
261
262
263
264
    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));
265
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(xd, mbmi)));
266

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

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

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

303
304
305
static void write_is_inter(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                           int segment_id, aom_writer *w, const int is_inter) {
  if (!segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
306
    const int ctx = av1_get_intra_inter_context(xd);
307
308
309
310
311
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    aom_write_symbol(w, is_inter, ec_ctx->intra_inter_cdf[ctx], 2);
  }
}

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

316
  MOTION_MODE last_motion_mode_allowed =
317
      motion_mode_allowed(0, cm->global_motion, xd, mi);
318
319
320
321
322
323
324
325
326
327
  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
328
329
  }
}
330

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

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

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

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

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

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

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

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

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

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

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

462
463
464
465
      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);
466
467
468
469
470
471

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

    ++count;
472
    if (eob_val == EARLY_EOB || count == seg_eob) break;
473
474
475
476
  }

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

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

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

524
    assert(bsw > 0 && bsh > 0);
525

526
527
528
529
530
    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;
531

532
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
533

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

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

559
560
561
  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
562

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

580
    assert(bsw > 0 && bsh > 0);
581

582
583
584
585
586
    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;
587

588
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
589

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

599
600
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
#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
667
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
668
                             struct segmentation_probs *segp, int segment_id) {
669
670
671
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
672
673
}

674
#define WRITE_REF_BIT(bname, pname) \
675
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
676
677
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
678

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

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

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

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

        return;
      }
739
740

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

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

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

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
755
756
757
758
759
      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
760
761
      }

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

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

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

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

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

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

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

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

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

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

940
941
942
943
944
// 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
945