bitstream.c 52.9 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <assert.h>
#include <stdio.h>
#include <limits.h>

#include "vpx/vpx_encoder.h"
#include "vpx_dsp/bitwriter_buffer.h"
17
#include "vpx_dsp/vpx_dsp_common.h"
Jingning Han's avatar
Jingning Han committed
18
19
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem_ops.h"
20
#include "vpx_ports/system_state.h"
Jingning Han's avatar
Jingning Han committed
21

Yaowu Xu's avatar
Yaowu Xu committed
22
23
24
#if CONFIG_CLPF
#include "vp10/common/clpf.h"
#endif
25
26
27
#if CONFIG_DERING
#include "vp10/common/dering.h"
#endif  // CONFIG_DERING
28
29
30
31
32
33
34
#include "vp10/common/entropy.h"
#include "vp10/common/entropymode.h"
#include "vp10/common/entropymv.h"
#include "vp10/common/mvref_common.h"
#include "vp10/common/pred_common.h"
#include "vp10/common/seg_common.h"
#include "vp10/common/tile_common.h"
Jingning Han's avatar
Jingning Han committed
35

36
37
38
39
40
41
42
#include "vp10/encoder/cost.h"
#include "vp10/encoder/bitstream.h"
#include "vp10/encoder/encodemv.h"
#include "vp10/encoder/mcomp.h"
#include "vp10/encoder/segmentation.h"
#include "vp10/encoder/subexp.h"
#include "vp10/encoder/tokenize.h"
Jingning Han's avatar
Jingning Han committed
43
44

static const struct vp10_token intra_mode_encodings[INTRA_MODES] = {
clang-format's avatar
clang-format committed
45
46
47
  { 0, 1 },  { 6, 3 },   { 28, 5 },  { 30, 5 }, { 58, 6 },
  { 59, 6 }, { 126, 7 }, { 127, 7 }, { 62, 6 }, { 2, 2 }
};
Jingning Han's avatar
Jingning Han committed
48
static const struct vp10_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
clang-format's avatar
clang-format committed
49
50
51
52
53
54
55
    { { 0, 1 }, { 2, 2 }, { 3, 2 } };
static const struct vp10_token partition_encodings[PARTITION_TYPES] = {
  { 0, 1 }, { 2, 2 }, { 6, 3 }, { 7, 3 }
};
static const struct vp10_token inter_mode_encodings[INTER_MODES] = {
  { 2, 2 }, { 6, 3 }, { 0, 1 }, { 7, 3 }
};
hui su's avatar
hui su committed
56

57
58
59
60
61
62
static struct vp10_token ext_tx_encodings[TX_TYPES];

void vp10_encode_token_init() {
  vp10_tokens_from_tree(ext_tx_encodings, vp10_ext_tx_tree);
}

Jingning Han's avatar
Jingning Han committed
63
64
65
66
67
68
69
70
71
static void write_intra_mode(vpx_writer *w, PREDICTION_MODE mode,
                             const vpx_prob *probs) {
  vp10_write_token(w, vp10_intra_mode_tree, probs, &intra_mode_encodings[mode]);
}

static void write_inter_mode(vpx_writer *w, PREDICTION_MODE mode,
                             const vpx_prob *probs) {
  assert(is_inter_mode(mode));
  vp10_write_token(w, vp10_inter_mode_tree, probs,
clang-format's avatar
clang-format committed
72
                   &inter_mode_encodings[INTER_OFFSET(mode)]);
Jingning Han's avatar
Jingning Han committed
73
74
}

clang-format's avatar
clang-format committed
75
76
static void encode_unsigned_max(struct vpx_write_bit_buffer *wb, int data,
                                int max) {
Jingning Han's avatar
Jingning Han committed
77
78
79
80
81
  vpx_wb_write_literal(wb, data, get_unsigned_bits(max));
}

static void prob_diff_update(const vpx_tree_index *tree,
                             vpx_prob probs[/*n - 1*/],
clang-format's avatar
clang-format committed
82
83
                             const unsigned int counts[/*n - 1*/], int n,
                             vpx_writer *w) {
Jingning Han's avatar
Jingning Han committed
84
85
86
87
88
89
90
91
92
93
94
  int i;
  unsigned int branch_ct[32][2];

  // Assuming max number of probabilities <= 32
  assert(n <= 32);

  vp10_tree_probs_from_distribution(tree, branch_ct, counts);
  for (i = 0; i < n - 1; ++i)
    vp10_cond_prob_diff_update(w, &probs[i], branch_ct[i]);
}

95
96
97
98
99
100
101
102
103
104
105
106
static int prob_diff_update_savings(const vpx_tree_index *tree,
                                    vpx_prob probs[/*n - 1*/],
                                    const unsigned int counts[/*n - 1*/],
                                    int n) {
  int i;
  unsigned int branch_ct[32][2];
  int savings = 0;

  // Assuming max number of probabilities <= 32
  assert(n <= 32);
  vp10_tree_probs_from_distribution(tree, branch_ct, counts);
  for (i = 0; i < n - 1; ++i) {
clang-format's avatar
clang-format committed
107
    savings += vp10_cond_prob_diff_update_savings(&probs[i], branch_ct[i]);
108
109
110
111
  }
  return savings;
}

