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

#include <assert.h>

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

19
#include "aom/aom_codec.h"
Yaowu Xu's avatar
Yaowu Xu committed
20
#include "aom_dsp/aom_dsp_common.h"
21
#include "aom_dsp/binary_codes_reader.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
#include "aom_ports/aom_timer.h"
26
27
#include "aom_ports/mem.h"
#include "aom_ports/mem_ops.h"
Yaowu Xu's avatar
Yaowu Xu committed
28
29
#include "aom_scale/aom_scale.h"
#include "aom_util/aom_thread.h"
Jingning Han's avatar
Jingning Han committed
30

Angie Chiang's avatar
Angie Chiang committed
31
#if CONFIG_BITSTREAM_DEBUG || CONFIG_MISMATCH_DEBUG
32
#include "aom_util/debug_util.h"
Angie Chiang's avatar
Angie Chiang committed
33
#endif  // CONFIG_BITSTREAM_DEBUG || CONFIG_MISMATCH_DEBUG
34

35
#include "av1/common/alloccommon.h"
36
#include "av1/common/cdef.h"
37
38
39
#if CONFIG_INSPECTION
#include "av1/decoder/inspection.h"
#endif
40
41
42
#include "av1/common/common.h"
#include "av1/common/entropy.h"
#include "av1/common/entropymode.h"
43
#include "av1/common/entropymv.h"
44
#include "av1/common/idct.h"
45
#include "av1/common/mvref_common.h"
46
47
48
#include "av1/common/pred_common.h"
#include "av1/common/quant_common.h"
#include "av1/common/reconinter.h"
Jingning Han's avatar
Jingning Han committed
49
#include "av1/common/reconintra.h"
50
#if CONFIG_HORZONLY_FRAME_SUPERRES
51
#include "av1/common/resize.h"
52
#endif  // CONFIG_HORZONLY_FRAME_SUPERRES
53
#include "av1/common/seg_common.h"
Jingning Han's avatar
Jingning Han committed
54
#include "av1/common/thread_common.h"
55
#include "av1/common/tile_common.h"
56
#include "av1/common/warped_motion.h"
57
58
59
#include "av1/decoder/decodeframe.h"
#include "av1/decoder/decodemv.h"
#include "av1/decoder/decoder.h"
Angie Chiang's avatar
Angie Chiang committed
60
61
62
#if CONFIG_LV_MAP
#include "av1/decoder/decodetxb.h"
#endif
Jingning Han's avatar
Jingning Han committed
63
#include "av1/decoder/detokenize.h"
Yue Chen's avatar
Yue Chen committed
64

Yaowu Xu's avatar
Yaowu Xu committed
65
#define MAX_AV1_HEADER_SIZE 80
Michael Bebenita's avatar
Michael Bebenita committed
66
#define ACCT_STR __func__
Jingning Han's avatar
Jingning Han committed
67

68
69
70
71
#if CONFIG_CFL
#include "av1/common/cfl.h"
#endif

72
73
74
75
76
77
78
#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

Yaowu Xu's avatar
Yaowu Xu committed
79
static void setup_compound_reference_mode(AV1_COMMON *cm) {
80
  cm->comp_fwd_ref[0] = LAST_FRAME;
81
82
83
84
  cm->comp_fwd_ref[1] = LAST2_FRAME;
  cm->comp_fwd_ref[2] = LAST3_FRAME;
  cm->comp_fwd_ref[3] = GOLDEN_FRAME;

85
  cm->comp_bwd_ref[0] = BWDREF_FRAME;
Zoe Liu's avatar
Zoe Liu committed
86
87
  cm->comp_bwd_ref[1] = ALTREF2_FRAME;
  cm->comp_bwd_ref[2] = ALTREF_FRAME;
Jingning Han's avatar
Jingning Han committed
88
89
90
91
92
93
}

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

94
95
96
97
98
99
#if CONFIG_SIMPLIFY_TX_MODE
static TX_MODE read_tx_mode(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
  if (cm->all_lossless) return ONLY_4X4;
  return aom_rb_read_bit(rb) ? TX_MODE_SELECT : TX_MODE_LARGEST;
}
#else
100
101
static TX_MODE read_tx_mode(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
  if (cm->all_lossless) return ONLY_4X4;
102
#if CONFIG_TX64X64
Urvang Joshi's avatar
Urvang Joshi committed
103
104
  TX_MODE tx_mode =
      aom_rb_read_bit(rb) ? TX_MODE_SELECT : aom_rb_read_literal(rb, 2);
105
106
107
  if (tx_mode == ALLOW_32X32) tx_mode += aom_rb_read_bit(rb);
  return tx_mode;
#else
Yaowu Xu's avatar
Yaowu Xu committed
108
  return aom_rb_read_bit(rb) ? TX_MODE_SELECT : aom_rb_read_literal(rb, 2);
109
#endif  // CONFIG_TX64X64
110
}
111
#endif  // CONFIG_SIMPLIFY_TX_MODE
Jingning Han's avatar
Jingning Han committed
112

