OSUOSL/Nero are experiencing Internet connectivity problems. This affects us as we're hosted with OSUOSL. We apologize for the inconvenience.

decodeframe.c 150 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
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 14
 */

#include <assert.h>
#include <stdlib.h>  // qsort()

15 16 17
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
#include "./aom_scale_rtcd.h"
Jingning Han's avatar
Jingning Han committed
18
#include "./av1_rtcd.h"
Jingning Han's avatar
Jingning Han committed
19

20
#include "aom/aom_codec.h"
21
#include "aom_dsp/aom_dsp_common.h"
22
#include "aom_dsp/binary_codes_reader.h"
Jingning Han's avatar
Jingning Han committed
23 24
#include "aom_dsp/bitreader.h"
#include "aom_dsp/bitreader_buffer.h"
25
#include "aom_mem/aom_mem.h"
26 27
#include "aom_ports/mem.h"
#include "aom_ports/mem_ops.h"
28 29
#include "aom_scale/aom_scale.h"
#include "aom_util/aom_thread.h"
Jingning Han's avatar
Jingning Han committed
30

31 32 33 34
#if CONFIG_BITSTREAM_DEBUG
#include "aom_util/debug_util.h"
#endif  // CONFIG_BITSTREAM_DEBUG

35
#include "av1/common/alloccommon.h"
36
#if CONFIG_CDEF
37
#include "av1/common/cdef.h"
38
#endif
39 40 41
#if CONFIG_INSPECTION
#include "av1/decoder/inspection.h"
#endif
42 43 44
#include "av1/common/common.h"
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
45
#include "av1/common/entropymv.h"
46
#include "av1/common/idct.h"
47
#include "av1/common/mvref_common.h"
48 49 50
#include "av1/common/pred_common.h"
#include "av1/common/quant_common.h"
#include "av1/common/reconinter.h"
Jingning Han's avatar
Jingning Han committed
51
#include "av1/common/reconintra.h"
52 53 54
#if CONFIG_FRAME_SUPERRES
#include "av1/common/resize.h"
#endif  // CONFIG_FRAME_SUPERRES
55
#include "av1/common/seg_common.h"
Jingning Han's avatar
Jingning Han committed
56
#include "av1/common/thread_common.h"
57
#include "av1/common/tile_common.h"
58

59 60 61
#include "av1/decoder/decodeframe.h"
#include "av1/decoder/decodemv.h"
#include "av1/decoder/decoder.h"
62 63 64
#if CONFIG_LV_MAP
#include "av1/decoder/decodetxb.h"
#endif
Jingning Han's avatar
Jingning Han committed
65
#include "av1/decoder/detokenize.h"
66
#include "av1/decoder/dsubexp.h"
67
#include "av1/decoder/symbolrate.h"
Jingning Han's avatar
Jingning Han committed
68

Yue Chen's avatar
Yue Chen committed
69 70
#include "av1/common/warped_motion.h"

71
#define MAX_AV1_HEADER_SIZE 80
Michael Bebenita's avatar
Michael Bebenita committed
72
#define ACCT_STR __func__
Jingning Han's avatar
Jingning Han committed
73

74 75 76 77
#if CONFIG_CFL
#include "av1/common/cfl.h"
#endif

78 79 80 81
#if CONFIG_STRIPED_LOOP_RESTORATION && !CONFIG_LOOP_RESTORATION
#error "striped_loop_restoration requires loop_restoration"
#endif

82 83 84 85 86 87 88
#if CONFIG_LOOP_RESTORATION
static void loop_restoration_read_sb_coeffs(const AV1_COMMON *const cm,
                                            MACROBLOCKD *xd,
                                            aom_reader *const r, int plane,
                                            int rtile_idx);
#endif

89 90 91 92 93 94 95 96
static struct aom_read_bit_buffer *init_read_bit_buffer(
    AV1Decoder *pbi, struct aom_read_bit_buffer *rb, const uint8_t *data,
    const uint8_t *data_end, uint8_t clear_data[MAX_AV1_HEADER_SIZE]);
static int read_compressed_header(AV1Decoder *pbi, const uint8_t *data,
                                  size_t partition_size);
static size_t read_uncompressed_header(AV1Decoder *pbi,
                                       struct aom_read_bit_buffer *rb);

97
static int is_compound_reference_allowed(const AV1_COMMON *cm) {
98
#if CONFIG_ONE_SIDED_COMPOUND  // Normative in decoder
99 100
  return !frame_is_intra_only(cm);
#else
Jingning Han's avatar
Jingning Han committed
101
  int i;
102
  if (frame_is_intra_only(cm)) return 0;
103
  for (i = 1; i < INTER_REFS_PER_FRAME; ++i)
104
    if (cm->ref_frame_sign_bias[i + 1] != cm->ref_frame_sign_bias[1]) return 1;
Jingning Han's avatar
Jingning Han committed
105 106

  return 0;
107
#endif  // CONFIG_ONE_SIDED_COMPOUND
Jingning Han's avatar
Jingning Han committed
108 109
}

110
static void setup_compound_reference_mode(AV1_COMMON *cm) {
111
  cm->comp_fwd_ref[0] = LAST_FRAME;
112 113 114 115
  cm->comp_fwd_ref[1] = LAST2_FRAME;
  cm->comp_fwd_ref[2] = LAST3_FRAME;
  cm->comp_fwd_ref[3] = GOLDEN_FRAME;

116
  cm->comp_bwd_ref[0] = BWDREF_FRAME;
Zoe Liu's avatar
Zoe Liu committed
117 118
  cm->comp_bwd_ref[1] = ALTREF2_FRAME;
  cm->comp_bwd_ref[2] = ALTREF_FRAME;
Jingning Han's avatar
Jingning Han committed
119 120 121 122 123 124
}

static int read_is_valid(const uint8_t *start, size_t len, const uint8_t *end) {
  return len != 0 && len <= (size_t)(end - start);
}

125 126
static int decode_unsigned_max(struct aom_read_bit_buffer *rb, int max) {
  const int data = aom_rb_read_literal(rb, get_unsigned_bits(max));
Jingning Han's avatar
Jingning Han committed
127 128 129
  return data > max ? max : data;
}

130
static TX_MODE read_tx_mode(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
131
#if CONFIG_TX64X64
132 133
  TX_MODE tx_mode;
#endif
134
  if (cm->all_lossless) return ONLY_4X4;
135 136 137 138
#if CONFIG_VAR_TX_NO_TX_MODE
  (void)rb;
  return TX_MODE_SELECT;
#else
139 140
#if CONFIG_TX64X64
  tx_mode = aom_rb_read_bit(rb) ? TX_MODE_SELECT : aom_rb_read_literal(rb, 2);
141 142 143
  if (tx_mode == ALLOW_32X32) tx_mode += aom_rb_read_bit(rb);
  return tx_mode;
#else
144
  return aom_rb_read_bit(rb) ? TX_MODE_SELECT : aom_rb_read_literal(rb, 2);
145
#endif  // CONFIG_TX64X64
146
#endif  // CONFIG_VAR_TX_NO_TX_MODE
147
}
Jingning Han's avatar
Jingning Han committed
148

