decodemv.c 88.7 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11 12 13
 */

#include <assert.h>

14 15 16 17 18 19 20
#include "av1/common/common.h"
#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"
hui su's avatar
hui su committed
21 22 23
#if CONFIG_EXT_INTRA
#include "av1/common/reconintra.h"
#endif  // CONFIG_EXT_INTRA
24
#include "av1/common/seg_common.h"
Yue Chen's avatar
Yue Chen committed
25
#include "av1/common/warped_motion.h"
26 27

#include "av1/decoder/decodeframe.h"
Jingning Han's avatar
Jingning Han committed
28
#include "av1/decoder/decodemv.h"
29

Yaowu Xu's avatar
Yaowu Xu committed
30
#include "aom_dsp/aom_dsp_common.h"
31

Luc Trudeau's avatar
Luc Trudeau committed
32 33 34 35
#if CONFIG_CFL
#include "av1/common/cfl.h"
#endif

Michael Bebenita's avatar
Michael Bebenita committed
36
#define ACCT_STR __func__
37

38
#define DEC_MISMATCH_DEBUG 0
39

40
static PREDICTION_MODE read_intra_mode(aom_reader *r, aom_cdf_prob *cdf) {
Hui Su's avatar
Hui Su committed
41
  return (PREDICTION_MODE)aom_read_symbol(r, cdf, INTRA_MODES, ACCT_STR);
42
}
Jingning Han's avatar
Jingning Han committed
43

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
static void read_cdef(AV1_COMMON *cm, aom_reader *r, MB_MODE_INFO *const mbmi,
                      int mi_col, int mi_row) {
  if (cm->all_lossless) return;

  const int m = ~((1 << (6 - MI_SIZE_LOG2)) - 1);
  if (!(mi_col & (cm->mib_size - 1)) &&
      !(mi_row & (cm->mib_size - 1))) {  // Top left?
#if CONFIG_EXT_PARTITION
    cm->cdef_preset[0] = cm->cdef_preset[1] = cm->cdef_preset[2] =
        cm->cdef_preset[3] = -1;
#else
    cm->cdef_preset = -1;
#endif
  }
// Read CDEF param at first a non-skip coding block
#if CONFIG_EXT_PARTITION
  const int mask = 1 << (6 - MI_SIZE_LOG2);
  const int index = cm->sb_size == BLOCK_128X128
                        ? !!(mi_col & mask) + 2 * !!(mi_row & mask)
                        : 0;
  cm->mi_grid_visible[(mi_row & m) * cm->mi_stride + (mi_col & m)]
      ->mbmi.cdef_strength = cm->cdef_preset[index] =
      cm->cdef_preset[index] == -1 && !mbmi->skip
          ? aom_read_literal(r, cm->cdef_bits, ACCT_STR)
          : cm->cdef_preset[index];
#else
  cm->mi_grid_visible[(mi_row & m) * cm->mi_stride + (mi_col & m)]
      ->mbmi.cdef_strength = cm->cdef_preset =
      cm->cdef_preset == -1 && !mbmi->skip
          ? aom_read_literal(r, cm->cdef_bits, ACCT_STR)
          : cm->cdef_preset;
#endif
}

