bitstream.c 127 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1 2 3 4 5 6 7 8 9 10 11 12
/*
 *  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 <limits.h>
13
#include <stdio.h>
Jingning Han's avatar
Jingning Han committed
14

15 16 17 18 19 20 21
#include "aom/vpx_encoder.h"
#include "aom_dsp/bitwriter_buffer.h"
#include "aom_dsp/vpx_dsp_common.h"
#include "aom_mem/vpx_mem.h"
#include "aom_ports/mem_ops.h"
#include "aom_ports/system_state.h"
#include "aom_util/debug_util.h"
Jingning Han's avatar
Jingning Han committed
22

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

Alex Converse's avatar
Alex Converse committed
38
#if CONFIG_ANS
39
#include "av1/encoder/buf_ans.h"
Alex Converse's avatar
Alex Converse committed
40
#endif  // CONFIG_ANS
41 42 43 44 45 46 47
#include "av1/encoder/bitstream.h"
#include "av1/encoder/cost.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/mcomp.h"
#include "av1/encoder/segmentation.h"
#include "av1/encoder/subexp.h"
#include "av1/encoder/tokenize.h"
Jingning Han's avatar
Jingning Han committed
48 49

static const struct vp10_token intra_mode_encodings[INTRA_MODES] = {
50 51 52
  { 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
53
#if CONFIG_EXT_INTERP
54
static const struct vp10_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
55
    { { 0, 1 }, { 4, 3 }, { 6, 3 }, { 5, 3 }, { 7, 3 } };
56
#else
Jingning Han's avatar
Jingning Han committed
57
static const struct vp10_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
58
    { { 0, 1 }, { 2, 2 }, { 3, 2 } };
Jingning Han's avatar
Jingning Han committed
59
#endif  // CONFIG_EXT_INTERP
60
#if CONFIG_EXT_PARTITION_TYPES
61 62 63 64
static const struct vp10_token ext_partition_encodings[EXT_PARTITION_TYPES] = {
  { 0, 1 },  { 4, 3 },  { 12, 4 }, { 7, 3 },
  { 10, 4 }, { 11, 4 }, { 26, 5 }, { 27, 5 }
};
65
#endif
66 67 68
static const struct vp10_token partition_encodings[PARTITION_TYPES] = {
  { 0, 1 }, { 2, 2 }, { 6, 3 }, { 7, 3 }
};
69
#if !CONFIG_REF_MV
Jingning Han's avatar
Jingning Han committed
70
static const struct vp10_token inter_mode_encodings[INTER_MODES] =
Yue Chen's avatar
Yue Chen committed
71
#if CONFIG_EXT_INTER
72
    { { 2, 2 }, { 6, 3 }, { 0, 1 }, { 14, 4 }, { 15, 4 } };
Yue Chen's avatar
Yue Chen committed
73
#else
74
    { { 2, 2 }, { 6, 3 }, { 0, 1 }, { 7, 3 } };
Yue Chen's avatar
Yue Chen committed
75
#endif  // CONFIG_EXT_INTER
76
#endif
77
#if CONFIG_EXT_INTER
78 79 80 81 82
static const struct vp10_token
    inter_compound_mode_encodings[INTER_COMPOUND_MODES] = {
      { 2, 2 },  { 50, 6 }, { 51, 6 }, { 24, 5 }, { 52, 6 },
      { 53, 6 }, { 54, 6 }, { 55, 6 }, { 0, 1 },  { 7, 3 }
    };
83
#endif  // CONFIG_EXT_INTER
hui su's avatar
hui su committed
84
static const struct vp10_token palette_size_encodings[] = {
85
  { 0, 1 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 30, 5 }, { 62, 6 }, { 63, 6 },
hui su's avatar
hui su committed
86
};
87
static const struct vp10_token
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    palette_color_encodings[PALETTE_MAX_SIZE - 1][PALETTE_MAX_SIZE] = {
      { { 0, 1 }, { 1, 1 } },                                  // 2 colors
      { { 0, 1 }, { 2, 2 }, { 3, 2 } },                        // 3 colors
      { { 0, 1 }, { 2, 2 }, { 6, 3 }, { 7, 3 } },              // 4 colors
      { { 0, 1 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 15, 4 } },  // 5 colors
      { { 0, 1 },
        { 2, 2 },
        { 6, 3 },
        { 14, 4 },
        { 30, 5 },
        { 31, 5 } },  // 6 colors
      { { 0, 1 },
        { 2, 2 },
        { 6, 3 },
        { 14, 4 },
        { 30, 5 },
        { 62, 6 },
        { 63, 6 } },  // 7 colors
      { { 0, 1 },
        { 2, 2 },
        { 6, 3 },
        { 14, 4 },
        { 30, 5 },
        { 62, 6 },
        { 126, 7 },
        { 127, 7 } },  // 8 colors
    };

static const struct vp10_token tx_size_encodings[TX_SIZES - 1][TX_SIZES] = {
  { { 0, 1 }, { 1, 1 } },                      // Max tx_size is 8X8
  { { 0, 1 }, { 2, 2 }, { 3, 2 } },            // Max tx_size is 16X16
  { { 0, 1 }, { 2, 2 }, { 6, 3 }, { 7, 3 } },  // Max tx_size is 32X32
120 121
};

122
static INLINE void write_uniform(vp10_writer *w, int n, int v) {
hui su's avatar
hui su committed
123 124
  int l = get_unsigned_bits(n);
  int m = (1 << l) - n;
125
  if (l == 0) return;
hui su's avatar
hui su committed
126
  if (v < m) {
127
    vp10_write_literal(w, v, l - 1);
hui su's avatar
hui su committed
128
  } else {
129 130
    vp10_write_literal(w, m + ((v - m) >> 1), l - 1);
    vp10_write_literal(w, (v - m) & 1, 1);
hui su's avatar
hui su committed
131 132
  }
}
Jingning Han's avatar
Jingning Han committed
133

134
#if CONFIG_EXT_TX
135 136
static struct vp10_token ext_tx_inter_encodings[EXT_TX_SETS_INTER][TX_TYPES];
static struct vp10_token ext_tx_intra_encodings[EXT_TX_SETS_INTRA][TX_TYPES];
137
#else
138
static struct vp10_token ext_tx_encodings[TX_TYPES];
139
#endif  // CONFIG_EXT_TX
140 141 142
#if CONFIG_GLOBAL_MOTION
static struct vp10_token global_motion_types_encodings[GLOBAL_MOTION_TYPES];
#endif  // CONFIG_GLOBAL_MOTION
143 144 145
#if CONFIG_EXT_INTRA
static struct vp10_token intra_filter_encodings[INTRA_FILTERS];
#endif  // CONFIG_EXT_INTRA
146 147 148
#if CONFIG_EXT_INTER
static struct vp10_token interintra_mode_encodings[INTERINTRA_MODES];
#endif  // CONFIG_EXT_INTER
149 150 151
#if CONFIG_OBMC || CONFIG_WARPED_MOTION
static struct vp10_token motvar_encodings[MOTION_VARIATIONS];
#endif  // CONFIG_OBMC || CONFIG_WARPED_MOTION
152

153
void vp10_encode_token_init(void) {
154
#if CONFIG_EXT_TX
155 156 157 158 159 160 161
  int s;
  for (s = 1; s < EXT_TX_SETS_INTER; ++s) {
    vp10_tokens_from_tree(ext_tx_inter_encodings[s], vp10_ext_tx_inter_tree[s]);
  }
  for (s = 1; s < EXT_TX_SETS_INTRA; ++s) {
    vp10_tokens_from_tree(ext_tx_intra_encodings[s], vp10_ext_tx_intra_tree[s]);
  }
162
#else
163
  vp10_tokens_from_tree(ext_tx_encodings, vp10_ext_tx_tree);
164
#endif  // CONFIG_EXT_TX
165 166 167
#if CONFIG_EXT_INTRA
  vp10_tokens_from_tree(intra_filter_encodings, vp10_intra_filter_tree);
#endif  // CONFIG_EXT_INTRA
168 169 170
#if CONFIG_EXT_INTER
  vp10_tokens_from_tree(interintra_mode_encodings, vp10_interintra_mode_tree);
#endif  // CONFIG_EXT_INTER
171 172 173
#if CONFIG_OBMC || CONFIG_WARPED_MOTION
  vp10_tokens_from_tree(motvar_encodings, vp10_motvar_tree);
#endif  // CONFIG_OBMC || CONFIG_WARPED_MOTION
174 175
#if CONFIG_GLOBAL_MOTION
  vp10_tokens_from_tree(global_motion_types_encodings,
176
                        vp10_global_motion_types_tree);
177
#endif  // CONFIG_GLOBAL_MOTION
178 179
}

180
static void write_intra_mode(vp10_writer *w, PREDICTION_MODE mode,
Jingning Han's avatar
Jingning Han committed
181 182 183 184
                             const vpx_prob *probs) {
  vp10_write_token(w, vp10_intra_mode_tree, probs, &intra_mode_encodings[mode]);
}

185
#if CONFIG_EXT_INTER
186
static void write_interintra_mode(vp10_writer *w, INTERINTRA_MODE mode,
187 188 189 190 191 192
                                  const vpx_prob *probs) {
  vp10_write_token(w, vp10_interintra_mode_tree, probs,
                   &interintra_mode_encodings[mode]);
}
#endif  // CONFIG_EXT_INTER

193 194
static void write_inter_mode(VP10_COMMON *cm, vp10_writer *w,
                             PREDICTION_MODE mode,
Yue Chen's avatar
Yue Chen committed
195 196 197
#if CONFIG_REF_MV && CONFIG_EXT_INTER
                             int is_compound,
#endif  // CONFIG_REF_MV && CONFIG_EXT_INTER
198
                             const int16_t mode_ctx) {
199
#if CONFIG_REF_MV
200
  const int16_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
201
  const vpx_prob newmv_prob = cm->fc->newmv_prob[newmv_ctx];
Yue Chen's avatar
Yue Chen committed
202
#if CONFIG_EXT_INTER
203
  vp10_write(w, mode != NEWMV && mode != NEWFROMNEARMV, newmv_prob);
Yue Chen's avatar
Yue Chen committed
204 205

  if (!is_compound && (mode == NEWMV || mode == NEWFROMNEARMV))
206
    vp10_write(w, mode == NEWFROMNEARMV, cm->fc->new2mv_prob);
Yue Chen's avatar
Yue Chen committed
207 208 209

  if (mode != NEWMV && mode != NEWFROMNEARMV) {
#else
210
  vp10_write(w, mode != NEWMV, newmv_prob);
211 212

  if (mode != NEWMV) {
Yue Chen's avatar
Yue Chen committed
213
#endif  // CONFIG_EXT_INTER
214
    const int16_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
215
    const vpx_prob zeromv_prob = cm->fc->zeromv_prob[zeromv_ctx];
216 217 218 219 220 221

    if (mode_ctx & (1 << ALL_ZERO_FLAG_OFFSET)) {
      assert(mode == ZEROMV);
      return;
    }

222
    vp10_write(w, mode != ZEROMV, zeromv_prob);
223 224

    if (mode != ZEROMV) {
225 226 227
      int16_t refmv_ctx = (mode_ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
      vpx_prob refmv_prob;

228 229 230
      if (mode_ctx & (1 << SKIP_NEARESTMV_OFFSET)) refmv_ctx = 6;
      if (mode_ctx & (1 << SKIP_NEARMV_OFFSET)) refmv_ctx = 7;
      if (mode_ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) refmv_ctx = 8;
231 232

      refmv_prob = cm->fc->refmv_prob[refmv_ctx];
233
      vp10_write(w, mode != NEARESTMV, refmv_prob);
234 235 236 237
    }
  }
#else
  const vpx_prob *const inter_probs = cm->fc->inter_mode_probs[mode_ctx];
Jingning Han's avatar
Jingning Han committed
238
  assert(is_inter_mode(mode));
239
  vp10_write_token(w, vp10_inter_mode_tree, inter_probs,
240
                   &inter_mode_encodings[INTER_OFFSET(mode)]);
241
#endif
Jingning Han's avatar
Jingning Han committed
242 243
}

244
#if CONFIG_REF_MV
245 246
static void write_drl_idx(const VP10_COMMON *cm, const MB_MODE_INFO *mbmi,
                          const MB_MODE_INFO_EXT *mbmi_ext, vp10_writer *w) {
247
  uint8_t ref_frame_type = vp10_ref_frame_type(mbmi->ref_frame);
248 249 250

  assert(mbmi->ref_mv_idx < 3);

251 252 253 254 255 256 257 258
  if (mbmi->mode == NEWMV) {
    int idx;
    for (idx = 0; idx < 2; ++idx) {
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
        uint8_t drl_ctx =
            vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
        vpx_prob drl_prob = cm->fc->drl_prob[drl_ctx];

259
        vp10_write(w, mbmi->ref_mv_idx != idx, drl_prob);
260
        if (mbmi->ref_mv_idx == idx) return;
261
      }
262 263 264 265
    }
    return;
  }

266 267 268 269 270 271 272 273 274
  if (mbmi->mode == NEARMV) {
    int idx;
    // TODO(jingning): Temporary solution to compensate the NEARESTMV offset.
    for (idx = 1; idx < 3; ++idx) {
      if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) {
        uint8_t drl_ctx =
            vp10_drl_ctx(mbmi_ext->ref_mv_stack[ref_frame_type], idx);
        vpx_prob drl_prob = cm->fc->drl_prob[drl_ctx];

275
        vp10_write(w, mbmi->ref_mv_idx != (idx - 1), drl_prob);
276
        if (mbmi->ref_mv_idx == (idx - 1)) return;
277
      }
278
    }
279
    return;
280 281 282 283
  }
}
#endif

284
#if CONFIG_EXT_INTER
285
static void write_inter_compound_mode(VP10_COMMON *cm, vp10_writer *w,
286 287 288
                                      PREDICTION_MODE mode,
                                      const int16_t mode_ctx) {
  const vpx_prob *const inter_compound_probs =
289
      cm->fc->inter_compound_mode_probs[mode_ctx];
290 291 292

  assert(is_inter_compound_mode(mode));
  vp10_write_token(w, vp10_inter_compound_mode_tree, inter_compound_probs,
293
                   &inter_compound_mode_encodings[INTER_COMPOUND_OFFSET(mode)]);
294 295 296
}
#endif  // CONFIG_EXT_INTER

297 298
static void encode_unsigned_max(struct vpx_write_bit_buffer *wb, int data,
                                int max) {
Jingning Han's avatar
Jingning Han committed
299 300 301 302 303
  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*/],
