decodeframe.c 158 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
14
 */

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

Yaowu Xu's avatar
Yaowu Xu committed
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"
Yaowu Xu's avatar
Yaowu Xu committed
21
#include "aom_dsp/aom_dsp_common.h"
Jingning Han's avatar
Jingning Han committed
22
23
#include "aom_dsp/bitreader.h"
#include "aom_dsp/bitreader_buffer.h"
Yaowu Xu's avatar
Yaowu Xu committed
24
#include "aom_mem/aom_mem.h"
25
26
#include "aom_ports/mem.h"
#include "aom_ports/mem_ops.h"
Yaowu Xu's avatar
Yaowu Xu committed
27
28
#include "aom_scale/aom_scale.h"
#include "aom_util/aom_thread.h"
Jingning Han's avatar
Jingning Han committed
29

30
#include "av1/common/alloccommon.h"
31
#if CONFIG_CLPF
Steinar Midtskogen's avatar
Steinar Midtskogen committed
32
#include "aom/aom_image.h"
33
#include "av1/common/clpf.h"
34
#endif
35
#include "av1/common/common.h"
Yaowu Xu's avatar
Yaowu Xu committed
36
#if CONFIG_DERING
37
#include "av1/common/dering.h"
Yaowu Xu's avatar
Yaowu Xu committed
38
#endif  // CONFIG_DERING
39
40
41
42
43
44
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
#include "av1/common/idct.h"
#include "av1/common/pred_common.h"
#include "av1/common/quant_common.h"
#include "av1/common/reconinter.h"
Jingning Han's avatar
Jingning Han committed
45
#include "av1/common/reconintra.h"
46
#include "av1/common/seg_common.h"
Jingning Han's avatar
Jingning Han committed
47
#include "av1/common/thread_common.h"
48
#include "av1/common/tile_common.h"
49

50
51
52
#include "av1/decoder/decodeframe.h"
#include "av1/decoder/decodemv.h"
#include "av1/decoder/decoder.h"
Jingning Han's avatar
Jingning Han committed
53
#include "av1/decoder/detokenize.h"
54
#include "av1/decoder/dsubexp.h"
Jingning Han's avatar
Jingning Han committed
55

Yaowu Xu's avatar
Yaowu Xu committed
56
#define MAX_AV1_HEADER_SIZE 80
Michael Bebenita's avatar
Michael Bebenita committed
57
#define ACCT_STR __func__
Jingning Han's avatar
Jingning Han committed
58

Yaowu Xu's avatar
Yaowu Xu committed
59
static int is_compound_reference_allowed(const AV1_COMMON *cm) {
Jingning Han's avatar
Jingning Han committed
60
  int i;
61
  if (frame_is_intra_only(cm)) return 0;
62
  for (i = 1; i < INTER_REFS_PER_FRAME; ++i)
63
    if (cm->ref_frame_sign_bias[i + 1] != cm->ref_frame_sign_bias[1]) return 1;
Jingning Han's avatar
Jingning Han committed
64
65
66
67

  return 0;
}

Yaowu Xu's avatar
Yaowu Xu committed
68
static void setup_compound_reference_mode(AV1_COMMON *cm) {
69
#if CONFIG_EXT_REFS
70
  cm->comp_fwd_ref[0] = LAST_FRAME;
71
72
73
74
  cm->comp_fwd_ref[1] = LAST2_FRAME;
  cm->comp_fwd_ref[2] = LAST3_FRAME;
  cm->comp_fwd_ref[3] = GOLDEN_FRAME;

75
76
  cm->comp_bwd_ref[0] = BWDREF_FRAME;
  cm->comp_bwd_ref[1] = ALTREF_FRAME;
77
#else
Jingning Han's avatar
Jingning Han committed
78
  if (cm->ref_frame_sign_bias[LAST_FRAME] ==
79
      cm->ref_frame_sign_bias[GOLDEN_FRAME]) {
Jingning Han's avatar
Jingning Han committed
80
81
82
83
    cm->comp_fixed_ref = ALTREF_FRAME;
    cm->comp_var_ref[0] = LAST_FRAME;
    cm->comp_var_ref[1] = GOLDEN_FRAME;
  } else if (cm->ref_frame_sign_bias[LAST_FRAME] ==
84
             cm->ref_frame_sign_bias[ALTREF_FRAME]) {
Jingning Han's avatar
Jingning Han committed
85
86
87
88
89
90
91
92
    cm->comp_fixed_ref = GOLDEN_FRAME;
    cm->comp_var_ref[0] = LAST_FRAME;
    cm->comp_var_ref[1] = ALTREF_FRAME;
  } else {
    cm->comp_fixed_ref = LAST_FRAME;
    cm->comp_var_ref[0] = GOLDEN_FRAME;
    cm->comp_var_ref[1] = ALTREF_FRAME;
  }
93
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
94
95
96
97
98
99
}

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

Yaowu Xu's avatar
Yaowu Xu committed
100
101
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
102
103
104
  return data > max ? max : data;
}

Yaowu Xu's avatar
Yaowu Xu committed
105
106
static TX_MODE read_tx_mode(struct aom_read_bit_buffer *rb) {
  return aom_rb_read_bit(rb) ? TX_MODE_SELECT : aom_rb_read_literal(rb, 2);
107
}
Jingning Han's avatar
Jingning Han committed
108