clang-format's avatar
clang-format committed
112
113
static void write_selected_tx_size(const VP10_COMMON *cm, const MACROBLOCKD *xd,
                                   vpx_writer *w) {
Jingning Han's avatar
Jingning Han committed
114
115
116
  TX_SIZE tx_size = xd->mi[0]->mbmi.tx_size;
  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
  const TX_SIZE max_tx_size = max_txsize_lookup[bsize];
clang-format's avatar
clang-format committed
117
118
  const vpx_prob *const tx_probs =
      get_tx_probs2(max_tx_size, xd, &cm->fc->tx_probs);
Jingning Han's avatar
Jingning Han committed
119
120
121
122
123
124
125
126
  vpx_write(w, tx_size != TX_4X4, tx_probs[0]);
  if (tx_size != TX_4X4 && max_tx_size >= TX_16X16) {
    vpx_write(w, tx_size != TX_8X8, tx_probs[1]);
    if (tx_size != TX_8X8 && max_tx_size >= TX_32X32)
      vpx_write(w, tx_size != TX_16X16, tx_probs[2]);
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
127
static int write_skip(const VP10_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
128
129
130
131
132
133
134
135
136
137
                      int segment_id, const MODE_INFO *mi, vpx_writer *w) {
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
    vpx_write(w, skip, vp10_get_skip_prob(cm, xd));
    return skip;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
138
static void update_skip_probs(VP10_COMMON *cm, vpx_writer *w,
Jingning Han's avatar
Jingning Han committed
139
140
141
142
143
144
145
                              FRAME_COUNTS *counts) {
  int k;

  for (k = 0; k < SKIP_CONTEXTS; ++k)
    vp10_cond_prob_diff_update(w, &cm->fc->skip_probs[k], counts->skip[k]);
}

Yaowu Xu's avatar
Yaowu Xu committed
146
static void update_switchable_interp_probs(VP10_COMMON *cm, vpx_writer *w,
Jingning Han's avatar
Jingning Han committed
147
148
149
150
151
152
153
154
                                           FRAME_COUNTS *counts) {
  int j;
  for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; ++j)
    prob_diff_update(vp10_switchable_interp_tree,
                     cm->fc->switchable_interp_prob[j],
                     counts->switchable_interp[j], SWITCHABLE_FILTERS, w);
}

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
static void update_ext_tx_probs(VP10_COMMON *cm, vpx_writer *w) {
  const int savings_thresh = vp10_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             vp10_cost_zero(GROUP_DIFF_UPDATE_PROB);
  int i, j;

  int savings = 0;
  int do_update = 0;
  for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
    for (j = 0; j < TX_TYPES; ++j)
      savings += prob_diff_update_savings(
          vp10_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
          cm->counts.intra_ext_tx[i][j], TX_TYPES);
  }
  do_update = savings > savings_thresh;
  vpx_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
      for (j = 0; j < TX_TYPES; ++j)
clang-format's avatar
clang-format committed
173
174
        prob_diff_update(vp10_ext_tx_tree, cm->fc->intra_ext_tx_prob[i][j],
                         cm->counts.intra_ext_tx[i][j], TX_TYPES, w);
175
176
177
178
    }
  }
  savings = 0;
  for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
clang-format's avatar
clang-format committed
179
180
181
    savings +=
        prob_diff_update_savings(vp10_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
                                 cm->counts.inter_ext_tx[i], TX_TYPES);
182
183
184
185
186
  }
  do_update = savings > savings_thresh;
  vpx_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
clang-format's avatar
clang-format committed
187
188
      prob_diff_update(vp10_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
                       cm->counts.inter_ext_tx[i], TX_TYPES, w);
189
190
191
192
    }
  }
}

clang-format's avatar
clang-format committed
193
194
static void pack_mb_tokens(vpx_writer *w, TOKENEXTRA **tp,
                           const TOKENEXTRA *const stop,
195
                           vpx_bit_depth_t bit_depth, const TX_SIZE tx) {
Jingning Han's avatar
Jingning Han committed
196
  TOKENEXTRA *p = *tp;
197
#if !CONFIG_MISC_FIXES
clang-format's avatar
clang-format committed
198
  (void)tx;
199
#endif
Jingning Han's avatar
Jingning Han committed
200
201
202
203
204
205
206

  while (p < stop && p->token != EOSB_TOKEN) {
    const int t = p->token;
    const struct vp10_token *const a = &vp10_coef_encodings[t];
    int i = 0;
    int v = a->value;
    int n = a->len;
207
#if CONFIG_VPX_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
208
209
210
211
212
213
214
215
216
    const vp10_extra_bit *b;
    if (bit_depth == VPX_BITS_12)
      b = &vp10_extra_bits_high12[t];
    else if (bit_depth == VPX_BITS_10)
      b = &vp10_extra_bits_high10[t];
    else
      b = &vp10_extra_bits[t];
#else
    const vp10_extra_bit *const b = &vp10_extra_bits[t];
clang-format's avatar
clang-format committed
217
    (void)bit_depth;
218
#endif  // CONFIG_VPX_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

    /* skip one or two nodes */
    if (p->skip_eob_node) {
      n -= p->skip_eob_node;
      i = 2 * p->skip_eob_node;
    }

    // TODO(jbb): expanding this can lead to big gains.  It allows
    // much better branch prediction and would enable us to avoid numerous
    // lookups and compares.

    // If we have a token that's in the constrained set, the coefficient tree
    // is split into two treed writes.  The first treed write takes care of the
    // unconstrained nodes.  The second treed write takes care of the
    // constrained nodes.
    if (t >= TWO_TOKEN && t < EOB_TOKEN) {
      int len = UNCONSTRAINED_NODES - p->skip_eob_node;
      int bits = v >> (n - len);
      vp10_write_tree(w, vp10_coef_tree, p->context_tree, bits, len, i);
      vp10_write_tree(w, vp10_coef_con_tree,
clang-format's avatar
clang-format committed
239
240
                      vp10_pareto8_full[p->context_tree[PIVOT_NODE] - 1], v,
                      n - len, 0);
Jingning Han's avatar
Jingning Han committed
241
242
243
244
245
246
    } else {
      vp10_write_tree(w, vp10_coef_tree, p->context_tree, v, n, i);
    }

    if (b->base_val) {
      const int e = p->extra, l = b->len;
247
#if CONFIG_MISC_FIXES
clang-format's avatar
clang-format committed
248
      int skip_bits = (b->base_val == CAT6_MIN_VAL) ? TX_SIZES - 1 - tx : 0;
249
250
251
#else
      int skip_bits = 0;
#endif
Jingning Han's avatar
Jingning Han committed
252
253
254
255

      if (l) {
        const unsigned char *pb = b->prob;
        int v = e >> 1;
clang-format's avatar
clang-format committed
256
        int n = l; /* number of bits in v, assumed nonzero */
Jingning Han's avatar
Jingning Han committed
257
258
259
260
        int i = 0;

        do {
          const int bb = (v >> --n) & 1;
261
262
263
264
265
266
          if (skip_bits) {
            skip_bits--;
            assert(!bb);
          } else {
            vpx_write(w, bb, pb[i >> 1]);
          }
Jingning Han's avatar
Jingning Han committed
267
268
269
270
271
272
273
274
275
          i = b->tree[i + bb];
        } while (n);
      }

      vpx_write_bit(w, e & 1);
    }
    ++p;
  }

276
  *tp = p;
Jingning Han's avatar
Jingning Han committed
277
278
279
}