113
static REFERENCE_MODE read_frame_reference_mode(
Yaowu Xu's avatar
Yaowu Xu committed
114
    const AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
115
  if (av1_is_compound_reference_allowed(cm)) {
Zoe Liu's avatar
Zoe Liu committed
116
    return aom_rb_read_bit(rb) ? REFERENCE_MODE_SELECT : SINGLE_REFERENCE;
117
118
119
120
  } else {
    return SINGLE_REFERENCE;
  }
}
Jingning Han's avatar
Jingning Han committed
121

122
static void inverse_transform_block(MACROBLOCKD *xd, int plane,
123
                                    const TX_TYPE tx_type,
124
                                    const TX_SIZE tx_size, uint8_t *dst,
125
126
                                    int stride, int16_t scan_line, int eob,
                                    int reduced_tx_set) {
Jingning Han's avatar
Jingning Han committed
127
  struct macroblockd_plane *const pd = &xd->plane[plane];
128
  tran_low_t *const dqcoeff = pd->dqcoeff;
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
129
130
  av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, dst, stride,
                              eob, reduced_tx_set);
131
  memset(dqcoeff, 0, (scan_line + 1) * sizeof(dqcoeff[0]));
Jingning Han's avatar
Jingning Han committed
132
133
}

134
135
136
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) {
137
  PLANE_TYPE plane_type = get_plane_type(plane);
Luc Trudeau's avatar
Luc Trudeau committed
138
  av1_predict_intra_block_facade(cm, xd, plane, col, row, tx_size);
Jingning Han's avatar
Jingning Han committed
139
140

  if (!mbmi->skip) {
141
    struct macroblockd_plane *const pd = &xd->plane[plane];
142
143
144
145
#if TXCOEFF_TIMER
    struct aom_usec_timer timer;
    aom_usec_timer_start(&timer);
#endif
Angie Chiang's avatar
Angie Chiang committed
146
147
#if CONFIG_LV_MAP
    int16_t max_scan_line = 0;
148
    int eob;
Luc Trudeau's avatar
Luc Trudeau committed
149
    av1_read_coeffs_txb_facade(cm, xd, r, row, col, plane, tx_size,
150
                               &max_scan_line, &eob);
151
    // tx_type will be read out in av1_read_coeffs_txb_facade
152
153
    const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, row, col, tx_size,
                                            cm->reduced_tx_set_used);
Angie Chiang's avatar
Angie Chiang committed
154
#else   // CONFIG_LV_MAP
155
156
    const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, row, col, tx_size,
                                            cm->reduced_tx_set_used);
Angie Chiang's avatar
Angie Chiang committed
157
    const SCAN_ORDER *scan_order = get_scan(cm, tx_size, tx_type, mbmi);
158
159
    int16_t max_scan_line = 0;
    const int eob =
160
        av1_decode_block_tokens(cm, xd, plane, scan_order, col, row, tx_size,
161
                                tx_type, &max_scan_line, r, mbmi->segment_id);
Angie Chiang's avatar
Angie Chiang committed
162
#endif  // CONFIG_LV_MAP
163
164
165
166
167
168
169

#if TXCOEFF_TIMER
    aom_usec_timer_mark(&timer);
    const int64_t elapsed_time = aom_usec_timer_elapsed(&timer);
    cm->txcoeff_timer += elapsed_time;
    ++cm->txb_count;
#endif
170
171
172
    if (eob) {
      uint8_t *dst =
          &pd->dst.buf[(row * pd->dst.stride + col) << tx_size_wide_log2[0]];
173
      inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
174
                              max_scan_line, eob, cm->reduced_tx_set_used);
175
    }
Jingning Han's avatar
Jingning Han committed
176
  }
177
#if CONFIG_CFL
178
  if (plane == AOM_PLANE_Y && xd->cfl.store_y && is_cfl_allowed(mbmi)) {
179
    cfl_store_tx(xd, row, col, tx_size, mbmi->sb_type);
180
  }
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
181
#endif  // CONFIG_CFL
Jingning Han's avatar
Jingning Han committed
182
183
}

Angie Chiang's avatar
Angie Chiang committed
184
185
static void decode_reconstruct_tx(AV1_COMMON *cm, MACROBLOCKD *const xd,
                                  aom_reader *r, MB_MODE_INFO *const mbmi,
186
                                  int plane, BLOCK_SIZE plane_bsize,
187
                                  int blk_row, int blk_col, int block,
Angie Chiang's avatar
Angie Chiang committed
188
189
190
191
                                  TX_SIZE tx_size, int *eob_total, int mi_row,
                                  int mi_col) {
  (void)mi_row;
  (void)mi_col;
192
  const struct macroblockd_plane *const pd = &xd->plane[plane];
193
194
  const int tx_row = blk_row >> (1 - pd->subsampling_y);
  const int tx_col = blk_col >> (1 - pd->subsampling_x);
195
  const TX_SIZE plane_tx_size =
196
      plane ? av1_get_uv_tx_size(mbmi, pd->subsampling_x, pd->subsampling_y)
197
            : mbmi->inter_tx_size[tx_row][tx_col];
198
  // Scale to match transform block unit.
199
200
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
201

202
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
203

204
  if (tx_size == plane_tx_size || plane) {
205
    PLANE_TYPE plane_type = get_plane_type(plane);
206
207
208
209
#if TXCOEFF_TIMER
    struct aom_usec_timer timer;
    aom_usec_timer_start(&timer);
#endif
Angie Chiang's avatar
Angie Chiang committed
210
211
#if CONFIG_LV_MAP
    int16_t max_scan_line = 0;
212
    int eob;
Luc Trudeau's avatar
Luc Trudeau committed
213
214
    av1_read_coeffs_txb_facade(cm, xd, r, blk_row, blk_col, plane, tx_size,
                               &max_scan_line, &eob);
215
    // tx_type will be read out in av1_read_coeffs_txb_facade
216
217
    const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
                                            tx_size, cm->reduced_tx_set_used);
Angie Chiang's avatar
Angie Chiang committed
218
#else   // CONFIG_LV_MAP
219
220
    const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, blk_row, blk_col,
                                            tx_size, cm->reduced_tx_set_used);