Yaowu Xu's avatar
Yaowu Xu committed
109
static void read_switchable_interp_probs(FRAME_CONTEXT *fc, aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
110
  int i, j;
111
  for (j = 0; j < SWITCHABLE_FILTER_CONTEXTS; ++j) {
Jingning Han's avatar
Jingning Han committed
112
    for (i = 0; i < SWITCHABLE_FILTERS - 1; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
113
      av1_diff_update_prob(r, &fc->switchable_interp_prob[j][i], ACCT_STR);
114
115
116
117
118
#if CONFIG_DAALA_EC
    av1_tree_to_cdf(av1_switchable_interp_tree, fc->switchable_interp_prob[j],
                    fc->switchable_interp_cdf[j]);
#endif
  }
Jingning Han's avatar
Jingning Han committed
119
120
}

Yaowu Xu's avatar
Yaowu Xu committed
121
static void read_inter_mode_probs(FRAME_CONTEXT *fc, aom_reader *r) {
122
123
124
  int i;
#if CONFIG_REF_MV
  for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
125
    av1_diff_update_prob(r, &fc->newmv_prob[i], ACCT_STR);
126
  for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
127
    av1_diff_update_prob(r, &fc->zeromv_prob[i], ACCT_STR);
128
  for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
129
    av1_diff_update_prob(r, &fc->refmv_prob[i], ACCT_STR);
130
  for (i = 0; i < DRL_MODE_CONTEXTS; ++i)
Michael Bebenita's avatar
Michael Bebenita committed
131
    av1_diff_update_prob(r, &fc->drl_prob[i], ACCT_STR);
Yue Chen's avatar
Yue Chen committed
132
#if CONFIG_EXT_INTER
Michael Bebenita's avatar
Michael Bebenita committed
133
  av1_diff_update_prob(r, &fc->new2mv_prob, ACCT_STR);
Yue Chen's avatar
Yue Chen committed
134
#endif  // CONFIG_EXT_INTER
135
136
#else
  int j;
Jingning Han's avatar
Jingning Han committed
137
138
  for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
    for (j = 0; j < INTER_MODES - 1; ++j)
Michael Bebenita's avatar
Michael Bebenita committed
139
      av1_diff_update_prob(r, &fc->inter_mode_probs[i][j], ACCT_STR);
140
#endif
Jingning Han's avatar
Jingning Han committed
141
142
}

143
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
144
static void read_inter_compound_mode_probs(FRAME_CONTEXT *fc, aom_reader *r) {
145
  int i, j;
Michael Bebenita's avatar
Michael Bebenita committed
146
  if (aom_read(r, GROUP_DIFF_UPDATE_PROB, ACCT_STR)) {
147
148
    for (j = 0; j < INTER_MODE_CONTEXTS; ++j) {
      for (i = 0; i < INTER_COMPOUND_MODES - 1; ++i) {
Michael Bebenita's avatar
Michael Bebenita committed
149
        av1_diff_update_prob(r, &fc->inter_compound_mode_probs[j][i], ACCT_STR);
150
151
152
153
154
155
      }
    }
  }
}
#endif  // CONFIG_EXT_INTER

156
static REFERENCE_MODE read_frame_reference_mode(
Yaowu Xu's avatar
Yaowu Xu committed
157
    const AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
158
  if (is_compound_reference_allowed(cm)) {
Yaowu Xu's avatar
Yaowu Xu committed
159
    return aom_rb_read_bit(rb)
160
               ? REFERENCE_MODE_SELECT
Yaowu Xu's avatar
Yaowu Xu committed
161
               : (aom_rb_read_bit(rb) ? COMPOUND_REFERENCE : SINGLE_REFERENCE);
162
163
164
165
  } else {
    return SINGLE_REFERENCE;
  }
}
Jingning Han's avatar
Jingning Han committed
166

Yaowu Xu's avatar
Yaowu Xu committed
167
static void read_frame_reference_mode_probs(AV1_COMMON *cm, aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
168
  FRAME_CONTEXT *const fc = cm->fc;
169
  int i, j;
Jingning Han's avatar
Jingning Han committed
170
171
172

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

175
  if (cm->reference_mode != COMPOUND_REFERENCE) {
Jingning Han's avatar
Jingning Han committed
176
    for (i = 0; i < REF_CONTEXTS; ++i) {
177
      for (j = 0; j < (SINGLE_REFS - 1); ++j) {
Michael Bebenita's avatar
Michael Bebenita committed
178
        av1_diff_update_prob(r, &fc->single_ref_prob[i][j], ACCT_STR);
179
      }
Jingning Han's avatar
Jingning Han committed
180
    }
181
  }
Jingning Han's avatar
Jingning Han committed
182

183
184
  if (cm->reference_mode != SINGLE_REFERENCE) {
    for (i = 0; i < REF_CONTEXTS; ++i) {
185
#if CONFIG_EXT_REFS
186
      for (j = 0; j < (FWD_REFS - 1); ++j)
Michael Bebenita's avatar
Michael Bebenita committed
187
        av1_diff_update_prob(r, &fc->comp_ref_prob[i][j], ACCT_STR);
188
      for (j = 0; j < (BWD_REFS - 1); ++j)
Michael Bebenita's avatar
Michael Bebenita committed
189
        av1_diff_update_prob(r, &fc->comp_bwdref_prob[i][j], ACCT_STR);
190
191
#else
      for (j = 0; j < (COMP_REFS - 1); ++j)
Michael Bebenita's avatar
Michael Bebenita committed
192
        av1_diff_update_prob(r, &fc->comp_ref_prob[i][j], ACCT_STR);
193
#endif  // CONFIG_EXT_REFS
194
195
    }
  }
Jingning Han's avatar
Jingning Han committed
196
197
}

Yaowu Xu's avatar
Yaowu Xu committed
198
static void update_mv_probs(aom_prob *p, int n, aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
199
  int i;
Michael Bebenita's avatar
Michael Bebenita committed
200
  for (i = 0; i < n; ++i) av1_diff_update_prob(r, &p[i], ACCT_STR);
Jingning Han's avatar
Jingning Han committed
201
202
}

Yaowu Xu's avatar
Yaowu Xu committed
203
static void read_mv_probs(nmv_context *ctx, int allow_hp, aom_reader *r) {
Jingning Han's avatar
Jingning Han committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  int i, j;

  update_mv_probs(ctx->joints, MV_JOINTS - 1, r);

  for (i = 0; i < 2; ++i) {
    nmv_component *const comp_ctx = &ctx->comps[i];
    update_mv_probs(&comp_ctx->sign, 1, r);
    update_mv_probs(comp_ctx->classes, MV_CLASSES - 1, r);
    update_mv_probs(comp_ctx->class0, CLASS0_SIZE - 1, r);
    update_mv_probs(comp_ctx->bits, MV_OFFSET_BITS, r);
  }

  for (i = 0; i < 2; ++i) {
    nmv_component *const comp_ctx = &ctx->comps[i];
    for (j = 0; j < CLASS0_SIZE; ++j)
      update_mv_probs(comp_ctx->class0_fp[j], MV_FP_SIZE - 1, r);
220
    update_mv_probs(comp_ctx->fp, MV_FP_SIZE - 1, r);
Jingning Han's avatar
Jingning Han committed
221
222
223
224
225
226
227
228
229
230
231
  }

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

232
static void inverse_transform_block(MACROBLOCKD *xd, int plane,
233
                                    const TX_TYPE tx_type,
234
235
                                    const TX_SIZE tx_size, uint8_t *dst,
                                    int stride, int eob) {
Jingning Han's avatar
Jingning Han committed
236
237
238
  struct macroblockd_plane *const pd = &xd->plane[plane];
  if (eob > 0) {
    tran_low_t *const dqcoeff = pd->dqcoeff;
Angie Chiang's avatar
Angie Chiang committed
239
240
241
242
    INV_TXFM_PARAM inv_txfm_param;
    inv_txfm_param.tx_type = tx_type;
    inv_txfm_param.tx_size = tx_size;
    inv_txfm_param.eob = eob;
243
    inv_txfm_param.lossless = xd->lossless[xd->mi[0]->mbmi.segment_id];
Angie Chiang's avatar
Angie Chiang committed
244

Yaowu Xu's avatar
Yaowu Xu committed
245
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
246
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Angie Chiang's avatar
Angie Chiang committed
247
248
      inv_txfm_param.bd = xd->bd;
      highbd_inv_txfm_add(dqcoeff, dst, stride, &inv_txfm_param);
Jingning Han's avatar
Jingning Han committed
249
    } else {
Yaowu Xu's avatar
Yaowu Xu committed
250
#endif  // CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
251
      inv_txfm_add(dqcoeff, dst, stride, &inv_txfm_param);
Yaowu Xu's avatar
Yaowu Xu committed
252
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
253
    }
Yaowu Xu's avatar
Yaowu Xu committed
254
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
255

256
257
258
    // TODO(jingning): This cleans up different reset requests from various
    // experiments, but incurs unnecessary memset size.
    if (eob == 1)
Jingning Han's avatar
Jingning Han committed
259
      dqcoeff[0] = 0;
260
261
    else
      memset(dqcoeff, 0, tx_size_2d[tx_size] * sizeof(dqcoeff[0]));
Jingning Han's avatar
Jingning Han committed
262
263
264
  }
}

Angie Chiang's avatar
Angie Chiang committed
265
266
static void predict_and_reconstruct_intra_block(AV1_COMMON *cm,
                                                MACROBLOCKD *const xd,
Alex Converse's avatar
Alex Converse committed
267
268
269
#if CONFIG_ANS
                                                struct AnsDecoder *const r,
#else
Yaowu Xu's avatar
Yaowu Xu committed
270
                                                aom_reader *r,
Alex Converse's avatar
Alex Converse committed
271
#endif  // CONFIG_ANS
Jingning Han's avatar
Jingning Han committed
272
                                                MB_MODE_INFO *const mbmi,
273
                                                int plane, int row, int col,
Jingning Han's avatar
Jingning Han committed
274
275
276
                                                TX_SIZE tx_size) {
  struct macroblockd_plane *const pd = &xd->plane[plane];
  PREDICTION_MODE mode = (plane == 0) ? mbmi->mode : mbmi->uv_mode;
hui su's avatar
hui su committed
277
  PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
Jingning Han's avatar
Jingning Han committed
278
  uint8_t *dst;
hui su's avatar
hui su committed
279
  int block_idx = (row << 1) + col;
Jingning Han's avatar
Jingning Han committed
280
281
282
  dst = &pd->dst.buf[4 * row * pd->dst.stride + 4 * col];

  if (mbmi->sb_type < BLOCK_8X8)
283
    if (plane == 0) mode = xd->mi[0]->bmi[(row << 1) + col].as_mode;
Jingning Han's avatar
Jingning Han committed
284

Yaowu Xu's avatar
Yaowu Xu committed
285
286
  av1_predict_intra_block(xd, pd->n4_wl, pd->n4_hl, tx_size, mode, dst,
                          pd->dst.stride, dst, pd->dst.stride, col, row, plane);
Jingning Han's avatar
Jingning Han committed
287
288

  if (!mbmi->skip) {
hui su's avatar
hui su committed
289
    TX_TYPE tx_type = get_tx_type(plane_type, xd, block_idx, tx_size);
Angie Chiang's avatar
Angie Chiang committed
290
    const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, 0);
291
292
    const int eob = av1_decode_block_tokens(
        xd, plane, scan_order, col, row, tx_size, tx_type, r, mbmi->segment_id);
293
294
    inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
                            eob);
Jingning Han's avatar
Jingning Han committed
295
296
297
  }
}