static void write_segment_id(vpx_writer *w, const struct segmentation *seg,
280
                             const struct segmentation_probs *segp,
Jingning Han's avatar
Jingning Han committed
281
282
                             int segment_id) {
  if (seg->enabled && seg->update_map)
283
    vp10_write_tree(w, vp10_segment_tree, segp->tree_probs, segment_id, 3, 0);
Jingning Han's avatar
Jingning Han committed
284
285
286
}

// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
287
static void write_ref_frames(const VP10_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
288
289
290
291
292
293
294
295
296
297
                             vpx_writer *w) {
  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] ==
clang-format's avatar
clang-format committed
298
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
Jingning Han's avatar
Jingning Han committed
299
300
301
302
303
304
  } else {
    // does the feature use compound prediction or not
    // (if not specified at the frame/segment level)
    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
      vpx_write(w, is_compound, vp10_get_reference_mode_prob(cm, xd));
    } else {
305
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
    }

    if (is_compound) {
      vpx_write(w, mbmi->ref_frame[0] == GOLDEN_FRAME,
                vp10_get_pred_prob_comp_ref_p(cm, xd));
    } else {
      const int bit0 = mbmi->ref_frame[0] != LAST_FRAME;
      vpx_write(w, bit0, vp10_get_pred_prob_single_ref_p1(cm, xd));
      if (bit0) {
        const int bit1 = mbmi->ref_frame[0] != GOLDEN_FRAME;
        vpx_write(w, bit1, vp10_get_pred_prob_single_ref_p2(cm, xd));
      }
    }
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
322
static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
Jingning Han's avatar
Jingning Han committed
323
                                vpx_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
324
  VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
325
326
327
328
  const nmv_context *nmvc = &cm->fc->nmvc;
  const MACROBLOCK *const x = &cpi->td.mb;
  const MACROBLOCKD *const xd = &x->e_mbd;
  const struct segmentation *const seg = &cm->seg;
329
330
331
332
333
#if CONFIG_MISC_FIXES
  const struct segmentation_probs *const segp = &cm->fc->seg;
#else
  const struct segmentation_probs *const segp = &cm->segp;
#endif
Jingning Han's avatar
Jingning Han committed
334
335
336
337
338
339
340
341
342
343
344
345
346
  const MB_MODE_INFO *const mbmi = &mi->mbmi;
  const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
  const PREDICTION_MODE mode = mbmi->mode;
  const int segment_id = mbmi->segment_id;
  const BLOCK_SIZE bsize = mbmi->sb_type;
  const int allow_hp = cm->allow_high_precision_mv;
  const int is_inter = is_inter_block(mbmi);
  const int is_compound = has_second_ref(mbmi);
  int skip, ref;

  if (seg->update_map) {
    if (seg->temporal_update) {
      const int pred_flag = mbmi->seg_id_predicted;
347
      vpx_prob pred_prob = vp10_get_pred_prob_seg_id(segp, xd);
Jingning Han's avatar
Jingning Han committed
348
      vpx_write(w, pred_flag, pred_prob);
clang-format's avatar
clang-format committed
349
      if (!pred_flag) write_segment_id(w, seg, segp, segment_id);
Jingning Han's avatar
Jingning Han committed
350
    } else {
351
      write_segment_id(w, seg, segp, segment_id);
Jingning Han's avatar
Jingning Han committed
352
353
354
355
356
357
358
359
360
    }
  }

  skip = write_skip(cm, xd, segment_id, mi, w);

  if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
    vpx_write(w, is_inter, vp10_get_intra_inter_prob(cm, xd));

  if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
361
      !(is_inter && skip) && !xd->lossless[segment_id]) {
Jingning Han's avatar
Jingning Han committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
    write_selected_tx_size(cm, xd, w);
  }

  if (!is_inter) {
    if (bsize >= BLOCK_8X8) {
      write_intra_mode(w, mode, cm->fc->y_mode_prob[size_group_lookup[bsize]]);
    } else {
      int idx, idy;
      const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
      const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
      for (idy = 0; idy < 2; idy += num_4x4_h) {
        for (idx = 0; idx < 2; idx += num_4x4_w) {
          const PREDICTION_MODE b_mode = mi->bmi[idy * 2 + idx].as_mode;
          write_intra_mode(w, b_mode, cm->fc->y_mode_prob[0]);
        }
      }
    }
    write_intra_mode(w, mbmi->uv_mode, cm->fc->uv_mode_prob[mode]);
  } else {
    const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
    const vpx_prob *const inter_probs = cm->fc->inter_mode_probs[mode_ctx];
    write_ref_frames(cm, xd, w);

    // If segment skip is not enabled code the mode.
    if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
      if (bsize >= BLOCK_8X8) {
        write_inter_mode(w, mode, inter_probs);
      }
    }

    if (cm->interp_filter == SWITCHABLE) {
      const int ctx = vp10_get_pred_context_switchable_interp(xd);
      vp10_write_token(w, vp10_switchable_interp_tree,
clang-format's avatar
clang-format committed
395
396
                       cm->fc->switchable_interp_prob[ctx],
                       &switchable_interp_encodings[mbmi->interp_filter]);
Jingning Han's avatar
Jingning Han committed
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
      ++cpi->interp_filter_selected[0][mbmi->interp_filter];
    } else {
      assert(mbmi->interp_filter == cm->interp_filter);
    }

    if (bsize < BLOCK_8X8) {
      const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
      const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
      int idx, idy;
      for (idy = 0; idy < 2; idy += num_4x4_h) {
        for (idx = 0; idx < 2; idx += num_4x4_w) {
          const int j = idy * 2 + idx;
          const PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
          write_inter_mode(w, b_mode, inter_probs);
          if (b_mode == NEWMV) {
            for (ref = 0; ref < 1 + is_compound; ++ref)
              vp10_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv,
clang-format's avatar
clang-format committed
414
415
                             &mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
                             nmvc, allow_hp);
Jingning Han's avatar
Jingning Han committed
416
417
418
419
420
421
422
          }
        }
      }
    } else {
      if (mode == NEWMV) {
        for (ref = 0; ref < 1 + is_compound; ++ref)
          vp10_encode_mv(cpi, w, &mbmi->mv[ref].as_mv,
clang-format's avatar
clang-format committed
423
424
                         &mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
                         nmvc, allow_hp);
Jingning Han's avatar
Jingning Han committed
425
426
427
      }
    }
  }