78 79 80 81 82
static int read_delta_qindex(AV1_COMMON *cm, MACROBLOCKD *xd, aom_reader *r,
                             MB_MODE_INFO *const mbmi, int mi_col, int mi_row) {
  FRAME_COUNTS *counts = xd->counts;
  int sign, abs, reduced_delta_qindex = 0;
  BLOCK_SIZE bsize = mbmi->sb_type;
83 84
  const int b_col = mi_col & (cm->mib_size - 1);
  const int b_row = mi_row & (cm->mib_size - 1);
85
  const int read_delta_q_flag = (b_col == 0 && b_row == 0);
Thomas Davies's avatar
Thomas Davies committed
86 87
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
88

Pavel Frolov's avatar
Pavel Frolov committed
89
  if ((bsize != cm->sb_size || mbmi->skip == 0) && read_delta_q_flag) {
Thomas Davies's avatar
Thomas Davies committed
90
    abs = aom_read_symbol(r, ec_ctx->delta_q_cdf, DELTA_Q_PROBS + 1, ACCT_STR);
91
    const int smallval = (abs < DELTA_Q_SMALL);
Thomas Davies's avatar
Thomas Davies committed
92
    if (counts) {
93
      for (int i = 0; i < abs; ++i) counts->delta_q[i][1]++;
Thomas Davies's avatar
Thomas Davies committed
94 95 96 97
      if (smallval) counts->delta_q[abs][0]++;
    }

    if (!smallval) {
98 99
      const int rem_bits = aom_read_literal(r, 3, ACCT_STR) + 1;
      const int thr = (1 << rem_bits) + 1;
100 101 102 103 104 105 106 107 108 109 110 111 112
      abs = aom_read_literal(r, rem_bits, ACCT_STR) + thr;
    }

    if (abs) {
      sign = aom_read_bit(r, ACCT_STR);
    } else {
      sign = 1;
    }

    reduced_delta_qindex = sign ? -abs : abs;
  }
  return reduced_delta_qindex;
}
Fangwen Fu's avatar
Fangwen Fu committed
113 114
#if CONFIG_EXT_DELTA_Q
static int read_delta_lflevel(AV1_COMMON *cm, MACROBLOCKD *xd, aom_reader *r,
115 116 117
#if CONFIG_LOOPFILTER_LEVEL
                              int lf_id,
#endif
Fangwen Fu's avatar
Fangwen Fu committed
118 119 120 121 122
                              MB_MODE_INFO *const mbmi, int mi_col,
                              int mi_row) {
  FRAME_COUNTS *counts = xd->counts;
  int sign, abs, reduced_delta_lflevel = 0;
  BLOCK_SIZE bsize = mbmi->sb_type;
123 124
  const int b_col = mi_col & (cm->mib_size - 1);
  const int b_row = mi_row & (cm->mib_size - 1);
Fangwen Fu's avatar
Fangwen Fu committed
125 126 127 128
  const int read_delta_lf_flag = (b_col == 0 && b_row == 0);
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;

129
  if ((bsize != cm->sb_size || mbmi->skip == 0) && read_delta_lf_flag) {
130
#if CONFIG_LOOPFILTER_LEVEL
131 132 133 134 135 136 137 138
    if (cm->delta_lf_multi) {
      assert(lf_id >= 0 && lf_id < FRAME_LF_COUNT);
      abs = aom_read_symbol(r, ec_ctx->delta_lf_multi_cdf[lf_id],
                            DELTA_LF_PROBS + 1, ACCT_STR);
    } else {
      abs = aom_read_symbol(r, ec_ctx->delta_lf_cdf, DELTA_LF_PROBS + 1,
                            ACCT_STR);
    }
139
#else
Fangwen Fu's avatar
Fangwen Fu committed
140 141
    abs =
        aom_read_symbol(r, ec_ctx->delta_lf_cdf, DELTA_LF_PROBS + 1, ACCT_STR);
142
#endif  // CONFIG_LOOPFILTER_LEVEL
143
    const int smallval = (abs < DELTA_LF_SMALL);
Fangwen Fu's avatar
Fangwen Fu committed
144
    if (counts) {
145
#if CONFIG_LOOPFILTER_LEVEL
146
      if (cm->delta_lf_multi) {
147
        for (int i = 0; i < abs; ++i) counts->delta_lf_multi[lf_id][i][1]++;
148 149
        if (smallval) counts->delta_lf_multi[lf_id][abs][0]++;
      } else {
150
        for (int i = 0; i < abs; ++i) counts->delta_lf[i][1]++;
151 152
        if (smallval) counts->delta_lf[abs][0]++;
      }
153
#else
154
      for (int i = 0; i < abs; ++i) counts->delta_lf[i][1]++;
Fangwen Fu's avatar
Fangwen Fu committed
155
      if (smallval) counts->delta_lf[abs][0]++;
156
#endif  // CONFIG_LOOPFILTER_LEVEL
Fangwen Fu's avatar
Fangwen Fu committed
157 158
    }
    if (!smallval) {
159 160
      const int rem_bits = aom_read_literal(r, 3, ACCT_STR) + 1;
      const int thr = (1 << rem_bits) + 1;
Fangwen Fu's avatar
Fangwen Fu committed
161 162 163 164 165 166 167 168 169 170 171 172 173 174
      abs = aom_read_literal(r, rem_bits, ACCT_STR) + thr;
    }

    if (abs) {
      sign = aom_read_bit(r, ACCT_STR);
    } else {
      sign = 1;
    }

    reduced_delta_lflevel = sign ? -abs : abs;
  }
  return reduced_delta_lflevel;
}
#endif
175

Luc Trudeau's avatar
Luc Trudeau committed
176
static UV_PREDICTION_MODE read_intra_mode_uv(FRAME_CONTEXT *ec_ctx,
177
                                             aom_reader *r,
Luc Trudeau's avatar
Luc Trudeau committed
178 179
                                             PREDICTION_MODE y_mode) {
  const UV_PREDICTION_MODE uv_mode =
180 181 182
#if CONFIG_CFL
      aom_read_symbol(r, ec_ctx->uv_mode_cdf[y_mode], UV_INTRA_MODES, ACCT_STR);
#else
183
      read_intra_mode(r, ec_ctx->uv_mode_cdf[y_mode]);
184
#endif  // CONFIG_CFL
Jingning Han's avatar
Jingning Han committed
185 186 187
  return uv_mode;
}

Luc Trudeau's avatar
Luc Trudeau committed
188
#if CONFIG_CFL
189
static int read_cfl_alphas(FRAME_CONTEXT *const ec_ctx, aom_reader *r,
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
                           int *signs_out) {
  const int joint_sign =
      aom_read_symbol(r, ec_ctx->cfl_sign_cdf, CFL_JOINT_SIGNS, "cfl:signs");
  int idx = 0;
  // Magnitudes are only coded for nonzero values
  if (CFL_SIGN_U(joint_sign) != CFL_SIGN_ZERO) {
    aom_cdf_prob *cdf_u = ec_ctx->cfl_alpha_cdf[CFL_CONTEXT_U(joint_sign)];
    idx = aom_read_symbol(r, cdf_u, CFL_ALPHABET_SIZE, "cfl:alpha_u")
          << CFL_ALPHABET_SIZE_LOG2;
  }
  if (CFL_SIGN_V(joint_sign) != CFL_SIGN_ZERO) {
    aom_cdf_prob *cdf_v = ec_ctx->cfl_alpha_cdf[CFL_CONTEXT_V(joint_sign)];
    idx += aom_read_symbol(r, cdf_v, CFL_ALPHABET_SIZE, "cfl:alpha_v");
  }
  *signs_out = joint_sign;
  return idx;
Luc Trudeau's avatar
Luc Trudeau committed
206 207 208
}
#endif

Yue Chen's avatar
Yue Chen committed
209 210
static INTERINTRA_MODE read_interintra_mode(MACROBLOCKD *xd, aom_reader *r,
                                            int size_group) {
211 212 213
  const INTERINTRA_MODE ii_mode = (INTERINTRA_MODE)aom_read_symbol(
      r, xd->tile_ctx->interintra_mode_cdf[size_group], INTERINTRA_MODES,
      ACCT_STR);
214
  FRAME_COUNTS *counts = xd->counts;
215
  if (counts) ++counts->interintra_mode[size_group][ii_mode];
216 217 218
  return ii_mode;
}