298
#if CONFIG_VAR_TX
Angie Chiang's avatar
Angie Chiang committed
299
300
301
static void decode_reconstruct_tx(AV1_COMMON *cm, MACROBLOCKD *const xd,
                                  aom_reader *r, MB_MODE_INFO *const mbmi,
                                  int plane, BLOCK_SIZE plane_bsize, int block,
302
303
                                  int blk_row, int blk_col, TX_SIZE tx_size,
                                  int *eob_total) {
304
  const struct macroblockd_plane *const pd = &xd->plane[plane];
305
  const BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
306
307
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
308
  const TX_SIZE plane_tx_size =
309
      plane ? uv_txsize_lookup[bsize][mbmi->inter_tx_size[tx_row][tx_col]][0][0]
310
            : mbmi->inter_tx_size[tx_row][tx_col];
311
312
313
314
315
316
317
318
  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);

319
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
320

321
  if (tx_size == plane_tx_size) {
322
    PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
323
    TX_TYPE tx_type = get_tx_type(plane_type, xd, block, plane_tx_size);
Angie Chiang's avatar
Angie Chiang committed
324
    const SCAN_ORDER *sc = get_scan(cm, plane_tx_size, tx_type, 1);
325
    const int eob =
Yaowu Xu's avatar
Yaowu Xu committed
326
327
        av1_decode_block_tokens(xd, plane, sc, blk_col, blk_row, plane_tx_size,
                                tx_type, r, mbmi->segment_id);
328
329
    inverse_transform_block(
        xd, plane, tx_type, plane_tx_size,
330
        &pd->dst.buf[4 * blk_row * pd->dst.stride + 4 * blk_col],
331
        pd->dst.stride, eob);
332
333
334
335
336
337
338
339
340
341
342
    *eob_total += eob;
  } 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);
343
      int step = num_4x4_blocks_txsize_lookup[tx_size - 1];
344

345
      if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
346

Angie Chiang's avatar
Angie Chiang committed
347
348
349
      decode_reconstruct_tx(cm, xd, r, mbmi, plane, plane_bsize,
                            block + i * step, offsetr, offsetc, tx_size - 1,
                            eob_total);
350
351
352
    }
  }
}
353
#endif  // CONFIG_VAR_TX
354