clang-format's avatar
clang-format committed
428
  if (mbmi->tx_size < TX_32X32 && cm->base_qindex > 0 && !mbmi->skip &&
429
430
      !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    if (is_inter) {
clang-format's avatar
clang-format committed
431
432
433
      vp10_write_token(w, vp10_ext_tx_tree,
                       cm->fc->inter_ext_tx_prob[mbmi->tx_size],
                       &ext_tx_encodings[mbmi->tx_type]);
434
435
436
437
438
439
440
441
    } else {
      vp10_write_token(
          w, vp10_ext_tx_tree,
          cm->fc->intra_ext_tx_prob[mbmi->tx_size]
                                   [intra_mode_to_tx_type_context[mbmi->mode]],
          &ext_tx_encodings[mbmi->tx_type]);
    }
  } else {
clang-format's avatar
clang-format committed
442
    if (!mbmi->skip) assert(mbmi->tx_type == DCT_DCT);
443
  }
Jingning Han's avatar
Jingning Han committed
444
445
}

Yaowu Xu's avatar
Yaowu Xu committed
446
static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
447
448
                              MODE_INFO **mi_8x8, vpx_writer *w) {
  const struct segmentation *const seg = &cm->seg;
449
450
451
452
453
#if CONFIG_MISC_FIXES
  const struct segmentation_probs *const segp = &cm->fc->seg;
#else
  const struct segmentation_probs *const segp = &cm->segp;
#endif
Jingning Han's avatar
Jingning Han committed
454
455
456
457
458
459
  const MODE_INFO *const mi = mi_8x8[0];
  const MODE_INFO *const above_mi = xd->above_mi;
  const MODE_INFO *const left_mi = xd->left_mi;
  const MB_MODE_INFO *const mbmi = &mi->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;

clang-format's avatar
clang-format committed
460
  if (seg->update_map) write_segment_id(w, seg, segp, mbmi->segment_id);
Jingning Han's avatar
Jingning Han committed
461
462
463

  write_skip(cm, xd, mbmi->segment_id, mi, w);

464
465
  if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
      !xd->lossless[mbmi->segment_id])
Jingning Han's avatar
Jingning Han committed
466
467
468
    write_selected_tx_size(cm, xd, w);

  if (bsize >= BLOCK_8X8) {
469
470
    write_intra_mode(w, mbmi->mode,
                     get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
Jingning Han's avatar
Jingning Han committed
471
472
473
474
475
476
477
478
479
  } else {
    const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
    const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
    int idx, idy;

    for (idy = 0; idy < 2; idy += num_4x4_h) {
      for (idx = 0; idx < 2; idx += num_4x4_w) {
        const int block = idy * 2 + idx;
        write_intra_mode(w, mi->bmi[block].as_mode,
480
                         get_y_mode_probs(cm, mi, above_mi, left_mi, block));
Jingning Han's avatar
Jingning Han committed
481
482
483
484
      }
    }
  }

485
  write_intra_mode(w, mbmi->uv_mode, cm->fc->uv_mode_prob[mbmi->mode]);
486

clang-format's avatar
clang-format committed
487
  if (mbmi->tx_size < TX_32X32 && cm->base_qindex > 0 && !mbmi->skip &&
488
489
490
491
492
493
494
      !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    vp10_write_token(
        w, vp10_ext_tx_tree,
        cm->fc->intra_ext_tx_prob[mbmi->tx_size]
                                 [intra_mode_to_tx_type_context[mbmi->mode]],
        &ext_tx_encodings[mbmi->tx_type]);
  }
Jingning Han's avatar
Jingning Han committed
495
496
}

Yaowu Xu's avatar
Yaowu Xu committed
497
static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile,
Jingning Han's avatar
Jingning Han committed
498
                          vpx_writer *w, TOKENEXTRA **tok,
clang-format's avatar
clang-format committed
499
500
                          const TOKENEXTRA *const tok_end, int mi_row,
                          int mi_col) {
Yaowu Xu's avatar
Yaowu Xu committed
501
  const VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
502
503
  MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
  MODE_INFO *m;
504
  int plane;
Jingning Han's avatar
Jingning Han committed
505
506
507
508

  xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col);
  m = xd->mi[0];

Jingning Han's avatar
Jingning Han committed
509
  cpi->td.mb.mbmi_ext = cpi->mbmi_ext_base + (mi_row * cm->mi_cols + mi_col);
Jingning Han's avatar
Jingning Han committed
510

