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"
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
                           aom_bit_depth_t bit_depth, const TX_SIZE tx_size,
Sarah Parker's avatar
Sarah Parker committed
424
425
426
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                           TX_TYPE tx_type, int is_inter,
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
427
                           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

Sarah Parker's avatar
Sarah Parker committed
432
433
434
435
436
437
438
439
440
441
442
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
  if (tx_type == MRC_DCT && ((is_inter && SIGNAL_MRC_MASK_INTER) ||
                             (!is_inter && SIGNAL_MRC_MASK_INTRA))) {
    int rows = tx_size_high[tx_size];
    int cols = tx_size_wide[tx_size];
    assert(tx_size == TX_32X32);
    assert(p < stop);
    pack_map_tokens(w, &p, 2, rows * cols);
  }
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK

Jingning Han's avatar
Jingning Han committed
443
  while (p < stop && p->token != EOSB_TOKEN) {
444
    const int token = p->token;
Yaowu Xu's avatar
Yaowu Xu committed
445
    const int8_t eob_val = p->eob_val;
446
    if (token == BLOCK_Z_TOKEN) {
447
      aom_write_symbol(w, 0, *p->head_cdf, HEAD_TOKENS + 1);
448
      p++;
449
      break;
450
451
      continue;
    }
Yaowu Xu's avatar
Yaowu Xu committed
452
453

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

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

476
477
478
479
      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);
480
481
482
483
484
485

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

    ++count;
486
    if (eob_val == EARLY_EOB || count == seg_eob) break;
487
488
489
490
  }

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

493
#if CONFIG_LV_MAP
494
static void pack_txb_tokens(aom_writer *w, AV1_COMMON *cm, MACROBLOCK *const x,
495
                            const TOKENEXTRA **tp,
496
497
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
                            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];

  if (tx_size == plane_tx_size) {
    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
523
524
    av1_write_coeffs_txb(cm, xd, w, blk_row, blk_col, block, plane, tx_size,
                         tcoeff, eob, &txb_ctx);
525
526
527
528
529
530
#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];
531
532
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
533

534
    assert(bsw > 0 && bsh > 0);
535

536
537
538
539
540
    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;
541

542
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
543

544
545
546
547
548
        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;
      }
549
550
551
552
    }
  }
}
#else  // CONFIG_LV_MAP
Yaowu Xu's avatar
Yaowu Xu committed
553
static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp,
Yushin Cho's avatar
Yushin Cho committed
554
555
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
Yaowu Xu's avatar
Yaowu Xu committed
556
                            BLOCK_SIZE plane_bsize, aom_bit_depth_t bit_depth,
557
                            int block, int blk_row, int blk_col,
558
                            TX_SIZE tx_size, TOKEN_STATS *token_stats) {
559
560
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
561
562
  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
563
  TX_SIZE plane_tx_size;
564
565
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
Sarah Parker's avatar
Sarah Parker committed
566
567
568
569
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
  TX_TYPE tx_type = av1_get_tx_type(plane ? PLANE_TYPE_UV : PLANE_TYPE_Y, xd,
                                    blk_row, blk_col, block, tx_size);
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
570

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

573
574
575
  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
576

577
  if (tx_size == plane_tx_size) {
578
579
    TOKEN_STATS tmp_token_stats;
    init_token_stats(&tmp_token_stats);
Sarah Parker's avatar
Sarah Parker committed
580
581
582
583
584
    pack_mb_tokens(w, tp, tok_end, bit_depth, tx_size,
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                   tx_type, is_inter_block(mbmi),
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                   &tmp_token_stats);
585
586
587
588
#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
589
  } else {
590
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
591
592
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
593

594
    assert(bsw > 0 && bsh > 0);
595

596
597
598
599
600
    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;
601

602
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
603

604
605
606
607
        pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                        block, offsetr, offsetc, sub_txs, token_stats);
        block += step;
      }