355
#if !CONFIG_VAR_TX || CONFIG_SUPERTX || (CONFIG_EXT_TX && CONFIG_RECT_TX)
Angie Chiang's avatar
Angie Chiang committed
356
static int reconstruct_inter_block(AV1_COMMON *cm, MACROBLOCKD *const xd,
Alex Converse's avatar
Alex Converse committed
357
358
359
#if CONFIG_ANS
                                   struct AnsDecoder *const r,
#else
Yaowu Xu's avatar
Yaowu Xu committed
360
                                   aom_reader *r,
Alex Converse's avatar
Alex Converse committed
361
#endif
362
363
                                   int segment_id, int plane, int row, int col,
                                   TX_SIZE tx_size) {
Jingning Han's avatar
Jingning Han committed
364
  struct macroblockd_plane *const pd = &xd->plane[plane];
hui su's avatar
hui su committed
365
366
  PLANE_TYPE plane_type = (plane == 0) ? PLANE_TYPE_Y : PLANE_TYPE_UV;
  int block_idx = (row << 1) + col;
hui su's avatar
hui su committed
367
  TX_TYPE tx_type = get_tx_type(plane_type, xd, block_idx, tx_size);
Angie Chiang's avatar
Angie Chiang committed
368
  const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, 1);
369
370
  const int eob = av1_decode_block_tokens(xd, plane, scan_order, col, row,
                                          tx_size, tx_type, r, segment_id);
Jingning Han's avatar
Jingning Han committed
371

372
373
374
  inverse_transform_block(xd, plane, tx_type, tx_size,
                          &pd->dst.buf[4 * row * pd->dst.stride + 4 * col],
                          pd->dst.stride, eob);
Jingning Han's avatar
Jingning Han committed
375
376
  return eob;
}
377
#endif  // !CONFIG_VAR_TX || CONFIG_SUPER_TX
Jingning Han's avatar
Jingning Han committed
378
379
380
381
382
383
384
385
386
387

static INLINE void dec_reset_skip_context(MACROBLOCKD *xd) {
  int i;
  for (i = 0; i < MAX_MB_PLANE; i++) {
    struct macroblockd_plane *const pd = &xd->plane[i];
    memset(pd->above_context, 0, sizeof(ENTROPY_CONTEXT) * pd->n4_w);
    memset(pd->left_context, 0, sizeof(ENTROPY_CONTEXT) * pd->n4_h);
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
388
static MB_MODE_INFO *set_offsets(AV1_COMMON *const cm, MACROBLOCKD *const xd,
Jingning Han's avatar
Jingning Han committed
389
                                 BLOCK_SIZE bsize, int mi_row, int mi_col,
390
391
                                 int bw, int bh, int x_mis, int y_mis, int bwl,
                                 int bhl) {
Jingning Han's avatar
Jingning Han committed
392
393
394
395
396
397
398
399
400
401
  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;
  for (y = 0; y < y_mis; ++y)
Jingning Han's avatar
Jingning Han committed
402
    for (x = !y; x < x_mis; ++x) xd->mi[y * cm->mi_stride + x] = xd->mi[0];
Jingning Han's avatar
Jingning Han committed
403
404
405
406

  set_plane_n4(xd, bw, bh, bwl, bhl);
  set_skip_context(xd, mi_row, mi_col);

407
408
409
410
#if CONFIG_VAR_TX
  xd->max_tx_size = max_txsize_lookup[bsize];
#endif

Jingning Han's avatar
Jingning Han committed
411
412
413
414
  // 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, cm->mi_rows, cm->mi_cols);

Yaowu Xu's avatar
Yaowu Xu committed
415
  av1_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
Jingning Han's avatar
Jingning Han committed
416
417
418
  return &xd->mi[0]->mbmi;
}

419
#if CONFIG_SUPERTX
Yaowu Xu's avatar
Yaowu Xu committed
420
static MB_MODE_INFO *set_offsets_extend(AV1_COMMON *const cm,
421
422
                                        MACROBLOCKD *const xd,
                                        const TileInfo *const tile,
423
424
425
                                        BLOCK_SIZE bsize_pred, int mi_row_pred,
                                        int mi_col_pred, int mi_row_ori,
                                        int mi_col_ori) {
426
427
428
429
430
431
432
433
434
435
  // Used in supertx
  // (mi_row_ori, mi_col_ori): location for mv
  // (mi_row_pred, mi_col_pred, bsize_pred): region to predict
  const int bw = num_8x8_blocks_wide_lookup[bsize_pred];
  const int bh = num_8x8_blocks_high_lookup[bsize_pred];
  const int offset = mi_row_ori * cm->mi_stride + mi_col_ori;
  const int bwl = b_width_log2_lookup[bsize_pred];
  const int bhl = b_height_log2_lookup[bsize_pred];
  xd->mi = cm->mi_grid_visible + offset;
  xd->mi[0] = cm->mi + offset;
436
437
  set_mi_row_col(xd, tile, mi_row_pred, bh, mi_col_pred, bw, cm->mi_rows,
                 cm->mi_cols);
438

439
440
  xd->up_available = (mi_row_ori > tile->mi_row_start);
  xd->left_available = (mi_col_ori > tile->mi_col_start);
441
442
443
444
445
446

  set_plane_n4(xd, bw, bh, bwl, bhl);

  return &xd->mi[0]->mbmi;
}

Yaowu Xu's avatar
Yaowu Xu committed
447
448
449
static MB_MODE_INFO *set_mb_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) {
450
451
452
453
454
455
456
457
  const int offset = mi_row * cm->mi_stride + mi_col;
  const TileInfo *const tile = &xd->tile;
  int x, y;

  xd->mi = cm->mi_grid_visible + offset;
  xd->mi[0] = cm->mi + offset;
  xd->mi[0]->mbmi.sb_type = bsize;
  for (y = 0; y < y_mis; ++y)
458
    for (x = !y; x < x_mis; ++x) xd->mi[y * cm->mi_stride + x] = xd->mi[0];
459
460
461
462
463

  set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, cm->mi_rows, cm->mi_cols);
  return &xd->mi[0]->mbmi;
}

Yaowu Xu's avatar
Yaowu Xu committed
464
static void set_offsets_topblock(AV1_COMMON *const cm, MACROBLOCKD *const xd,
465
466
                                 const TileInfo *const tile, BLOCK_SIZE bsize,
                                 int mi_row, int mi_col) {
467
468
469
470
471
472
473
474
475
476
477
478
479
  const int bw = num_8x8_blocks_wide_lookup[bsize];
  const int bh = num_8x8_blocks_high_lookup[bsize];
  const int offset = mi_row * cm->mi_stride + mi_col;
  const int bwl = b_width_log2_lookup[bsize];
  const int bhl = b_height_log2_lookup[bsize];

  xd->mi = cm->mi_grid_visible + offset;
  xd->mi[0] = cm->mi + offset;

  set_plane_n4(xd, bw, bh, bwl, bhl);

  set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, cm->mi_rows, cm->mi_cols);

Yaowu Xu's avatar
Yaowu Xu committed
480
  av1_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
481
482
}