221
    const SCAN_ORDER *sc = get_scan(cm, tx_size, tx_type, mbmi);
222
    int16_t max_scan_line = 0;
223
224
225
    const int eob =
        av1_decode_block_tokens(cm, xd, plane, sc, blk_col, blk_row, tx_size,
                                tx_type, &max_scan_line, r, mbmi->segment_id);
Angie Chiang's avatar
Angie Chiang committed
226
#endif  // CONFIG_LV_MAP
227
228
229
230
231
232
233
234

#if TXCOEFF_TIMER
    aom_usec_timer_mark(&timer);
    const int64_t elapsed_time = aom_usec_timer_elapsed(&timer);
    cm->txcoeff_timer += elapsed_time;
    ++cm->txb_count;
#endif

Angie Chiang's avatar
Angie Chiang committed
235
    uint8_t *dst =
236
        &pd->dst
Angie Chiang's avatar
Angie Chiang committed
237
238
239
240
241
             .buf[(blk_row * pd->dst.stride + blk_col) << tx_size_wide_log2[0]];
    inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
                            max_scan_line, eob, cm->reduced_tx_set_used);
#if CONFIG_MISMATCH_DEBUG
    int pixel_c, pixel_r;
242
    BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
243
244
    int blk_w = block_size_wide[bsize];
    int blk_h = block_size_high[bsize];
Angie Chiang's avatar
Angie Chiang committed
245
246
247
    mi_to_pixel_loc(&pixel_c, &pixel_r, mi_col, mi_row, blk_col, blk_row,
                    pd->subsampling_x, pd->subsampling_y);
    mismatch_check_block_tx(dst, pd->dst.stride, plane, pixel_c, pixel_r, blk_w,
248
                            blk_h, xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH);
Angie Chiang's avatar
Angie Chiang committed
249
#endif
250
251
    *eob_total += eob;
  } else {
252
    const TX_SIZE sub_txs = sub_tx_size_map[1][tx_size];
253
254
    assert(IMPLIES(tx_size <= TX_4X4, sub_txs == tx_size));
    assert(IMPLIES(tx_size > TX_4X4, sub_txs < tx_size));
255
256
257
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
    const int sub_step = bsw * bsh;
258

259
    assert(bsw > 0 && bsh > 0);
260

261
262
263
264
    for (int row = 0; row < tx_size_high_unit[tx_size]; row += bsh) {
      for (int col = 0; col < tx_size_wide_unit[tx_size]; col += bsw) {
        const int offsetr = blk_row + row;
        const int offsetc = blk_col + col;
265

266
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
267

268
        decode_reconstruct_tx(cm, xd, r, mbmi, plane, plane_bsize, offsetr,
Angie Chiang's avatar
Angie Chiang committed
269
270
                              offsetc, block, sub_txs, eob_total, mi_row,
                              mi_col);
271
272
        block += sub_step;
      }
273
274
275
    }
  }
}
Jingning Han's avatar
Jingning Han committed
276

277
278
279
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) {
280
281
  const int num_planes = av1_num_planes(cm);

Jingning Han's avatar
Jingning Han committed
282
283
284
285
286
287
288
289
  const int offset = mi_row * cm->mi_stride + mi_col;
  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;
290
291
292
#if CONFIG_RD_DEBUG
  xd->mi[0]->mbmi.mi_row = mi_row;
  xd->mi[0]->mbmi.mi_col = mi_col;
293
294
#endif
#if CONFIG_CFL
295
296
  xd->cfl.mi_row = mi_row;
  xd->cfl.mi_col = mi_col;
297
#endif
298
299

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

307
308
  set_plane_n4(xd, bw, bh, num_planes);
  set_skip_context(xd, mi_row, mi_col, num_planes);
Jingning Han's avatar
Jingning Han committed
309

310
311
312
  // 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,
313
#if CONFIG_DEPENDENT_HORZTILES
314
315
316
                 cm->dependent_horz_tiles,
#endif  // CONFIG_DEPENDENT_HORZTILES
                 cm->mi_rows, cm->mi_cols);
Jingning Han's avatar
Jingning Han committed
317

318
  av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
319
                       mi_col, num_planes);
Jingning Han's avatar
Jingning Han committed
320
321
}