304 305
                             const unsigned int counts[/*n - 1*/], int n,
                             vp10_writer *w) {
Jingning Han's avatar
Jingning Han committed
306 307 308 309 310 311 312 313 314 315 316
  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]);
}

317 318 319 320 321 322 323 324 325 326 327 328
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) {
329
    savings += vp10_cond_prob_diff_update_savings(&probs[i], branch_ct[i]);
330 331 332 333
  }
  return savings;
}

334
#if CONFIG_VAR_TX
Debargha Mukherjee's avatar
Debargha Mukherjee committed
335
static void write_tx_size_vartx(const VP10_COMMON *cm, const MACROBLOCKD *xd,
336 337
                                const MB_MODE_INFO *mbmi, TX_SIZE tx_size,
                                int blk_row, int blk_col, vp10_writer *w) {
338 339
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
340 341
  int max_blocks_high = num_4x4_blocks_high_lookup[mbmi->sb_type];
  int max_blocks_wide = num_4x4_blocks_wide_lookup[mbmi->sb_type];
342
  int ctx = txfm_partition_context(xd->above_txfm_context + tx_col,
343
                                   xd->left_txfm_context + tx_row, tx_size);
344

345 346
  if (xd->mb_to_bottom_edge < 0) max_blocks_high += xd->mb_to_bottom_edge >> 5;
  if (xd->mb_to_right_edge < 0) max_blocks_wide += xd->mb_to_right_edge >> 5;
347

348
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
349

350
  if (tx_size == mbmi->inter_tx_size[tx_row][tx_col]) {
351
    vp10_write(w, 0, cm->fc->txfm_partition_prob[ctx]);
352 353
    txfm_partition_update(xd->above_txfm_context + tx_col,
                          xd->left_txfm_context + tx_row, tx_size);
354 355
  } else {
    const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
356
    int bsl = b_width_log2_lookup[bsize];
357
    int i;
358
    vp10_write(w, 1, cm->fc->txfm_partition_prob[ctx]);
359

360
    if (tx_size == TX_8X8) {
361 362
      txfm_partition_update(xd->above_txfm_context + tx_col,
                            xd->left_txfm_context + tx_row, TX_4X4);
363
      return;
364
    }
365 366 367 368

    assert(bsl > 0);
    --bsl;
    for (i = 0; i < 4; ++i) {
369 370
      int offsetr = blk_row + ((i >> 1) << bsl);
      int offsetc = blk_col + ((i & 0x01) << bsl);
Debargha Mukherjee's avatar
Debargha Mukherjee committed
371
      write_tx_size_vartx(cm, xd, mbmi, tx_size - 1, offsetr, offsetc, w);
372 373 374
    }
  }
}
375