Thomas Davies's avatar
Thomas Davies committed
149
#if !CONFIG_NEW_MULTISYMBOL
150
static void read_inter_mode_probs(FRAME_CONTEXT *fc, aom_reader *r) {
151
  int i;
152
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
153
    av1_diff_update_prob(r, &fc->newmv_prob[i], ACCT_STR);
Sarah Parker's avatar
Sarah Parker committed
154
  for (i = 0; i < GLOBALMV_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
155
    av1_diff_update_prob(r, &fc->zeromv_prob[i], ACCT_STR);
156
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
157
    av1_diff_update_prob(r, &fc->refmv_prob[i], ACCT_STR);
158
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
159
    av1_diff_update_prob(r, &fc->drl_prob[i], ACCT_STR);
Jingning Han's avatar
Jingning Han committed
160
}
161
#endif
Jingning Han's avatar
Jingning Han committed
162

163
static REFERENCE_MODE read_frame_reference_mode(
164
    const AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
165
  if (is_compound_reference_allowed(cm)) {
Zoe Liu's avatar
Zoe Liu committed
166 167 168
#if CONFIG_REF_ADAPT
    return aom_rb_read_bit(rb) ? REFERENCE_MODE_SELECT : SINGLE_REFERENCE;
#else
169
    return aom_rb_read_bit(rb)
170
               ? REFERENCE_MODE_SELECT
171
               : (aom_rb_read_bit(rb) ? COMPOUND_REFERENCE : SINGLE_REFERENCE);
Zoe Liu's avatar
Zoe Liu committed
172
#endif  // CONFIG_REF_ADAPT
173 174 175 176
  } else {
    return SINGLE_REFERENCE;
  }
}
Jingning Han's avatar
Jingning Han committed
177

Thomas Davies's avatar
Thomas Davies committed
178
#if !CONFIG_NEW_MULTISYMBOL
179
static void read_frame_reference_mode_probs(AV1_COMMON *cm, aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
180
  FRAME_CONTEXT *const fc = cm->fc;
181
  int i;
Jingning Han's avatar
Jingning Han committed
182 183 184

  if (cm->reference_mode == REFERENCE_MODE_SELECT)
    for (i = 0; i < COMP_INTER_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
185
      av1_diff_update_prob(r, &fc->comp_inter_prob[i], ACCT_STR);
Jingning Han's avatar
Jingning Han committed
186

187
  if (cm->reference_mode != COMPOUND_REFERENCE) {
Jingning Han's avatar
Jingning Han committed
188
    for (i = 0; i < REF_CONTEXTS; ++i) {
189
      int j;
190
      for (j = 0; j < (SINGLE_REFS - 1); ++j) {
Michael Bebenita's avatar
Michael Bebenita committed
191
        av1_diff_update_prob(r, &fc->single_ref_prob[i][j], ACCT_STR);
192
      }
Jingning Han's avatar
Jingning Han committed
193
    }
194
  }
Jingning Han's avatar
Jingning Han committed
195

196
  if (cm->reference_mode != SINGLE_REFERENCE) {
197 198 199 200
#if CONFIG_EXT_COMP_REFS
    for (i = 0; i < COMP_REF_TYPE_CONTEXTS; ++i)
      av1_diff_update_prob(r, &fc->comp_ref_type_prob[i], ACCT_STR);

201 202
    for (i = 0; i < UNI_COMP_REF_CONTEXTS; ++i) {
      int j;
203 204
      for (j = 0; j < (UNIDIR_COMP_REFS - 1); ++j)
        av1_diff_update_prob(r, &fc->uni_comp_ref_prob[i][j], ACCT_STR);
205
    }
206 207
#endif  // CONFIG_EXT_COMP_REFS

208
    for (i = 0; i < REF_CONTEXTS; ++i) {
209
      int j;
210
      for (j = 0; j < (FWD_REFS - 1); ++j)
Michael Bebenita's avatar
Michael Bebenita committed
211
        av1_diff_update_prob(r, &fc->comp_ref_prob[i][j], ACCT_STR);
212
      for (j = 0; j < (BWD_REFS - 1); ++j)
Michael Bebenita's avatar
Michael Bebenita committed
213
        av1_diff_update_prob(r, &fc->comp_bwdref_prob[i][j], ACCT_STR);
214 215
    }
  }
Jingning Han's avatar
Jingning Han committed
216 217
}

218
static void update_mv_probs(aom_prob *p, int n, aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
219
  int i;
Michael Bebenita's avatar
Michael Bebenita committed
220
  for (i = 0; i < n; ++i) av1_diff_update_prob(r, &p[i], ACCT_STR);
Jingning Han's avatar
Jingning Han committed
221 222
}

223
static void read_mv_probs(nmv_context *ctx, int allow_hp, aom_reader *r) {
224
  int i;
Jingning Han's avatar
Jingning Han committed
225 226 227 228 229 230 231 232
  if (allow_hp) {
    for (i = 0; i < 2; ++i) {
      nmv_component *const comp_ctx = &ctx->comps[i];
      update_mv_probs(&comp_ctx->class0_hp, 1, r);
      update_mv_probs(&comp_ctx->hp, 1, r);
    }
  }
}
233
#endif
Jingning Han's avatar
Jingning Han committed
234

235
static void inverse_transform_block(MACROBLOCKD *xd, int plane,
236
#if CONFIG_LGT_FROM_PRED
Lester Lu's avatar
Lester Lu committed
237 238
                                    PREDICTION_MODE mode,
#endif
239
                                    const TX_TYPE tx_type,
240
                                    const TX_SIZE tx_size, uint8_t *dst,
241
                                    int stride, int16_t scan_line, int eob) {
Jingning Han's avatar
Jingning Han committed
242
  struct macroblockd_plane *const pd = &xd->plane[plane];
243
  tran_low_t *const dqcoeff = pd->dqcoeff;
Lester Lu's avatar
Lester Lu committed
244
  av1_inverse_transform_block(xd, dqcoeff,
245
#if CONFIG_LGT_FROM_PRED
Lester Lu's avatar
Lester Lu committed
246 247
                              mode,
#endif
Sarah Parker's avatar
Sarah Parker committed
248 249 250
#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
                              xd->mrc_mask,
#endif  // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK
251 252 253
#if CONFIG_EXT_TX
                              plane,
#endif  // CONFIG_EXT_TX
Lester Lu's avatar
Lester Lu committed
254
                              tx_type, tx_size, dst, stride, eob);
255
  memset(dqcoeff, 0, (scan_line + 1) * sizeof(dqcoeff[0]));
Jingning Han's avatar
Jingning Han committed
256 257
}

258 259 260 261 262 263
static int get_block_idx(const MACROBLOCKD *xd, int plane, int row, int col) {
  const int bsize = xd->mi[0]->mbmi.sb_type;
  const struct macroblockd_plane *pd = &xd->plane[plane];
  const BLOCK_SIZE plane_bsize =
      AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
264
  const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
265 266 267 268
  const uint8_t txh_unit = tx_size_high_unit[tx_size];
  return row * max_blocks_wide + col * txh_unit;
}

269 270 271
static void predict_and_reconstruct_intra_block(
    AV1_COMMON *cm, MACROBLOCKD *const xd, aom_reader *const r,
    MB_MODE_INFO *const mbmi, int plane, int row, int col, TX_SIZE tx_size) {
272
  PLANE_TYPE plane_type = get_plane_type(plane);
273
  const int block_idx = get_block_idx(xd, plane, row, col);
274
  av1_predict_intra_block_facade(cm, xd, plane, block_idx, col, row, tx_size);
Jingning Han's avatar
Jingning Han committed
275 276

  if (!mbmi->skip) {
277
    struct macroblockd_plane *const pd = &xd->plane[plane];
278 279
#if CONFIG_LV_MAP
    int16_t max_scan_line = 0;
280 281
    int eob;
    av1_read_coeffs_txb_facade(cm, xd, r, row, col, block_idx, plane,
282
                               pd->dqcoeff, tx_size, &max_scan_line, &eob);
283
    // tx_type will be read out in av1_read_coeffs_txb_facade
284 285
    const TX_TYPE tx_type =
        av1_get_tx_type(plane_type, xd, row, col, block_idx, tx_size);
286
#else   // CONFIG_LV_MAP
287 288
    const TX_TYPE tx_type =
        av1_get_tx_type(plane_type, xd, row, col, block_idx, tx_size);
Angie Chiang's avatar
Angie Chiang committed
289
    const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
290 291
    int16_t max_scan_line = 0;
    const int eob =
292
        av1_decode_block_tokens(cm, xd, plane, scan_order, col, row, tx_size,
293
                                tx_type, &max_scan_line, r, mbmi->segment_id);
294
#endif  // CONFIG_LV_MAP
295 296 297
    if (eob) {
      uint8_t *dst =
          &pd->dst.buf[(row * pd->dst.stride + col) << tx_size_wide_log2[0]];
Hui Su's avatar
Hui Su committed
298
      inverse_transform_block(xd, plane,
299
#if CONFIG_LGT_FROM_PRED
Lester Lu's avatar
Lester Lu committed
300
                              mbmi->mode,
Lester Lu's avatar
Lester Lu committed
301
#endif
Hui Su's avatar
Hui Su committed
302 303
                              tx_type, tx_size, dst, pd->dst.stride,
                              max_scan_line, eob);
304
    }
Jingning Han's avatar
Jingning Han committed
305
  }
306
#if CONFIG_CFL
307
  if (plane == AOM_PLANE_Y && xd->cfl->store_y) {
308
    cfl_store_tx(xd, row, col, tx_size, mbmi->sb_type);
309
  }
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
310
#endif  // CONFIG_CFL
Jingning Han's avatar
Jingning Han committed
311 312
}

Angie Chiang's avatar
Angie Chiang committed
313 314
static void decode_reconstruct_tx(AV1_COMMON *cm, MACROBLOCKD *const xd,
                                  aom_reader *r, MB_MODE_INFO *const mbmi,
315
                                  int plane, BLOCK_SIZE plane_bsize,
316 317
                                  int blk_row, int blk_col, int block,
                                  TX_SIZE tx_size, int *eob_total) {
318
  const struct macroblockd_plane *const pd = &xd->plane[plane];
319
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
320 321
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
322
  const TX_SIZE plane_tx_size =
323
      plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
324
            : mbmi->inter_tx_size[tx_row][tx_col];
325
  // Scale to match transform block unit.
326 327
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
328

329
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
330

331
  if (tx_size == plane_tx_size) {
332
    PLANE_TYPE plane_type = get_plane_type(plane);
333 334
#if CONFIG_LV_MAP
    int16_t max_scan_line = 0;
335
    int eob;
336
    av1_read_coeffs_txb_facade(cm, xd, r, blk_row, blk_col, block, plane,
337
                               pd->dqcoeff, tx_size, &max_scan_line, &eob);
338
    // tx_type will be read out in av1_read_coeffs_txb_facade
hui su's avatar
hui su committed
339
    const TX_TYPE tx_type =
340
        av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, plane_tx_size);
341
#else   // CONFIG_LV_MAP
hui su's avatar
hui su committed
342
    const TX_TYPE tx_type =
343
        av1_get_tx_type(plane_type, xd, blk_row, blk_col, block, plane_tx_size);
Angie Chiang's avatar
Angie Chiang committed
344
    const SCAN_ORDER *sc = get_scan(cm, plane_tx_size, tx_type, mbmi);
345
    int16_t max_scan_line = 0;
346 347 348
    const int eob = av1_decode_block_tokens(
        cm, xd, plane, sc, blk_col, blk_row, plane_tx_size, tx_type,
        &max_scan_line, r, mbmi->segment_id);
349
#endif  // CONFIG_LV_MAP
Lester Lu's avatar
Lester Lu committed
350
    inverse_transform_block(xd, plane,
351
#if CONFIG_LGT_FROM_PRED
Lester Lu's avatar
Lester Lu committed
352 353 354
                            mbmi->mode,
#endif
                            tx_type, plane_tx_size,
355 356 357
                            &pd->dst.buf[(blk_row * pd->dst.stride + blk_col)
                                         << tx_size_wide_log2[0]],
                            pd->dst.stride, max_scan_line, eob);
358 359
    *eob_total += eob;
  } else {
Yue Chen's avatar
Yue Chen committed
360 361 362 363 364
#if CONFIG_RECT_TX_EXT
    int is_qttx = plane_tx_size == quarter_txsize_lookup[plane_bsize];
    const TX_SIZE sub_txs = is_qttx ? plane_tx_size : sub_tx_size_map[tx_size];
    if (is_qttx) assert(blk_row == 0 && blk_col == 0 && block == 0);
#else
365
    const TX_SIZE sub_txs = sub_tx_size_map[tx_size];
366 367
    assert(IMPLIES(tx_size <= TX_4X4, sub_txs == tx_size));
    assert(IMPLIES(tx_size > TX_4X4, sub_txs < tx_size));
Yue Chen's avatar
Yue Chen committed
368
#endif
369
    const int bsl = tx_size_wide_unit[sub_txs];
370
    int sub_step = tx_size_wide_unit[sub_txs] * tx_size_high_unit[sub_txs];
371 372 373 374 375
    int i;

    assert(bsl > 0);

    for (i = 0; i < 4; ++i) {
Yue Chen's avatar
Yue Chen committed
376 377 378 379 380 381 382 383 384
#if CONFIG_RECT_TX_EXT
      int is_wide_tx = tx_size_wide_unit[sub_txs] > tx_size_high_unit[sub_txs];
      const int offsetr =
          is_qttx ? (is_wide_tx ? i * tx_size_high_unit[sub_txs] : 0)
                  : blk_row + ((i >> 1) * bsl);
      const int offsetc =
          is_qttx ? (is_wide_tx ? 0 : i * tx_size_wide_unit[sub_txs])
                  : blk_col + (i & 0x01) * bsl;
#else
385 386
      const int offsetr = blk_row + (i >> 1) * bsl;
      const int offsetc = blk_col + (i & 0x01) * bsl;
Yue Chen's avatar
Yue Chen committed
387
#endif
388

389
      if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
390

391
      decode_reconstruct_tx(cm, xd, r, mbmi, plane, plane_bsize, offsetr,
392 393
                            offsetc, block, sub_txs, eob_total);
      block += sub_step;
394 395 396
    }
  }
}
Jingning Han's avatar
Jingning Han committed
397

398 399 400
static void set_offsets(AV1_COMMON *const cm, MACROBLOCKD *const xd,
                        BLOCK_SIZE bsize, int mi_row, int mi_col, int bw,
                        int bh, int x_mis, int y_mis) {
Jingning Han's avatar
Jingning Han committed
401 402 403 404 405 406 407 408 409
  const int offset = mi_row * cm->mi_stride + mi_col;
  int x, y;
  const TileInfo *const tile = &xd->tile;

  xd->mi = cm->mi_grid_visible + offset;
  xd->mi[0] = &cm->mi[offset];
  // TODO(slavarnway): Generate sb_type based on bwl and bhl, instead of
  // passing bsize from decode_partition().
  xd->mi[0]->mbmi.sb_type = bsize;
410 411 412
#if CONFIG_RD_DEBUG
  xd->mi[0]->mbmi.mi_row = mi_row;
  xd->mi[0]->mbmi.mi_col = mi_col;
413 414 415 416
#endif
#if CONFIG_CFL
  xd->cfl->mi_row = mi_row;
  xd->cfl->mi_col = mi_col;
417
#endif
418 419 420 421 422 423 424 425

  assert(x_mis && y_mis);
  for (x = 1; x < x_mis; ++x) xd->mi[x] = xd->mi[0];
  int idx = cm->mi_stride;
  for (y = 1; y < y_mis; ++y) {
    memcpy(&xd->mi[idx], &xd->mi[0], x_mis * sizeof(xd->mi[0]));
    idx += cm->mi_stride;
  }
Jingning Han's avatar
Jingning Han committed
426

Jingning Han's avatar
Jingning Han committed
427
  set_plane_n4(xd, bw, bh);
Jingning Han's avatar
Jingning Han committed
428 429
  set_skip_context(xd, mi_row, mi_col);

430 431 432
  // Distance of Mb to the various image edges. These are specified to 8th pel
  // as they are always compared to values that are in 1/8th pel units
  set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw,
433
#if CONFIG_DEPENDENT_HORZTILES
434 435 436
                 cm->dependent_horz_tiles,
#endif  // CONFIG_DEPENDENT_HORZTILES
                 cm->mi_rows, cm->mi_cols);
Jingning Han's avatar
Jingning Han committed
437

438 439
  av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
                       mi_col);
