bitstream.c 52.1 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

22 23 24 25 26 27 28
#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"
Steinar Midtskogen's avatar
Steinar Midtskogen committed
29 30 31
#if CONFIG_CLPF
#include "vp10/common/clpf.h"
#endif
Jingning Han's avatar
Jingning Han committed
32

33 34 35 36 37 38 39
#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
40 41

static const struct vp10_token intra_mode_encodings[INTRA_MODES] = {
clang-format's avatar
clang-format committed
42 43 44
  { 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
45
static const struct vp10_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
clang-format's avatar
clang-format committed
46 47 48 49 50 51 52
    { { 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
53

54 55 56 57 58 59
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
60 61 62 63 64 65 66 67 68
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
69
                   &inter_mode_encodings[INTER_OFFSET(mode)]);
Jingning Han's avatar
Jingning Han committed
70 71
}

clang-format's avatar
clang-format committed
72 73
static void encode_unsigned_max(struct vpx_write_bit_buffer *wb, int data,
                                int max) {
Jingning Han's avatar
Jingning Han committed
74 75 76 77 78
  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
79 80
                             const unsigned int counts[/*n - 1*/], int n,
                             vpx_writer *w) {
Jingning Han's avatar
Jingning Han committed
81 82 83 84 85 86 87 88 89 90 91
  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]);
}

92 93 94 95 96 97 98 99 100 101 102 103
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
104
    savings += vp10_cond_prob_diff_update_savings(&probs[i], branch_ct[i]);
105 106 107 108
  }
  return savings;
}

clang-format's avatar
clang-format committed
109 110
static void write_selected_tx_size(const VP10_COMMON *cm, const MACROBLOCKD *xd,
                                   vpx_writer *w) {
Jingning Han's avatar
Jingning Han committed
111 112 113
  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
114 115
  const vpx_prob *const tx_probs =
      get_tx_probs2(max_tx_size, xd, &cm->fc->tx_probs);
Jingning Han's avatar
Jingning Han committed
116 117 118 119 120 121 122 123
  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
124
static int write_skip(const VP10_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
125 126 127 128 129 130 131 132 133 134
                      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
135
static void update_skip_probs(VP10_COMMON *cm, vpx_writer *w,
Jingning Han's avatar
Jingning Han committed
136 137 138 139 140 141 142
                              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
143
static void update_switchable_interp_probs(VP10_COMMON *cm, vpx_writer *w,
Jingning Han's avatar
Jingning Han committed
144 145 146 147 148 149 150 151
                                           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);
}

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
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
170 171
        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);
172 173 174 175
    }
  }
  savings = 0;
  for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
clang-format's avatar
clang-format committed
176 177 178
    savings +=
        prob_diff_update_savings(vp10_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
                                 cm->counts.inter_ext_tx[i], TX_TYPES);
179 180 181 182 183
  }
  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
184 185
      prob_diff_update(vp10_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
                       cm->counts.inter_ext_tx[i], TX_TYPES, w);
186 187 188 189
    }
  }
}

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

  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;
204
#if CONFIG_VPX_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
205 206 207 208 209 210 211 212 213
    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
214
    (void)bit_depth;