clang-format's avatar
clang-format committed
511
  set_mi_row_col(xd, tile, mi_row, num_8x8_blocks_high_lookup[m->mbmi.sb_type],
Jingning Han's avatar
Jingning Han committed
512
513
514
515
516
517
518
519
                 mi_col, num_8x8_blocks_wide_lookup[m->mbmi.sb_type],
                 cm->mi_rows, cm->mi_cols);
  if (frame_is_intra_only(cm)) {
    write_mb_modes_kf(cm, xd, xd->mi, w);
  } else {
    pack_inter_mode_mvs(cpi, m, w);
  }

520
521
522
  if (!m->mbmi.skip) {
    assert(*tok < tok_end);
    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
clang-format's avatar
clang-format committed
523
524
      TX_SIZE tx =
          plane ? get_uv_tx_size(&m->mbmi, &xd->plane[plane]) : m->mbmi.tx_size;
525
526
527
528
529
      pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx);
      assert(*tok < tok_end && (*tok)->token == EOSB_TOKEN);
      (*tok)++;
    }
  }
Jingning Han's avatar
Jingning Han committed
530
531
}

Yaowu Xu's avatar
Yaowu Xu committed
532
static void write_partition(const VP10_COMMON *const cm,
clang-format's avatar
clang-format committed
533
534
535
                            const MACROBLOCKD *const xd, int hbs, int mi_row,
                            int mi_col, PARTITION_TYPE p, BLOCK_SIZE bsize,
                            vpx_writer *w) {
Jingning Han's avatar
Jingning Han committed
536
  const int ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
537
  const vpx_prob *const probs = cm->fc->partition_prob[ctx];
Jingning Han's avatar
Jingning Han committed
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  const int has_rows = (mi_row + hbs) < cm->mi_rows;
  const int has_cols = (mi_col + hbs) < cm->mi_cols;

  if (has_rows && has_cols) {
    vp10_write_token(w, vp10_partition_tree, probs, &partition_encodings[p]);
  } else if (!has_rows && has_cols) {
    assert(p == PARTITION_SPLIT || p == PARTITION_HORZ);
    vpx_write(w, p == PARTITION_SPLIT, probs[1]);
  } else if (has_rows && !has_cols) {
    assert(p == PARTITION_SPLIT || p == PARTITION_VERT);
    vpx_write(w, p == PARTITION_SPLIT, probs[2]);
  } else {
    assert(p == PARTITION_SPLIT);
  }
}

clang-format's avatar
clang-format committed
554
555
556
557
static void write_modes_sb(VP10_COMP *cpi, const TileInfo *const tile,
                           vpx_writer *w, TOKENEXTRA **tok,
                           const TOKENEXTRA *const tok_end, int mi_row,
                           int mi_col, BLOCK_SIZE bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
558
  const VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
559
560
561
562
563
564
565
566
  MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;

  const int bsl = b_width_log2_lookup[bsize];
  const int bs = (1 << bsl) / 4;
  PARTITION_TYPE partition;
  BLOCK_SIZE subsize;
  const MODE_INFO *m = NULL;

clang-format's avatar
clang-format committed
567
  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
Jingning Han's avatar
Jingning Han committed
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

  m = cm->mi_grid_visible[mi_row * cm->mi_stride + mi_col];

  partition = partition_lookup[bsl][m->mbmi.sb_type];
  write_partition(cm, xd, bs, mi_row, mi_col, partition, bsize, w);
  subsize = get_subsize(bsize, partition);
  if (subsize < BLOCK_8X8) {
    write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
  } else {
    switch (partition) {
      case PARTITION_NONE:
        write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
        break;
      case PARTITION_HORZ:
        write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
        if (mi_row + bs < cm->mi_rows)
          write_modes_b(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col);
        break;
      case PARTITION_VERT:
        write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
        if (mi_col + bs < cm->mi_cols)
          write_modes_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs);
        break;
      case PARTITION_SPLIT:
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, subsize);
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs,
                       subsize);
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col,
                       subsize);
        write_modes_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col + bs,
                       subsize);
        break;
clang-format's avatar
clang-format committed
600
      default: assert(0);