Jingning Han's avatar
Jingning Han committed
440 441
}

442 443
static void decode_mbmi_block(AV1Decoder *const pbi, MACROBLOCKD *const xd,
                              int mi_row, int mi_col, aom_reader *r,
444
#if CONFIG_EXT_PARTITION_TYPES
445
                              PARTITION_TYPE partition,
446
#endif  // CONFIG_EXT_PARTITION_TYPES
447
                              BLOCK_SIZE bsize) {
448
  AV1_COMMON *const cm = &pbi->common;
449 450
  const int bw = mi_size_wide[bsize];
  const int bh = mi_size_high[bsize];
451 452
  const int x_mis = AOMMIN(bw, cm->mi_cols - mi_col);
  const int y_mis = AOMMIN(bh, cm->mi_rows - mi_row);
453

Michael Bebenita's avatar
Michael Bebenita committed
454 455 456
#if CONFIG_ACCOUNTING
  aom_accounting_set_context(&pbi->accounting, mi_col, mi_row);
#endif
457
  set_offsets(cm, xd, bsize, mi_row, mi_col, bw, bh, x_mis, y_mis);
458 459 460
#if CONFIG_EXT_PARTITION_TYPES
  xd->mi[0]->mbmi.partition = partition;
#endif
461
  av1_read_mode_info(pbi, xd, mi_row, mi_col, r, x_mis, y_mis);
Jingning Han's avatar
Jingning Han committed
462 463 464 465
  if (bsize >= BLOCK_8X8 && (cm->subsampling_x || cm->subsampling_y)) {
    const BLOCK_SIZE uv_subsize =
        ss_size_lookup[bsize][cm->subsampling_x][cm->subsampling_y];
    if (uv_subsize == BLOCK_INVALID)
466
      aom_internal_error(xd->error_info, AOM_CODEC_CORRUPT_FRAME,
467
                         "Invalid block size.");
Jingning Han's avatar
Jingning Han committed
468 469
  }

470 471
  int reader_corrupted_flag = aom_reader_has_error(r);
  aom_merge_corrupted_flag(&xd->corrupted, reader_corrupted_flag);
472 473
}

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
#if CONFIG_NCOBMC_ADAPT_WEIGHT
static void set_mode_info_offsets(AV1_COMMON *const cm, MACROBLOCKD *const xd,
                                  int mi_row, int mi_col) {
  const int offset = mi_row * cm->mi_stride + mi_col;
  xd->mi = cm->mi_grid_visible + offset;
  xd->mi[0] = &cm->mi[offset];
}