Yaowu Xu's avatar
Yaowu Xu committed
483
static void set_param_topblock(AV1_COMMON *const cm, MACROBLOCKD *const xd,
484
                               BLOCK_SIZE bsize, int mi_row, int mi_col,
485
                               int txfm, int skip) {
486
487
  const int bw = num_8x8_blocks_wide_lookup[bsize];
  const int bh = num_8x8_blocks_high_lookup[bsize];
Yaowu Xu's avatar
Yaowu Xu committed
488
489
  const int x_mis = AOMMIN(bw, cm->mi_cols - mi_col);
  const int y_mis = AOMMIN(bh, cm->mi_rows - mi_row);
490
491
492
493
494
495
496
497
498
499
500
  const int offset = mi_row * cm->mi_stride + mi_col;
  int x, y;

  xd->mi = cm->mi_grid_visible + offset;
  xd->mi[0] = cm->mi + offset;

  for (y = 0; y < y_mis; ++y)
    for (x = 0; x < x_mis; ++x) {
      xd->mi[y * cm->mi_stride + x]->mbmi.skip = skip;
      xd->mi[y * cm->mi_stride + x]->mbmi.tx_type = txfm;
    }
501
502
#if CONFIG_VAR_TX
  xd->above_txfm_context = cm->above_txfm_context + mi_col;
503
  xd->left_txfm_context =
504
      xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
505
  set_txfm_ctxs(xd->mi[0]->mbmi.tx_size, bw, bh, xd);
506
#endif
507
508
}

Yaowu Xu's avatar
Yaowu Xu committed
509
static void set_ref(AV1_COMMON *const cm, MACROBLOCKD *const xd, int idx,
510
                    int mi_row, int mi_col) {
511
512
513
  MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
  RefBuffer *ref_buffer = &cm->frame_refs[mbmi->ref_frame[idx] - LAST_FRAME];
  xd->block_refs[idx] = ref_buffer;
Yaowu Xu's avatar
Yaowu Xu committed
514
515
  if (!av1_is_valid_scale(&ref_buffer->sf))
    aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
516
                       "Invalid scale factors");
Yaowu Xu's avatar
Yaowu Xu committed
517
518
  av1_setup_pre_planes(xd, idx, ref_buffer->buf, mi_row, mi_col,
                       &ref_buffer->sf);
519
520
521
522
  xd->corrupted |= ref_buffer->buf->corrupted;
}

static void dec_predict_b_extend(
Yaowu Xu's avatar
Yaowu Xu committed
523
    AV1Decoder *const pbi, MACROBLOCKD *const xd, const TileInfo *const tile,
524
525
526
    int block, int mi_row_ori, int mi_col_ori, int mi_row_pred, int mi_col_pred,
    int mi_row_top, int mi_col_top, uint8_t *dst_buf[3], int dst_stride[3],
    BLOCK_SIZE bsize_top, BLOCK_SIZE bsize_pred, int b_sub8x8, int bextend) {
527
528
529
530
531
532
533
534
535
536
537
538
  // Used in supertx
  // (mi_row_ori, mi_col_ori): location for mv
  // (mi_row_pred, mi_col_pred, bsize_pred): region to predict
  // (mi_row_top, mi_col_top, bsize_top): region of the top partition size
  // block: sub location of sub8x8 blocks
  // b_sub8x8: 1: ori is sub8x8; 0: ori is not sub8x8
  // bextend: 1: region to predict is an extension of ori; 0: not
  int r = (mi_row_pred - mi_row_top) * MI_SIZE;
  int c = (mi_col_pred - mi_col_top) * MI_SIZE;
  const int mi_width_top = num_8x8_blocks_wide_lookup[bsize_top];
  const int mi_height_top = num_8x8_blocks_high_lookup[bsize_top];
  MB_MODE_INFO *mbmi;
Yaowu Xu's avatar
Yaowu Xu committed
539
  AV1_COMMON *const cm = &pbi->common;
540
541
542

  if (mi_row_pred < mi_row_top || mi_col_pred < mi_col_top ||
      mi_row_pred >= mi_row_top + mi_height_top ||
543
544
      mi_col_pred >= mi_col_top + mi_width_top || mi_row_pred >= cm->mi_rows ||
      mi_col_pred >= cm->mi_cols)
545
546
    return;

547
  mbmi = set_offsets_extend(cm, xd, tile, bsize_pred, mi_row_pred, mi_col_pred,
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
                            mi_row_ori, mi_col_ori);
  set_ref(cm, xd, 0, mi_row_pred, mi_col_pred);
  if (has_second_ref(&xd->mi[0]->mbmi))
    set_ref(cm, xd, 1, mi_row_pred, mi_col_pred);

  if (!bextend) {
    mbmi->tx_size = b_width_log2_lookup[bsize_top];
  }

  xd->plane[0].dst.stride = dst_stride[0];
  xd->plane[1].dst.stride = dst_stride[1];
  xd->plane[2].dst.stride = dst_stride[2];
  xd->plane[0].dst.buf = dst_buf[0] +
                         (r >> xd->plane[0].subsampling_y) * dst_stride[0] +
                         (c >> xd->plane[0].subsampling_x);
  xd->plane[1].dst.buf = dst_buf[1] +
                         (r >> xd->plane[1].subsampling_y) * dst_stride[1] +
                         (c >> xd->plane[1].subsampling_x);
  xd->plane[2].dst.buf = dst_buf[2] +
                         (r >> xd->plane[2].subsampling_y) * dst_stride[2] +
                         (c >> xd->plane[2].subsampling_x);

  if (!b_sub8x8)
Yaowu Xu's avatar
Yaowu Xu committed
571
    av1_build_inter_predictors_sb_extend(xd,
572
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
573
                                         mi_row_ori, mi_col_ori,
574
#endif  // CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
575
                                         mi_row_pred, mi_col_pred, bsize_pred);
576
  else
Yaowu Xu's avatar
Yaowu Xu committed
577
    av1_build_inter_predictors_sb_sub8x8_extend(xd,
578
#if CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
579
                                                mi_row_ori, mi_col_ori,
580
#endif  // CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
581
582
                                                mi_row_pred, mi_col_pred,
                                                bsize_pred, block);
583
584
}

