decodeframe.c 129 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

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"
64
#include "av1/decoder/symbolrate.h"
Jingning Han's avatar
Jingning Han committed
65

Yue Chen's avatar
Yue Chen committed
66
67
#include "av1/common/warped_motion.h"

Yaowu Xu's avatar
Yaowu Xu committed
68
#define MAX_AV1_HEADER_SIZE 80
Michael Bebenita's avatar
Michael Bebenita committed
69
#define ACCT_STR __func__
Jingning Han's avatar
Jingning Han committed
70

71
72
73
74
#if CONFIG_CFL
#include "av1/common/cfl.h"
#endif

75
76
77
78
#if CONFIG_STRIPED_LOOP_RESTORATION && !CONFIG_LOOP_RESTORATION
#error "striped_loop_restoration requires loop_restoration"
#endif

79
80
81
82
83
84
85
#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
86
static void setup_compound_reference_mode(AV1_COMMON *cm) {
87
  cm->comp_fwd_ref[0] = LAST_FRAME;
88
89
90
91
  cm->comp_fwd_ref[1] = LAST2_FRAME;
  cm->comp_fwd_ref[2] = LAST3_FRAME;
  cm->comp_fwd_ref[3] = GOLDEN_FRAME;

92
  cm->comp_bwd_ref[0] = BWDREF_FRAME;
Zoe Liu's avatar
Zoe Liu committed
93
94
  cm->comp_bwd_ref[1] = ALTREF2_FRAME;
  cm->comp_bwd_ref[2] = ALTREF_FRAME;
Jingning Han's avatar
Jingning Han committed
95
96
97
98
99
100
}

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

101
102
103
104
105
106
#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
107
108
static TX_MODE read_tx_mode(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
  if (cm->all_lossless) return ONLY_4X4;
109
#if CONFIG_TX64X64
Urvang Joshi's avatar
Urvang Joshi committed
110
111
  TX_MODE tx_mode =
      aom_rb_read_bit(rb) ? TX_MODE_SELECT : aom_rb_read_literal(rb, 2);
112
113
114
  if (tx_mode == ALLOW_32X32) tx_mode += aom_rb_read_bit(rb);
  return tx_mode;
#else
Yaowu Xu's avatar
Yaowu Xu committed
115
  return aom_rb_read_bit(rb) ? TX_MODE_SELECT : aom_rb_read_literal(rb, 2);
116
#endif  // CONFIG_TX64X64
117
}
118
#endif  // CONFIG_SIMPLIFY_TX_MODE
Jingning Han's avatar
Jingning Han committed
119

120
static REFERENCE_MODE read_frame_reference_mode(
Yaowu Xu's avatar
Yaowu Xu committed
121
    const AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
122
  if (av1_is_compound_reference_allowed(cm)) {
Zoe Liu's avatar
Zoe Liu committed
123
    return aom_rb_read_bit(rb) ? REFERENCE_MODE_SELECT : SINGLE_REFERENCE;
124
125
126
127
  } else {
    return SINGLE_REFERENCE;
  }
}
Jingning Han's avatar
Jingning Han committed
128

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

141
142
143
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) {
144
  PLANE_TYPE plane_type = get_plane_type(plane);
Luc Trudeau's avatar
Luc Trudeau committed
145
  av1_predict_intra_block_facade(cm, xd, plane, col, row, tx_size);
Jingning Han's avatar
Jingning Han committed
146
147

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

#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
175
176
177
    if (eob) {
      uint8_t *dst =
          &pd->dst.buf[(row * pd->dst.stride + col) << tx_size_wide_log2[0]];
178
      inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
179
                              max_scan_line, eob, cm->reduced_tx_set_used);
180
    }
Jingning Han's avatar
Jingning Han committed
181
  }
182
#if CONFIG_CFL
183
  if (plane == AOM_PLANE_Y && xd->cfl.store_y && is_cfl_allowed(mbmi)) {
184
    cfl_store_tx(xd, row, col, tx_size, mbmi->sb_type);
185
  }
Sebastien Alaiwan's avatar
Sebastien Alaiwan committed
186
#endif  // CONFIG_CFL
Jingning Han's avatar
Jingning Han committed
187
188
}

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

207
  if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return;
208

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

#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
240
    uint8_t *dst =
241
        &pd->dst
Angie Chiang's avatar
Angie Chiang committed
242
243
244
245
246
             .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;
247
    BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
248
249
    int blk_w = block_size_wide[bsize];
    int blk_h = block_size_high[bsize];
Angie Chiang's avatar
Angie Chiang committed
250
251
252
253
254
    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,
                            blk_h);