static void get_ncobmc_recon(AV1_COMMON *const cm, MACROBLOCKD *xd, int mi_row,
                             int mi_col, int bsize, int mode) {
  uint8_t *pred_buf[4][MAX_MB_PLANE];
  int pred_stride[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE };
  // target block in pxl
  int pxl_row = mi_row << MI_SIZE_LOG2;
  int pxl_col = mi_col << MI_SIZE_LOG2;

  int plane;
#if CONFIG_HIGHBITDEPTH
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    int len = sizeof(uint16_t);
494 495 496 497 498 499 500 501
    ASSIGN_ALIGNED_PTRS_HBD(pred_buf[0], cm->ncobmcaw_buf[0], MAX_SB_SQUARE,
                            len);
    ASSIGN_ALIGNED_PTRS_HBD(pred_buf[1], cm->ncobmcaw_buf[1], MAX_SB_SQUARE,
                            len);
    ASSIGN_ALIGNED_PTRS_HBD(pred_buf[2], cm->ncobmcaw_buf[2], MAX_SB_SQUARE,
                            len);
    ASSIGN_ALIGNED_PTRS_HBD(pred_buf[3], cm->ncobmcaw_buf[3], MAX_SB_SQUARE,
                            len);
502 503
  } else {
#endif  // CONFIG_HIGHBITDEPTH
504 505 506 507
    ASSIGN_ALIGNED_PTRS(pred_buf[0], cm->ncobmcaw_buf[0], MAX_SB_SQUARE);
    ASSIGN_ALIGNED_PTRS(pred_buf[1], cm->ncobmcaw_buf[1], MAX_SB_SQUARE);
    ASSIGN_ALIGNED_PTRS(pred_buf[2], cm->ncobmcaw_buf[2], MAX_SB_SQUARE);
    ASSIGN_ALIGNED_PTRS(pred_buf[3], cm->ncobmcaw_buf[3], MAX_SB_SQUARE);
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
#if CONFIG_HIGHBITDEPTH
  }