Yaowu Xu's avatar
Yaowu Xu committed
585
static void dec_extend_dir(AV1Decoder *const pbi, MACROBLOCKD *const xd,
586
                           const TileInfo *const tile, int block,
587
588
589
                           BLOCK_SIZE bsize, BLOCK_SIZE top_bsize, int mi_row,
                           int mi_col, int mi_row_top, int mi_col_top,
                           uint8_t *dst_buf[3], int dst_stride[3], int dir) {
590
591
592
593
594
595
596
597
598
599
600
  // dir: 0-lower, 1-upper, 2-left, 3-right
  //      4-lowerleft, 5-upperleft, 6-lowerright, 7-upperright
  const int mi_width = num_8x8_blocks_wide_lookup[bsize];
  const int mi_height = num_8x8_blocks_high_lookup[bsize];
  int xss = xd->plane[1].subsampling_x;
  int yss = xd->plane[1].subsampling_y;
  int b_sub8x8 = (bsize < BLOCK_8X8) ? 1 : 0;
  BLOCK_SIZE extend_bsize;
  int unit, mi_row_pred, mi_col_pred;

  if (dir == 0 || dir == 1) {
601
602
603
    extend_bsize = (mi_width == 1 || bsize < BLOCK_8X8 || xss < yss)
                       ? BLOCK_8X8
                       : BLOCK_16X8;
604
605
606
607
    unit = num_8x8_blocks_wide_lookup[extend_bsize];
    mi_row_pred = mi_row + ((dir == 0) ? mi_height : -1);
    mi_col_pred = mi_col;

608
609
610
    dec_predict_b_extend(pbi, xd, tile, block, mi_row, mi_col, mi_row_pred,
                         mi_col_pred, mi_row_top, mi_col_top, dst_buf,
                         dst_stride, top_bsize, extend_bsize, b_sub8x8, 1);
611
612
613
614

    if (mi_width > unit) {
      int i;
      assert(!b_sub8x8);
615
      for (i = 0; i < mi_width / unit - 1; i++) {
616
        mi_col_pred += unit;
617
618
619
        dec_predict_b_extend(pbi, xd, tile, block, mi_row, mi_col, mi_row_pred,
                             mi_col_pred, mi_row_top, mi_col_top, dst_buf,
                             dst_stride, top_bsize, extend_bsize, b_sub8x8, 1);
620
621
622
      }
    }
  } else if (dir == 2 || dir == 3) {
623
624
625
    extend_bsize = (mi_height == 1 || bsize < BLOCK_8X8 || yss < xss)
                       ? BLOCK_8X8
                       : BLOCK_8X16;
626
627
628
629
    unit = num_8x8_blocks_high_lookup[extend_bsize];
    mi_row_pred = mi_row;
    mi_col_pred = mi_col + ((dir == 3) ? mi_width : -1);

630
631
632
    dec_predict_b_extend(pbi, xd, tile, block, mi_row, mi_col, mi_row_pred,
                         mi_col_pred, mi_row_top, mi_col_top, dst_buf,
                         dst_stride, top_bsize, extend_bsize, b_sub8x8, 1);
633
634
635

    if (mi_height > unit) {
      int i;
636
      for (i = 0; i < mi_height / unit - 1; i++) {
637
        mi_row_pred += unit;
638
639
640
        dec_predict_b_extend(pbi, xd, tile, block, mi_row, mi_col, mi_row_pred,
                             mi_col_pred, mi_row_top, mi_col_top, dst_buf,
                             dst_stride, top_bsize, extend_bsize, b_sub8x8, 1);
641
642
643
644
645
646
      }
    }
  } else {
    extend_bsize = BLOCK_8X8;
    mi_row_pred = mi_row + ((dir == 4 || dir == 6) ? mi_height : -1);
    mi_col_pred = mi_col + ((dir == 6 || dir == 7) ? mi_width : -1);
647
648
649
    dec_predict_b_extend(pbi, xd, tile, block, mi_row, mi_col, mi_row_pred,
                         mi_col_pred, mi_row_top, mi_col_top, dst_buf,
                         dst_stride, top_bsize, extend_bsize, b_sub8x8, 1);
650
651
652
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
653
static void dec_extend_all(AV1Decoder *const pbi, MACROBLOCKD *const xd,
654
                           const TileInfo *const tile, int block,
655
656
657
                           BLOCK_SIZE bsize, BLOCK_SIZE top_bsize, int mi_row,
                           int mi_col, int mi_row_top, int mi_col_top,
                           uint8_t *dst_buf[3], int dst_stride[3]) {
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 0);
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 1);
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 2);
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 3);
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 4);
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 5);
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 6);
  dec_extend_dir(pbi, xd, tile, block, bsize, top_bsize, mi_row, mi_col,
                 mi_row_top, mi_col_top, dst_buf, dst_stride, 7);
}

Yaowu Xu's avatar
Yaowu Xu committed
676
static void dec_predict_sb_complex(AV1Decoder *const pbi, MACROBLOCKD *const xd,
677
678
                                   const TileInfo *const tile, int mi_row,
                                   int mi_col, int mi_row_top, int mi_col_top,
679
680
                                   BLOCK_SIZE bsize, BLOCK_SIZE top_bsize,
                                   uint8_t *dst_buf[3], int dst_stride[3]) {
Yaowu Xu's avatar
Yaowu Xu committed
681
  const AV1_COMMON *const cm = &pbi->common;
682
683
684
  const int hbs = num_8x8_blocks_wide_lookup[bsize] / 2;
  const PARTITION_TYPE partition = get_partition(cm, mi_row, mi_col, bsize);
  const BLOCK_SIZE subsize = get_subsize(bsize, partition);
685
#if CONFIG_EXT_PARTITION_TYPES
686
  const BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
687
#endif
688
689
  int i;
  const int mi_offset = mi_row * cm->mi_stride + mi_col;
690
691
  uint8_t *dst_buf1[3], *dst_buf2[3], *dst_buf3[3];

692
693
694
695
696
697
  DECLARE_ALIGNED(16, uint8_t, tmp_buf1[MAX_MB_PLANE * MAX_TX_SQUARE * 2]);
  DECLARE_ALIGNED(16, uint8_t, tmp_buf2[MAX_MB_PLANE * MAX_TX_SQUARE * 2]);
  DECLARE_ALIGNED(16, uint8_t, tmp_buf3[MAX_MB_PLANE * MAX_TX_SQUARE * 2]);
  int dst_stride1[3] = { MAX_TX_SIZE, MAX_TX_SIZE, MAX_TX_SIZE };
  int dst_stride2[3] = { MAX_TX_SIZE, MAX_TX_SIZE, MAX_TX_SIZE };
  int dst_stride3[3] = { MAX_TX_SIZE, MAX_TX_SIZE, MAX_TX_SIZE };
698

Yaowu Xu's avatar
Yaowu Xu committed
699
#if CONFIG_AOM_HIGHBITDEPTH
700
701
702
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    int len = sizeof(uint16_t);
    dst_buf1[0] = CONVERT_TO_BYTEPTR(tmp_buf1);
703
704
    dst_buf1[1] = CONVERT_TO_BYTEPTR(tmp_buf1 + MAX_TX_SQUARE * len);
    dst_buf1[2] = CONVERT_TO_BYTEPTR(tmp_buf1 + 2 * MAX_TX_SQUARE * len);
705
    dst_buf2[0] = CONVERT_TO_BYTEPTR(tmp_buf2);
706
707
    dst_buf2[1] = CONVERT_TO_BYTEPTR(tmp_buf2 + MAX_TX_SQUARE * len);
    dst_buf2[2] = CONVERT_TO_BYTEPTR(tmp_buf2 + 2 * MAX_TX_SQUARE * len);
708
    dst_buf3[0] = CONVERT_TO_BYTEPTR(tmp_buf3);
709
710
    dst_buf3[1] = CONVERT_TO_BYTEPTR(tmp_buf3 + MAX_TX_SQUARE * len);
    dst_buf3[2] = CONVERT_TO_BYTEPTR(tmp_buf3 + 2 * MAX_TX_SQUARE * len);
711
712
713
  } else {
#endif
    dst_buf1[0] = tmp_buf1;
714
715
    dst_buf1[1] = tmp_buf1 + MAX_TX_SQUARE;
    dst_buf1[2] = tmp_buf1 + 2 * MAX_TX_SQUARE;
716
    dst_buf2[0] = tmp_buf2;
717
718
    dst_buf2[1] = tmp_buf2 + MAX_TX_SQUARE;
    dst_buf2[2] = tmp_buf2 + 2 * MAX_TX_SQUARE;
719
    dst_buf3[0] = tmp_buf3;
720
721
    dst_buf3[1] = tmp_buf3 + MAX_TX_SQUARE;
    dst_buf3[2] = tmp_buf3 + 2 * MAX_TX_SQUARE;
Yaowu Xu's avatar
Yaowu Xu committed
722
#if CONFIG_AOM_HIGHBITDEPTH
723
724
725
  }