376
static void update_txfm_partition_probs(VP10_COMMON *cm, vp10_writer *w,
377 378 379 380 381 382
                                        FRAME_COUNTS *counts) {
  int k;
  for (k = 0; k < TXFM_PARTITION_CONTEXTS; ++k)
    vp10_cond_prob_diff_update(w, &cm->fc->txfm_partition_prob[k],
                               counts->txfm_partition[k]);
}
383 384
#endif

385 386
static void write_selected_tx_size(const VP10_COMMON *cm, const MACROBLOCKD *xd,
                                   vp10_writer *w) {
387 388
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
389 390
  // For sub8x8 blocks the tx_size symbol does not need to be sent
  if (bsize >= BLOCK_8X8) {
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
    const TX_SIZE tx_size = mbmi->tx_size;
    const int is_inter = is_inter_block(mbmi);
    const int tx_size_ctx = get_tx_size_context(xd);
    const int tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize]
                                     : intra_tx_size_cat_lookup[bsize];
    const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size];

#if CONFIG_EXT_TX && CONFIG_RECT_TX
    assert(IMPLIES(is_rect_tx(tx_size), is_rect_tx_allowed(mbmi)));
    assert(
        IMPLIES(is_rect_tx(tx_size), tx_size == max_txsize_rect_lookup[bsize]));