#endif
255
256
    *eob_total += eob;
  } else {
257
    const TX_SIZE sub_txs = sub_tx_size_map[1][tx_size];
258
259
    assert(IMPLIES(tx_size <= TX_4X4, sub_txs == tx_size));
    assert(IMPLIES(tx_size > TX_4X4, sub_txs < tx_size));
260
261
262
    const int bsw = tx_size_wide_unit[sub_txs];
    const int bsh = tx_size_high_unit[sub_txs];
    const int sub_step = bsw * bsh;
263

264
    assert(bsw > 0 && bsh > 0);
265

266
267
268
269
    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;
270

271
        if (offsetr >= max_blocks_high || offsetc >= max_blocks_wide) continue;
272

273
        decode_reconstruct_tx(cm, xd, r, mbmi, plane, plane_bsize, offsetr,
Angie Chiang's avatar
Angie Chiang committed
274
275
                              offsetc, block, sub_txs, eob_total, mi_row,
                              mi_col);
276
277
        block += sub_step;
      }
278
279
280
    }
  }
}
Jingning Han's avatar
Jingning Han committed
281

282
283
284
static void set_offsets(AV1_COMMON *const cm, MACROBLOCKD *const xd,
                        BLOCK_SIZE bsize, int mi_row, int mi_col, int bw,
                        int bh, int x_mis, int y_mis) {
Jingning Han's avatar
Jingning Han committed
285
286
287
288
289
290
291
292
  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;
293
294
295
#if CONFIG_RD_DEBUG
  xd->mi[0]->mbmi.mi_row = mi_row;
  xd->mi[0]->mbmi.mi_col = mi_col;
296
297
#endif
#if CONFIG_CFL
298
299
  xd->cfl.mi_row = mi_row;
  xd->cfl.mi_col = mi_col;
300
#endif
301
302

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

Jingning Han's avatar
Jingning Han committed
310
  set_plane_n4(xd, bw, bh);
Jingning Han's avatar
Jingning Han committed
311
312
  set_skip_context(xd, mi_row, mi_col);

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

321
322
  av1_setup_dst_planes(xd->plane, bsize, get_frame_new_buffer(cm), mi_row,
                       mi_col);
Jingning Han's avatar
Jingning Han committed
323
324
}

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

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

353
354
  int reader_corrupted_flag = aom_reader_has_error(r);
  aom_merge_corrupted_flag(&xd->corrupted, reader_corrupted_flag);
355
356
357
358
359
360
361
362
363
364
365
366
}

static void decode_token_and_recon_block(AV1Decoder *const pbi,
                                         MACROBLOCKD *const xd, int mi_row,
                                         int mi_col, aom_reader *r,
                                         BLOCK_SIZE bsize) {
  AV1_COMMON *const cm = &pbi->common;
  const int bw = mi_size_wide[bsize];
  const int bh = mi_size_high[bsize];
  const int x_mis = AOMMIN(bw, cm->mi_cols - mi_col);
  const int y_mis = AOMMIN(bh, cm->mi_rows - mi_row);

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

375
  if (cm->delta_q_present_flag) {
376
    for (int i = 0; i < MAX_SEGMENTS; i++) {
Fangwen Fu's avatar
Fangwen Fu committed
377
#if CONFIG_EXT_DELTA_Q
378
379
      const int current_qindex =
          av1_get_qindex(&cm->seg, i, xd->current_qindex);
Fangwen Fu's avatar
Fangwen Fu committed
380
#else
381
382
      const int current_qindex = xd->current_qindex;
#endif  // CONFIG_EXT_DELTA_Q
383
      for (int j = 0; j < av1_num_planes(cm); ++j) {
384
385
386
387
388
        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);
389
390
391
392
        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);
393
      }
394
395
    }
  }
396
  if (mbmi->skip) av1_reset_skip_context(xd, mi_row, mi_col, bsize);
397

398
  if (!is_inter_block(mbmi)) {
399
400
    const int num_planes = av1_num_planes(cm);
    for (int plane = 0; plane < AOMMIN(2, num_planes); ++plane) {
401
      if (mbmi->palette_mode_info.palette_size[plane])
Yaowu Xu's avatar
Yaowu Xu committed
402
        av1_decode_palette_tokens(xd, plane, r);
Jingning Han's avatar
Jingning Han committed
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
437
438
439
    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)
440
441
442
443
              predict_and_reconstruct_intra_block(cm, xd, r, mbmi, plane,
                                                  blk_row, blk_col, tx_size);
        }
      }