Jingning Han's avatar
Jingning Han committed
601
602
603
604
605
606
607
    }
  }

  // update partition context
  if (bsize >= BLOCK_8X8 &&
      (bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
    update_partition_context(xd, mi_row, mi_col, subsize, bsize);
608
609
610
611
612
613

#if DERING_REFINEMENT
  if (bsize == BLOCK_64X64 && cm->dering_level != 0 &&
      !sb_all_skip(cm, mi_row, mi_col)) {
    vpx_write_literal(
        w, cm->mi_grid_visible[mi_row*cm->mi_stride + mi_col]->mbmi.dering_gain,
614
        DERING_REFINEMENT_BITS);
615
616
  }
#endif
Jingning Han's avatar
Jingning Han committed
617
618
}

clang-format's avatar
clang-format committed
619
620
621
static void write_modes(VP10_COMP *cpi, const TileInfo *const tile,
                        vpx_writer *w, TOKENEXTRA **tok,
                        const TOKENEXTRA *const tok_end) {
Jingning Han's avatar
Jingning Han committed
622
623
624
625
626
627
628
629
  MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
  int mi_row, mi_col;

  for (mi_row = tile->mi_row_start; mi_row < tile->mi_row_end;
       mi_row += MI_BLOCK_SIZE) {
    vp10_zero(xd->left_seg_context);
    for (mi_col = tile->mi_col_start; mi_col < tile->mi_col_end;
         mi_col += MI_BLOCK_SIZE)
clang-format's avatar
clang-format committed
630
      write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, BLOCK_64X64);
Jingning Han's avatar
Jingning Han committed
631
632
633
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
634
static void build_tree_distribution(VP10_COMP *cpi, TX_SIZE tx_size,
Jingning Han's avatar
Jingning Han committed
635
636
637
                                    vp10_coeff_stats *coef_branch_ct,
                                    vp10_coeff_probs_model *coef_probs) {
  vp10_coeff_count *coef_counts = cpi->td.rd_counts.coef_counts[tx_size];
clang-format's avatar
clang-format committed
638
  unsigned int(*eob_branch_ct)[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS] =
Jingning Han's avatar
Jingning Han committed
639
640
641
642
643
644
645
646
      cpi->common.counts.eob_branch[tx_size];
  int i, j, k, l, m;

  for (i = 0; i < PLANE_TYPES; ++i) {
    for (j = 0; j < REF_TYPES; ++j) {
      for (k = 0; k < COEF_BANDS; ++k) {
        for (l = 0; l < BAND_COEFF_CONTEXTS(k); ++l) {
          vp10_tree_probs_from_distribution(vp10_coef_tree,
clang-format's avatar
clang-format committed
647
648
649
650
                                            coef_branch_ct[i][j][k][l],
                                            coef_counts[i][j][k][l]);
          coef_branch_ct[i][j][k][l][0][1] =
              eob_branch_ct[i][j][k][l] - coef_branch_ct[i][j][k][l][0][0];
Jingning Han's avatar
Jingning Han committed
651
          for (m = 0; m < UNCONSTRAINED_NODES; ++m)
clang-format's avatar
clang-format committed
652
653
654
            coef_probs[i][j][k][l][m] =
                get_binary_prob(coef_branch_ct[i][j][k][l][m][0],
                                coef_branch_ct[i][j][k][l][m][1]);
Jingning Han's avatar
Jingning Han committed
655
656
657
658
659
660
        }
      }
    }
  }
}

clang-format's avatar
clang-format committed
661
static void update_coef_probs_common(vpx_writer *const bc, VP10_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
662
663
664
665
666
667
668
669
670
671
672
673
674
                                     TX_SIZE tx_size,
                                     vp10_coeff_stats *frame_branch_ct,
                                     vp10_coeff_probs_model *new_coef_probs) {
  vp10_coeff_probs_model *old_coef_probs = cpi->common.fc->coef_probs[tx_size];
  const vpx_prob upd = DIFF_UPDATE_PROB;
  const int entropy_nodes_update = UNCONSTRAINED_NODES;
  int i, j, k, l, t;
  int stepsize = cpi->sf.coeff_prob_appx_step;

  switch (cpi->sf.use_fast_coef_updates) {
    case TWO_LOOP: {
      /* dry run to see if there is any update at all needed */
      int savings = 0;
clang-format's avatar
clang-format committed
675
      int update[2] = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
      for (i = 0; i < PLANE_TYPES; ++i) {
        for (j = 0; j < REF_TYPES; ++j) {
          for (k = 0; k < COEF_BANDS; ++k) {
            for (l = 0; l < BAND_COEFF_CONTEXTS(k); ++l) {
              for (t = 0; t < entropy_nodes_update; ++t) {
                vpx_prob newp = new_coef_probs[i][j][k][l][t];
                const vpx_prob oldp = old_coef_probs[i][j][k][l][t];
                int s;
                int u = 0;
                if (t == PIVOT_NODE)
                  s = vp10_prob_diff_update_savings_search_model(
                      frame_branch_ct[i][j][k][l][0],
                      old_coef_probs[i][j][k][l], &newp, upd, stepsize);
                else
                  s = vp10_prob_diff_update_savings_search(
                      frame_branch_ct[i][j][k][l][t], oldp, &newp, upd);
clang-format's avatar
clang-format committed
692
                if (s > 0 && newp != oldp) u = 1;
Jingning Han's avatar
Jingning Han committed
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
                if (u)
                  savings += s - (int)(vp10_cost_zero(upd));
                else
                  savings -= (int)(vp10_cost_zero(upd));
                update[u]++;
              }
            }
          }
        }
      }

      // printf("Update %d %d, savings %d\n", update[0], update[1], savings);
      /* Is coef updated at all */
      if (update[1] == 0 || savings < 0) {
        vpx_write_bit(bc, 0);
        return;
      }
      vpx_write_bit(bc, 1);
      for (i = 0; i < PLANE_TYPES; ++i) {
        for (j = 0; j < REF_TYPES; ++j) {
          for (k = 0; k < COEF_BANDS; ++k) {
            for (l = 0; l < BAND_COEFF_CONTEXTS(k); ++l) {
              // calc probs and branch cts for this frame only
              for (t = 0; t < entropy_nodes_update; ++t) {
                vpx_prob newp = new_coef_probs[i][j][k][l][t];
                vpx_prob *oldp = old_coef_probs[i][j][k][l] + t;
                const vpx_prob upd = DIFF_UPDATE_PROB;
                int s;
                int u = 0;
                if (t == PIVOT_NODE)
                  s = vp10_prob_diff_update_savings_search_model(
                      frame_branch_ct[i][j][k][l][0],
                      old_coef_probs[i][j][k][l], &newp, upd, stepsize);
                else
                  s = vp10_prob_diff_update_savings_search(
clang-format's avatar
clang-format committed
728
729
                      frame_branch_ct[i][j][k][l][t], *oldp, &newp, upd);
                if (s > 0 && newp != *oldp) u = 1;
Jingning Han's avatar
Jingning Han committed
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
                vpx_write(bc, u, upd);
                if (u) {
                  /* send/use new probability */
                  vp10_write_prob_diff_update(bc, newp, *oldp);
                  *oldp = newp;
                }
              }
            }
          }
        }
      }
      return;
    }

    case ONE_LOOP_REDUCED: {
      int updates = 0;
      int noupdates_before_first = 0;
      for (i = 0; i < PLANE_TYPES; ++i) {
        for (j = 0; j < REF_TYPES; ++j) {
          for (k = 0; k < COEF_BANDS; ++k) {
            for (l = 0; l < BAND_COEFF_CONTEXTS(k); ++l) {
              // calc probs and branch cts for this frame only
              for (t = 0; t < entropy_nodes_update; ++t) {
                vpx_prob newp = new_coef_probs[i][j][k][l][t];
                vpx_prob *oldp = old_coef_probs[i][j][k][l] + t;
                int s;
                int u = 0;

                if (t == PIVOT_NODE) {
                  s = vp10_prob_diff_update_savings_search_model(
                      frame_branch_ct[i][j][k][l][0],
                      old_coef_probs[i][j][k][l], &newp, upd, stepsize);
                } else {
                  s = vp10_prob_diff_update_savings_search(
clang-format's avatar
clang-format committed
764
                      frame_branch_ct[i][j][k][l][t], *oldp, &newp, upd);
Jingning Han's avatar
Jingning Han committed
765
766
                }

clang-format's avatar
clang-format committed
767
                if (s > 0 && newp != *oldp) u = 1;
Jingning Han's avatar
Jingning Han committed
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
                updates += u;
                if (u == 0 && updates == 0) {
                  noupdates_before_first++;
                  continue;
                }
                if (u == 1 && updates == 1) {
                  int v;
                  // first update
                  vpx_write_bit(bc, 1);
                  for (v = 0; v < noupdates_before_first; ++v)
                    vpx_write(bc, 0, upd);
                }
                vpx_write(bc, u, upd);
                if (u) {
                  /* send/use new probability */
                  vp10_write_prob_diff_update(bc, newp, *oldp);
                  *oldp = newp;
                }
              }
            }
          }
        }
      }
      if (updates == 0) {
        vpx_write_bit(bc, 0);  // no updates
      }
      return;
    }
clang-format's avatar
clang-format committed
796
    default: assert(0);
Jingning Han's avatar
Jingning Han committed
797
798
799
  }
}

clang-format's avatar
clang-format committed
800
static void update_coef_probs(VP10_COMP *cpi, vpx_writer *w) {
Jingning Han's avatar
Jingning Han committed
801
802
803
804
805
806
807
808
809
810
  const TX_MODE tx_mode = cpi->common.tx_mode;
  const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode];
  TX_SIZE tx_size;
  for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size) {
    vp10_coeff_stats frame_branch_ct[PLANE_TYPES];
    vp10_coeff_probs_model frame_coef_probs[PLANE_TYPES];
    if (cpi->td.counts->tx.tx_totals[tx_size] <= 20 ||
        (tx_size >= TX_16X16 && cpi->sf.tx_size_search_method == USE_TX_8X8)) {
      vpx_write_bit(w, 0);
    } else {
clang-format's avatar
clang-format committed
811
      build_tree_distribution(cpi, tx_size, frame_branch_ct, frame_coef_probs);
Jingning Han's avatar
Jingning Han committed
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
      update_coef_probs_common(w, cpi, tx_size, frame_branch_ct,
                               frame_coef_probs);
    }
  }
}