#endif  // CONFIG_EXT_TX && CONFIG_RECT_TX

    vp10_write_token(w, vp10_tx_size_tree[tx_size_cat],
                     cm->fc->tx_size_probs[tx_size_cat][tx_size_ctx],
                     &tx_size_encodings[tx_size_cat][coded_tx_size]);
Jingning Han's avatar
Jingning Han committed
407 408 409
  }
}

410
#if CONFIG_REF_MV
411
static void update_inter_mode_probs(VP10_COMMON *cm, vp10_writer *w,
412 413 414 415 416 417 418 419 420 421 422
                                    FRAME_COUNTS *counts) {
  int i;
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
    vp10_cond_prob_diff_update(w, &cm->fc->newmv_prob[i],
                               counts->newmv_mode[i]);
  for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
    vp10_cond_prob_diff_update(w, &cm->fc->zeromv_prob[i],
                               counts->zeromv_mode[i]);
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
    vp10_cond_prob_diff_update(w, &cm->fc->refmv_prob[i],
                               counts->refmv_mode[i]);
423
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
424
    vp10_cond_prob_diff_update(w, &cm->fc->drl_prob[i], counts->drl_mode[i]);
Yue Chen's avatar
Yue Chen committed
425 426 427
#if CONFIG_EXT_INTER
  vp10_cond_prob_diff_update(w, &cm->fc->new2mv_prob, counts->new2mv_mode);
#endif  // CONFIG_EXT_INTER
428 429 430
}
#endif

431
#if CONFIG_EXT_INTER
432
static void update_inter_compound_mode_probs(VP10_COMMON *cm, vp10_writer *w) {
433 434 435 436 437 438
  const int savings_thresh = vp10_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             vp10_cost_zero(GROUP_DIFF_UPDATE_PROB);
  int i;
  int savings = 0;
  int do_update = 0;
  for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
439 440 441
    savings += prob_diff_update_savings(
        vp10_inter_compound_mode_tree, cm->fc->inter_compound_mode_probs[i],
        cm->counts.inter_compound_mode[i], INTER_COMPOUND_MODES);
442 443
  }
  do_update = savings > savings_thresh;