#endif

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

728
729
  xd->mi = cm->mi_grid_visible + mi_offset;
  xd->mi[0] = cm->mi + mi_offset;
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

  for (i = 0; i < MAX_MB_PLANE; i++) {
    xd->plane[i].dst.buf = dst_buf[i];
    xd->plane[i].dst.stride = dst_stride[i];
  }

  switch (partition) {
    case PARTITION_NONE:
      assert(bsize < top_bsize);
      dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col, mi_row, mi_col,
                           mi_row_top, mi_col_top, dst_buf, dst_stride,
                           top_bsize, bsize, 0, 0);
      dec_extend_all(pbi, xd, tile, 0, bsize, top_bsize, mi_row, mi_col,
                     mi_row_top, mi_col_top, dst_buf, dst_stride);
      break;
    case PARTITION_HORZ:
      if (bsize == BLOCK_8X8) {
        // For sub8x8, predict in 8x8 unit
        // First half
        dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf, dst_stride,
                             top_bsize, BLOCK_8X8, 1, 0);
        if (bsize < top_bsize)
          dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf, dst_stride);

        // Second half
        dec_predict_b_extend(pbi, xd, tile, 2, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf1, dst_stride1,
                             top_bsize, BLOCK_8X8, 1, 1);
        if (bsize < top_bsize)
          dec_extend_all(pbi, xd, tile, 2, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf1, dst_stride1);

        // weighted average to smooth the boundary
        xd->plane[0].dst.buf = dst_buf[0];
        xd->plane[0].dst.stride = dst_stride[0];
Yaowu Xu's avatar
Yaowu Xu committed
767
        av1_build_masked_inter_predictor_complex(
768
769
770
            xd, dst_buf[0], dst_stride[0], dst_buf1[0], dst_stride1[0], mi_row,
            mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_HORZ,
            0);
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
      } else {
        // First half
        dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf, dst_stride,
                             top_bsize, subsize, 0, 0);
        if (bsize < top_bsize)
          dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf, dst_stride);
        else
          dec_extend_dir(pbi, xd, tile, 0, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf, dst_stride, 0);

        if (mi_row + hbs < cm->mi_rows) {
          // Second half
          dec_predict_b_extend(pbi, xd, tile, 0, mi_row + hbs, mi_col,
786
787
                               mi_row + hbs, mi_col, mi_row_top, mi_col_top,
                               dst_buf1, dst_stride1, top_bsize, subsize, 0, 0);
788
          if (bsize < top_bsize)
789
790
791
            dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row + hbs,
                           mi_col, mi_row_top, mi_col_top, dst_buf1,
                           dst_stride1);
792
          else
793
794
795
            dec_extend_dir(pbi, xd, tile, 0, subsize, top_bsize, mi_row + hbs,
                           mi_col, mi_row_top, mi_col_top, dst_buf1,
                           dst_stride1, 1);
796
797
798
799
800

          // weighted average to smooth the boundary
          for (i = 0; i < MAX_MB_PLANE; i++) {
            xd->plane[i].dst.buf = dst_buf[i];
            xd->plane[i].dst.stride = dst_stride[i];
Yaowu Xu's avatar
Yaowu Xu committed
801
            av1_build_masked_inter_predictor_complex(
802
                xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i],
803
804
                mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
                PARTITION_HORZ, i);
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
          }
        }
      }
      break;
    case PARTITION_VERT:
      if (bsize == BLOCK_8X8) {
        // First half
        dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf, dst_stride,
                             top_bsize, BLOCK_8X8, 1, 0);
        if (bsize < top_bsize)
          dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf, dst_stride);

        // Second half
        dec_predict_b_extend(pbi, xd, tile, 1, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf1, dst_stride1,
                             top_bsize, BLOCK_8X8, 1, 1);
        if (bsize < top_bsize)
          dec_extend_all(pbi, xd, tile, 1, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf1, dst_stride1);

        // Smooth
        xd->plane[0].dst.buf = dst_buf[0];
        xd->plane[0].dst.stride = dst_stride[0];
Yaowu Xu's avatar
Yaowu Xu committed
830
        av1_build_masked_inter_predictor_complex(
831
832
833
            xd, dst_buf[0], dst_stride[0], dst_buf1[0], dst_stride1[0], mi_row,
            mi_col, mi_row_top, mi_col_top, bsize, top_bsize, PARTITION_VERT,
            0);