322
323
static void decode_mbmi_block(AV1Decoder *const pbi, MACROBLOCKD *const xd,
                              int mi_row, int mi_col, aom_reader *r,
324
#if CONFIG_EXT_PARTITION_TYPES
325
                              PARTITION_TYPE partition,
326
#endif  // CONFIG_EXT_PARTITION_TYPES
327
                              BLOCK_SIZE bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
328
  AV1_COMMON *const cm = &pbi->common;
329
330
  const int bw = mi_size_wide[bsize];
  const int bh = mi_size_high[bsize];
Yaowu Xu's avatar
Yaowu Xu committed
331
332
  const int x_mis = AOMMIN(bw, cm->mi_cols - mi_col);
  const int y_mis = AOMMIN(bh, cm->mi_rows - mi_row);
333

Michael Bebenita's avatar
Michael Bebenita committed
334
335
336
#if CONFIG_ACCOUNTING
  aom_accounting_set_context(&pbi->accounting, mi_col, mi_row);
#endif
337
  set_offsets(cm, xd, bsize, mi_row, mi_col, bw, bh, x_mis, y_mis);
338
339
340
#if CONFIG_EXT_PARTITION_TYPES
  xd->mi[0]->mbmi.partition = partition;
#endif
Yaowu Xu's avatar
Yaowu Xu committed
341
  av1_read_mode_info(pbi, xd, mi_row, mi_col, r, x_mis, y_mis);
Jingning Han's avatar
Jingning Han committed
342
343
344
345
  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)
Yaowu Xu's avatar
Yaowu Xu committed
346
      aom_internal_error(xd->error_info, AOM_CODEC_CORRUPT_FRAME,
347
                         "Invalid block size.");
Jingning Han's avatar
Jingning Han committed
348
349
  }

350
351
  int reader_corrupted_flag = aom_reader_has_error(r);
  aom_merge_corrupted_flag(&xd->corrupted, reader_corrupted_flag);
352
353
354
355
356
357
358
}

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;
359
  const int num_planes = av1_num_planes(cm);
360
361
362
363
364
  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);

365
366
  set_offsets(cm, xd, bsize, mi_row, mi_col, bw, bh, x_mis, y_mis);
  MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
367
#if CONFIG_CFL
368
  CFL_CTX *const cfl = &xd->cfl;
369
370
  cfl->is_chroma_reference = is_chroma_reference(
      mi_row, mi_col, bsize, cfl->subsampling_x, cfl->subsampling_y);
371
#endif  // CONFIG_CFL
372

373
  if (cm->delta_q_present_flag) {
374
    for (int i = 0; i < MAX_SEGMENTS; i++) {
Fangwen Fu's avatar
Fangwen Fu committed
375
#if CONFIG_EXT_DELTA_Q
376
377
      const int current_qindex =
          av1_get_qindex(&cm->seg, i, xd->current_qindex);
Fangwen Fu's avatar
Fangwen Fu committed
378
#else
379
380
      const int current_qindex = xd->current_qindex;
#endif  // CONFIG_EXT_DELTA_Q
381
      for (int j = 0; j < num_planes; ++j) {
382
383
384
385
386
        const int dc_delta_q =
            j == 0 ? cm->y_dc_delta_q
                   : (j == 1 ? cm->u_dc_delta_q : cm->v_dc_delta_q);
        const int ac_delta_q =
            j == 0 ? 0 : (j == 1 ? cm->u_ac_delta_q : cm->v_ac_delta_q);
387
388
389
390
        xd->plane[j].seg_dequant_QTX[i][0] =
            av1_dc_quant_QTX(current_qindex, dc_delta_q, cm->bit_depth);
        xd->plane[j].seg_dequant_QTX[i][1] =
            av1_ac_quant_QTX(current_qindex, ac_delta_q, cm->bit_depth);
391
      }
392
393
    }
  }
394
  if (mbmi->skip) av1_reset_skip_context(xd, mi_row, mi_col, bsize, num_planes);
395

396
  if (!is_inter_block(mbmi)) {
397
    for (int plane = 0; plane < AOMMIN(2, num_planes); ++plane) {
398
      if (mbmi->palette_mode_info.palette_size[plane])
Yaowu Xu's avatar
Yaowu Xu committed
399
        av1_decode_palette_tokens(xd, plane, r);
Jingning Han's avatar
Jingning Han committed
400
    }
401

402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
    const struct macroblockd_plane *const y_pd = &xd->plane[0];
    const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, y_pd);
    int row, col;
    const int max_blocks_wide = max_block_wide(xd, plane_bsize, 0);
    const int max_blocks_high = max_block_high(xd, plane_bsize, 0);

    const BLOCK_SIZE max_unit_bsize = get_plane_block_size(BLOCK_64X64, y_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) {
      for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
        for (int plane = 0; plane < num_planes; ++plane) {
          const struct macroblockd_plane *const pd = &xd->plane[plane];
          if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
                                   pd->subsampling_y))
            continue;

          const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
          const int stepr = tx_size_high_unit[tx_size];
          const int stepc = tx_size_wide_unit[tx_size];

          const int unit_height = ROUND_POWER_OF_TWO(
              AOMMIN(mu_blocks_high + row, max_blocks_high), pd->subsampling_y);
          const int unit_width = ROUND_POWER_OF_TWO(
              AOMMIN(mu_blocks_wide + col, max_blocks_wide), pd->subsampling_x);

          for (int blk_row = row >> pd->subsampling_y; blk_row < unit_height;
               blk_row += stepr)
            for (int blk_col = col >> pd->subsampling_x; blk_col < unit_width;
                 blk_col += stepc)