444
  vp10_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
445 446
  if (do_update) {
    for (i = 0; i < INTER_MODE_CONTEXTS; ++i) {
447 448 449
      prob_diff_update(
          vp10_inter_compound_mode_tree, cm->fc->inter_compound_mode_probs[i],
          cm->counts.inter_compound_mode[i], INTER_COMPOUND_MODES, w);
450 451 452 453 454
    }
  }
}
#endif  // CONFIG_EXT_INTER

Yaowu Xu's avatar
Yaowu Xu committed
455
static int write_skip(const VP10_COMMON *cm, const MACROBLOCKD *xd,
456
                      int segment_id, const MODE_INFO *mi, vp10_writer *w) {
Jingning Han's avatar
Jingning Han committed
457 458 459 460
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
461
    vp10_write(w, skip, vp10_get_skip_prob(cm, xd));
Jingning Han's avatar
Jingning Han committed
462 463 464 465
    return skip;
  }
}

466
static void update_skip_probs(VP10_COMMON *cm, vp10_writer *w,
Jingning Han's avatar
Jingning Han committed
467 468 469 470 471 472 473
                              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]);
}

474
static void update_switchable_interp_probs(VP10_COMMON *cm, vp10_writer *w,
Jingning Han's avatar
Jingning Han committed
475 476 477 478 479 480 481 482
                                           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);
}

483
#if CONFIG_EXT_TX
484
static void update_ext_tx_probs(VP10_COMMON *cm, vp10_writer *w) {
485 486
  const int savings_thresh = vp10_cost_one(GROUP_DIFF_UPDATE_PROB) -
                             vp10_cost_zero(GROUP_DIFF_UPDATE_PROB);
487
  int i, j;
488 489 490 491 492
  int s;
  for (s = 1; s < EXT_TX_SETS_INTER; ++s) {
    int savings = 0;
    int do_update = 0;
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
493
      if (!use_inter_ext_tx_for_txsize[s][i]) continue;
494 495 496 497 498
      savings += prob_diff_update_savings(
          vp10_ext_tx_inter_tree[s], cm->fc->inter_ext_tx_prob[s][i],
          cm->counts.inter_ext_tx[s][i], num_ext_tx_set_inter[s]);
    }
    do_update = savings > savings_thresh;
499
    vp10_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
500 501
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
502
        if (!use_inter_ext_tx_for_txsize[s][i]) continue;
503 504 505
        prob_diff_update(
            vp10_ext_tx_inter_tree[s], cm->fc->inter_ext_tx_prob[s][i],
            cm->counts.inter_ext_tx[s][i], num_ext_tx_set_inter[s], w);
506
      }
507 508
    }
  }
509

510 511 512 513
  for (s = 1; s < EXT_TX_SETS_INTRA; ++s) {
    int savings = 0;
    int do_update = 0;
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
514
      if (!use_intra_ext_tx_for_txsize[s][i]) continue;
515
      for (j = 0; j < INTRA_MODES; ++j)
516 517 518 519 520
        savings += prob_diff_update_savings(
            vp10_ext_tx_intra_tree[s], cm->fc->intra_ext_tx_prob[s][i][j],
            cm->counts.intra_ext_tx[s][i][j], num_ext_tx_set_intra[s]);
    }
    do_update = savings > savings_thresh;
521
    vp10_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
522 523
    if (do_update) {
      for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
524
        if (!use_intra_ext_tx_for_txsize[s][i]) continue;
525
        for (j = 0; j < INTRA_MODES; ++j)
526 527 528
          prob_diff_update(
              vp10_ext_tx_intra_tree[s], cm->fc->intra_ext_tx_prob[s][i][j],
              cm->counts.intra_ext_tx[s][i][j], num_ext_tx_set_intra[s], w);
529 530
      }
    }
531
  }
532
}
Debargha Mukherjee's avatar
Debargha Mukherjee committed
533

534
#else
Debargha Mukherjee's avatar
Debargha Mukherjee committed
535

536
static void update_ext_tx_probs(VP10_COMMON *cm, vp10_writer *w) {
537 538 539 540 541 542 543 544 545 546 547 548 549
  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;
550
  vp10_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
551 552 553
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
      for (j = 0; j < TX_TYPES; ++j)
554 555
        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);
556 557 558 559
    }
  }
  savings = 0;
  for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
560 561 562
    savings +=
        prob_diff_update_savings(vp10_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
                                 cm->counts.inter_ext_tx[i], TX_TYPES);
563 564
  }
  do_update = savings > savings_thresh;
565
  vp10_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
566 567
  if (do_update) {
    for (i = TX_4X4; i < EXT_TX_SIZES; ++i) {
568 569
      prob_diff_update(vp10_ext_tx_tree, cm->fc->inter_ext_tx_prob[i],
                       cm->counts.inter_ext_tx[i], TX_TYPES, w);
570 571 572
    }
  }
}
573 574
#endif  // CONFIG_EXT_TX