219
static PREDICTION_MODE read_inter_mode(FRAME_CONTEXT *ec_ctx, MACROBLOCKD *xd,
Yaowu Xu's avatar
Yaowu Xu committed
220
                                       aom_reader *r, int16_t ctx) {
221
  FRAME_COUNTS *counts = xd->counts;
222
  int16_t mode_ctx = ctx & NEWMV_CTX_MASK;
223 224 225
  int is_newmv, is_zeromv, is_refmv;
  is_newmv = aom_read_symbol(r, ec_ctx->newmv_cdf[mode_ctx], 2, ACCT_STR) == 0;
  if (is_newmv) {
226
    if (counts) ++counts->newmv_mode[mode_ctx][0];
227
    return NEWMV;
228
  }
229
  if (counts) ++counts->newmv_mode[mode_ctx][1];
Sarah Parker's avatar
Sarah Parker committed
230
  mode_ctx = (ctx >> GLOBALMV_OFFSET) & GLOBALMV_CTX_MASK;
231 232 233
  is_zeromv =
      aom_read_symbol(r, ec_ctx->zeromv_cdf[mode_ctx], 2, ACCT_STR) == 0;
  if (is_zeromv) {
234
    if (counts) ++counts->zeromv_mode[mode_ctx][0];
Sarah Parker's avatar
Sarah Parker committed
235
    return GLOBALMV;
236
  }
237
  if (counts) ++counts->zeromv_mode[mode_ctx][1];
238
  mode_ctx = (ctx >> REFMV_OFFSET) & REFMV_CTX_MASK;
239 240 241
  if (ctx & (1 << SKIP_NEARESTMV_OFFSET)) mode_ctx = 6;
  if (ctx & (1 << SKIP_NEARMV_OFFSET)) mode_ctx = 7;
  if (ctx & (1 << SKIP_NEARESTMV_SUB8X8_OFFSET)) mode_ctx = 8;
242 243
  is_refmv = aom_read_symbol(r, ec_ctx->refmv_cdf[mode_ctx], 2, ACCT_STR) == 0;
  if (is_refmv) {
244
    if (counts) ++counts->refmv_mode[mode_ctx][0];
245 246
    return NEARESTMV;
  } else {
247
    if (counts) ++counts->refmv_mode[mode_ctx][1];
248 249
    return NEARMV;
  }
Jingning Han's avatar
Jingning Han committed
250 251
}

252
static void read_drl_idx(FRAME_CONTEXT *ec_ctx, MACROBLOCKD *xd,
Yaowu Xu's avatar
Yaowu Xu committed
253 254
                         MB_MODE_INFO *mbmi, aom_reader *r) {
  uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
255
  mbmi->ref_mv_idx = 0;
256
  if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
257
    for (int idx = 0; idx < 2; ++idx) {
258
      if (xd->ref_mv_count[ref_frame_type] > idx + 1) {
Yaowu Xu's avatar
Yaowu Xu committed
259
        uint8_t drl_ctx = av1_drl_ctx(xd->ref_mv_stack[ref_frame_type], idx);
260 261 262 263
        int drl_idx = aom_read_symbol(r, ec_ctx->drl_cdf[drl_ctx], 2, ACCT_STR);
        mbmi->ref_mv_idx = idx + drl_idx;
        if (xd->counts) ++xd->counts->drl_mode[drl_ctx][drl_idx];
        if (!drl_idx) return;
264 265 266
      }
    }
  }
David Barker's avatar
David Barker committed
267
  if (have_nearmv_in_inter_mode(mbmi->mode)) {
268 269 270
    // Offset the NEARESTMV mode.
    // TODO(jingning): Unify the two syntax decoding loops after the NEARESTMV
    // mode is factored in.
271
    for (int idx = 1; idx < 3; ++idx) {
272
      if (xd->ref_mv_count[ref_frame_type] > idx + 1) {
Yaowu Xu's avatar
Yaowu Xu committed
273
        uint8_t drl_ctx = av1_drl_ctx(xd->ref_mv_stack[ref_frame_type], idx);
274 275 276 277
        int drl_idx = aom_read_symbol(r, ec_ctx->drl_cdf[drl_ctx], 2, ACCT_STR);
        mbmi->ref_mv_idx = idx + drl_idx - 1;
        if (xd->counts) ++xd->counts->drl_mode[drl_ctx][drl_idx];
        if (!drl_idx) return;
278 279 280 281 282
      }
    }
  }
}

283 284
static MOTION_MODE read_motion_mode(MACROBLOCKD *xd, MODE_INFO *mi,
                                    aom_reader *r) {
285
  MB_MODE_INFO *mbmi = &mi->mbmi;
Thomas Davies's avatar
Thomas Davies committed
286

Zoe Liu's avatar
Zoe Liu committed
287 288 289 290
#if CONFIG_EXT_SKIP
  if (mbmi->skip_mode) return SIMPLE_TRANSLATION;
#endif  // CONFIG_EXT_SKIP

291
  const MOTION_MODE last_motion_mode_allowed =
Luc Trudeau's avatar
Luc Trudeau committed
292
      motion_mode_allowed(xd->global_motion, xd, mi);
Yue Chen's avatar
Yue Chen committed
293 294
  int motion_mode;
  FRAME_COUNTS *counts = xd->counts;
Yaowu Xu's avatar
Yaowu Xu committed
295

Yue Chen's avatar
Yue Chen committed
296
  if (last_motion_mode_allowed == SIMPLE_TRANSLATION) return SIMPLE_TRANSLATION;
Yue Chen's avatar
Yue Chen committed
297

Yue Chen's avatar
Yue Chen committed
298
  if (last_motion_mode_allowed == OBMC_CAUSAL) {
299 300
    motion_mode =
        aom_read_symbol(r, xd->tile_ctx->obmc_cdf[mbmi->sb_type], 2, ACCT_STR);
Yue Chen's avatar
Yue Chen committed
301 302 303
    if (counts) ++counts->obmc[mbmi->sb_type][motion_mode];
    return (MOTION_MODE)(SIMPLE_TRANSLATION + motion_mode);
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
304
    motion_mode =
Thomas Davies's avatar
Thomas Davies committed
305 306
        aom_read_symbol(r, xd->tile_ctx->motion_mode_cdf[mbmi->sb_type],
                        MOTION_MODES, ACCT_STR);
Yaowu Xu's avatar
Yaowu Xu committed
307 308 309 310
    if (counts) ++counts->motion_mode[mbmi->sb_type][motion_mode];
    return (MOTION_MODE)(SIMPLE_TRANSLATION + motion_mode);
  }
}
311