#endif
  av1_get_ext_blk_preds(cm, xd, bsize, mi_row, mi_col, pred_buf, pred_stride);
  av1_get_ori_blk_pred(cm, xd, bsize, mi_row, mi_col, pred_buf[3], pred_stride);
  for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
    build_ncobmc_intrpl_pred(cm, xd, plane, pxl_row, pxl_col, bsize, pred_buf,
                             pred_stride, mode);
  }
}

static void av1_get_ncobmc_recon(AV1_COMMON *const cm, MACROBLOCKD *const xd,
                                 int bsize, const int mi_row, const int mi_col,
                                 const NCOBMC_MODE modes) {
  const int mi_width = mi_size_wide[bsize];
  const int mi_height = mi_size_high[bsize];

  assert(bsize >= BLOCK_8X8);

  reset_xd_boundary(xd, mi_row, mi_height, mi_col, mi_width, cm->mi_rows,
                    cm->mi_cols);
  get_ncobmc_recon(cm, xd, mi_row, mi_col, bsize, modes);
}

static void recon_ncobmc_intrpl_pred(AV1_COMMON *const cm,
                                     MACROBLOCKD *const xd, int mi_row,
                                     int mi_col, BLOCK_SIZE bsize) {
  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  const int mi_width = mi_size_wide[bsize];
  const int mi_height = mi_size_high[bsize];
  const int hbs = AOMMAX(mi_size_wide[bsize] / 2, mi_size_high[bsize] / 2);
  const BLOCK_SIZE sqr_blk = bsize_2_sqr_bsize[bsize];
  if (mi_width > mi_height) {
    // horizontal partition
    av1_get_ncobmc_recon(cm, xd, sqr_blk, mi_row, mi_col, mbmi->ncobmc_mode[0]);
    xd->mi += hbs;
    av1_get_ncobmc_recon(cm, xd, sqr_blk, mi_row, mi_col + hbs,
                         mbmi->ncobmc_mode[1]);
  } else if (mi_height > mi_width) {
    // vertical partition
    av1_get_ncobmc_recon(cm, xd, sqr_blk, mi_row, mi_col, mbmi->ncobmc_mode[0]);
    xd->mi += hbs * xd->mi_stride;
    av1_get_ncobmc_recon(cm, xd, sqr_blk, mi_row + hbs, mi_col,
                         mbmi->ncobmc_mode[1]);
  } else {
    av1_get_ncobmc_recon(cm, xd, sqr_blk, mi_row, mi_col, mbmi->ncobmc_mode[0]);
  }
  set_mode_info_offsets(cm, xd, mi_row, mi_col);
  // restore dst buffer and mode info
  av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
                       mi_col);
}
#endif  // CONFIG_NCOBMC_ADAPT_WEIGHT

562 563 564 565 566 567 568 569 570 571
static void decode_token_and_recon_block(AV1Decoder *const pbi,
                                         MACROBLOCKD *const xd, int mi_row,
                                         int mi_col, aom_reader *r,
                                         BLOCK_SIZE bsize) {
  AV1_COMMON *const cm = &pbi->common;
  const int bw = mi_size_wide[bsize];
  const int bh = mi_size_high[bsize];
  const int x_mis = AOMMIN(bw, cm->mi_cols - mi_col);
  const int y_mis = AOMMIN(bh, cm->mi_rows - mi_row);

572 573
  set_offsets(cm, xd, bsize, mi_row, mi_col, bw, bh, x_mis, y_mis);
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
574
#if CONFIG_CFL
575 576 577
  CFL_CTX *const cfl = xd->cfl;
  cfl->is_chroma_reference = is_chroma_reference(
      mi_row, mi_col, bsize, cfl->subsampling_x, cfl->subsampling_y);
578
#endif  // CONFIG_CFL
579

580 581 582
  if (cm->delta_q_present_flag) {
    int i;
    for (i = 0; i < MAX_SEGMENTS; i++) {
Fangwen Fu's avatar
Fangwen Fu committed
583
#if CONFIG_EXT_DELTA_Q
584 585
      const int current_qindex =
          av1_get_qindex(&cm->seg, i, xd->current_qindex);
Fangwen Fu's avatar
Fangwen Fu committed
586
#else
587 588 589 590 591 592 593 594 595 596 597 598
      const int current_qindex = xd->current_qindex;
#endif  // CONFIG_EXT_DELTA_Q
      int j;
      for (j = 0; j < MAX_MB_PLANE; ++j) {
        const int dc_delta_q = j == 0 ? cm->y_dc_delta_q : cm->uv_dc_delta_q;
        const int ac_delta_q = j == 0 ? 0 : cm->uv_ac_delta_q;

        xd->plane[j].seg_dequant[i][0] =
            av1_dc_quant(current_qindex, dc_delta_q, cm->bit_depth);
        xd->plane[j].seg_dequant[i][1] =
            av1_ac_quant(current_qindex, ac_delta_q, cm->bit_depth);
      }
599 600
    }
  }
601
  if (mbmi->skip) av1_reset_skip_context(xd, mi_row, mi_col, bsize);
602

603 604
  if (!is_inter_block(mbmi)) {
    int plane;
605

606 607
    for (plane = 0; plane <= 1; ++plane) {
      if (mbmi->palette_mode_info.palette_size[plane])
608
        av1_decode_palette_tokens(xd, plane, r);
Jingning Han's avatar
Jingning Han committed
609
    }
610

611 612
    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
      const struct macroblockd_plane *const pd = &xd->plane[plane];
613
      const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
614 615
      const int stepr = tx_size_high_unit[tx_size];
      const int stepc = tx_size_wide_unit[tx_size];
616 617
      const BLOCK_SIZE plane_bsize =
          AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
618
      int row, col;
619 620
      const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
      const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
621 622
      if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
                               pd->subsampling_y))