437
438
439
440
              predict_and_reconstruct_intra_block(cm, xd, r, mbmi, plane,
                                                  blk_row, blk_col, tx_size);
        }
      }
441
442
    }
  } else {
443
    for (int ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
444
      const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
Alex Converse's avatar
Alex Converse committed
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
      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,
461
                             &ref_buf->sf, num_planes);
Alex Converse's avatar
Alex Converse committed
462
      }
463
    }
464

465
    av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
466

Yue Chen's avatar
Yue Chen committed
467
    if (mbmi->motion_mode == OBMC_CAUSAL) {
468
      av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
469
    }
Angie Chiang's avatar
Angie Chiang committed
470
471

#if CONFIG_MISMATCH_DEBUG
472
    for (int plane = 0; plane < num_planes; ++plane) {
Angie Chiang's avatar
Angie Chiang committed
473
474
475
476
477
478
479
480
      const struct macroblockd_plane *pd = &xd->plane[plane];
      int pixel_c, pixel_r;
      mi_to_pixel_loc(&pixel_c, &pixel_r, mi_col, mi_row, 0, 0,
                      pd->subsampling_x, pd->subsampling_y);
      if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
                               pd->subsampling_y))
        continue;
      mismatch_check_block_pre(pd->dst.buf, pd->dst.stride, plane, pixel_c,
481
482
                               pixel_r, pd->width, pd->height,
                               xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH);
Angie Chiang's avatar
Angie Chiang committed
483
484
485
    }
#endif

486
487
488
    // Reconstruction
    if (!mbmi->skip) {
      int eobtotal = 0;
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505

      const struct macroblockd_plane *const y_pd = &xd->plane[0];
      const int max_blocks_wide = max_block_wide(xd, bsize, 0);
      const int max_blocks_high = max_block_high(xd, bsize, 0);
      int row, col;

      const BLOCK_SIZE max_unit_bsize = get_plane_block_size(BLOCK_64X64, y_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) {
        for (col = 0; col < max_blocks_wide; col += mu_blocks_wide) {
506
          for (int plane = 0; plane < num_planes; ++plane) {
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
            const struct macroblockd_plane *const pd = &xd->plane[plane];
            if (!is_chroma_reference(mi_row, mi_col, bsize, pd->subsampling_x,
                                     pd->subsampling_y))
              continue;
            const BLOCK_SIZE bsizec =
                scale_chroma_bsize(bsize, pd->subsampling_x, pd->subsampling_y);
            const BLOCK_SIZE plane_bsize = get_plane_block_size(bsizec, pd);

            TX_SIZE max_tx_size = get_vartx_max_txsize(
                xd, plane_bsize, pd->subsampling_x || pd->subsampling_y);
            const int bh_var_tx = tx_size_high_unit[max_tx_size];
            const int bw_var_tx = tx_size_wide_unit[max_tx_size];
            int block = 0;
            int step =
                tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size];
522
            int blk_row, blk_col;
523
524
525
526
527
528
529
530
531
532
533
            const int unit_height = ROUND_POWER_OF_TWO(
                AOMMIN(mu_blocks_high + row, max_blocks_high),
                pd->subsampling_y);
            const int unit_width = ROUND_POWER_OF_TWO(
                AOMMIN(mu_blocks_wide + col, max_blocks_wide),
                pd->subsampling_x);

            for (blk_row = row >> pd->subsampling_y; blk_row < unit_height;
                 blk_row += bh_var_tx) {
              for (blk_col = col >> pd->subsampling_x; blk_col < unit_width;
                   blk_col += bw_var_tx) {
534
535
                decode_reconstruct_tx(cm, xd, r, mbmi, plane, plane_bsize,
                                      blk_row, blk_col, block, max_tx_size,
Angie Chiang's avatar
Angie Chiang committed
536
                                      &eobtotal, mi_row, mi_col);
537
538
539
                block += step;
              }
            }
540
541
          }
        }
542
      }
Jingning Han's avatar
Jingning Han committed
543
544
    }
  }
545
#if CONFIG_CFL
546
  if (mbmi->uv_mode != UV_CFL_PRED) {
547
    if (!cfl->is_chroma_reference && is_inter_block(mbmi) &&
548
        is_cfl_allowed(mbmi)) {
549
550
551
      cfl_store_block(xd, mbmi->sb_type, mbmi->tx_size);
    }
  }
552
#endif  // CONFIG_CFL
Jingning Han's avatar
Jingning Han committed
553

554
555
  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
556
557
}

558
559
560
561
562
563
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) {
564
  decode_mbmi_block(pbi, xd, mi_row, mi_col, r,
565
566
567
568
#if CONFIG_EXT_PARTITION_TYPES
                    partition,
#endif
                    bsize);
569
  decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, bsize);
570
571
}