Yaowu Xu's avatar
Yaowu Xu committed
312 313
static PREDICTION_MODE read_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
                                                aom_reader *r, int16_t ctx) {
314 315 316 317
  (void)cm;
  const int mode =
      aom_read_symbol(r, xd->tile_ctx->inter_compound_mode_cdf[ctx],
                      INTER_COMPOUND_MODES, ACCT_STR);
318
  FRAME_COUNTS *counts = xd->counts;
319
  if (counts) ++counts->inter_compound_mode[ctx][mode];
320 321 322
  assert(is_inter_compound_mode(NEAREST_NEARESTMV + mode));
  return NEAREST_NEARESTMV + mode;
}
323

324
#if CONFIG_SPATIAL_SEGMENTATION
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
static int neg_deinterleave(int diff, int ref, int max) {
  if (!ref) return diff;
  if (ref >= (max - 1)) return max - diff - 1;
  if (2 * ref < max) {
    if (diff <= 2 * ref) {
      if (diff & 1)
        return ref + ((diff + 1) >> 1);
      else
        return ref - (diff >> 1);
    }
    return diff;
  } else {
    if (diff <= 2 * (max - ref - 1)) {
      if (diff & 1)
        return ref + ((diff + 1) >> 1);
      else
        return ref - (diff >> 1);
    }
    return max - (diff + 1);
  }
}

347 348
static int read_segment_id(AV1_COMMON *const cm, MACROBLOCKD *const xd,
                           int mi_row, int mi_col, aom_reader *r, int skip) {
349 350 351 352 353 354 355 356 357 358 359 360
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  struct segmentation_probs *const segp = &ec_ctx->seg;
  int prev_ul = 0; /* Top left segment_id */
  int prev_l = 0;  /* Current left segment_id */
  int prev_u = 0;  /* Current top segment_id */

  MODE_INFO *const mi = cm->mi + mi_row * cm->mi_stride + mi_col;
  int tinfo = mi->mbmi.boundary_info;
  int above = (!(tinfo & TILE_ABOVE_BOUNDARY)) && ((mi_row - 1) >= 0);
  int left = (!(tinfo & TILE_LEFT_BOUNDARY)) && ((mi_col - 1) >= 0);

  if (above && left)
361 362
    prev_ul = get_segment_id(cm, cm->current_frame_seg_map, BLOCK_4X4,
                             mi_row - 1, mi_col - 1);
363 364

  if (above)
365 366
    prev_u = get_segment_id(cm, cm->current_frame_seg_map, BLOCK_4X4,
                            mi_row - 1, mi_col - 0);
367 368

  if (left)
369 370
    prev_l = get_segment_id(cm, cm->current_frame_seg_map, BLOCK_4X4,
                            mi_row - 0, mi_col - 1);
371

372 373
  int cdf_num = pick_spatial_seg_cdf(prev_ul, prev_u, prev_l);
  int pred = pick_spatial_seg_pred(prev_ul, prev_u, prev_l);
374

375
  if (skip) return pred;
376

377
  aom_cdf_prob *pred_cdf = segp->spatial_pred_seg_cdf[cdf_num];
378 379
  int coded_id = aom_read_symbol(r, pred_cdf, 8, ACCT_STR);

380
  int segment_id = neg_deinterleave(coded_id, pred, cm->last_active_segid + 1);
381

382
  assert(segment_id >= 0 && segment_id <= cm->last_active_segid);
383 384 385

  return segment_id;
}
386 387 388 389
#else
static int read_segment_id(aom_reader *r, struct segmentation_probs *segp) {
  return aom_read_symbol(r, segp->tree_cdf, MAX_SEGMENTS, ACCT_STR);
}
390 391
#endif