215
#endif  // CONFIG_VPX_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235

    /* 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
236 237
                      vp10_pareto8_full[p->context_tree[PIVOT_NODE] - 1], v,
                      n - len, 0);
Jingning Han's avatar
Jingning Han committed
238 239 240 241 242 243
    } 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;
244
#if CONFIG_MISC_FIXES
clang-format's avatar
clang-format committed
245
      int skip_bits = (b->base_val == CAT6_MIN_VAL) ? TX_SIZES - 1 - tx : 0;
246 247 248
#else
      int skip_bits = 0;
#endif
Jingning Han's avatar
Jingning Han committed
249 250 251 252

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

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

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

273
  *tp = p;
Jingning Han's avatar
Jingning Han committed
274 275 276
}

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

// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
284
static void write_ref_frames(const VP10_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
285 286 287 288 289 290 291 292 293 294
                             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
295
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
Jingning Han's avatar
Jingning Han committed
296 297 298 299 300 301
  } 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 {
302
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
    }

    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
319
static void pack_inter_mode_mvs(VP10_COMP *cpi, const MODE_INFO *mi,
Jingning Han's avatar
Jingning Han committed
320
                                vpx_writer *w) {
Yaowu Xu's avatar
Yaowu Xu committed
321
  VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
322 323 324 325
  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;
326 327 328 329 330
#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
331 332 333 334 335 336 337 338 339 340 341 342 343
  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;
344
      vpx_prob pred_prob = vp10_get_pred_prob_seg_id(segp, xd);
Jingning Han's avatar
Jingning Han committed
345
      vpx_write(w, pred_flag, pred_prob);
clang-format's avatar
clang-format committed
346
      if (!pred_flag) write_segment_id(w, seg, segp, segment_id);
Jingning Han's avatar
Jingning Han committed
347
    } else {
348
      write_segment_id(w, seg, segp, segment_id);
Jingning Han's avatar
Jingning Han committed
349 350 351 352 353 354 355 356 357
    }
  }

  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 &&
358
      !(is_inter && skip) && !xd->lossless[segment_id]) {
Jingning Han's avatar
Jingning Han committed
359 360 361 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
    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
392 393
                       cm->fc->switchable_interp_prob[ctx],
                       &switchable_interp_encodings[mbmi->interp_filter]);
Jingning Han's avatar
Jingning Han committed
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
      ++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
411 412
                             &mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
                             nmvc, allow_hp);
Jingning Han's avatar
Jingning Han committed
413 414 415 416 417 418 419
          }
        }
      }
    } 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
420 421
                         &mbmi_ext->ref_mvs[mbmi->ref_frame[ref]][0].as_mv,
                         nmvc, allow_hp);
Jingning Han's avatar
Jingning Han committed
422 423 424
      }
    }
  }
clang-format's avatar
clang-format committed
425
  if (mbmi->tx_size < TX_32X32 && cm->base_qindex > 0 && !mbmi->skip &&
426 427
      !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    if (is_inter) {
clang-format's avatar
clang-format committed
428 429 430
      vp10_write_token(w, vp10_ext_tx_tree,
                       cm->fc->inter_ext_tx_prob[mbmi->tx_size],
                       &ext_tx_encodings[mbmi->tx_type]);
431 432 433 434 435 436 437 438
    } 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
439
    if (!mbmi->skip) assert(mbmi->tx_type == DCT_DCT);
440
  }
Jingning Han's avatar
Jingning Han committed
441 442
}

Yaowu Xu's avatar
Yaowu Xu committed
443
static void write_mb_modes_kf(const VP10_COMMON *cm, const MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
444 445
                              MODE_INFO **mi_8x8, vpx_writer *w) {
  const struct segmentation *const seg = &cm->seg;
446 447 448 449 450
#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
451 452 453 454 455 456
  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
457
  if (seg->update_map) write_segment_id(w, seg, segp, mbmi->segment_id);
Jingning Han's avatar
Jingning Han committed
458 459 460

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

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

  if (bsize >= BLOCK_8X8) {
466 467
    write_intra_mode(w, mbmi->mode,
                     get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
Jingning Han's avatar
Jingning Han committed
468 469 470 471 472 473 474 475 476
  } 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,
477
                         get_y_mode_probs(cm, mi, above_mi, left_mi, block));
Jingning Han's avatar
Jingning Han committed
478 479 480 481
      }
    }
  }

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

clang-format's avatar
clang-format committed
484
  if (mbmi->tx_size < TX_32X32 && cm->base_qindex > 0 && !mbmi->skip &&
485 486 487 488 489 490 491
      !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
492 493
}

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

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

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

clang-format's avatar
clang-format committed
508
  set_mi_row_col(xd, tile, mi_row, num_8x8_blocks_high_lookup[m->mbmi.sb_type],
Jingning Han's avatar
Jingning Han committed
509 510 511 512 513 514 515 516
                 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);
  }

517 518 519
  if (!m->mbmi.skip) {
    assert(*tok < tok_end);
    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
clang-format's avatar
clang-format committed
520 521
      TX_SIZE tx =
          plane ? get_uv_tx_size(&m->mbmi, &xd->plane[plane]) : m->mbmi.tx_size;
522 523 524 525 526
      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
527 528
}

Yaowu Xu's avatar
Yaowu Xu committed
529
static void write_partition(const VP10_COMMON *const cm,
clang-format's avatar
clang-format committed
530 531 532
                            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
533
  const int ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
534
  const vpx_prob *const probs = cm->fc->partition_prob[ctx];
Jingning Han's avatar
Jingning Han committed
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
  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
551 552 553 554
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
555
  const VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
556 557 558 559 560 561 562 563
  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
564
  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
Jingning Han's avatar
Jingning Han committed
565 566 567 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

  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
597
      default: assert(0);
Jingning Han's avatar
Jingning Han committed
598 599 600 601 602 603 604 605 606
    }
  }

  // update partition context
  if (bsize >= BLOCK_8X8 &&
      (bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
    update_partition_context(xd, mi_row, mi_col, subsize, bsize);
}

clang-format's avatar
clang-format committed
607 608 609
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
610 611 612 613 614 615 616 617
  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
618
      write_modes_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, BLOCK_64X64);
Jingning Han's avatar
Jingning Han committed
619 620 621
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
622
static void build_tree_distribution(VP10_COMP *cpi, TX_SIZE tx_size,
Jingning Han's avatar
Jingning Han committed
623 624 625
                                    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
626
  unsigned int(*eob_branch_ct)[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS] =
Jingning Han's avatar
Jingning Han committed
627 628 629 630 631 632 633 634
      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
635 636 637 638
                                            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
639
          for (m = 0; m < UNCONSTRAINED_NODES; ++m)
clang-format's avatar
clang-format committed
640 641 642
            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
643 644 645 646 647 648
        }
      }
    }
  }
}

clang-format's avatar
clang-format committed
649
static void update_coef_probs_common(vpx_writer *const bc, VP10_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
650 651 652 653 654 655 656 657 658 659 660 661 662
                                     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
663
      int update[2] = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
      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
680
                if (s > 0 && newp != oldp) u = 1;
Jingning Han's avatar
Jingning Han committed
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
                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
716 717
                      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
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
                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
752
                      frame_branch_ct[i][j][k][l][t], *oldp, &newp, upd);
Jingning Han's avatar
Jingning Han committed
753 754
                }

clang-format's avatar
clang-format committed
755
                if (s > 0 && newp != *oldp) u = 1;
Jingning Han's avatar
Jingning Han committed
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
                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
784
    default: assert(0);
Jingning Han's avatar
Jingning Han committed
785 786 787
  }
}

clang-format's avatar
clang-format committed
788
static void update_coef_probs(VP10_COMP *cpi, vpx_writer *w) {
Jingning Han's avatar
Jingning Han committed
789 790 791 792 793 794 795 796 797 798
  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
799
      build_tree_distribution(cpi, tx_size, frame_branch_ct, frame_coef_probs);
Jingning Han's avatar
Jingning Han committed
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
      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) {
821
      for (i = 0; i < MAX_REF_FRAMES; i++) {
Jingning Han's avatar
Jingning Han committed
822 823 824 825 826
        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;
827
          vpx_wb_write_inv_signed_literal(wb, delta, 6);
Jingning Han's avatar
Jingning Han committed
828 829 830 831 832 833 834 835 836
        }
      }

      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;
837
          vpx_wb_write_inv_signed_literal(wb, delta, 6);
Jingning Han's avatar
Jingning Han committed
838 839 840 841 842 843
        }
      }
    }
  }
}

Steinar Midtskogen's avatar
Steinar Midtskogen committed
844 845 846 847 848 849 850
#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

Jingning Han's avatar
Jingning Han committed
851 852 853
static void write_delta_q(struct vpx_write_bit_buffer *wb, int delta_q) {
  if (delta_q != 0) {
    vpx_wb_write_bit(wb, 1);
854
    vpx_wb_write_inv_signed_literal(wb, delta_q, CONFIG_MISC_FIXES ? 6 : 4);
Jingning Han's avatar
Jingning Han committed
855 856 857 858 859
  } else {
    vpx_wb_write_bit(wb, 0);
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
860
static void encode_quantization(const VP10_COMMON *const cm,
Jingning Han's avatar
Jingning Han committed
861 862 863 864 865 866 867
                                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);
}

Yaowu Xu's avatar
Yaowu Xu committed
868
static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
Jingning Han's avatar
Jingning Han committed
869 870 871 872
                                struct vpx_write_bit_buffer *wb) {
  int i, j;

  const struct segmentation *seg = &cm->seg;
873 874 875
#if !CONFIG_MISC_FIXES
  const struct segmentation_probs *segp = &cm->segp;
#endif
Jingning Han's avatar
Jingning Han committed
876 877

  vpx_wb_write_bit(wb, seg->enabled);
clang-format's avatar
clang-format committed
878
  if (!seg->enabled) return;
Jingning Han's avatar
Jingning Han committed
879 880

  // Segmentation map
881 882 883 884 885
  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
886 887 888
  if (seg->update_map) {
    // Select the coding strategy (temporal or spatial)
    vp10_choose_segmap_coding_method(cm, xd);
889
#if !CONFIG_MISC_FIXES
Jingning Han's avatar
Jingning Han committed
890 891
    // Write out probabilities used to decode unpredicted  macro-block segments
    for (i = 0; i < SEG_TREE_PROBS; i++) {
892
      const int prob = segp->tree_probs[i];
Jingning Han's avatar
Jingning Han committed
893 894
      const int update = prob != MAX_PROB;
      vpx_wb_write_bit(wb, update);
clang-format's avatar
clang-format committed
895
      if (update) vpx_wb_write_literal(wb, prob, 8);
Jingning Han's avatar
Jingning Han committed
896
    }
897
#endif
Jingning Han's avatar
Jingning Han committed
898 899

    // Write out the chosen coding method.
900 901 902 903 904
    if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
      vpx_wb_write_bit(wb, seg->temporal_update);
    } else {
      assert(seg->temporal_update == 0);
    }
905 906

#if !CONFIG_MISC_FIXES
Jingning Han's avatar
Jingning Han committed
907 908
    if (seg->temporal_update) {
      for (i = 0; i < PREDICTION_PROBS; i++) {
909
        const int prob = segp->pred_probs[i];
Jingning Han's avatar
Jingning Han committed
910 911
        const int update = prob != MAX_PROB;
        vpx_wb_write_bit(wb, update);
clang-format's avatar
clang-format committed
912
        if (update) vpx_wb_write_literal(wb, prob, 8);
Jingning Han's avatar
Jingning Han committed
913 914
      }
    }
915
#endif
Jingning Han's avatar
Jingning Han committed
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
  }

  // 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);
          }
        }
      }
    }
  }
}

943
#if CONFIG_MISC_FIXES
944 945 946
static void update_seg_probs(VP10_COMP *cpi, vpx_writer *w) {
  VP10_COMMON *cm = &cpi->common;

clang-format's avatar
clang-format committed
947
  if (!cpi->common.seg.enabled) return;
948 949 950 951 952 953

  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
954
                                 cm->counts.seg.pred[i]);
955 956

    prob_diff_update(vp10_segment_tree, cm->fc->seg.tree_probs,
clang-format's avatar
clang-format committed
957
                     cm->counts.seg.tree_mispred, MAX_SEGMENTS, w);
958 959
  } else {
    prob_diff_update(vp10_segment_tree, cm->fc->seg.tree_probs,
clang-format's avatar
clang-format committed
960
                     cm->counts.seg.tree_total, MAX_SEGMENTS, w);
961 962 963
  }
}

964 965
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
966
  if (mode != TX_MODE_SELECT) vpx_wb_write_literal(wb, mode, 2);
967
}
968 969 970
#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
971
  if (mode >= ALLOW_32X32) vpx_write_bit(wb, mode == TX_MODE_SELECT);
972
}
973 974 975
#endif

static void update_txfm_probs(VP10_COMMON *cm, vpx_writer *w,
Jingning Han's avatar
Jingning Han committed
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
                              FRAME_COUNTS *counts) {
  if (cm->tx_mode == TX_MODE_SELECT) {
    int i, j;
    unsigned int ct_8x8p[TX_SIZES - 3][2];
    unsigned int ct_16x16p[TX_SIZES - 2][2];
    unsigned int ct_32x32p[TX_SIZES - 1][2];

    for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
      vp10_tx_counts_to_branch_counts_8x8(counts->tx.p8x8[i], ct_8x8p);
      for (j = 0; j < TX_SIZES - 3; j++)
        vp10_cond_prob_diff_update(w, &cm->fc->tx_probs.p8x8[i][j], ct_8x8p[j]);
    }

    for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
      vp10_tx_counts_to_branch_counts_16x16(counts->tx.p16x16[i], ct_16x16p);
      for (j = 0; j < TX_SIZES - 2; j++)
        vp10_cond_prob_diff_update(w, &cm->fc->tx_probs.p16x16[i][j],
clang-format's avatar
clang-format committed
993
                                   ct_16x16p[j]);
Jingning Han's avatar
Jingning Han committed
994 995 996 997 998 999
    }

    for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
      vp10_tx_counts_to_branch_counts_32x32(counts->tx.p32x32[i], ct_32x32p);
      for (j = 0; j < TX_SIZES - 1; j++)
        vp10_cond_prob_diff_update(w, &cm->fc->tx_probs.p32x32[i][j],
clang-format's avatar
clang-format committed
1000
                                   ct_32x32p[j]);
Jingning Han's avatar
Jingning Han committed
1001 1002 1003 1004 1005 1006 1007
    }
  }
}

static void write_interp_filter(INTERP_FILTER filter,
                                struct vpx_write_bit_buffer *wb) {
  vpx_wb_write_bit(wb, filter == SWITCHABLE);
clang-format's avatar
clang-format committed
1008
  if (filter != SWITCHABLE) vpx_wb_write_literal(wb, filter, 2);
Jingning Han's avatar
Jingning Han committed
1009 1010
}

Yaowu Xu's avatar
Yaowu Xu committed
1011
static void fix_interp_filter(VP10_COMMON *cm, FRAME_COUNTS *counts) {
Jingning Han's avatar
Jingning Han committed
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
  if (cm->interp_filter == SWITCHABLE) {
    // Check to see if only one of the filters is actually used
    int count[SWITCHABLE_FILTERS];
    int i, j, c = 0;
    for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
      count[i] = 0;
      for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; ++j)
        count[i] += counts->switchable_interp[j][i];
      c += (count[i] > 0);
    }
    if (c == 1) {
      // Only one filter is used. So set the filter at frame level
      for (i = 0; i < SWITCHABLE_FILTERS; ++i) {
        if (count[i]) {
          cm->interp_filter = i;
          break;
        }
      }
    }
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
1034
static void write_tile_info(const VP10_COMMON *const cm,
Jingning Han's avatar
Jingning Han committed
1035 1036 1037 1038 1039 1040
                            struct vpx_write_bit_buffer *wb) {
  int min_log2_tile_cols, max_log2_tile_cols, ones;
  vp10_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);

  // columns
  ones = cm->log2_tile_cols - min_log2_tile_cols;
clang-format's avatar
clang-format committed
1041
  while (ones--) vpx_wb_write_bit(wb, 1);
Jingning Han's avatar
Jingning Han committed
1042

clang-format's avatar
clang-format committed
1043
  if (cm->log2_tile_cols < max_log2_tile_cols) vpx_wb_write_bit(wb, 0);
Jingning Han's avatar
Jingning Han committed
1044 1045 1046

  // rows
  vpx_wb_write_bit(wb, cm->log2_tile_rows != 0);
clang-format's avatar
clang-format committed
1047
  if (cm->log2_tile_rows != 0) vpx_wb_write_bit(wb, cm->log2_tile_rows != 1);
Jingning Han's avatar
Jingning Han committed
1048 1049
}

Yaowu Xu's avatar
Yaowu Xu committed
1050
static int get_refresh_mask(VP10_COMP *cpi) {
Jingning Han's avatar
Jingning Han committed
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
  if (vp10_preserve_existing_gf(cpi)) {
    // We have decided to preserve the previously existing golden frame as our
    // new ARF frame. However, in the short term we leave it in the GF slot and,
    // if we're updating the GF with the current decoded frame, we save it
    // instead to the ARF slot.
    // Later, in the function vp10_encoder.c:vp10_update_reference_frames() we
    // will swap gld_fb_idx and alt_fb_idx to achieve our objective. We do it
    // there so that it can be done outside of the recode loop.
    // Note: This is highly specific to the use of ARF as a forward reference,
    // and this needs to be generalized as other uses are implemented
    // (like RTC/temporal scalability).
    return (cpi->refresh_last_frame << cpi->lst_fb_idx) |
           (cpi->refresh_golden_frame << cpi->alt_fb_idx);
  } else {
    int arf_idx = cpi->alt_fb_idx;
    if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
      const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
      arf_idx = gf_group->arf_update_idx[gf_group->index];
    }
    return (cpi->refresh_last_frame << cpi->lst_fb_idx) |
           (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
           (cpi->refresh_alt_ref_frame << arf_idx);
  }
}

1076 1077
static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr,
                           unsigned int *max_tile_sz) {
Yaowu Xu's avatar
Yaowu Xu committed
1078
  VP10_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
1079 1080 1081 1082 1083 1084
  vpx_writer residual_bc;
  int tile_row, tile_col;
  TOKENEXTRA *tok_end;
  size_t total_size = 0;
  const int tile_cols = 1 << cm->log2_tile_cols;
  const int tile_rows = 1 << cm->log2_tile_rows;
1085
  unsigned int max_tile = 0;
Jingning Han's avatar
Jingning Han committed
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095

  memset(cm->above_seg_context, 0,
         sizeof(*cm->above_seg_context) * mi_cols_aligned_to_sb(cm->mi_cols));

  for (tile_row = 0; tile_row < tile_rows; tile_row++) {
    for (tile_col = 0; tile_col < tile_cols; tile_col++) {
      int tile_idx = tile_row * tile_cols + tile_col;
      TOKENEXTRA *tok = cpi->tile_tok[tile_row][tile_col];

      tok_end = cpi->tile_tok[tile_row][tile_col] +
clang-format's avatar
clang-format committed
1096
                cpi->tok_count[tile_row][tile_col];
Jingning Han's avatar
Jingning Han committed
1097 1098 1099 1100 1101 1102

      if (tile_col < tile_cols - 1 || tile_row < tile_rows - 1)
        vpx_start_encode(&residual_bc, data_ptr + total_size + 4);
      else
        vpx_start_encode(&residual_bc, data_ptr + total_size);

clang-format's avatar
clang-format committed
1103 1104
      write_modes(cpi, &cpi->tile_data[tile_idx].tile_info, &residual_bc, &tok,
                  tok_end);
Jingning Han's avatar
Jingning Han committed
1105 1106 1107
      assert(tok == tok_end);
      vpx_stop_encode(&residual_bc);
      if (tile_col < tile_cols - 1 || tile_row < tile_rows - 1) {
1108 1109
        unsigned int tile_sz;

Jingning Han's avatar
Jingning Han committed
1110
        // size of this tile
1111 1112 1113 1114
        assert(residual_bc.pos > 0);
        tile_sz = residual_bc.pos - CONFIG_MISC_FIXES;
        mem_put_le32(data_ptr + total_size, tile_sz);
        max_tile = max_tile > tile_sz ? max_tile : tile_sz;
Jingning Han's avatar
Jingning Han committed
1115 1116 1117 1118 1119 1120
        total_size += 4;
      }

      total_size += residual_bc.pos;
    }
  }
1121
  *max_tile_sz = max_tile;
Jingning Han's avatar
Jingning Han committed
1122 1123 1124 1125

  return total_size;
}

1126 1127
static void write_render_size(const VP10_COMMON *cm,
                              struct vpx_write_bit_buffer *wb) {
clang-format's avatar
clang-format committed
1128 1129
  const int scaling_active =
      cm->width != cm->render_width || cm->height != cm->render_height;
Jingning Han's avatar
Jingning Han committed
1130 1131
  vpx_wb_write_bit<