572
573
static PARTITION_TYPE read_partition(MACROBLOCKD *xd, int mi_row, int mi_col,
                                     aom_reader *r, int has_rows, int has_cols,
574
575
                                     BLOCK_SIZE bsize) {
  const int ctx = partition_plane_context(xd, mi_row, mi_col, bsize);
576
  FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
Jingning Han's avatar
Jingning Han committed
577

578
  if (!has_rows && !has_cols) return PARTITION_SPLIT;
Jingning Han's avatar
Jingning Han committed
579

580
581
  assert(ctx >= 0);
  aom_cdf_prob *partition_cdf = ec_ctx->partition_cdf[ctx];
582
  if (has_rows && has_cols) {
583
584
    return (PARTITION_TYPE)aom_read_symbol(
        r, partition_cdf, partition_cdf_length(bsize), ACCT_STR);
585
  } else if (!has_rows && has_cols) {
586
587
    assert(bsize > BLOCK_8X8);
    aom_cdf_prob cdf[2];
588
    partition_gather_vert_alike(cdf, partition_cdf, bsize);
589
    assert(cdf[1] == AOM_ICDF(CDF_PROB_TOP));
590
591
592
    return aom_read_cdf(r, cdf, 2, ACCT_STR) ? PARTITION_SPLIT : PARTITION_HORZ;
  } else {
    assert(has_rows && !has_cols);
593
594
    assert(bsize > BLOCK_8X8);
    aom_cdf_prob cdf[2];
595
    partition_gather_horz_alike(cdf, partition_cdf, bsize);
596
    assert(cdf[1] == AOM_ICDF(CDF_PROB_TOP));
597
    return aom_read_cdf(r, cdf, 2, ACCT_STR) ? PARTITION_SPLIT : PARTITION_VERT;
598
  }
Jingning Han's avatar
Jingning Han committed
599
600
601
}

// TODO(slavarnway): eliminate bsize and subsize in future commits
Yaowu Xu's avatar
Yaowu Xu committed
602
603
static void decode_partition(AV1Decoder *const pbi, MACROBLOCKD *const xd,
                             int mi_row, int mi_col, aom_reader *r,
604
                             BLOCK_SIZE bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
605
  AV1_COMMON *const cm = &pbi->common;
606
  const int num_8x8_wh = mi_size_wide[bsize];
Jingning Han's avatar
Jingning Han committed
607
608
609
  const int hbs = num_8x8_wh >> 1;
  PARTITION_TYPE partition;
  BLOCK_SIZE subsize;
610
#if CONFIG_EXT_PARTITION_TYPES
611
  const int quarter_step = num_8x8_wh / 4;
612
  BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
613
#endif
Jingning Han's avatar
Jingning Han committed
614
615
616
  const int has_rows = (mi_row + hbs) < cm->mi_rows;
  const int has_cols = (mi_col + hbs) < cm->mi_cols;

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

619
#if CONFIG_LOOP_RESTORATION
620
  const int num_planes = av1_num_planes(cm);
621
  for (int plane = 0; plane < num_planes; ++plane) {
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
    int rcol0, rcol1, rrow0, rrow1, tile_tl_idx;
    if (av1_loop_restoration_corners_in_sb(cm, plane, mi_row, mi_col, bsize,
                                           &rcol0, &rcol1, &rrow0, &rrow1,
                                           &tile_tl_idx)) {
      const int rstride = cm->rst_info[plane].horz_units_per_tile;
      for (int rrow = rrow0; rrow < rrow1; ++rrow) {
        for (int rcol = rcol0; rcol < rcol1; ++rcol) {
          const int rtile_idx = tile_tl_idx + rcol + rrow * rstride;
          loop_restoration_read_sb_coeffs(cm, xd, r, plane, rtile_idx);
        }
      }
    }
  }
#endif

637
  partition = (bsize < BLOCK_8X8) ? PARTITION_NONE
638
                                  : read_partition(xd, mi_row, mi_col, r,
639
                                                   has_rows, has_cols, bsize);
Jingning Han's avatar
Jingning Han committed
640
  subsize = subsize_lookup[partition][bsize];  // get_subsize(bsize, partition);
641

642
643
644
645
646
647
648
649
650
  // 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]);
  }

651
652
653
654
655
656
657
658
659
660
661
662
#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))

663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
  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;
679
#if CONFIG_EXT_PARTITION_TYPES
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
    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;
    case PARTITION_HORZ_4:
701
      for (int i = 0; i < 4; ++i) {
702
703
704
705
706
707
        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:
708
      for (int i = 0; i < 4; ++i) {
709
710
711
712
713
        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;
714
#endif  // CONFIG_EXT_PARTITION_TYPES
715
    default: assert(0 && "Invalid partition type");
Jingning Han's avatar
Jingning Han committed
716
717
  }

718
719
720
721
722
#undef DEC_PARTITION
#undef DEC_BLOCK
#undef DEC_BLOCK_EPT_ARG
#undef DEC_BLOCK_STX_ARG

723
#if CONFIG_EXT_PARTITION_TYPES
724
  update_ext_partition_context(xd, mi_row, mi_col, subsize, bsize, partition);
725
#else
Jingning Han's avatar
Jingning Han committed
726
727
728
  // update partition context
  if (bsize >= BLOCK_8X8 &&
      (bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
729
    update_partition_context(xd, mi_row, mi_col, subsize, bsize);
730
#endif  // CONFIG_EXT_PARTITION_TYPES
Jingning Han's avatar
Jingning Han committed
731
732
}

733
static void setup_bool_decoder(const uint8_t *data, const uint8_t *data_end,
Alex Converse's avatar
Alex Converse committed
734
                               const size_t read_size,
Yaowu Xu's avatar
Yaowu Xu committed
735
                               struct aom_internal_error_info *error_info,
736
                               aom_reader *r, uint8_t allow_update_cdf) {
Alex Converse's avatar
Alex Converse committed
737
738
739
740
  // Validate the calculated partition length. If the buffer
  // described by the partition can't be fully read, then restrict
  // it to the portion that can be (for EC mode) or throw an error.
  if (!read_is_valid(data, read_size, data_end))
Yaowu Xu's avatar
Yaowu Xu committed
741
    aom_internal_error(error_info, AOM_CODEC_CORRUPT_FRAME,
Alex Converse's avatar
Alex Converse committed
742
743
                       "Truncated packet or corrupt tile length");

744
  if (aom_reader_init(r, data, read_size))
Yaowu Xu's avatar
Yaowu Xu committed
745
    aom_internal_error(error_info, AOM_CODEC_MEM_ERROR,
Alex Converse's avatar
Alex Converse committed
746
                       "Failed to allocate bool decoder %d", 1);
747
748

  r->allow_update_cdf = allow_update_cdf;
Alex Converse's avatar
Alex Converse committed
749
}
Jingning Han's avatar
Jingning Han committed
750

Yaowu Xu's avatar
Yaowu Xu committed
751
752
static void setup_segmentation(AV1_COMMON *const cm,
                               struct aom_read_bit_buffer *rb) {
753
  struct segmentation *const seg = &cm->seg;
Jingning Han's avatar
Jingning Han committed
754
755
756

  seg->update_map = 0;
  seg->update_data = 0;
757
  seg->temporal_update = 0;
Jingning Han's avatar
Jingning Han committed
758

Yaowu Xu's avatar
Yaowu Xu committed
759
  seg->enabled = aom_rb_read_bit(rb);
760
  if (!seg->enabled) return;
761
762
763
764
#if CONFIG_SEGMENT_PRED_LAST
  if (cm->seg.enabled && !cm->frame_parallel_decode && cm->prev_frame)
    cm->last_frame_seg_map = cm->prev_frame->seg_map;
#endif
Jingning Han's avatar
Jingning Han committed
765
  // Segmentation map update
766
767
768
  if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
    seg->update_map = 1;
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
769
    seg->update_map = aom_rb_read_bit(rb);
770
  }
Jingning Han's avatar
Jingning Han committed
771
  if (seg->update_map) {
772
773
774
    if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
      seg->temporal_update = 0;
    } else {
Yaowu Xu's avatar
Yaowu Xu committed
775
      seg->temporal_update = aom_rb_read_bit(rb);
776
    }
Jingning Han's avatar
Jingning Han committed
777
778
  }

779
780
781
782
#if CONFIG_SPATIAL_SEGMENTATION
  cm->preskip_segid = 0;
#endif

Jingning Han's avatar
Jingning Han committed
783
  // Segmentation data update
Yaowu Xu's avatar
Yaowu Xu committed
784
  seg->update_data = aom_rb_read_bit(rb);
Jingning Han's avatar
Jingning Han committed
785
  if (seg->update_data) {
Yaowu Xu's avatar
Yaowu Xu committed
786
    av1_clearall_segfeatures(seg);
Jingning Han's avatar
Jingning Han committed
787

788
789
    for (int i = 0; i < MAX_SEGMENTS; i++) {
      for (int j = 0; j < SEG_LVL_MAX; j++) {
Jingning Han's avatar
Jingning Han committed
790
        int data = 0;
Yaowu Xu's avatar
Yaowu Xu committed
791
        const int feature_enabled = aom_rb_read_bit(rb);
Jingning Han's avatar
Jingning Han committed
792
        if (feature_enabled) {
793
794
795
796
#if CONFIG_SPATIAL_SEGMENTATION
          cm->preskip_segid |= j >= SEG_LVL_REF_FRAME;
          cm->last_active_segid = i;
#endif
Yaowu Xu's avatar
Yaowu Xu committed
797
          av1_enable_segfeature(seg, i, j);
798
799
800
801
802
803
804
805
806
807
808
809

          const int data_max = av1_seg_feature_data_max(j);
          const int data_min = -data_max;
          const int ubits = get_unsigned_bits(data_max);

          if (av1_is_segfeature_signed(j)) {
            data = aom_rb_read_inv_signed_literal(rb, ubits);
          } else {
            data = aom_rb_read_literal(rb, ubits);
          }

          data = clamp(data, data_min, data_max);
Jingning Han's avatar
Jingning Han committed
810
        }
Yaowu Xu's avatar
Yaowu Xu committed
811
        av1_set_segdata(seg, i, j, data);
Jingning Han's avatar
Jingning Han committed
812
813
814
815
816
      }
    }
  }
}