Yaowu Xu's avatar
Yaowu Xu committed
392
static void read_tx_size_vartx(AV1_COMMON *cm, MACROBLOCKD *xd,
393
                               MB_MODE_INFO *mbmi, FRAME_COUNTS *counts,
394 395
                               TX_SIZE tx_size, int depth, int blk_row,
                               int blk_col, aom_reader *r) {
396 397
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
398
  int is_split = 0;
399 400
  const int tx_row = blk_row >> 1;
  const int tx_col = blk_col >> 1;
401 402
  const int max_blocks_high = max_block_high(xd, mbmi->sb_type, 0);
  const int max_blocks_wide = max_block_wide(xd, mbmi->sb_type, 0);
403 404
  int ctx = txfm_partition_context(xd->above_txfm_context + blk_col,
                                   xd->left_txfm_context + blk_row,
405
                                   mbmi->sb_type, tx_size);
clang-format's avatar
clang-format committed
406
  TX_SIZE(*const inter_tx_size)
407 408 409
  [MAX_MIB_SIZE] =
      (TX_SIZE(*)[MAX_MIB_SIZE]) & mbmi->inter_tx_size[tx_row][tx_col];
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
David Barker's avatar
David Barker committed
410
  assert(tx_size > TX_4X4);
411

Jingning Han's avatar
Jingning Han committed
412
  if (depth == MAX_VARTX_DEPTH) {
413 414
    int idx, idy;
    inter_tx_size[0][0] = tx_size;
415 416
    for (idy = 0; idy < AOMMAX(1, tx_size_high_unit[tx_size] / 2); ++idy)
      for (idx = 0; idx < AOMMAX(1, tx_size_wide_unit[tx_size] / 2); ++idx)
417 418
        inter_tx_size[idy][idx] = tx_size;
    mbmi->tx_size = tx_size;
419
    mbmi->min_tx_size = TXSIZEMIN(mbmi->min_tx_size, tx_size);
420 421
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
422 423 424
    return;
  }

425
  is_split = aom_read_symbol(r, ec_ctx->txfm_partition_cdf[ctx], 2, ACCT_STR);
426 427

  if (is_split) {
428
    const TX_SIZE sub_txs = sub_tx_size_map[1][tx_size];
429 430
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
431

432
    if (counts) ++counts->txfm_partition[ctx][1];
433

David Barker's avatar
David Barker committed
434
    if (sub_txs == TX_4X4) {
435
      int idx, idy;
436
      inter_tx_size[0][0] = sub_txs;
437 438
      for (idy = 0; idy < AOMMAX(1, tx_size_high_unit[tx_size] / 2); ++idy)
        for (idx = 0; idx < AOMMAX(1, tx_size_wide_unit[tx_size] / 2); ++idx)
439
          inter_tx_size[idy][idx] = inter_tx_size[0][0];
440
      mbmi->tx_size = sub_txs;
441
      mbmi->min_tx_size = mbmi->tx_size;
442 443
      txfm_partition_update(xd->above_txfm_context + blk_col,
                            xd->left_txfm_context + blk_row, sub_txs, tx_size);
444 445 446
      return;
    }

447 448 449 450 451 452 453 454
    assert(bsw > 0 && bsh > 0);
    for (int row = 0; row < tx_size_high_unit[tx_size]; row += bsh) {
      for (int col = 0; col < tx_size_wide_unit[tx_size]; col += bsw) {
        int offsetr = blk_row + row;
        int offsetc = blk_col + col;
        read_tx_size_vartx(cm, xd, mbmi, counts, sub_txs, depth + 1, offsetr,
                           offsetc, r);
      }
455 456
    }
  } else {
457
    int idx, idy;
458
    inter_tx_size[0][0] = tx_size;
459 460
    for (idy = 0; idy < AOMMAX(1, tx_size_high_unit[tx_size] / 2); ++idy)
      for (idx = 0; idx < AOMMAX(1, tx_size_wide_unit[tx_size] / 2); ++idx)
461 462
        inter_tx_size[idy][idx] = tx_size;
    mbmi->tx_size = tx_size;
463
    mbmi->min_tx_size = TXSIZEMIN(mbmi->min_tx_size, tx_size);
464
    if (counts) ++counts->txfm_partition[ctx][0];
465 466
    txfm_partition_update(xd->above_txfm_context + blk_col,
                          xd->left_txfm_context + blk_row, tx_size, tx_size);
467 468 469
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
470
static TX_SIZE read_selected_tx_size(AV1_COMMON *cm, MACROBLOCKD *xd,
471 472 473 474
                                     int is_inter, aom_reader *r) {
  // TODO(debargha): Clean up the logic here. This function should only
  // be called for intra.
  const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
475
  const int32_t tx_size_cat = bsize_to_tx_size_cat(bsize, is_inter);
476
  const int max_depths = bsize_to_max_depth(bsize, 0);
Jingning Han's avatar
Jingning Han committed
477
  const int ctx = get_tx_size_context(xd);
478 479 480
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;

481
  const int depth = aom_read_symbol(r, ec_ctx->tx_size_cdf[tx_size_cat][ctx],
482 483
                                    max_depths + 1, ACCT_STR);
  assert(depth >= 0 && depth <= max_depths);
484
  const TX_SIZE tx_size = depth_to_tx_size(depth, bsize, 0);
485
  return tx_size;
Jingning Han's avatar
Jingning Han committed
486 487
}

488 489 490 491
static TX_SIZE read_tx_size(AV1_COMMON *cm, MACROBLOCKD *xd, int is_inter,
                            int allow_select_inter, aom_reader *r) {
  const TX_MODE tx_mode = cm->tx_mode;
  const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
492
  if (xd->lossless[xd->mi[0]->mbmi.segment_id]) return TX_4X4;
493 494

  if (block_signals_txsize(bsize)) {
495
    if ((!is_inter || allow_select_inter) && tx_mode == TX_MODE_SELECT) {
496
      const TX_SIZE coded_tx_size = read_selected_tx_size(cm, xd, is_inter, r);
497
      return coded_tx_size;
498
    } else {
499
      return tx_size_from_tx_mode(bsize, tx_mode, is_inter);
500 501
    }
  } else {
Debargha Mukherjee's avatar
Debargha Mukherjee committed
502
    assert(IMPLIES(tx_mode == ONLY_4X4, bsize == BLOCK_4X4));
503
    return get_max_rect_tx_size(bsize, is_inter);
504
  }
Jingning Han's avatar
Jingning Han committed
505 506
}

Yaowu Xu's avatar
Yaowu Xu committed
507
static int dec_get_segment_id(const AV1_COMMON *cm, const uint8_t *segment_ids,
Jingning Han's avatar
Jingning Han committed
508
                              int mi_offset, int x_mis, int y_mis) {
509
  int segment_id = INT_MAX;
Jingning Han's avatar
Jingning Han committed
510

511 512
  for (int y = 0; y < y_mis; y++)
    for (int x = 0; x < x_mis; x++)
513
      segment_id =
Yaowu Xu's avatar
Yaowu Xu committed
514
          AOMMIN(segment_id, segment_ids[mi_offset + y * cm->mi_cols + x]);
Jingning Han's avatar
Jingning Han committed
515 516 517 518 519

  assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
  return segment_id;
}

Yaowu Xu's avatar
Yaowu Xu committed
520
static void set_segment_id(AV1_COMMON *cm, int mi_offset, int x_mis, int y_mis,
521
                           int segment_id) {
Jingning Han's avatar
Jingning Han committed
522 523
  assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);

524 525
  for (int y = 0; y < y_mis; y++)
    for (int x = 0; x < x_mis; x++)
Jingning Han's avatar
Jingning Han committed
526 527 528
      cm->current_frame_seg_map[mi_offset + y * cm->mi_cols + x] = segment_id;
}

Yaowu Xu's avatar
Yaowu Xu committed
529
static int read_intra_segment_id(AV1_COMMON *const cm, MACROBLOCKD *const xd,
530 531
                                 MB_MODE_INFO *const mbmi, int mi_row,
                                 int mi_col, int bsize, int preskip,
Yaowu Xu's avatar
Yaowu Xu committed
532
                                 aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
533
  struct segmentation *const seg = &cm->seg;
534 535 536 537 538
  const int mi_offset = mi_row * cm->mi_cols + mi_col;
  const int bw = mi_size_wide[bsize];
  const int bh = mi_size_high[bsize];
  const int x_mis = AOMMIN(cm->mi_cols - mi_col, bw);
  const int y_mis = AOMMIN(cm->mi_rows - mi_row, bh);
Jingning Han's avatar
Jingning Han committed
539

540
  if (!seg->enabled) return 0;  // Default for disabled segmentation
Jingning Han's avatar
Jingning Han committed
541

542
  assert(seg->update_map && !seg->temporal_update);
Jingning Han's avatar
Jingning Han committed
543

544 545 546 547 548 549
#if CONFIG_SPATIAL_SEGMENTATION
  if (preskip) {
    if (!cm->preskip_segid) return 0;
  } else {
    if (cm->preskip_segid) return mbmi->segment_id;
  }
550
  const int segment_id =
551 552 553 554 555
      read_segment_id(cm, xd, mi_row, mi_col, r, preskip ? 0 : mbmi->skip);
#else
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)preskip;
  (void)mbmi;
556
  const int segment_id = read_segment_id(r, &ec_ctx->seg);
557
#endif
558
  FRAME_COUNTS *counts = xd->counts;
559
  if (counts) ++counts->seg.tree_total[segment_id];
Jingning Han's avatar
Jingning Han committed
560 561 562 563
  set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
  return segment_id;
}