608
609
610
    }
  }
}
611
#endif  // CONFIG_LV_MAP
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
670
671
672
673
674
675
676
677
678
679
680
#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
681
static void write_segment_id(aom_writer *w, const struct segmentation *seg,
682
                             struct segmentation_probs *segp, int segment_id) {
683
684
685
  if (seg->enabled && seg->update_map) {
    aom_write_symbol(w, segment_id, segp->tree_cdf, MAX_SEGMENTS);
  }
Jingning Han's avatar
Jingning Han committed
686
687
}

688
#define WRITE_REF_BIT(bname, pname) \
689
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
690
691
#define WRITE_REF_BIT2(bname, pname) \
  aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
692

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

    if (is_compound) {
Zoe Liu's avatar
Zoe Liu committed
727
728
729
730
#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
731
732
      aom_write_symbol(w, comp_ref_type, av1_get_comp_reference_type_cdf(xd),
                       2);
Zoe Liu's avatar
Zoe Liu committed
733
734
735

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

Zoe Liu's avatar
Zoe Liu committed
738
        if (!bit) {
739
          assert(mbmi->ref_frame[0] == LAST_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
740
741
742
743
744
745
          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);
746
747
748
          }
        } else {
          assert(mbmi->ref_frame[1] == ALTREF_FRAME);
Zoe Liu's avatar
Zoe Liu committed
749
750
751
752
        }

        return;
      }
753
754

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

757
      const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
758
                       mbmi->ref_frame[0] == LAST3_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
759
      WRITE_REF_BIT(bit, comp_ref_p);
760
761

      if (!bit) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
762
763
        const int bit1 = mbmi->ref_frame[0] == LAST_FRAME;
        WRITE_REF_BIT(bit1, comp_ref_p1);
764
      } else {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
765
766
        const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
        WRITE_REF_BIT(bit2, comp_ref_p2);
767
768
      }

Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
769
770
771
772
773
      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
774
775
      }

Jingning Han's avatar
Jingning Han committed
776
    } else {
Zoe Liu's avatar
Zoe Liu committed
777
778
      const int bit0 = (mbmi->ref_frame[0] <= ALTREF_FRAME &&
                        mbmi->ref_frame[0] >= BWDREF_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
779
      WRITE_REF_BIT(bit0, single_ref_p1);
780
781

      if (bit0) {
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
782
783
784
785
786
        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
787
        }
788
789
      } else {
        const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
790
                          mbmi->ref_frame[0] == GOLDEN_FRAME);
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
791
        WRITE_REF_BIT(bit2, single_ref_p3);
792
793

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

805
#if CONFIG_FILTER_INTRA
806
static void write_filter_intra_mode_info(const MACROBLOCKD *xd,
807
808
                                         const MB_MODE_INFO *const mbmi,
                                         aom_writer *w) {
809
810
  if (mbmi->mode == DC_PRED && mbmi->palette_mode_info.palette_size[0] == 0 &&
      av1_filter_intra_allowed_txsize(mbmi->tx_size)) {
811
812
    aom_write_symbol(w, mbmi->filter_intra_mode_info.use_filter_intra_mode[0],
                     xd->tile_ctx->filter_intra_cdfs[mbmi->tx_size], 2);
813
814
815
    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];
816
817
      aom_write_symbol(w, mode, xd->tile_ctx->filter_intra_mode_cdf[0],
                       FILTER_INTRA_MODES);
hui su's avatar
hui su committed
818
819
820
    }
  }
}
821
#endif  // CONFIG_FILTER_INTRA
822

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

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

Luc Trudeau's avatar
Luc Trudeau committed
842
  if (av1_is_directional_mode(get_uv_mode(mbmi->uv_mode), bsize)) {
Joe Young's avatar
Joe Young committed
843
844
845
846
847
#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
848
849
    write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,
                  MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
Joe Young's avatar
Joe Young committed
850
#endif
851
852
  }
}
hui su's avatar
hui su committed
853
854
#endif  // CONFIG_EXT_INTRA

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

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

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