575 576
static void pack_palette_tokens(vp10_writer *w, const TOKENEXTRA **tp, int n,
                                int num) {
hui su's avatar
hui su committed
577
  int i;
578
  const TOKENEXTRA *p = *tp;
hui su's avatar
hui su committed
579

580
  for (i = 0; i < num; ++i) {
hui su's avatar
hui su committed
581 582 583 584 585 586 587 588
    vp10_write_token(w, vp10_palette_color_tree[n - 2], p->context_tree,
                     &palette_color_encodings[n - 2][p->token]);
    ++p;
  }

  *tp = p;
}

589
#if CONFIG_SUPERTX
590
static void update_supertx_probs(VP10_COMMON *cm, vp10_writer *w) {
591 592 593 594 595 596 597 598 599 600 601 602
  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 = 0; i < PARTITION_SUPERTX_CONTEXTS; ++i) {
    for (j = 1; j < TX_SIZES; ++j) {
      savings += vp10_cond_prob_diff_update_savings(&cm->fc->supertx_prob[i][j],
                                                    cm->counts.supertx[i][j]);
    }
  }
  do_update = savings > savings_thresh;
603
  vp10_write(w, do_update, GROUP_DIFF_UPDATE_PROB);
604 605 606 607 608 609 610 611 612 613 614
  if (do_update) {
    for (i = 0; i < PARTITION_SUPERTX_CONTEXTS; ++i) {
      for (j = 1; j < TX_SIZES; ++j) {
        vp10_cond_prob_diff_update(w, &cm->fc->supertx_prob[i][j],
                                   cm->counts.supertx[i][j]);
      }
    }
  }
}
#endif  // CONFIG_SUPERTX

Alex Converse's avatar
Alex Converse committed
615
#if !CONFIG_ANS
616 617
static void pack_mb_tokens(vp10_writer *w, const TOKENEXTRA **tp,
                           const TOKENEXTRA *const stop,
618
                           vpx_bit_depth_t bit_depth, const TX_SIZE tx) {
619
  const TOKENEXTRA *p = *tp;
620 621
#if CONFIG_VAR_TX
  int count = 0;
Debargha Mukherjee's avatar
Debargha Mukherjee committed
622
  const int seg_eob = get_tx2d_size(tx);
623
#endif
Jingning Han's avatar
Jingning Han committed
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639

  while (p < stop && p->token != EOSB_TOKEN) {
    const int t = p->token;
    const struct vp10_token *const a = &vp10_coef_encodings[t];
    int v = a->value;
    int n = a->len;
#if CONFIG_VP9_HIGHBITDEPTH
    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];
640
    (void)bit_depth;
Jingning Han's avatar
Jingning Han committed
641 642 643
#endif  // CONFIG_VP9_HIGHBITDEPTH

    /* skip one or two nodes */
644
    if (p->skip_eob_node)
Jingning Han's avatar
Jingning Han committed
645
      n -= p->skip_eob_node;
646
    else
647
      vp10_write(w, t != EOB_TOKEN, p->context_tree[0]);
648 649

    if (t != EOB_TOKEN) {
650
      vp10_write(w, t != ZERO_TOKEN, p->context_tree[1]);
Jingning Han's avatar
Jingning Han committed
651

652
      if (t != ZERO_TOKEN) {
653
        vp10_write(w, t != ONE_TOKEN, p->context_tree[2]);
654 655 656 657

        if (t != ONE_TOKEN) {
          int len = UNCONSTRAINED_NODES - p->skip_eob_node;
          vp10_write_tree(w, vp10_coef_con_tree,
658 659
                          vp10_pareto8_full[p->context_tree[PIVOT_NODE] - 1], v,
                          n - len, 0);
660 661
        }
      }
Jingning Han's avatar
Jingning Han committed
662 663 664 665
    }

    if (b->base_val) {
      const int e = p->extra, l = b->len;
Debargha Mukherjee's avatar
Debargha Mukherjee committed
666 667 668
      int skip_bits = (b->base_val == CAT6_MIN_VAL)
                          ? TX_SIZES - 1 - txsize_sqr_up_map[tx]
                          : 0;
Jingning Han's avatar
Jingning Han committed
669 670 671 672

      if (l) {
        const unsigned char *pb = b->prob;
        int v = e >> 1;
673
        int n = l; /* number of bits in v, assumed nonzero */
Jingning Han's avatar
Jingning Han committed
674 675 676 677
        int i = 0;

        do {
          const int bb = (v >> --n) & 1;
678 679 680 681
          if (skip_bits) {
            skip_bits--;
            assert(!bb);
          } else {
682
            vp10_write(w, bb, pb[i >> 1]);
683
          }
Jingning Han's avatar
Jingning Han committed
684 685 686 687
          i = b->tree[i + bb];
        } while (n);
      }

688
      vp10_write_bit(w, e & 1);
Jingning Han's avatar
Jingning Han committed
689 690
    }
    ++p;
691 692 693

#if CONFIG_VAR_TX
    ++count;
694
    if (t == EOB_TOKEN || count == seg_eob) break;
695
#endif
Jingning Han's avatar
Jingning Han committed
696 697
  }

698
  *tp = p;