Yaowu Xu's avatar
Yaowu Xu committed
564
static void copy_segment_id(const AV1_COMMON *cm,
565 566 567
                            const uint8_t *last_segment_ids,
                            uint8_t *current_segment_ids, int mi_offset,
                            int x_mis, int y_mis) {
568 569
  for (int y = 0; y < y_mis; y++)
    for (int x = 0; x < x_mis; x++)
570 571 572
      current_segment_ids[mi_offset + y * cm->mi_cols + x] =
          last_segment_ids ? last_segment_ids[mi_offset + y * cm->mi_cols + x]
                           : 0;
573 574
}

Yaowu Xu's avatar
Yaowu Xu committed
575
static int read_inter_segment_id(AV1_COMMON *const cm, MACROBLOCKD *const xd,
576 577
                                 int mi_row, int mi_col, int preskip,
                                 aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
578
  struct segmentation *const seg = &cm->seg;
579
  FRAME_COUNTS *counts = xd->counts;
580 581 582
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  struct segmentation_probs *const segp = &ec_ctx->seg;

Jingning Han's avatar
Jingning Han committed
583 584 585
  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  int predicted_segment_id, segment_id;
  const int mi_offset = mi_row * cm->mi_cols + mi_col;
586 587
  const int bw = mi_size_wide[mbmi->sb_type];
  const int bh = mi_size_high[mbmi->sb_type];
Jingning Han's avatar
Jingning Han committed
588 589

  // TODO(slavarnway): move x_mis, y_mis into xd ?????
Yaowu Xu's avatar
Yaowu Xu committed
590 591
  const int x_mis = AOMMIN(cm->mi_cols - mi_col, bw);
  const int y_mis = AOMMIN(cm->mi_rows - mi_row, bh);
Jingning Han's avatar
Jingning Han committed
592

593
  if (!seg->enabled) return 0;  // Default for disabled segmentation
Jingning Han's avatar
Jingning Han committed
594

595 596 597 598
  predicted_segment_id = cm->last_frame_seg_map
                             ? dec_get_segment_id(cm, cm->last_frame_seg_map,
                                                  mi_offset, x_mis, y_mis)
                             : 0;
Jingning Han's avatar
Jingning Han committed
599 600 601 602 603 604 605

  if (!seg->update_map) {
    copy_segment_id(cm, cm->last_frame_seg_map, cm->current_frame_seg_map,
                    mi_offset, x_mis, y_mis);
    return predicted_segment_id;
  }

606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
#if CONFIG_SPATIAL_SEGMENTATION
  if (preskip) {
    if (!cm->preskip_segid) return 0;
  } else {
    if (cm->preskip_segid) return mbmi->segment_id;
    if (mbmi->skip) {
      if (seg->temporal_update) {
        const int ctx = av1_get_pred_context_seg_id(xd);
        mbmi->seg_id_predicted = 0;
        if (counts) ++counts->seg.pred[ctx][mbmi->seg_id_predicted];
      }
      segment_id = read_segment_id(cm, xd, mi_row, mi_col, r, 0);
      if (counts) ++counts->seg.tree_total[segment_id];
      set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
      return segment_id;
    }
  }
#endif
  (void)preskip;
Jingning Han's avatar
Jingning Han committed
625
  if (seg->temporal_update) {
Yaowu Xu's avatar
Yaowu Xu committed
626
    const int ctx = av1_get_pred_context_seg_id(xd);
627 628
    aom_cdf_prob *pred_cdf = segp->pred_cdf[ctx];
    mbmi->seg_id_predicted = aom_read_symbol(r, pred_cdf, 2, ACCT_STR);
629
    if (counts) ++counts->seg.pred[ctx][mbmi->seg_id_predicted];
630 631 632
    if (mbmi->seg_id_predicted) {
      segment_id = predicted_segment_id;
    } else {
633 634 635
#if CONFIG_SPATIAL_SEGMENTATION
      segment_id = read_segment_id(cm, xd, mi_row, mi_col, r, 0);
#else
636
      segment_id = read_segment_id(r, segp);
637
#endif
638
      if (counts) ++counts->seg.tree_mispred[segment_id];
639
    }
Jingning Han's avatar
Jingning Han committed
640
  } else {
641 642 643
#if CONFIG_SPATIAL_SEGMENTATION
    segment_id = read_segment_id(cm, xd, mi_row, mi_col, r, 0);
#else
644
    segment_id = read_segment_id(r, segp);
645
#endif
646
    if (counts) ++counts->seg.tree_total[segment_id];
Jingning Han's avatar
Jingning Han committed
647 648 649 650 651
  }
  set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
  return segment_id;
}