817
#if CONFIG_LOOP_RESTORATION
818
819
static void decode_restoration_mode(AV1_COMMON *cm,
                                    struct aom_read_bit_buffer *rb) {
820
  const int num_planes = av1_num_planes(cm);
821
822
823
#if CONFIG_INTRABC
  if (cm->allow_intrabc && NO_FILTER_FOR_IBC) return;
#endif  // CONFIG_INTRABC
824
  int all_none = 1, chroma_none = 1;
825
  for (int p = 0; p < num_planes; ++p) {
826
    RestorationInfo *rsi = &cm->rst_info[p];
827
828
829
830
    if (aom_rb_read_bit(rb)) {
      rsi->frame_restoration_type =
          aom_rb_read_bit(rb) ? RESTORE_SGRPROJ : RESTORE_WIENER;
    } else {
831
832
      rsi->frame_restoration_type =
          aom_rb_read_bit(rb) ? RESTORE_SWITCHABLE : RESTORE_NONE;
833
    }
834
835
836
837
    if (rsi->frame_restoration_type != RESTORE_NONE) {
      all_none = 0;
      chroma_none &= p == 0;
    }
838
  }
839
  if (!all_none) {
840
    const int qsize = RESTORATION_TILESIZE_MAX >> 2;
841
    for (int p = 0; p < num_planes; ++p)
842
843
844
      cm->rst_info[p].restoration_unit_size = qsize;

    RestorationInfo *rsi = &cm->rst_info[0];
845
    rsi->restoration_unit_size <<= aom_rb_read_bit(rb);
846
    if (rsi->restoration_unit_size != qsize) {
847
      rsi->restoration_unit_size <<= aom_rb_read_bit(rb);
848
    }
849
850
  } else {
    const int size = RESTORATION_TILESIZE_MAX;
851
    for (int p = 0; p < num_planes; ++p)
852
      cm->rst_info[p].restoration_unit_size = size;
853
  }
854

855
  if (num_planes > 1) {
856
857
858
859
860
861
862
863
864
865
    int s = AOMMIN(cm->subsampling_x, cm->subsampling_y);
    if (s && !chroma_none) {
      cm->rst_info[1].restoration_unit_size =
          cm->rst_info[0].restoration_unit_size >> (aom_rb_read_bit(rb) * s);
    } else {
      cm->rst_info[1].restoration_unit_size =
          cm->rst_info[0].restoration_unit_size;
    }
    cm->rst_info[2].restoration_unit_size =
        cm->rst_info[1].restoration_unit_size;
866
  }
867
868
}

869
static void read_wiener_filter(int wiener_win, WienerInfo *wiener_info,
870
                               WienerInfo *ref_wiener_info, aom_reader *rb) {
871
872
873
  memset(wiener_info->vfilter, 0, sizeof(wiener_info->vfilter));
  memset(wiener_info->hfilter, 0, sizeof(wiener_info->hfilter));

874
875
876
877
878
879
880
881
882
  if (wiener_win == WIENER_WIN)
    wiener_info->vfilter[0] = wiener_info->vfilter[WIENER_WIN - 1] =
        aom_read_primitive_refsubexpfin(
            rb, WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1,
            WIENER_FILT_TAP0_SUBEXP_K,
            ref_wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV, ACCT_STR) +
        WIENER_FILT_TAP0_MINV;
  else
    wiener_info->vfilter[0] = wiener_info->vfilter[WIENER_WIN - 1] = 0;
883
  wiener_info->vfilter[1] = wiener_info->vfilter[WIENER_WIN - 2] =
884
885
886
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
          WIENER_FILT_TAP1_SUBEXP_K,
887
          ref_wiener_info->vfilter[1] - WIENER_FILT_TAP1_MINV, ACCT_STR) +
888
      WIENER_FILT_TAP1_MINV;
889
  wiener_info->vfilter[2] = wiener_info->vfilter[WIENER_WIN - 3] =
890
891
892
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
          WIENER_FILT_TAP2_SUBEXP_K,
893
          ref_wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV, ACCT_STR) +
894
      WIENER_FILT_TAP2_MINV;
895
  // The central element has an implicit +WIENER_FILT_STEP
896
  wiener_info->vfilter[WIENER_HALFWIN] =
897
898
899
      -2 * (wiener_info->vfilter[0] + wiener_info->vfilter[1] +
            wiener_info->vfilter[2]);

900
901
902
903
904
905
906
907
908
  if (wiener_win == WIENER_WIN)
    wiener_info->hfilter[0] = wiener_info->hfilter[WIENER_WIN - 1] =
        aom_read_primitive_refsubexpfin(
            rb, WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1,
            WIENER_FILT_TAP0_SUBEXP_K,
            ref_wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV, ACCT_STR) +
        WIENER_FILT_TAP0_MINV;
  else
    wiener_info->hfilter[0] = wiener_info->hfilter[WIENER_WIN - 1] = 0;
909
  wiener_info->hfilter[1] = wiener_info->hfilter[WIENER_WIN - 2] =
910
911
912
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
          WIENER_FILT_TAP1_SUBEXP_K,
913
          ref_wiener_info->hfilter[1] - WIENER_FILT_TAP1_MINV, ACCT_STR) +
914
      WIENER_FILT_TAP1_MINV;
915
  wiener_info->hfilter[2] = wiener_info->hfilter[WIENER_WIN - 3] =
916
917
918
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
          WIENER_FILT_TAP2_SUBEXP_K,
919
          ref_wiener_info->hfilter[2] - WIENER_FILT_TAP2_MINV, ACCT_STR) +
920
      WIENER_FILT_TAP2_MINV;
921
  // The central element has an implicit +WIENER_FILT_STEP
922
  wiener_info->hfilter[WIENER_HALFWIN] =
923
924
      -2 * (wiener_info->hfilter[0] + wiener_info->hfilter[1] +
            wiener_info->hfilter[2]);
Debargha Mukherjee's avatar