Jingning Han's avatar
Jingning Han committed
699
}
Alex Converse's avatar
Alex Converse committed
700
#else
701 702
// This function serializes the tokens in forward order using a buffered ans
// coder.
703
static void pack_mb_tokens(struct BufAnsCoder *ans, const TOKENEXTRA **tp,
704
                           const TOKENEXTRA *const stop,
705
                           vpx_bit_depth_t bit_depth, const TX_SIZE tx) {
706
  const TOKENEXTRA *p = *tp;
707 708 709 710
#if CONFIG_VAR_TX
  int count = 0;
  const int seg_eob = 16 << (tx << 1);
#endif  // CONFIG_VAR_TX
Alex Converse's avatar
Alex Converse committed
711

712
  while (p < stop && p->token != EOSB_TOKEN) {
Alex Converse's avatar
Alex Converse committed
713 714
    const int t = p->token;
#if CONFIG_VP9_HIGHBITDEPTH
715 716 717 718 719 720 721
    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];
Alex Converse's avatar
Alex Converse committed
722 723
#else
    const vp10_extra_bit *const b = &vp10_extra_bits[t];
724
    (void)bit_depth;
Alex Converse's avatar
Alex Converse committed
725 726
#endif  // CONFIG_VP9_HIGHBITDEPTH

727 728 729 730 731
    /* skip one or two nodes */
    if (!p->skip_eob_node)
      buf_uabs_write(ans, t != EOB_TOKEN, p->context_tree[0]);

    if (t != EOB_TOKEN) {
732 733 734 735 736 737 738 739 740
      struct rans_sym s;
      const rans_dec_lut *token_cdf = p->token_cdf;
      assert(token_cdf);
      s.cum_prob = (*token_cdf)[t - ZERO_TOKEN];
      s.prob = (*token_cdf)[t - ZERO_TOKEN + 1] - s.cum_prob;
      buf_rans_write(ans, &s);

      if (b->base_val) {
        const int e = p->extra, l = b->len;
Debargha Mukherjee's avatar
Debargha Mukherjee committed
741 742 743
        int skip_bits = (b->base_val == CAT6_MIN_VAL)
                            ? TX_SIZES - 1 - txsize_sqr_up_map[tx]
                            : 0;
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761

        if (l) {
          const unsigned char *pb = b->prob;
          int v = e >> 1;
          int n = l; /* number of bits in v, assumed nonzero */
          int i = 0;

          do {
            const int bb = (v >> --n) & 1;
            if (skip_bits) {
              skip_bits--;
              assert(!bb);
            } else {
              buf_uabs_write(ans, bb, pb[i >> 1]);
            }
            i = b->tree[i + bb];
          } while (n);
        }
762

763
        buf_uabs_write(ans, e & 1, 128);
764 765 766 767 768 769 770 771
      }
    }
    ++p;

#if CONFIG_VAR_TX
    ++count;
    if (t == EOB_TOKEN || count == seg_eob) break;
#endif  // CONFIG_VAR_TX
Alex Converse's avatar
Alex Converse committed
772
  }
773 774

  *tp = p;
Alex Converse's avatar
Alex Converse committed
775 776
}
#endif  // !CONFIG_ANS
Jingning Han's avatar
Jingning Han committed
777

778
#if CONFIG_VAR_TX
779 780 781 782 783 784
static void pack_txb_tokens(vp10_writer *w, const TOKENEXTRA **tp,
                            const TOKENEXTRA *const tok_end, MACROBLOCKD *xd,
                            MB_MODE_INFO *mbmi, int plane,
                            BLOCK_SIZE plane_bsize, vpx_bit_depth_t bit_depth,
                            int block, int blk_row, int blk_col,
                            TX_SIZE tx_size) {
785 786
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
787 788
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
Debargha Mukherjee's avatar
Debargha Mukherjee committed
789
  TX_SIZE plane_tx_size;
790 791 792 793 794 795 796 797
  int max_blocks_high = num_4x4_blocks_high_lookup[plane_bsize];
  int max_blocks_wide = num_4x4_blocks_wide_lookup[plane_bsize];

  if (xd->mb_to_bottom_edge < 0)
    max_blocks_high += xd->mb_to_bottom_edge >> (5 + pd->subsampling_y);
  if (xd->mb_to_right_edge < 0)
    max_blocks_wide += xd->mb_to_right_edge >> (5 + pd->subsampling_x);

798
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
799

Debargha Mukherjee's avatar
Debargha Mukherjee committed
800 801 802 803
  plane_tx_size = plane ? get_uv_tx_size_impl(
                              mbmi->inter_tx_size[tx_row][tx_col], bsize, 0, 0)
                        : mbmi->inter_tx_size[tx_row][tx_col];

804 805 806 807 808 809 810 811 812 813 814 815
  if (tx_size == plane_tx_size) {
    pack_mb_tokens(w, tp, tok_end, bit_depth, tx_size);
  } else {
    int bsl = b_width_log2_lookup[bsize];
    int i;

    assert(bsl > 0);
    --bsl;

    for (i = 0; i < 4; ++i) {
      const int offsetr = blk_row + ((i >> 1) << bsl);
      const int offsetc = blk_col + ((i & 0x01) << bsl);
816
      int step = num_4x4_blocks_txsize_lookup[tx_size - 1];
817

818
      if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
819

820 821
      pack_txb_tokens(w, tp, tok_end, xd, mbmi, plane, plane_bsize, bit_depth,
                      block + i * step, offsetr, offsetc, tx_size - 1);
822 823 824 825 826
    }
  }
}
#endif