623
        continue;
624 625 626 627 628 629 630 631 632 633
      int blk_row, blk_col;
      const BLOCK_SIZE max_unit_bsize = get_plane_block_size(BLOCK_64X64, pd);
      int mu_blocks_wide =
          block_size_wide[max_unit_bsize] >> tx_size_wide_log2[0];
      int mu_blocks_high =
          block_size_high[max_unit_bsize] >> tx_size_high_log2[0];
      mu_blocks_wide = AOMMIN(max_blocks_wide, mu_blocks_wide);
      mu_blocks_high = AOMMIN(max_blocks_high, mu_blocks_high);

      for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
634
        const int unit_height = AOMMIN(mu_blocks_high + row, max_blocks_high);
635 636 637 638 639 640 641 642 643
        for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
          const int unit_width = AOMMIN(mu_blocks_wide + col, max_blocks_wide);

          for (blk_row = row; blk_row < unit_height; blk_row += stepr)
            for (blk_col = col; blk_col < unit_width; blk_col += stepc)
              predict_and_reconstruct_intra_block(cm, xd, r, mbmi, plane,
                                                  blk_row, blk_col, tx_size);
        }
      }
644 645
    }
  } else {
646 647
    int ref;

648
#if CONFIG_COMPOUND_SINGLEREF
649 650 651
    for (ref = 0; ref < 1 + is_inter_anyref_comp_mode(mbmi->mode); ++ref)
#else
    for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref)
652
#endif  // CONFIG_COMPOUND_SINGLEREF
653
    {
654
      const MV_REFERENCE_FRAME frame =
655
#if CONFIG_COMPOUND_SINGLEREF
656 657
          has_second_ref(mbmi) ? mbmi->ref_frame[ref] : mbmi->ref_frame[0];
#else
658
          mbmi->ref_frame[ref];
659
#endif  // CONFIG_COMPOUND_SINGLEREF
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
      if (frame < LAST_FRAME) {
#if CONFIG_INTRABC
        assert(is_intrabc_block(mbmi));
        assert(frame == INTRA_FRAME);
        assert(ref == 0);
#else
        assert(0);
#endif  // CONFIG_INTRABC
      } else {
        RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];

        xd->block_refs[ref] = ref_buf;
        if ((!av1_is_valid_scale(&ref_buf->sf)))
          aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
                             "Reference frame has invalid dimensions");
        av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col,
                             &ref_buf->sf);
      }
678
    }
679

680
    av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
681

Yue Chen's avatar
Yue Chen committed
682
    if (mbmi->motion_mode == OBMC_CAUSAL) {
Yue Chen's avatar
Yue Chen committed
683 684 685
#if CONFIG_NCOBMC
      av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
#else
686
      av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
Yue Chen's avatar
Yue Chen committed
687
#endif
688
    }
689 690 691 692 693 694 695 696 697
#if CONFIG_NCOBMC_ADAPT_WEIGHT
    if (mbmi->motion_mode == NCOBMC_ADAPT_WEIGHT) {
      int plane;
      recon_ncobmc_intrpl_pred(cm, xd, mi_row, mi_col, bsize);
      for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
        get_pred_from_intrpl_buf(xd, mi_row, mi_col, bsize, plane);
      }
    }
#endif
698 699 700 701 702
    // Reconstruction
    if (!mbmi->skip) {
      int eobtotal = 0;
      int plane;

Jingning Han's avatar
Jingning Han committed
703 704
      for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
        const struct macroblockd_plane *const pd = &xd->plane[plane];
705 706
        const BLOCK_SIZE plane_bsize =
            AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
707 708
        const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
        const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
709
        int row, col;
710

711 712
        if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
                                 pd->subsampling_y))
713 714
          continue;

715 716 717 718 719 720 721 722 723
        const BLOCK_SIZE max_unit_bsize = get_plane_block_size(BLOCK_64X64, pd);
        int mu_blocks_wide =
            block_size_wide[max_unit_bsize] >> tx_size_wide_log2[0];
        int mu_blocks_high =
            block_size_high[max_unit_bsize] >> tx_size_high_log2[0];

        mu_blocks_wide = AOMMIN(max_blocks_wide, mu_blocks_wide);
        mu_blocks_high = AOMMIN(max_blocks_high, mu_blocks_high);

724 725
        const TX_SIZE max_tx_size = get_vartx_max_txsize(
            mbmi, plane_bsize, pd->subsampling_x || pd->subsampling_y);
726 727
        const int bh_var_tx = tx_size_high_unit[max_tx_size];
        const int bw_var_tx = tx_size_wide_unit[max_tx_size];
728 729 730
        int block = 0;
        int step =
            tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746

        for (row = 0; row < max_blocks_high; row += mu_blocks_high) {
          for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
            int blk_row, blk_col;
            const int unit_height =
                AOMMIN(mu_blocks_high + row, max_blocks_high);
            const int unit_width =
                AOMMIN(mu_blocks_wide + col, max_blocks_wide);
            for (blk_row = row; blk_row < unit_height; blk_row += bh_var_tx) {
              for (blk_col = col; blk_col < unit_width; blk_col += bw_var_tx) {
                decode_reconstruct_tx(cm, xd, r, mbmi, plane, plane_bsize,
                                      blk_row, blk_col, block, max_tx_size,
                                      &eobtotal);
                block += step;
              }
            }
747 748
          }
        }
749
      }
Jingning Han's avatar
Jingning Han committed
750 751
    }
  }
752
#if CONFIG_CFL
753 754 755 756 757
  if (mbmi->uv_mode != UV_CFL_PRED) {
    if (!cfl->is_chroma_reference && is_inter_block(mbmi)) {
      cfl_store_block(xd, mbmi->sb_type, mbmi->tx_size);
    }
  }
758
#endif  // CONFIG_CFL
Jingning Han's avatar
Jingning Han committed
759

760 761
  int reader_corrupted_flag = aom_reader_has_error(r);
  aom_merge_corrupted_flag(&xd->corrupted, reader_corrupted_flag);
Jingning Han's avatar
Jingning Han committed
762 763
}