static void encode_loopfilter(struct loopfilter *lf,
                              struct vpx_write_bit_buffer *wb) {
  int i;

  // Encode the loop filter level and type
  vpx_wb_write_literal(wb, lf->filter_level, 6);
  vpx_wb_write_literal(wb, lf->sharpness_level, 3);

  // Write out loop filter deltas applied at the MB level based on mode or
  // ref frame (if they are enabled).
  vpx_wb_write_bit(wb, lf->mode_ref_delta_enabled);

  if (lf->mode_ref_delta_enabled) {
    vpx_wb_write_bit(wb, lf->mode_ref_delta_update);
    if (lf->mode_ref_delta_update) {
833
      for (i = 0; i < MAX_REF_FRAMES; i++) {
Jingning Han's avatar
Jingning Han committed
834
835
836
837
838
        const int delta = lf->ref_deltas[i];
        const int changed = delta != lf->last_ref_deltas[i];
        vpx_wb_write_bit(wb, changed);
        if (changed) {
          lf->last_ref_deltas[i] = delta;
839
          vpx_wb_write_inv_signed_literal(wb, delta, 6);
Jingning Han's avatar
Jingning Han committed
840
841
842
843
844
845
846
847
848
        }
      }

      for (i = 0; i < MAX_MODE_LF_DELTAS; i++) {
        const int delta = lf->mode_deltas[i];
        const int changed = delta != lf->last_mode_deltas[i];
        vpx_wb_write_bit(wb, changed);
        if (changed) {
          lf->last_mode_deltas[i] = delta;
849
          vpx_wb_write_inv_signed_literal(wb, delta, 6);
Jingning Han's avatar
Jingning Han committed
850
851
852
853
854
855
        }
      }
    }
  }
}

Steinar Midtskogen's avatar
Steinar Midtskogen committed
856
857
858
859
860
861
862
#if CONFIG_CLPF
static void encode_clpf(const VP10_COMMON *cm,
                        struct vpx_write_bit_buffer *wb) {
  vpx_wb_write_literal(wb, cm->clpf, 1);
}
#endif

863
864
865
866
867
868
#if CONFIG_DERING
static void encode_dering(int level, struct vpx_write_bit_buffer *wb) {
  vpx_wb_write_literal(wb, level, DERING_LEVEL_BITS);
}
#endif  // CONFIG_DERING