827
static void write_segment_id(vp10_writer *w, const struct segmentation *seg,
828
                             const struct segmentation_probs *segp,
Jingning Han's avatar
Jingning Han committed
829 830
                             int segment_id) {
  if (seg->enabled && seg->update_map)
831
    vp10_write_tree(w, vp10_segment_tree, segp->tree_probs, segment_id, 3, 0);
Jingning Han's avatar
Jingning Han committed
832 833 834
}

// This function encodes the reference frame
Yaowu Xu's avatar
Yaowu Xu committed
835
static void write_ref_frames(const VP10_COMMON *cm, const MACROBLOCKD *xd,
836
                             vp10_writer *w) {
Jingning Han's avatar
Jingning Han committed
837 838 839 840 841 842 843 844 845
  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] ==
846
           get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
Jingning Han's avatar
Jingning Han committed
847 848 849 850
  } else {
    // does the feature use compound prediction or not
    // (if not specified at the frame/segment level)
    if (cm->reference_mode == REFERENCE_MODE_SELECT) {
851
      vp10_write(w, is_compound, vp10_get_reference_mode_prob(cm, xd));
Jingning Han's avatar
Jingning Han committed
852
    } else {
853
      assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE));
Jingning Han's avatar
Jingning Han committed
854 855 856
    }

    if (is_compound) {
857 858
#if CONFIG_EXT_REFS
      const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
859 860
                       mbmi->ref_frame[0] == LAST3_FRAME);
      const int bit_bwd = mbmi->ref_frame[1] == ALTREF_FRAME;
861
#else  // CONFIG_EXT_REFS
862 863
      const int bit = mbmi->ref_frame[0] == GOLDEN_FRAME;
#endif  // CONFIG_EXT_REFS
864

865
      vp10_write(w, bit, vp10_get_pred_prob_comp_ref_p(cm, xd));
866 867 868 869

#if CONFIG_EXT_REFS
      if (!bit) {
        const int bit1 = mbmi->ref_frame[0] == LAST_FRAME;
870
        vp10_write(w, bit1, vp10_get_pred_prob_comp_ref_p1(cm, xd));
871 872
      } else {
        const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
873
        vp10_write(w, bit2, vp10_get_pred_prob_comp_ref_p2(cm, xd));
874
      }
875
      vp10_write(w, bit_bwd, vp10_get_pred_prob_comp_bwdref_p(cm, xd));
876
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
877
    } else {
878
#if CONFIG_EXT_REFS
879 880
      const int bit0 = (mbmi->ref_frame[0] == ALTREF_FRAME ||
                        mbmi->ref_frame[0] == BWDREF_FRAME);
881
      vp10_write(w, bit0, vp10_get_pred_prob_single_ref_p1(cm, xd));
882 883

      if (bit0) {
884
        const int bit1 = mbmi->ref_frame[0] == ALTREF_FRAME;
885
        vp10_write(w, bit1, vp10_get_pred_prob_single_ref_p2(cm, xd));
886 887
      } else {
        const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
888
                          mbmi->ref_frame[0] == GOLDEN_FRAME);
889
        vp10_write(w, bit2, vp10_get_pred_prob_single_ref_p3(cm, xd));
890 891 892

        if (!bit2) {
          const int bit3 = mbmi->ref_frame[0] != LAST_FRAME;
893
          vp10_write(w, bit3, vp10_get_pred_prob_single_ref_p4(cm, xd));
894 895
        } else {
          const int bit4 = mbmi->ref_frame[0] != LAST3_FRAME;
896
          vp10_write(w, bit4, vp10_get_pred_prob_single_ref_p5(cm, xd));
897 898
        }
      }
899
#else   // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
900
      const int bit0 = mbmi->ref_frame[0] != LAST_FRAME;
901
      vp10_write(w, bit0, vp10_get_pred_prob_single_ref_p1(cm, xd));
902

Jingning Han's avatar
Jingning Han committed
903 904
      if (bit0) {
        const int bit1 = mbmi->ref_frame[0] != GOLDEN_FRAME;
905
        vp10_write(w, bit1, vp10_get_pred_prob_single_ref_p2(cm, xd));
Jingning Han's avatar
Jingning Han committed
906
      }
907
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
908 909 910 911
    }
  }
}

hui su's avatar
hui su committed
912 913 914
#if CONFIG_EXT_INTRA
static void write_ext_intra_mode_info(const VP10_COMMON *const cm,
                                      const MB_MODE_INFO *const mbmi,
915
                                      vp10_writer *w) {
hui su's avatar
hui su committed
916 917 918
#if !ALLOW_FILTER_INTRA_MODES
  return;
#endif
919
  if (mbmi->mode == DC_PRED && mbmi->palette_mode_info.palette_size[0] == 0) {
920
    vp10_write(w, mbmi->ext_intra_mode_info.use_ext_intra_mode[0],
921
               cm->fc->ext_intra_probs[0]);
hui su's avatar
hui su committed
922 923
    if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) {
      EXT_INTRA_MODE mode = mbmi->ext_intra_mode_info.ext_intra_mode[0];
hui su's avatar
hui su committed