Zoe Liu's avatar
Zoe Liu committed
652 653 654
#if CONFIG_EXT_SKIP
static int read_skip_mode(AV1_COMMON *cm, const MACROBLOCKD *xd, int segment_id,
                          aom_reader *r) {
Zoe Liu's avatar
Zoe Liu committed
655
  if (!cm->skip_mode_flag) return 0;
Zoe Liu's avatar
Zoe Liu committed
656 657 658 659 660

  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    // TODO(zoeliu): To revisit the handling of this scenario.
    return 0;
  }
Zoe Liu's avatar
Zoe Liu committed
661 662 663 664 665 666 667 668 669 670 671

  if (!is_comp_ref_allowed(xd->mi[0]->mbmi.sb_type)) return 0;

  const int ctx = av1_get_skip_mode_context(xd);
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  const int skip_mode =
      aom_read_symbol(r, ec_ctx->skip_mode_cdfs[ctx], 2, ACCT_STR);
  FRAME_COUNTS *counts = xd->counts;
  if (counts) ++counts->skip_mode[ctx][skip_mode];

  return skip_mode;
Zoe Liu's avatar
Zoe Liu committed
672 673 674
}
#endif  // CONFIG_EXT_SKIP

Yaowu Xu's avatar
Yaowu Xu committed
675 676
static int read_skip(AV1_COMMON *cm, const MACROBLOCKD *xd, int segment_id,
                     aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
677 678 679
  if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
680
    const int ctx = av1_get_skip_context(xd);
681 682
    FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
    const int skip = aom_read_symbol(r, ec_ctx->skip_cdfs[ctx], 2, ACCT_STR);
Jingning Han's avatar
Jingning Han committed
683
    FRAME_COUNTS *counts = xd->counts;
684
    if (counts) ++counts->skip[ctx][skip];
Jingning Han's avatar
Jingning Han committed
685 686 687 688
    return skip;
  }
}

689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
// Merge the sorted list of cached colors(cached_colors[0...n_cached_colors-1])
// and the sorted list of transmitted colors(colors[n_cached_colors...n-1]) into
// one single sorted list(colors[...]).
static void merge_colors(uint16_t *colors, uint16_t *cached_colors,
                         int n_colors, int n_cached_colors) {
  if (n_cached_colors == 0) return;
  int cache_idx = 0, trans_idx = n_cached_colors;
  for (int i = 0; i < n_colors; ++i) {
    if (cache_idx < n_cached_colors &&
        (trans_idx >= n_colors ||
         cached_colors[cache_idx] <= colors[trans_idx])) {
      colors[i] = cached_colors[cache_idx++];
    } else {
      assert(trans_idx < n_colors);
      colors[i] = colors[trans_idx++];
    }
  }
706 707 708 709 710
}

static void read_palette_colors_y(MACROBLOCKD *const xd, int bit_depth,
                                  PALETTE_MODE_INFO *const pmi, aom_reader *r) {
  uint16_t color_cache[2 * PALETTE_MAX_SIZE];
711
  uint16_t cached_colors[PALETTE_MAX_SIZE];
712
  const int n_cache = av1_get_palette_cache(xd, 0, color_cache);
713 714 715
  const int n = pmi->palette_size[0];
  int idx = 0;
  for (int i = 0; i < n_cache && idx < n; ++i)
716
    if (aom_read_bit(r, ACCT_STR)) cached_colors[idx++] = color_cache[i];
717
  if (idx < n) {
718
    const int n_cached_colors = idx;
719 720 721 722 723 724
    pmi->palette_colors[idx++] = aom_read_literal(r, bit_depth, ACCT_STR);
    if (idx < n) {
      const int min_bits = bit_depth - 3;
      int bits = min_bits + aom_read_literal(r, 2, ACCT_STR);
      int range = (1 << bit_depth) - pmi->palette_colors[idx - 1] - 1;
      for (; idx < n; ++idx) {
725
        assert(range >= 0);
726
        const int delta = aom_read_literal(r, bits, ACCT_STR) + 1;
727 728 729
        pmi->palette_colors[idx] = clamp(pmi->palette_colors[idx - 1] + delta,
                                         0, (1 << bit_depth) - 1);
        range -= (pmi->palette_colors[idx] - pmi->palette_colors[idx - 1]);
730 731 732
        bits = AOMMIN(bits, av1_ceil_log2(range));
      }
    }
733 734 735
    merge_colors(pmi->palette_colors, cached_colors, n, n_cached_colors);
  } else {
    memcpy(pmi->palette_colors, cached_colors, n * sizeof(cached_colors[0]));
736 737 738 739 740 741 742 743 744
  }
}