444
445
    }
  } else {
446
    for (int ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
447
      const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
Alex Converse's avatar
Alex Converse committed
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
      if (frame < LAST_FRAME) {
#if CONFIG_INTRABC
        assert(is_intrabc_block(mbmi));
        assert(frame == INTRA_FRAME);
        assert(ref == 0);
#else
        assert(0);
#endif  // CONFIG_INTRABC
      } else {
        RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];

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

468
    av1_build_inter_predictors_sb(cm, xd, mi_row, mi_col, NULL, bsize);
469

Yue Chen's avatar
Yue Chen committed
470
    if (mbmi->motion_mode == OBMC_CAUSAL) {
471
      av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
472
    }
Angie Chiang's avatar
Angie Chiang committed
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487

#if CONFIG_MISMATCH_DEBUG
    for (int plane = 0; plane < 3; ++plane) {
      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,
                               pixel_r, pd->width, pd->height);
    }
#endif

488
489
490
    // Reconstruction
    if (!mbmi->skip) {
      int eobtotal = 0;
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

      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) {
          for (int plane = 0; plane < av1_num_planes(cm); ++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 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];

525
            int blk_row, blk_col;
526
527
528
529
530
531
532
533
534
535
536
            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) {
537
538
                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
539
                                      &eobtotal, mi_row, mi_col);
540
541
542
                block += step;
              }
            }
543
544
          }
        }
545
      }
Jingning Han's avatar
Jingning Han committed
546
547
    }
  }
548
#if CONFIG_CFL
549
  if (mbmi->uv_mode != UV_CFL_PRED) {
550
    if (!cfl->is_chroma_reference && is_inter_block(mbmi) &&
551
        is_cfl_allowed(mbmi)) {
552
553
554
      cfl_store_block(xd, mbmi->sb_type, mbmi->tx_size);
    }
  }
555
#endif  // CONFIG_CFL
Jingning Han's avatar
Jingning Han committed
556

557
558
  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
559
560
}

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

573
  decode_token_and_recon_block(pbi, xd, mi_row, mi_col, r, bsize);
574
575
}

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

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

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

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

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

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
#if CONFIG_LOOP_RESTORATION
  for (int plane = 0; plane < av1_num_planes(cm); ++plane) {
    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

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

645
646
647
648
649
650
651
652
653
  // 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]);
  }

654
655
656
657
658
659
660
661
662
663
664
665
#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))

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

721
722
723
724
725
#undef DEC_PARTITION
#undef DEC_BLOCK
#undef DEC_BLOCK_EPT_ARG
#undef DEC_BLOCK_STX_ARG

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

736
static void setup_bool_decoder(const uint8_t *data, const uint8_t *data_end,
Alex Converse's avatar
Alex Converse committed
737
                               const size_t read_size,
Yaowu Xu's avatar
Yaowu Xu committed
738
                               struct aom_internal_error_info *error_info,
739
                               aom_reader *r, uint8_t allow_update_cdf) {
Alex Converse's avatar
Alex Converse committed
740
741
742
743
  // 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
744
    aom_internal_error(error_info, AOM_CODEC_CORRUPT_FRAME,
Alex Converse's avatar
Alex Converse committed
745
746
                       "Truncated packet or corrupt tile length");

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

  r->allow_update_cdf = allow_update_cdf;
Alex Converse's avatar
Alex Converse committed
752
}
Jingning Han's avatar
Jingning Han committed
753

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

  seg->update_map = 0;
  seg->update_data = 0;
760
  seg->temporal_update = 0;
Jingning Han's avatar
Jingning Han committed
761

Yaowu Xu's avatar
Yaowu Xu committed
762
  seg->enabled = aom_rb_read_bit(rb);
763
  if (!seg->enabled) return;
764
765
766
767
#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
768
  // Segmentation map update
769
770
771
  if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
    seg->update_map = 1;
  } else {
Yaowu Xu's avatar
Yaowu Xu committed
772
    seg->update_map = aom_rb_read_bit(rb);
773
  }
Jingning Han's avatar
Jingning Han committed
774
  if (seg->update_map) {
775
776
777
    if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
      seg->temporal_update = 0;
    } else {
Yaowu Xu's avatar
Yaowu Xu committed
778
      seg->temporal_update = aom_rb_read_bit(rb);
779
    }
Jingning Han's avatar
Jingning Han committed
780
781
  }

782
783
784
785
#if CONFIG_SPATIAL_SEGMENTATION
  cm->preskip_segid = 0;
#endif

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