834
835
836
837
838
839
840
841
842
843
844
845
846
847
      } else {
        // First half
        dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf, dst_stride,
                             top_bsize, subsize, 0, 0);
        if (bsize < top_bsize)
          dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf, dst_stride);
        else
          dec_extend_dir(pbi, xd, tile, 0, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf, dst_stride, 3);

        // Second half
        if (mi_col + hbs < cm->mi_cols) {
848
849
850
          dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col + hbs, mi_row,
                               mi_col + hbs, mi_row_top, mi_col_top, dst_buf1,
                               dst_stride1, top_bsize, subsize, 0, 0);
851
          if (bsize < top_bsize)
852
853
854
            dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row,
                           mi_col + hbs, mi_row_top, mi_col_top, dst_buf1,
                           dst_stride1);
855
          else
856
857
858
            dec_extend_dir(pbi, xd, tile, 0, subsize, top_bsize, mi_row,
                           mi_col + hbs, mi_row_top, mi_col_top, dst_buf1,
                           dst_stride1, 2);
859
860
861
862
863

          // Smooth
          for (i = 0; i < MAX_MB_PLANE; i++) {
            xd->plane[i].dst.buf = dst_buf[i];
            xd->plane[i].dst.stride = dst_stride[i];
Yaowu Xu's avatar
Yaowu Xu committed
864
            av1_build_masked_inter_predictor_complex(
865
                xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i],
866
867
                mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
                PARTITION_VERT, i);
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
          }
        }
      }
      break;
    case PARTITION_SPLIT:
      if (bsize == BLOCK_8X8) {
        dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf, dst_stride,
                             top_bsize, BLOCK_8X8, 1, 0);
        dec_predict_b_extend(pbi, xd, tile, 1, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf1, dst_stride1,
                             top_bsize, BLOCK_8X8, 1, 1);
        dec_predict_b_extend(pbi, xd, tile, 2, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf2, dst_stride2,
                             top_bsize, BLOCK_8X8, 1, 1);
        dec_predict_b_extend(pbi, xd, tile, 3, mi_row, mi_col, mi_row, mi_col,
                             mi_row_top, mi_col_top, dst_buf3, dst_stride3,
                             top_bsize, BLOCK_8X8, 1, 1);
        if (bsize < top_bsize) {
          dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf, dst_stride);
          dec_extend_all(pbi, xd, tile, 1, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf1, dst_stride1);
          dec_extend_all(pbi, xd, tile, 2, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf2, dst_stride2);
          dec_extend_all(pbi, xd, tile, 3, subsize, top_bsize, mi_row, mi_col,
                         mi_row_top, mi_col_top, dst_buf3, dst_stride3);
        }
      } else {
897
898
899
        dec_predict_sb_complex(pbi, xd, tile, mi_row, mi_col, mi_row_top,
                               mi_col_top, subsize, top_bsize, dst_buf,
                               dst_stride);
900
901
902
903
904
905
906
907
908
909
910
911
912
        if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols)
          dec_predict_sb_complex(pbi, xd, tile, mi_row, mi_col + hbs,
                                 mi_row_top, mi_col_top, subsize, top_bsize,
                                 dst_buf1, dst_stride1);
        if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols)
          dec_predict_sb_complex(pbi, xd, tile, mi_row + hbs, mi_col,
                                 mi_row_top, mi_col_top, subsize, top_bsize,
                                 dst_buf2, dst_stride2);
        if (mi_row + hbs < cm->mi_rows && mi_col + hbs < cm->mi_cols)
          dec_predict_sb_complex(pbi, xd, tile, mi_row + hbs, mi_col + hbs,
                                 mi_row_top, mi_col_top, subsize, top_bsize,
                                 dst_buf3, dst_stride3);
      }
913
914
915
916
      for (i = 0; i < MAX_MB_PLANE; i++) {
        if (bsize == BLOCK_8X8 && i != 0)
          continue;  // Skip <4x4 chroma smoothing
        if (mi_row < cm->mi_rows && mi_col + hbs < cm->mi_cols) {
Yaowu Xu's avatar
Yaowu Xu committed
917
          av1_build_masked_inter_predictor_complex(
918
919
920
921
              xd, dst_buf[i], dst_stride[i], dst_buf1[i], dst_stride1[i],
              mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
              PARTITION_VERT, i);
          if (mi_row + hbs < cm->mi_rows) {
Yaowu Xu's avatar
Yaowu Xu committed
922
            av1_build_masked_inter_predictor_complex(
923
924
925
                xd, dst_buf2[i], dst_stride2[i], dst_buf3[i], dst_stride3[i],
                mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
                PARTITION_VERT, i);
Yaowu Xu's avatar
Yaowu Xu committed
926
            av1_build_masked_inter_predictor_complex(
927
928
929
                xd, dst_buf[i], dst_stride[i], dst_buf2[i], dst_stride2[i],
                mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
                PARTITION_HORZ, i);
930
          }
931
        } else if (mi_row + hbs < cm->mi_rows && mi_col < cm->mi_cols) {
Yaowu Xu's avatar
Yaowu Xu committed
932
          av1_build_masked_inter_predictor_complex(
933
934
935
              xd, dst_buf[i], dst_stride[i], dst_buf2[i], dst_stride2[i],
              mi_row, mi_col, mi_row_top, mi_col_top, bsize, top_bsize,
              PARTITION_HORZ, i);
936
        }
937
      }
938
      break;
939
940
941
942
943
944
945
946
947
#if CONFIG_EXT_PARTITION_TYPES
    case PARTITION_HORZ_A:
      dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col, mi_row, mi_col,
                           mi_row_top, mi_col_top, dst_buf, dst_stride,
                           top_bsize, bsize2, 0, 0);
      dec_extend_all(pbi, xd, tile, 0, bsize2, top_bsize, mi_row, mi_col,
                     mi_row_top, mi_col_top, dst_buf, dst_stride);

      dec_predict_b_extend(pbi, xd, tile, 0, mi_row, mi_col + hbs, mi_row,
948
949
                           mi_col + hbs, mi_row_top, mi_col_top, dst_buf1,
                           dst_stride1, top_bsize, bsize2, 0, 0);
950
951
952
      dec_extend_all(pbi, xd, tile, 0, bsize2, top_bsize, mi_row, mi_col + hbs,
                     mi_row_top, mi_col_top, dst_buf1, dst_stride1);

953
954
955
      dec_predict_b_extend(pbi, xd, tile, 0, mi_row + hbs, mi_col, mi_row + hbs,
                           mi_col, mi_row_top, mi_col_top, dst_buf2,
                           dst_stride2, top_bsize, subsize, 0, 0);
956
      if (bsize < top_bsize)
957
958
        dec_extend_all(pbi, xd, tile, 0, subsize, top_bsize, mi_row + hbs,
                       mi_col, mi_row_top, mi_col_top, dst_buf2, dst_stride2);
959
      else
960
961