static void read_palette_colors_uv(MACROBLOCKD *const xd, int bit_depth,
                                   PALETTE_MODE_INFO *const pmi,
                                   aom_reader *r) {
  const int n = pmi->palette_size[1];
  // U channel colors.
  uint16_t color_cache[2 * PALETTE_MAX_SIZE];
745
  uint16_t cached_colors[PALETTE_MAX_SIZE];
746
  const int n_cache = av1_get_palette_cache(xd, 1, color_cache);
747 748 749 750 751 752
  int idx = 0;
  for (int i = 0; i < n_cache && idx < n; ++i)
    if (aom_read_bit(r, ACCT_STR)) cached_colors[idx++] = color_cache[i];
  if (idx < n) {
    const int n_cached_colors = idx;
    idx += PALETTE_MAX_SIZE;
753 754 755 756 757 758
    pmi->palette_colors[idx++] = aom_read_literal(r, bit_depth, ACCT_STR);
    if (idx < PALETTE_MAX_SIZE + n) {
      const int min_bits = bit_depth - 3;
      int bits = min_bits + aom_read_literal(r, 2, ACCT_STR);
      int range = (1 << bit_depth) - pmi->palette_colors[idx - 1];
      for (; idx < PALETTE_MAX_SIZE + n; ++idx) {
759
        assert(range >= 0);
760
        const int delta = aom_read_literal(r, bits, ACCT_STR);
761 762 763
        pmi->palette_colors[idx] = clamp(pmi->palette_colors[idx - 1] + delta,
                                         0, (1 << bit_depth) - 1);
        range -= (pmi->palette_colors[idx] - pmi->palette_colors[idx - 1]);
764 765 766
        bits = AOMMIN(bits, av1_ceil_log2(range));
      }
    }
767 768 769 770 771
    merge_colors(pmi->palette_colors + PALETTE_MAX_SIZE, cached_colors, n,
                 n_cached_colors);
  } else {
    memcpy(pmi->palette_colors + PALETTE_MAX_SIZE, cached_colors,
           n * sizeof(cached_colors[0]));
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
  }

  // V channel colors.
  if (aom_read_bit(r, ACCT_STR)) {  // Delta encoding.
    const int min_bits_v = bit_depth - 4;
    const int max_val = 1 << bit_depth;
    int bits = min_bits_v + aom_read_literal(r, 2, ACCT_STR);
    pmi->palette_colors[2 * PALETTE_MAX_SIZE] =
        aom_read_literal(r, bit_depth, ACCT_STR);
    for (int i = 1; i < n; ++i) {
      int delta = aom_read_literal(r, bits, ACCT_STR);
      if (delta && aom_read_bit(r, ACCT_STR)) delta = -delta;
      int val = (int)pmi->palette_colors[2 * PALETTE_MAX_SIZE + i - 1] + delta;
      if (val < 0) val += max_val;
      if (val >= max_val) val -= max_val;
      pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] = val;
    }
  } else {
    for (int i = 0; i < n; ++i) {
      pmi->palette_colors[2 * PALETTE_MAX_SIZE + i] =
          aom_read_literal(r, bit_depth, ACCT_STR);
    }
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
797
static void read_palette_mode_info(AV1_COMMON *const cm, MACROBLOCKD *const xd,
798
                                   int mi_row, int mi_col, aom_reader *r) {
hui su's avatar
hui su committed
799 800
  MODE_INFO *const mi = xd->mi[0];
  MB_MODE_INFO *const mbmi = &mi->mbmi;
801
  const MODE_INFO *const above_mi = xd->above_mi;
802
  const MODE_INFO *const left_mi = xd->left_mi;
hui su's avatar
hui su committed
803
  const BLOCK_SIZE bsize = mbmi->sb_type;
804
  assert(av1_allow_palette(cm->allow_screen_content_tools, bsize));
805
  PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
Hui Su's avatar
Hui Su committed
806
  const int bsize_ctx = av1_get_palette_bsize_ctx(bsize);
807

808
  if (mbmi->mode == DC_PRED) {
809
    int palette_y_mode_ctx = 0;
810
    if (above_mi) {
811 812
      palette_y_mode_ctx +=
          (above_mi->mbmi.palette_mode_info.palette_size[0] > 0);
813 814
    }
    if (left_mi) {
815 816
      palette_y_mode_ctx +=
          (left_mi->mbmi.palette_mode_info.palette_size[0] > 0);
817
    }
818
    const int modev = aom_read_symbol(
Hui Su's avatar
Hui Su committed
819 820
        r, xd->tile_ctx->palette_y_mode_cdf[bsize_ctx][palette_y_mode_ctx], 2,
        ACCT_STR);
821
    if (modev) {
822
      pmi->palette_size[0] =
Hui Su's avatar
Hui Su committed
823
          aom_read_symbol(r, xd->tile_ctx->palette_y_size_cdf[bsize_ctx],
824 825
                          PALETTE_SIZES, ACCT_STR) +
          2;
826
      read_palette_colors_y(xd, cm->bit_depth, pmi, r);