Jingning Han's avatar
Jingning Han committed
869
870
871
static void write_delta_q(struct vpx_write_bit_buffer *wb, int delta_q) {
  if (delta_q != 0) {
    vpx_wb_write_bit(wb, 1);
872
    vpx_wb_write_inv_signed_literal(wb, delta_q, CONFIG_MISC_FIXES ? 6 : 4);
Jingning Han's avatar
Jingning Han committed
873
874
875
876
877
  } else {
    vpx_wb_write_bit(wb, 0);
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
878
static void encode_quantization(const VP10_COMMON *const cm,
Jingning Han's avatar
Jingning Han committed
879
880
881
882
883
                                struct vpx_write_bit_buffer *wb) {
  vpx_wb_write_literal(wb, cm->base_qindex, QINDEX_BITS);
  write_delta_q(wb, cm->y_dc_delta_q);
  write_delta_q(wb, cm->uv_dc_delta_q);
  write_delta_q(wb, cm->uv_ac_delta_q);
884
885
#if CONFIG_AOM_QM
  vpx_wb_write_bit(wb, cm->using_qmatrix);
886
887
888
889
  if (cm->using_qmatrix) {
    vpx_wb_write_literal(wb, cm->min_qmlevel, QM_LEVEL_BITS);
    vpx_wb_write_literal(wb, cm->max_qmlevel, QM_LEVEL_BITS);
  }
890
#endif
Jingning Han's avatar
Jingning Han committed
891
892
}

Yaowu Xu's avatar
Yaowu Xu committed
893
static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
894
895
896
897
                                struct vpx_write_bit_buffer *wb) {
  int i, j;

  const struct segmentation *seg = &cm->seg;
898
899
900
#if !CONFIG_MISC_FIXES
  const struct segmentation_probs *segp = &cm->segp;
#endif
Jingning Han's avatar
Jingning Han committed
901
902

  vpx_wb_write_bit(wb, seg->enabled);
clang-format's avatar
clang-format committed
903
  if (!seg->enabled) return;
Jingning Han's avatar
Jingning Han committed
904
905

  // Segmentation map
906
907
908
909
910
  if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
    vpx_wb_write_bit(wb, seg->update_map);
  } else {
    assert(seg->update_map == 1);
  }
Jingning Han's avatar
Jingning Han committed
911
912
913
  if (seg->update_map) {
    // Select the coding strategy (temporal or spatial)
    vp10_choose_segmap_coding_method(cm, xd);
914
#if !CONFIG_MISC_FIXES
Jingning Han's avatar
Jingning Han committed
915
916
    // Write out probabilities used to decode unpredicted  macro-block segments
    for (i = 0; i < SEG_TREE_PROBS; i++) {
917
      const int prob = segp->tree_probs[i];
Jingning Han's avatar
Jingning Han committed
918
919
      const int update = prob != MAX_PROB;
      vpx_wb_write_bit(wb, update);
clang-format's avatar
clang-format committed
920
      if (update) vpx_wb_write_literal(wb, prob, 8);
Jingning Han's avatar
Jingning Han committed
921
    }
922
#endif
Jingning Han's avatar
Jingning Han committed
923
924

    // Write out the chosen coding method.
925
926
927
928
929
    if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
      vpx_wb_write_bit(wb, seg->temporal_update);
    } else {
      assert(seg->temporal_update == 0);
    }
930
931

#if !CONFIG_MISC_FIXES
Jingning Han's avatar
Jingning Han committed
932
933
    if (seg->temporal_update) {
      for (i = 0; i < PREDICTION_PROBS; i++) {
934
        const int prob = segp->pred_probs[i];
Jingning Han's avatar
Jingning Han committed
935
936
        const int update = prob != MAX_PROB;
        vpx_wb_write_bit(wb, update);
clang-format's avatar
clang-format committed
937
        if (update) vpx_wb_write_literal(wb, prob, 8);
Jingning Han's avatar
Jingning Han committed
938
939
      }
    }
940
#endif
Jingning Han's avatar
Jingning Han committed
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
  }

  // Segmentation data
  vpx_wb_write_bit(wb, seg->update_data);
  if (seg->update_data) {
    vpx_wb_write_bit(wb, seg->abs_delta);

    for (i = 0; i < MAX_SEGMENTS; i++) {
      for (j = 0; j < SEG_LVL_MAX; j++) {
        const int active = segfeature_active(seg, i, j);
        vpx_wb_write_bit(wb, active);
        if (active) {
          const int data = get_segdata(seg, i, j);
          const int data_max = vp10_seg_feature_data_max(j);

          if (vp10_is_segfeature_signed(j)) {
            encode_unsigned_max(wb, abs(data), data_max);
            vpx_wb_write_bit(wb, data < 0);
          } else {
            encode_unsigned_max(wb, data, data_max);
          }
        }
      }
    }
  }
}

968
#if CONFIG_MISC_FIXES
969
970
971
static void update_seg_probs(VP10_COMP *cpi, vpx_writer *w) {
  VP10_COMMON *cm = &cpi->common;

clang-format's avatar
clang-format committed
972
  if (!cpi->common.seg.enabled) return;
973
974
975
976
977
978

  if (cpi->common.seg.temporal_update) {
    int i;

    for (i = 0; i < PREDICTION_PROBS; i++)
      vp10_cond_prob_diff_update(w, &cm->fc->seg.pred_probs[i],
clang-format's avatar
clang-format committed
979
                                 cm->counts.seg.pred[i]);
980
981

    prob_diff_update(vp10_segment_tree, cm->fc->seg.tree_probs,
clang-format's avatar
clang-format committed
982
                     cm->counts.seg.tree_mispred, MAX_SEGMENTS, w);
983
984
  } else {
    prob_diff_update(vp10_segment_tree, cm->fc->seg.tree_probs,
clang-format's avatar
clang-format committed
985
                     cm->counts.seg.tree_total, MAX_SEGMENTS, w);
986
987
988
  }
}

989
990
static void write_txfm_mode(TX_MODE mode, struct vpx_write_bit_buffer *wb) {
  vpx_wb_write_bit(wb, mode == TX_MODE_SELECT);
clang-format's avatar
clang-format committed
991
  if (mode != TX_MODE_SELECT) vpx_wb_write_literal(wb, mode, 2);
992
}
993
994
995
#else
static void write_txfm_mode(TX_MODE mode, struct vpx_writer *wb) {
  vpx_write_literal(wb, VPXMIN(mode, ALLOW_32X32), 2);
clang-format's avatar
clang-format committed
996
  if (mode >= ALLOW_32X32) vpx_write_bit(wb, mode == TX_MODE_SELECT);
997
}
998
999
1000
#endif

static void update_txfm_probs(VP10_COMMON *cm, vpx_writer *w,
For faster browsing, not all history is shown. View entire blame