791
792
    for (int i = 0; i < MAX_SEGMENTS; i++) {
      for (int j = 0; j < SEG_LVL_MAX; j++) {
Jingning Han's avatar
Jingning Han committed
793
        int data = 0;
Yaowu Xu's avatar
Yaowu Xu committed
794
        const int feature_enabled = aom_rb_read_bit(rb);
Jingning Han's avatar
Jingning Han committed
795
        if (feature_enabled) {
796
797
798
799
#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
800
          av1_enable_segfeature(seg, i, j);
801
802
803
804
805
806
807
808
809
810
811
812

          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
813
        }
Yaowu Xu's avatar
Yaowu Xu committed
814
        av1_set_segdata(seg, i, j, data);
Jingning Han's avatar
Jingning Han committed
815
816
817
818
819
      }
    }
  }
}

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

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

857
858
859
860
861
862
863
864
865
866
867
  if (av1_num_planes(cm) > 1) {
    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;
868
  }
869
870
}

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

876
877
878
879
880
881
882
883
884
  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;
885
  wiener_info->vfilter[1] = wiener_info->vfilter[WIENER_WIN - 2] =
886
887
888
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
          WIENER_FILT_TAP1_SUBEXP_K,
889
          ref_wiener_info->vfilter[1] - WIENER_FILT_TAP1_MINV, ACCT_STR) +
890
      WIENER_FILT_TAP1_MINV;
891
  wiener_info->vfilter[2] = wiener_info->vfilter[WIENER_WIN - 3] =
892
893
894
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
          WIENER_FILT_TAP2_SUBEXP_K,
895
          ref_wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV, ACCT_STR) +
896
      WIENER_FILT_TAP2_MINV;
897
  // The central element has an implicit +WIENER_FILT_STEP
898
  wiener_info->vfilter[WIENER_HALFWIN] =
899
900
901
      -2 * (wiener_info->vfilter[0] + wiener_info->vfilter[1] +
            wiener_info->vfilter[2]);

902
903
904
905
906
907
908
909
910
  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;
911
  wiener_info->hfilter[1] = wiener_info->hfilter[WIENER_WIN - 2] =
912
913
914
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1,
          WIENER_FILT_TAP1_SUBEXP_K,
915
          ref_wiener_info->hfilter[1] - WIENER_FILT_TAP1_MINV, ACCT_STR) +
916
      WIENER_FILT_TAP1_MINV;
917
  wiener_info->hfilter[2] = wiener_info->hfilter[WIENER_WIN - 3] =
918
919
920
      aom_read_primitive_refsubexpfin(
          rb, WIENER_FILT_TAP2_MAXV - WIENER_FILT_TAP2_MINV + 1,
          WIENER_FILT_TAP2_SUBEXP_K,
921
          ref_wiener_info->hfilter[2] - WIENER_FILT_TAP2_MINV, ACCT_STR) +
922
      WIENER_FILT_TAP2_MINV;
923
  // The central element has an implicit +WIENER_FILT_STEP
924
  wiener_info->hfilter[WIENER_HALFWIN] =
925
926
      -2 * (wiener_info->hfilter[0] + wiener_info->hfilter[1] +
            wiener_info->hfilter[2]);
927
  memcpy(ref_wiener_info, wiener_info, sizeof(*wiener_info));
928
929
}

930
931
static void read_sgrproj_filter(SgrprojInfo *sgrproj_info,
                                SgrprojInfo *ref_sgrproj_info, aom_reader *rb) {
932
933
  sgrproj_info->ep = aom_read_literal(rb, SGRPROJ_PARAMS_BITS, ACCT_STR);
  sgrproj_info->xqd[0] =
934
935
      aom_read_primitive_refsubexpfin(
          rb, SGRPROJ_PRJ_MAX0 - SGRPROJ_PRJ_MIN0 + 1, SGRPROJ_PRJ_SUBEXP_K,
936
          ref_sgrproj_info->xqd[0] - SGRPROJ_PRJ_MIN0, ACCT_STR) +
937
      SGRPROJ_PRJ_MIN0;
938
  sgrproj_info->xqd[1] =
939
940
      aom_read_primitive_refsubexpfin(
          rb, SGRPROJ_PRJ_MAX1 - SGRPROJ_PRJ_MIN1 + 1, SGRPROJ_PRJ_SUBEXP_K,
941
          ref_sgrproj_info->xqd[1] - SGRPROJ_PRJ_MIN1, ACCT_STR) +
942
943
      SGRPROJ_PRJ_MIN1;
  memcpy(ref_sgrproj_info, sgrproj_info, sizeof(*sgrproj_info));
944
945
}

946
947
948
949
static void loop_restoration_read_sb_coeffs(const AV1_COMMON *const cm,
                                            MACROBLOCKD *xd,
                                            aom_reader *const r, int plane,
                                            int rtile_idx) {