764
#if NC_MODE_INFO
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
static void detoken_and_recon_sb(AV1Decoder *const pbi, MACROBLOCKD *const xd,
                                 int mi_row, int mi_col, aom_reader *r,
                                 BLOCK_SIZE bsize) {
  AV1_COMMON *const cm = &pbi->common;
  const int hbs = mi_size_wide[bsize] >> 1;
#if CONFIG_EXT_PARTITION_TYPES
  BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
#endif
  PARTITION_TYPE partition;
  BLOCK_SIZE subsize;
  const int has_rows = (mi_row + hbs) < cm->mi_rows;
  const int has_cols = (mi_col + hbs) < cm->mi_cols;

  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;

  partition = get_partition(cm, mi_row, mi_col, bsize);
  subsize = subsize_lookup[partition][bsize];

783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
  switch (partition) {
    case PARTITION_NONE:
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, bsize);
      break;
    case PARTITION_HORZ:
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, subsize);
      if (has_rows)
        decode_token_and_recon_block(pbi, xd, mi_row + hbs, mi_col, r, subsize);
      break;
    case PARTITION_VERT:
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, subsize);
      if (has_cols)
        decode_token_and_recon_block(pbi, xd, mi_row, mi_col + hbs, r, subsize);
      break;
    case PARTITION_SPLIT:
      detoken_and_recon_sb(pbi, xd, mi_row, mi_col, r, subsize);
      detoken_and_recon_sb(pbi, xd, mi_row, mi_col + hbs, r, subsize);
      detoken_and_recon_sb(pbi, xd, mi_row + hbs, mi_col, r, subsize);
      detoken_and_recon_sb(pbi, xd, mi_row + hbs, mi_col + hbs, r, subsize);
      break;
803
#if CONFIG_EXT_PARTITION_TYPES
804 805 806
#if CONFIG_EXT_PARTITION_TYPES_AB
#error NC_MODE_INFO+MOTION_VAR not yet supported for new HORZ/VERT_AB partitions
#endif
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
    case PARTITION_HORZ_A:
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, bsize2);
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col + hbs, r, bsize2);
      decode_token_and_recon_block(pbi, xd, mi_row + hbs, mi_col, r, subsize);
      break;
    case PARTITION_HORZ_B:
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, subsize);
      decode_token_and_recon_block(pbi, xd, mi_row + hbs, mi_col, r, bsize2);
      decode_token_and_recon_block(pbi, xd, mi_row + hbs, mi_col + hbs, r,
                                   bsize2);
      break;
    case PARTITION_VERT_A:
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, bsize2);
      decode_token_and_recon_block(pbi, xd, mi_row + hbs, mi_col, r, bsize2);
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col + hbs, r, subsize);
      break;
    case PARTITION_VERT_B:
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, subsize);
      decode_token_and_recon_block(pbi, xd, mi_row, mi_col + hbs, r, bsize2);
      decode_token_and_recon_block(pbi, xd, mi_row + hbs, mi_col + hbs, r,
                                   bsize2);
      break;
829
#endif
830
    default: assert(0 && "Invalid partition type");
831 832 833 834
  }
}
#endif

835 836 837 838 839 840
static void decode_block(AV1Decoder *const pbi, MACROBLOCKD *const xd,
                         int mi_row, int mi_col, aom_reader *r,
#if CONFIG_EXT_PARTITION_TYPES
                         PARTITION_TYPE partition,
#endif  // CONFIG_EXT_PARTITION_TYPES
                         BLOCK_SIZE bsize) {
841
  decode_mbmi_block(pbi, xd, mi_row, mi_col, r,
842 843 844 845
#if CONFIG_EXT_PARTITION_TYPES
                    partition,
#endif
                    bsize);
846

847
#if !(NC_MODE_INFO)
848
  decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, bsize);
849
#endif
850 851
}

852 853
static PARTITION_TYPE read_partition(AV1_COMMON *cm, MACROBLOCKD *xd,
                                     int mi_row, int mi_col, aom_reader *r,
854
                                     int has_rows, int has_cols,
855
                                     BLOCK_SIZE bsize) {
856 857 858 859
#if CONFIG_UNPOISON_PARTITION_CTX
  const int ctx =
      partition_plane_context(xd, mi_row, mi_col, has_rows, has_cols, bsize);
#else
860
  const int ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
861
#endif
Jingning Han's avatar
Jingning Han committed
862
  PARTITION_TYPE p;
863 864
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
  (void)cm;
Jingning Han's avatar
Jingning Han committed
865

Jingning Han's avatar
Jingning Han committed
866 867
  aom_cdf_prob *partition_cdf = (ctx >= 0) ? ec_ctx->partition_cdf[ctx] : NULL;

868
  if (has_rows && has_cols) {
869
#if CONFIG_EXT_PARTITION_TYPES
870 871 872 873
    const int num_partition_types =
        (mi_width_log2_lookup[bsize] > mi_width_log2_lookup[BLOCK_8X8])
            ? EXT_PARTITION_TYPES
            : PARTITION_TYPES;
874
#else
875
    const int num_partition_types = PARTITION_TYPES;
876
#endif  // CONFIG_EXT_PARTITION_TYPES
877 878
    p = (PARTITION_TYPE)aom_read_symbol(r, partition_cdf, num_partition_types,
                                        ACCT_STR);
879
  } else if (!has_rows && has_cols) {
880 881 882 883 884 885
    assert(bsize > BLOCK_8X8);
    aom_cdf_prob cdf[2];
    partition_gather_vert_alike(cdf, partition_cdf);
    assert(cdf[1] == AOM_ICDF(CDF_PROB_TOP));
    p = aom_read_cdf(r, cdf, 2, ACCT_STR) ? PARTITION_SPLIT : PARTITION_HORZ;
    // gather cols
886
  } else if (has_rows && !has_cols) {
887 888 889 890 891
    assert(bsize > BLOCK_8X8);
    aom_cdf_prob cdf[2];
    partition_gather_horz_alike(cdf, partition_cdf);
    assert(cdf[1] == AOM_ICDF(CDF_PROB_TOP));
    p = aom_read_cdf(r, cdf, 2, ACCT_STR) ? PARTITION_SPLIT : PARTITION_VERT;
892
  } else {
Jingning Han's avatar
Jingning Han committed
893
    p = PARTITION_SPLIT;
894
  }
Jingning Han's avatar
Jingning Han committed
895 896 897 898 899

  return p;
}

// TODO(slavarnway): eliminate bsize and subsize in future commits
900 901
static void decode_partition(AV1Decoder *const pbi, MACROBLOCKD *const xd,
                             int mi_row, int mi_col, aom_reader *r,
902
                             BLOCK_SIZE bsize) {
903
  AV1_COMMON *const cm = &pbi->common;
904
  const int num_8x8_wh = mi_size_wide[bsize];
Jingning Han's avatar
Jingning Han committed
905
  const int hbs = num_8x8_wh >> 1;
906 907 908
#if CONFIG_EXT_PARTITION_TYPES && CONFIG_EXT_PARTITION_TYPES_AB
  const int qbs = num_8x8_wh >> 2;
#endif
Jingning Han's avatar
Jingning Han committed
909 910
  PARTITION_TYPE partition;
  BLOCK_SIZE subsize;
911
#if CONFIG_EXT_PARTITION_TYPES
912 913
  const int quarter_step = num_8x8_wh / 4;
  int i;
914 915 916
#if !CONFIG_EXT_PARTITION_TYPES_AB
  BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
#endif
917
#endif
Jingning Han's avatar
Jingning Han committed
918 919 920
  const int has_rows = (mi_row + hbs) < cm->mi_rows;
  const int has_cols = (mi_col + hbs) < cm->mi_cols;

921
  if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
Jingning Han's avatar
Jingning Han committed
922

923 924 925
  partition = (bsize < BLOCK_8X8) ? PARTITION_NONE
                                  : read_partition(cm, xd, mi_row, mi_col, r,
                                                   has_rows, has_cols, bsize);
Jingning Han's avatar
Jingning Han committed
926
  subsize = subsize_lookup[partition][bsize];  // get_subsize(bsize, partition);
927

928 929 930 931 932 933 934 935 936
  // Check the bitstream is conformant: if there is subsampling on the
  // chroma planes, subsize must subsample to a valid block size.
  const struct macroblockd_plane *const pd_u = &xd->plane[1];
  if (get_plane_block_size(subsize, pd_u) == BLOCK_INVALID) {
    aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
                       "Block size %dx%d invalid with this subsampling mode",
                       block_size_wide[subsize], block_size_high[subsize]);
  }

937 938 939 940 941 942 943 944 945 946 947 948
#define DEC_BLOCK_STX_ARG
#if CONFIG_EXT_PARTITION_TYPES
#define DEC_BLOCK_EPT_ARG partition,
#else
#define DEC_BLOCK_EPT_ARG
#endif
#define DEC_BLOCK(db_r, db_c, db_subsize)                   \
  decode_block(pbi, xd, DEC_BLOCK_STX_ARG(db_r), (db_c), r, \
               DEC_BLOCK_EPT_ARG(db_subsize))
#define DEC_PARTITION(db_r, db_c, db_subsize) \
  decode_partition(pbi, xd, DEC_BLOCK_STX_ARG(db_r), (db_c), r, (db_subsize))

949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964
  switch (partition) {
    case PARTITION_NONE: DEC_BLOCK(mi_row, mi_col, subsize); break;
    case PARTITION_HORZ:
      DEC_BLOCK(mi_row, mi_col, subsize);
      if (has_rows) DEC_BLOCK(mi_row + hbs, mi_col, subsize);
      break;
    case PARTITION_VERT:
      DEC_BLOCK(mi_row, mi_col, subsize);
      if (has_cols) DEC_BLOCK(mi_row, mi_col + hbs, subsize);
      break;
    case PARTITION_SPLIT:
      DEC_PARTITION(mi_row, mi_col, subsize);
      DEC_PARTITION(mi_row, mi_col + hbs, subsize);
      DEC_PARTITION(mi_row + hbs, mi_col, subsize);
      DEC_PARTITION(mi_row + hbs, mi_col + hbs, subsize);
      break;
965
#if CONFIG_EXT_PARTITION_TYPES
966
#if CONFIG_EXT_PARTITION_TYPES_AB
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990
    case PARTITION_HORZ_A:
      DEC_BLOCK(mi_row, mi_col, get_subsize(bsize, PARTITION_HORZ_4));
      DEC_BLOCK(mi_row + qbs, mi_col, get_subsize(bsize, PARTITION_HORZ_4));
      DEC_BLOCK(mi_row + hbs, mi_col, subsize);
      break;
    case PARTITION_HORZ_B:
      DEC_BLOCK(mi_row, mi_col, subsize);
      DEC_BLOCK(mi_row + hbs, mi_col, get_subsize(bsize, PARTITION_HORZ_4));
      if (mi_row + 3 * qbs < cm->mi_rows)
        DEC_BLOCK(mi_row + 3 * qbs, mi_col,
                  get_subsize(bsize, PARTITION_HORZ_4));
      break;
    case PARTITION_VERT_A:
      DEC_BLOCK(mi_row, mi_col, get_subsize(bsize, PARTITION_VERT_4));
      DEC_BLOCK(mi_row, mi_col + qbs, get_subsize(bsize, PARTITION_VERT_4));
      DEC_BLOCK(mi_row, mi_col + hbs, subsize);
      break;
    case PARTITION_VERT_B:
      DEC_BLOCK(mi_row, mi_col, subsize);
      DEC_BLOCK(mi_row, mi_col + hbs, get_subsize(bsize, PARTITION_VERT_4));
      if (mi_col + 3 * qbs < cm->mi_cols)
        DEC_BLOCK(mi_row, mi_col + 3 * qbs,
                  get_subsize(bsize, PARTITION_VERT_4));
      break;
991
#else
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
    case PARTITION_HORZ_A:
      DEC_BLOCK(mi_row, mi_col, bsize2);
      DEC_BLOCK(mi_row, mi_col + hbs, bsize2);
      DEC_BLOCK(mi_row + hbs, mi_col, subsize);
      break;
    case PARTITION_HORZ_B:
      DEC_BLOCK(mi_row, mi_col, subsize);
      DEC_BLOCK(mi_row + hbs, mi_col, bsize2);
      DEC_BLOCK(mi_row + hbs, mi_col + hbs, bsize2);
      break;
    case PARTITION_VERT_A:
      DEC_BLOCK(mi_row, mi_col, bsize2);
      DEC_BLOCK(mi_row + hbs, mi_col, bsize2);
      DEC_BLOCK(mi_row, mi_col + hbs, subsize);
      break;
    case PARTITION_VERT_B:
      DEC_BLOCK(mi_row, mi_col, subsize);
      DEC_BLOCK(mi_row, mi_col + hbs, bsize2);
      DEC_BLOCK(mi_row + hbs, mi_col + hbs, bsize2);
      break;
1012
#endif
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
    case PARTITION_HORZ_4:
      for (i = 0; i < 4; ++i) {
        int this_mi_row = mi_row + i * quarter_step;
        if (i > 0 && this_mi_row >= cm->mi_rows) break;
        DEC_BLOCK(this_mi_row, mi_col, subsize);
      }
      break;
    case PARTITION_VERT_4:
      for (i = 0; i < 4; ++i) {
        int this_mi_col = mi_col + i * quarter_step;
        if (i > 0 && this_mi_col >= cm->mi_cols) break;
        DEC_BLOCK(mi_row, this_mi_col, subsize);
      }
      break;
1027
#endif  // CONFIG_EXT_PARTITION_TYPES
1028
    default: assert(0 && "Invalid partition type");
Jingning Han's avatar
Jingning Han committed
1029 1030
  }

1031 1032 1033 1034 1035
#undef DEC_PARTITION
#undef DEC_BLOCK
#undef DEC_BLOCK_EPT_ARG
#undef DEC_BLOCK_STX_ARG

1036
#if CONFIG_EXT_PARTITION_TYPES
1037
  update_ext_partition_context(xd, mi_row, mi_col, subsize, bsize, partition);
1038
#else