Coverage Report

Created: 2026-10-28 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/dav1d/src/decode.c
Line
Count
Source
1
/*
2
 * Copyright © 2018-2021, VideoLAN and dav1d authors
3
 * Copyright © 2018, Two Orioles, LLC
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright notice, this
10
 *    list of conditions and the following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright notice,
13
 *    this list of conditions and the following disclaimer in the documentation
14
 *    and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
#include "config.h"
29
30
#include <errno.h>
31
#include <limits.h>
32
#include <string.h>
33
#include <stdio.h>
34
#include <inttypes.h>
35
36
#include "dav1d/data.h"
37
38
#include "common/frame.h"
39
#include "common/intops.h"
40
41
#include "src/ctx.h"
42
#include "src/decode.h"
43
#include "src/dequant_tables.h"
44
#include "src/env.h"
45
#include "src/filmgrain.h"
46
#include "src/log.h"
47
#include "src/qm.h"
48
#include "src/recon.h"
49
#include "src/ref.h"
50
#include "src/tables.h"
51
#include "src/thread_task.h"
52
#include "src/warpmv.h"
53
54
static void init_quant_tables(const Dav1dSequenceHeader *const seq_hdr,
55
                              const Dav1dFrameHeader *const frame_hdr,
56
                              const int qidx, uint16_t (*dq)[3][2])
57
38.0k
{
58
195k
    for (int i = 0; i < (frame_hdr->segmentation.enabled ? 8 : 1); i++) {
59
157k
        const int yac = frame_hdr->segmentation.enabled ?
60
136k
            iclip_u8(qidx + frame_hdr->segmentation.seg_data.d[i].delta_q) : qidx;
61
157k
        const int ydc = iclip_u8(yac + frame_hdr->quant.ydc_delta);
62
157k
        const int uac = iclip_u8(yac + frame_hdr->quant.uac_delta);
63
157k
        const int udc = iclip_u8(yac + frame_hdr->quant.udc_delta);
64
157k
        const int vac = iclip_u8(yac + frame_hdr->quant.vac_delta);
65
157k
        const int vdc = iclip_u8(yac + frame_hdr->quant.vdc_delta);
66
67
157k
        dq[i][0][0] = dav1d_dq_tbl[seq_hdr->hbd][ydc][0];
68
157k
        dq[i][0][1] = dav1d_dq_tbl[seq_hdr->hbd][yac][1];
69
157k
        dq[i][1][0] = dav1d_dq_tbl[seq_hdr->hbd][udc][0];
70
157k
        dq[i][1][1] = dav1d_dq_tbl[seq_hdr->hbd][uac][1];
71
157k
        dq[i][2][0] = dav1d_dq_tbl[seq_hdr->hbd][vdc][0];
72
157k
        dq[i][2][1] = dav1d_dq_tbl[seq_hdr->hbd][vac][1];
73
157k
    }
74
38.0k
}
75
76
static int read_mv_component_diff(MsacContext *const msac,
77
                                  CdfMvComponent *const mv_comp,
78
                                  const int mv_prec)
79
289k
{
80
289k
    const int sign = dav1d_msac_decode_bool_adapt(msac, mv_comp->sign);
81
289k
    const int cl = dav1d_msac_decode_symbol_adapt16(msac, mv_comp->classes, 10);
82
289k
    int up, fp = 3, hp = 1;
83
84
289k
    if (!cl) {
85
156k
        up = dav1d_msac_decode_bool_adapt(msac, mv_comp->class0);
86
156k
        if (mv_prec >= 0) {  // !force_integer_mv
87
33.3k
            fp = dav1d_msac_decode_symbol_adapt4(msac, mv_comp->class0_fp[up], 3);
88
33.3k
            if (mv_prec > 0) // allow_high_precision_mv
89
13.7k
                hp = dav1d_msac_decode_bool_adapt(msac, mv_comp->class0_hp);
90
33.3k
        }
91
156k
    } else {
92
132k
        up = 1 << cl;
93
1.27M
        for (int n = 0; n < cl; n++)
94
1.14M
            up |= dav1d_msac_decode_bool_adapt(msac, mv_comp->classN[n]) << n;
95
132k
        if (mv_prec >= 0) {  // !force_integer_mv
96
4.94k
            fp = dav1d_msac_decode_symbol_adapt4(msac, mv_comp->classN_fp, 3);
97
4.94k
            if (mv_prec > 0) // allow_high_precision_mv
98
2.45k
                hp = dav1d_msac_decode_bool_adapt(msac, mv_comp->classN_hp);
99
4.94k
        }
100
132k
    }
101
102
289k
    const int diff = ((up << 3) | (fp << 1) | hp) + 1;
103
104
289k
    return sign ? -diff : diff;
105
289k
}
106
107
static void read_mv_residual(Dav1dTileState *const ts, mv *const ref_mv,
108
                             const int mv_prec)
109
195k
{
110
195k
    MsacContext *const msac = &ts->msac;
111
195k
    const enum MVJoint mv_joint =
112
195k
        dav1d_msac_decode_symbol_adapt4(msac, ts->cdf.mv.joint, N_MV_JOINTS - 1);
113
195k
    if (mv_joint & MV_JOINT_V)
114
145k
        ref_mv->y += read_mv_component_diff(msac, &ts->cdf.mv.comp[0], mv_prec);
115
195k
    if (mv_joint & MV_JOINT_H)
116
143k
        ref_mv->x += read_mv_component_diff(msac, &ts->cdf.mv.comp[1], mv_prec);
117
195k
}
118
119
static void read_tx_tree(Dav1dTaskContext *const t,
120
                         const enum RectTxfmSize from,
121
                         const int depth, uint16_t *const masks,
122
                         const int x_off, const int y_off)
123
131k
{
124
131k
    const Dav1dFrameContext *const f = t->f;
125
131k
    const int bx4 = t->bx & 31, by4 = t->by & 31;
126
131k
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];
127
131k
    const int txw = t_dim->lw, txh = t_dim->lh;
128
131k
    int is_split;
129
130
131k
    if (depth < 2 && from > (int) TX_4X4) {
131
112k
        const int cat = 2 * (TX_64X64 - t_dim->max) - depth;
132
112k
        const int a = t->a->tx[bx4] < txw;
133
112k
        const int l = t->l.tx[by4] < txh;
134
135
112k
        is_split = dav1d_msac_decode_bool_adapt(&t->ts->msac,
136
112k
                       t->ts->cdf.m.txpart[cat][a + l]);
137
112k
        if (is_split)
138
30.3k
            masks[depth] |= 1 << (y_off * 4 + x_off);
139
112k
    } else {
140
18.8k
        is_split = 0;
141
18.8k
    }
142
143
131k
    if (is_split && t_dim->max > TX_8X8) {
144
21.8k
        const enum RectTxfmSize sub = t_dim->sub;
145
21.8k
        const TxfmInfo *const sub_t_dim = &dav1d_txfm_dimensions[sub];
146
21.8k
        const int txsw = sub_t_dim->w, txsh = sub_t_dim->h;
147
148
21.8k
        read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 0);
149
21.8k
        t->bx += txsw;
150
21.8k
        if (txw >= txh && t->bx < f->bw)
151
16.4k
            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 1, y_off * 2 + 0);
152
21.8k
        t->bx -= txsw;
153
21.8k
        t->by += txsh;
154
21.8k
        if (txh >= txw && t->by < f->bh) {
155
14.4k
            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 1);
156
14.4k
            t->bx += txsw;
157
14.4k
            if (txw >= txh && t->bx < f->bw)
158
9.21k
                read_tx_tree(t, sub, depth + 1, masks,
159
9.21k
                             x_off * 2 + 1, y_off * 2 + 1);
160
14.4k
            t->bx -= txsw;
161
14.4k
        }
162
21.8k
        t->by -= txsh;
163
109k
    } else {
164
109k
        dav1d_memset_pow2[t_dim->lw](&t->a->tx[bx4], is_split ? TX_4X4 : txw);
165
109k
        dav1d_memset_pow2[t_dim->lh](&t->l.tx[by4], is_split ? TX_4X4 : txh);
166
109k
    }
167
131k
}
168
169
770k
static int neg_deinterleave(int diff, int ref, int max) {
170
770k
    if (!ref) return diff;
171
527k
    if (ref >= (max - 1)) return max - diff - 1;
172
473k
    if (2 * ref < max) {
173
280k
        if (diff <= 2 * ref) {
174
228k
            if (diff & 1)
175
31.2k
                return ref + ((diff + 1) >> 1);
176
197k
            else
177
197k
                return ref - (diff >> 1);
178
228k
        }
179
52.0k
        return diff;
180
280k
    } else {
181
193k
        if (diff <= 2 * (max - ref - 1)) {
182
160k
            if (diff & 1)
183
23.8k
                return ref + ((diff + 1) >> 1);
184
136k
            else
185
136k
                return ref - (diff >> 1);
186
160k
        }
187
32.4k
        return max - (diff + 1);
188
193k
    }
189
473k
}
190
191
static void find_matching_ref(const Dav1dTaskContext *const t,
192
                              const enum EdgeFlags intra_edge_flags,
193
                              const int bw4, const int bh4,
194
                              const int w4, const int h4,
195
                              const int have_left, const int have_top,
196
                              const int ref, uint64_t masks[2])
197
113k
{
198
113k
    /*const*/ refmvs_block *const *r = &t->rt.r[(t->by & 31) + 5];
199
113k
    int count = 0;
200
113k
    int have_topleft = have_top && have_left;
201
113k
    int have_topright = imax(bw4, bh4) < 32 &&
202
109k
                        have_top && t->bx + bw4 < t->ts->tiling.col_end &&
203
94.1k
                        (intra_edge_flags & EDGE_I444_TOP_HAS_RIGHT);
204
205
264k
#define bs(rp) dav1d_block_dimensions[(rp)->bs]
206
350k
#define matches(rp) ((rp)->ref.ref[0] == ref + 1 && (rp)->ref.ref[1] == -1)
207
208
113k
    if (have_top) {
209
99.1k
        const refmvs_block *r2 = &r[-1][t->bx];
210
99.1k
        if (matches(r2)) {
211
75.6k
            masks[0] |= 1;
212
75.6k
            count = 1;
213
75.6k
        }
214
99.1k
        int aw4 = bs(r2)[0];
215
99.1k
        if (aw4 >= bw4) {
216
85.8k
            const int off = t->bx & (aw4 - 1);
217
85.8k
            if (off) have_topleft = 0;
218
85.8k
            if (aw4 - off > bw4) have_topright = 0;
219
85.8k
        } else {
220
13.3k
            unsigned mask = 1 << aw4;
221
31.7k
            for (int x = aw4; x < w4; x += aw4) {
222
18.4k
                r2 += aw4;
223
18.4k
                if (matches(r2)) {
224
12.8k
                    masks[0] |= mask;
225
12.8k
                    if (++count >= 8) return;
226
12.8k
                }
227
18.3k
                aw4 = bs(r2)[0];
228
18.3k
                mask <<= aw4;
229
18.3k
            }
230
13.3k
        }
231
99.1k
    }
232
113k
    if (have_left) {
233
109k
        /*const*/ refmvs_block *const *r2 = r;
234
109k
        if (matches(&r2[0][t->bx - 1])) {
235
84.3k
            masks[1] |= 1;
236
84.3k
            if (++count >= 8) return;
237
84.3k
        }
238
109k
        int lh4 = bs(&r2[0][t->bx - 1])[1];
239
109k
        if (lh4 >= bh4) {
240
91.0k
            if (t->by & (lh4 - 1)) have_topleft = 0;
241
91.0k
        } else {
242
18.8k
            unsigned mask = 1 << lh4;
243
45.2k
            for (int y = lh4; y < h4; y += lh4) {
244
26.5k
                r2 += lh4;
245
26.5k
                if (matches(&r2[0][t->bx - 1])) {
246
17.4k
                    masks[1] |= mask;
247
17.4k
                    if (++count >= 8) return;
248
17.4k
                }
249
26.3k
                lh4 = bs(&r2[0][t->bx - 1])[1];
250
26.3k
                mask <<= lh4;
251
26.3k
            }
252
18.8k
        }
253
109k
    }
254
113k
    if (have_topleft && matches(&r[-1][t->bx - 1])) {
255
43.0k
        masks[1] |= 1ULL << 32;
256
43.0k
        if (++count >= 8) return;
257
43.0k
    }
258
113k
    if (have_topright && matches(&r[-1][t->bx + bw4])) {
259
24.5k
        masks[0] |= 1ULL << 32;
260
24.5k
    }
261
113k
#undef matches
262
113k
}
263
264
static void derive_warpmv(const Dav1dTaskContext *const t,
265
                          const int bw4, const int bh4,
266
                          const uint64_t masks[2], const union mv mv,
267
                          Dav1dWarpedMotionParams *const wmp)
268
1.82k
{
269
1.82k
    int pts[8][2 /* in, out */][2 /* x, y */], np = 0;
270
1.82k
    /*const*/ refmvs_block *const *r = &t->rt.r[(t->by & 31) + 5];
271
272
4.52k
#define add_sample(dx, dy, sx, sy, rp) do { \
273
4.52k
    pts[np][0][0] = 16 * (2 * dx + sx * bs(rp)[0]) - 8; \
274
4.52k
    pts[np][0][1] = 16 * (2 * dy + sy * bs(rp)[1]) - 8; \
275
4.52k
    pts[np][1][0] = pts[np][0][0] + (rp)->mv.mv[0].x; \
276
4.52k
    pts[np][1][1] = pts[np][0][1] + (rp)->mv.mv[0].y; \
277
4.52k
    np++; \
278
4.52k
} while (0)
279
280
    // use masks[] to find the projectable motion vectors in the edges
281
1.82k
    if ((unsigned) masks[0] == 1 && !(masks[1] >> 32)) {
282
520
        const int off = t->bx & (bs(&r[-1][t->bx])[0] - 1);
283
520
        add_sample(-off, 0, 1, -1, &r[-1][t->bx]);
284
2.31k
    } else for (unsigned off = 0, xmask = (uint32_t) masks[0]; np < 8 && xmask;) { // top
285
1.01k
        const int tz = ctz(xmask);
286
1.01k
        off += tz;
287
1.01k
        xmask >>= tz;
288
1.01k
        add_sample(off, 0, 1, -1, &r[-1][t->bx + off]);
289
1.01k
        xmask &= ~1;
290
1.01k
    }
291
1.82k
    if (np < 8 && masks[1] == 1) {
292
712
        const int off = t->by & (bs(&r[0][t->bx - 1])[1] - 1);
293
712
        add_sample(0, -off, -1, 1, &r[-off][t->bx - 1]);
294
2.16k
    } else for (unsigned off = 0, ymask = (uint32_t) masks[1]; np < 8 && ymask;) { // left
295
1.05k
        const int tz = ctz(ymask);
296
1.05k
        off += tz;
297
1.05k
        ymask >>= tz;
298
1.05k
        add_sample(0, off, -1, 1, &r[off][t->bx - 1]);
299
1.05k
        ymask &= ~1;
300
1.05k
    }
301
1.82k
    if (np < 8 && masks[1] >> 32) // top/left
302
736
        add_sample(0, 0, -1, -1, &r[-1][t->bx - 1]);
303
1.82k
    if (np < 8 && masks[0] >> 32) // top/right
304
496
        add_sample(bw4, 0, 1, -1, &r[-1][t->bx + bw4]);
305
1.82k
    assert(np > 0 && np <= 8);
306
1.82k
#undef bs
307
308
    // select according to motion vector difference against a threshold
309
1.82k
    int mvd[8], ret = 0;
310
1.82k
    const int thresh = 4 * iclip(imax(bw4, bh4), 4, 28);
311
6.35k
    for (int i = 0; i < np; i++) {
312
4.52k
        mvd[i] = abs(pts[i][1][0] - pts[i][0][0] - mv.x) +
313
4.52k
                 abs(pts[i][1][1] - pts[i][0][1] - mv.y);
314
4.52k
        if (mvd[i] > thresh)
315
1.43k
            mvd[i] = -1;
316
3.09k
        else
317
3.09k
            ret++;
318
4.52k
    }
319
1.82k
    if (!ret) {
320
346
        ret = 1;
321
1.82k
    } else for (int i = 0, j = np - 1, k = 0; k < np - ret; k++, i++, j--) {
322
1.12k
        while (mvd[i] != -1) i++;
323
1.10k
        while (mvd[j] == -1) j--;
324
653
        assert(i != j);
325
653
        if (i > j) break;
326
        // replace the discarded samples;
327
348
        mvd[i] = mvd[j];
328
348
        memcpy(pts[i], pts[j], sizeof(*pts));
329
348
    }
330
331
1.82k
    if (!dav1d_find_affine_int(pts, ret, bw4, bh4, mv, wmp, t->bx, t->by) &&
332
1.74k
        !dav1d_get_shear_params(wmp))
333
1.57k
    {
334
1.57k
        wmp->type = DAV1D_WM_TYPE_AFFINE;
335
1.57k
    } else
336
248
        wmp->type = DAV1D_WM_TYPE_IDENTITY;
337
1.82k
}
338
339
119k
static inline int findoddzero(const uint8_t *buf, int len) {
340
132k
    for (int n = 0; n < len; n++)
341
127k
        if (!buf[n * 2]) return 1;
342
5.30k
    return 0;
343
119k
}
344
345
// Resolve a decoded rank (color_idx) to a palette entry, given the ordered
346
// priority candidates p[0..prio_count-1] and the bitmask of values already
347
// used by those candidates. Ranks below prio_count select a priority
348
// candidate directly; higher ranks select the (rank - prio_count)th value
349
// (counting from 0) that is not present in mask, in ascending order.
350
static inline int resolve_pal_color(const int color_idx, const uint8_t *const p,
351
                                    const int prio_count, unsigned mask)
352
2.43M
{
353
2.43M
    if (color_idx < prio_count)
354
2.03M
        return p[color_idx];
355
398k
    unsigned rank = color_idx - prio_count + (mask & 1);
356
398k
    rank += ((mask >> 1) & 1) & (rank > 0);
357
    // Unset-bit positions minus their ranks, packed in 2-bit fields.
358
    // Mask bits 0 and 1 are cleared and compensated in rank.
359
    // At most three priority colors keep each offset within 0..3.
360
398k
    static const uint8_t free_offsets2[] = {
361
398k
        0x00, 0x00, 0x50, 0x15, 0x40, 0x15, 0xa0, 0x0a, 0x00, 0x15, 0x90, 0x0a,
362
398k
        0x80, 0x0a, 0xf0, 0x03, 0x00, 0x14, 0x50, 0x0a, 0x40, 0x0a, 0xe0, 0x03,
363
398k
        0x00, 0x0a, 0xd0, 0x03, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x10, 0x50, 0x09,
364
398k
        0x40, 0x09, 0xa0, 0x03, 0x00, 0x09, 0x90, 0x03, 0x80, 0x03, 0x00, 0x00,
365
398k
        0x00, 0x08, 0x50, 0x03, 0x40, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
366
398k
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x40, 0x05, 0xa0, 0x02,
367
398k
        0x00, 0x05, 0x90, 0x02, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x50, 0x02,
368
398k
        0x40, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369
398k
        0x00, 0x00, 0x50, 0x01, 0x40, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
370
398k
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371
398k
    };
372
398k
    const unsigned byte_idx = 2 * (mask >> 2) + (rank >> 2);
373
398k
    assert(byte_idx < sizeof(free_offsets2));
374
398k
    return rank + ((free_offsets2[byte_idx] >> (2 * (rank & 3))) & 3);
375
398k
}
376
377
static void read_pal_indices(Dav1dTaskContext *const t,
378
                             uint8_t *const pal_idx,
379
                             const int pal_sz, const int pl,
380
                             const int w4, const int h4,
381
                             const int bw4, const int bh4)
382
16.1k
{
383
16.1k
    Dav1dTileState *const ts = t->ts;
384
16.1k
    const ptrdiff_t stride = bw4 * 4;
385
16.1k
    assert(pal_idx);
386
16.1k
    uint8_t *const pal_tmp = t->scratch.pal_idx_uv;
387
16.1k
    pal_tmp[0] = dav1d_msac_decode_uniform(&ts->msac, pal_sz);
388
16.1k
    uint16_t (*const color_map_cdf)[8] =
389
16.1k
        ts->cdf.m.color_map[pl][pal_sz - 2];
390
391
16.1k
    if (pal_sz == 2) {
392
        // Binary palette: ctx 1 is unreachable (needs 3 distinct neighbours),
393
        // and resolve always toggles the single priority value. Use a bool
394
        // decode instead of a symbol decode. ctx formula collapses to:
395
        // border -> 0, interior -> 2 + same_t_l + (same_t_l & same_t_tl)
396
101k
        for (int i = 1; i < 4 * (w4 + h4) - 1; i++) {
397
97.7k
            const int first = imin(i, w4 * 4 - 1);
398
97.7k
            const int last = imax(0, i - h4 * 4 + 1);
399
97.7k
            int have_top = i > first;
400
97.7k
            const uint8_t *pal_row = pal_tmp + first + (i - first) * stride;
401
918k
            for (int j = first; j >= last; have_top = 1, j--, pal_row += stride - 1) {
402
821k
                const int have_left = j > 0;
403
821k
                int ctx, p0;
404
821k
                if (!have_left) {
405
45.0k
                    ctx = 0;
406
45.0k
                    p0 = pal_row[-stride];
407
775k
                } else if (!have_top) {
408
52.6k
                    ctx = 0;
409
52.6k
                    p0 = pal_row[-1];
410
723k
                } else {
411
723k
                    const int l = pal_row[-1], tp = pal_row[-stride];
412
723k
                    const int tl = pal_row[-(stride + 1)];
413
723k
                    const int same_t_l = tp == l;
414
723k
                    const int same_t_tl = tp == tl;
415
723k
                    ctx = 2 + same_t_l + (same_t_l & same_t_tl);
416
723k
                    p0 = same_t_l ? tp : tl;
417
723k
                }
418
821k
                const int bit = dav1d_msac_decode_bool_adapt(
419
821k
                    &ts->msac, color_map_cdf[ctx]);
420
821k
                pal_tmp[(i - j) * stride + j] = bit ^ p0;
421
821k
            }
422
97.7k
        }
423
3.87k
        t->c->pal_dsp.pal_idx_finish(pal_idx, pal_tmp, bw4 * 4, bh4 * 4,
424
3.87k
                                     w4 * 4, h4 * 4);
425
3.87k
        return;
426
3.87k
    }
427
428
12.3k
    unsigned (*const symbol_adapt)(MsacContext *, uint16_t *, size_t) =
429
12.3k
        pal_sz <= 4 ? dav1d_msac_decode_symbol_adapt4 : dav1d_msac_decode_symbol_adapt8;
430
431
316k
    for (int i = 1; i < 4 * (w4 + h4) - 1; i++) {
432
        // top/left-to-bottom/right diagonals ("wave-front")
433
304k
        const int first = imin(i, w4 * 4 - 1);
434
304k
        const int last = imax(0, i - h4 * 4 + 1);
435
304k
        int have_top = i > first;
436
304k
        const uint8_t *pal_row = pal_tmp + first + (i - first) * stride;
437
2.73M
        for (int j = first; j >= last; have_top = 1, j--, pal_row += stride - 1) {
438
2.43M
            const int have_left = j > 0;
439
2.43M
            uint8_t p[3];
440
2.43M
            unsigned mask;
441
2.43M
            int ctx, prio_count;
442
2.43M
            if (!have_left) {
443
137k
                ctx = 0; prio_count = 1;
444
137k
                p[0] = pal_row[-stride];
445
137k
                mask = 1u << p[0];
446
2.29M
            } else if (!have_top) {
447
167k
                ctx = 0; prio_count = 1;
448
167k
                p[0] = pal_row[-1];
449
167k
                mask = 1u << p[0];
450
2.12M
            } else {
451
2.12M
                const int l = pal_row[-1], tp = pal_row[-stride];
452
2.12M
                const int tl = pal_row[-(stride + 1)];
453
2.12M
                const int same_t_l = tp == l;
454
2.12M
                const int same_t_tl = tp == tl;
455
2.12M
                const int same_l_tl = l == tl;
456
2.12M
                if (same_t_l & same_t_tl) {
457
989k
                    ctx = 4; prio_count = 1;
458
989k
                    p[0] = tp; mask = 1u << tp;
459
1.13M
                } else if (same_t_l) {
460
82.0k
                    ctx = 3; prio_count = 2;
461
82.0k
                    p[0] = tp; p[1] = tl;
462
82.0k
                    mask = (1u << tp) | (1u << tl);
463
1.05M
                } else if (same_t_tl | same_l_tl) {
464
822k
                    ctx = 2; prio_count = 2;
465
822k
                    p[0] = tl; p[1] = same_t_tl ? l : tp;
466
822k
                    mask = (1u << tl) | (1u << p[1]);
467
822k
                } else {
468
232k
                    ctx = 1; prio_count = 3;
469
232k
                    p[0] = imin(tp, l); p[1] = imax(tp, l); p[2] = tl;
470
232k
                    mask = (1u << tp) | (1u << l) | (1u << tl);
471
232k
                }
472
2.12M
            }
473
2.43M
            const int color_idx = symbol_adapt(&ts->msac, color_map_cdf[ctx], pal_sz - 1);
474
2.43M
            pal_tmp[(i - j) * stride + j] =
475
2.43M
                resolve_pal_color(color_idx, p, prio_count, mask);
476
2.43M
        }
477
304k
    }
478
479
12.3k
    t->c->pal_dsp.pal_idx_finish(pal_idx, pal_tmp, bw4 * 4, bh4 * 4,
480
12.3k
                                 w4 * 4, h4 * 4);
481
12.3k
}
482
483
static void read_vartx_tree(Dav1dTaskContext *const t,
484
                            Av1Block *const b, const enum BlockSize bs,
485
                            const int bx4, const int by4)
486
395k
{
487
395k
    const Dav1dFrameContext *const f = t->f;
488
395k
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
489
395k
    const int bw4 = b_dim[0], bh4 = b_dim[1];
490
491
    // var-tx tree coding
492
395k
    uint16_t tx_split[2] = { 0 };
493
395k
    b->max_ytx = dav1d_max_txfm_size_for_bs[bs][0];
494
395k
    if (!b->skip && (f->frame_hdr->segmentation.lossless[b->seg_id] ||
495
191k
                     b->max_ytx == TX_4X4))
496
15.1k
    {
497
15.1k
        b->max_ytx = b->uvtx = TX_4X4;
498
15.1k
        if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE) {
499
5.11k
            dav1d_memset_pow2[b_dim[2]](&t->a->tx[bx4], TX_4X4);
500
5.11k
            dav1d_memset_pow2[b_dim[3]](&t->l.tx[by4], TX_4X4);
501
5.11k
        }
502
380k
    } else if (f->frame_hdr->txfm_mode != DAV1D_TX_SWITCHABLE || b->skip) {
503
313k
        if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE) {
504
35.7k
            dav1d_memset_pow2[b_dim[2]](&t->a->tx[bx4], b_dim[2 + 0]);
505
35.7k
            dav1d_memset_pow2[b_dim[3]](&t->l.tx[by4], b_dim[2 + 1]);
506
35.7k
        }
507
313k
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
508
313k
    } else {
509
66.5k
        assert(bw4 <= 16 || bh4 <= 16 || b->max_ytx == TX_64X64);
510
66.5k
        int y, x, y_off, x_off;
511
66.5k
        const TxfmInfo *const ytx = &dav1d_txfm_dimensions[b->max_ytx];
512
134k
        for (y = 0, y_off = 0; y < bh4; y += ytx->h, y_off++) {
513
136k
            for (x = 0, x_off = 0; x < bw4; x += ytx->w, x_off++) {
514
69.1k
                read_tx_tree(t, b->max_ytx, 0, tx_split, x_off, y_off);
515
                // contexts are updated inside read_tx_tree()
516
69.1k
                t->bx += ytx->w;
517
69.1k
            }
518
67.4k
            t->bx -= x;
519
67.4k
            t->by += ytx->h;
520
67.4k
        }
521
66.5k
        t->by -= y;
522
66.5k
        if (DEBUG_BLOCK_INFO)
523
0
            printf("Post-vartxtree[%x/%x]: r=%d\n",
524
0
                   tx_split[0], tx_split[1], t->ts->msac.rng);
525
66.5k
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
526
66.5k
    }
527
395k
    assert(!(tx_split[0] & ~0x33));
528
395k
    b->tx_split0 = (uint8_t)tx_split[0];
529
395k
    b->tx_split1 = tx_split[1];
530
395k
}
531
532
static inline unsigned get_prev_frame_segid(const Dav1dFrameContext *const f,
533
                                            const int by, const int bx,
534
                                            const int w4, int h4,
535
                                            const uint8_t *ref_seg_map,
536
                                            const ptrdiff_t stride)
537
3.47k
{
538
3.47k
    assert(f->frame_hdr->primary_ref_frame != DAV1D_PRIMARY_REF_NONE);
539
540
3.47k
    unsigned seg_id = 8;
541
3.47k
    ref_seg_map += by * stride + bx;
542
8.08k
    do {
543
43.8k
        for (int x = 0; x < w4; x++)
544
35.7k
            seg_id = imin(seg_id, ref_seg_map[x]);
545
8.08k
        ref_seg_map += stride;
546
8.08k
    } while (--h4 > 0 && seg_id);
547
3.47k
    assert(seg_id < 8);
548
549
3.47k
    return seg_id;
550
3.47k
}
551
552
static inline void splat_oneref_mv(const Dav1dContext *const c,
553
                                   Dav1dTaskContext *const t,
554
                                   const enum BlockSize bs,
555
                                   const Av1Block *const b,
556
                                   const int bw4, const int bh4)
557
238k
{
558
238k
    const enum InterPredMode mode = b->inter_mode;
559
238k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
560
238k
        .ref.ref = { b->ref[0] + 1, b->interintra_type ? 0 : -1 },
561
238k
        .mv.mv[0] = b->mv[0],
562
238k
        .bs = bs,
563
238k
        .mf = (mode == GLOBALMV && imin(bw4, bh4) >= 2) | ((mode == NEWMV) * 2),
564
238k
    };
565
238k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
566
238k
}
567
568
static inline void splat_intrabc_mv(const Dav1dContext *const c,
569
                                    Dav1dTaskContext *const t,
570
                                    const enum BlockSize bs,
571
                                    const Av1Block *const b,
572
                                    const int bw4, const int bh4)
573
115k
{
574
115k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
575
115k
        .ref.ref = { 0, -1 },
576
115k
        .mv.mv[0] = b->mv[0],
577
115k
        .bs = bs,
578
115k
        .mf = 0,
579
115k
    };
580
115k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
581
115k
}
582
583
static inline void splat_tworef_mv(const Dav1dContext *const c,
584
                                   Dav1dTaskContext *const t,
585
                                   const enum BlockSize bs,
586
                                   const Av1Block *const b,
587
                                   const int bw4, const int bh4)
588
41.0k
{
589
41.0k
    assert(bw4 >= 2 && bh4 >= 2);
590
41.0k
    const enum CompInterPredMode mode = b->inter_mode;
591
41.0k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
592
41.0k
        .ref.ref = { b->ref[0] + 1, b->ref[1] + 1 },
593
41.0k
        .mv.mv = { b->mv[0], b->mv[1] },
594
41.0k
        .bs = bs,
595
41.0k
        .mf = (mode == GLOBALMV_GLOBALMV) | !!((1 << mode) & (0xbc)) * 2,
596
41.0k
    };
597
41.0k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
598
41.0k
}
599
600
static inline void splat_intraref(const Dav1dContext *const c,
601
                                  Dav1dTaskContext *const t,
602
                                  const enum BlockSize bs,
603
                                  const int bw4, const int bh4)
604
431k
{
605
431k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
606
431k
        .ref.ref = { 0, -1 },
607
431k
        .mv.mv[0].n = INVALID_MV,
608
431k
        .bs = bs,
609
431k
        .mf = 0,
610
431k
    };
611
431k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
612
431k
}
613
614
static void mc_lowest_px(int *const dst, const int by4, const int bh4,
615
                         const int mvy, const int ss_ver,
616
                         const struct ScalableMotionParams *const smp)
617
693k
{
618
693k
    const int v_mul = 4 >> ss_ver;
619
693k
    if (!smp->scale) {
620
92.1k
        const int my = mvy >> (3 + ss_ver), dy = mvy & (15 >> !ss_ver);
621
92.1k
        *dst = imax(*dst, (by4 + bh4) * v_mul + my + 4 * !!dy);
622
601k
    } else {
623
601k
        int y = (by4 * v_mul << 4) + mvy * (1 << !ss_ver);
624
601k
        const int64_t tmp = (int64_t)(y) * smp->scale + (smp->scale - 0x4000) * 8;
625
601k
        y = apply_sign64((int)((llabs(tmp) + 128) >> 8), tmp) + 32;
626
601k
        const int bottom = ((y + (bh4 * v_mul - 1) * smp->step) >> 10) + 1 + 4;
627
601k
        *dst = imax(*dst, bottom);
628
601k
    }
629
693k
}
630
631
static ALWAYS_INLINE void affine_lowest_px(Dav1dTaskContext *const t, int *const dst,
632
                                           const uint8_t *const b_dim,
633
                                           const Dav1dWarpedMotionParams *const wmp,
634
                                           const int ss_ver, const int ss_hor)
635
4.33k
{
636
4.33k
    const int h_mul = 4 >> ss_hor, v_mul = 4 >> ss_ver;
637
4.33k
    assert(!((b_dim[0] * h_mul) & 7) && !((b_dim[1] * v_mul) & 7));
638
4.33k
    const int32_t *const mat = wmp->matrix;
639
4.33k
    const int y = b_dim[1] * v_mul - 8; // lowest y
640
641
4.33k
    const int src_y = t->by * 4 + ((y + 4) << ss_ver);
642
4.33k
    const int64_t mat5_y = (int64_t) mat[5] * src_y + mat[1];
643
    // check left- and right-most blocks
644
10.8k
    for (int x = 0; x < b_dim[0] * h_mul; x += imax(8, b_dim[0] * h_mul - 8)) {
645
        // calculate transformation relative to center of 8x8 block in
646
        // luma pixel units
647
6.55k
        const int src_x = t->bx * 4 + ((x + 4) << ss_hor);
648
6.55k
        const int64_t mvy = ((int64_t) mat[4] * src_x + mat5_y) >> ss_ver;
649
6.55k
        const int dy = (int) (mvy >> 16) - 4;
650
6.55k
        *dst = imax(*dst, dy + 4 + 8);
651
6.55k
    }
652
4.33k
}
653
654
static NOINLINE void affine_lowest_px_luma(Dav1dTaskContext *const t, int *const dst,
655
                                           const uint8_t *const b_dim,
656
                                           const Dav1dWarpedMotionParams *const wmp)
657
3.92k
{
658
3.92k
    affine_lowest_px(t, dst, b_dim, wmp, 0, 0);
659
3.92k
}
660
661
static NOINLINE void affine_lowest_px_chroma(Dav1dTaskContext *const t, int *const dst,
662
                                             const uint8_t *const b_dim,
663
                                             const Dav1dWarpedMotionParams *const wmp)
664
942
{
665
942
    const Dav1dFrameContext *const f = t->f;
666
942
    assert(f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400);
667
942
    if (f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I444)
668
540
        affine_lowest_px_luma(t, dst, b_dim, wmp);
669
402
    else
670
402
        affine_lowest_px(t, dst, b_dim, wmp, f->cur.p.layout & DAV1D_PIXEL_LAYOUT_I420, 1);
671
942
}
672
673
static void obmc_lowest_px(Dav1dTaskContext *const t,
674
                           int (*const dst)[2], const int is_chroma,
675
                           const uint8_t *const b_dim,
676
                           const int bx4, const int by4, const int w4, const int h4)
677
104k
{
678
104k
    assert(!(t->bx & 1) && !(t->by & 1));
679
104k
    const Dav1dFrameContext *const f = t->f;
680
104k
    /*const*/ refmvs_block **r = &t->rt.r[(t->by & 31) + 5];
681
104k
    const int ss_ver = is_chroma && f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
682
104k
    const int ss_hor = is_chroma && f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
683
104k
    const int h_mul = 4 >> ss_hor, v_mul = 4 >> ss_ver;
684
685
104k
    if (t->by > t->ts->tiling.row_start &&
686
96.5k
        (!is_chroma || b_dim[0] * h_mul + b_dim[1] * v_mul >= 16))
687
70.3k
    {
688
148k
        for (int i = 0, x = 0; x < w4 && i < imin(b_dim[2], 4); ) {
689
            // only odd blocks are considered for overlap handling, hence +1
690
78.1k
            const refmvs_block *const a_r = &r[-1][t->bx + x + 1];
691
78.1k
            const uint8_t *const a_b_dim = dav1d_block_dimensions[a_r->bs];
692
693
78.1k
            if (a_r->ref.ref[0] > 0) {
694
76.0k
                const int oh4 = imin(b_dim[1], 16) >> 1;
695
76.0k
                mc_lowest_px(&dst[a_r->ref.ref[0] - 1][is_chroma], t->by,
696
76.0k
                             (oh4 * 3 + 3) >> 2, a_r->mv.mv[0].y, ss_ver,
697
76.0k
                             &f->svc[a_r->ref.ref[0] - 1][1]);
698
76.0k
                i++;
699
76.0k
            }
700
78.1k
            x += imax(a_b_dim[0], 2);
701
78.1k
        }
702
70.3k
    }
703
704
104k
    if (t->bx > t->ts->tiling.col_start)
705
213k
        for (int i = 0, y = 0; y < h4 && i < imin(b_dim[3], 4); ) {
706
            // only odd blocks are considered for overlap handling, hence +1
707
111k
            const refmvs_block *const l_r = &r[y + 1][t->bx - 1];
708
111k
            const uint8_t *const l_b_dim = dav1d_block_dimensions[l_r->bs];
709
710
111k
            if (l_r->ref.ref[0] > 0) {
711
109k
                const int oh4 = iclip(l_b_dim[1], 2, b_dim[1]);
712
109k
                mc_lowest_px(&dst[l_r->ref.ref[0] - 1][is_chroma],
713
109k
                             t->by + y, oh4, l_r->mv.mv[0].y, ss_ver,
714
109k
                             &f->svc[l_r->ref.ref[0] - 1][1]);
715
109k
                i++;
716
109k
            }
717
111k
            y += imax(l_b_dim[1], 2);
718
111k
        }
719
104k
}
720
721
static int decode_b(Dav1dTaskContext *const t,
722
                    const enum BlockLevel bl,
723
                    const enum BlockSize bs,
724
                    const enum BlockPartition bp,
725
2.03M
                    const enum EdgeFlags intra_edge_flags) {
726
2.03M
    Dav1dTileState *const ts = t->ts;
727
2.03M
    const Dav1dFrameContext *const f = t->f;
728
2.03M
    Av1Block b_mem, *const b = t->frame_thread.pass ?
729
18.4E
        &f->frame_thread.b[t->by * f->b4_stride + t->bx] : &b_mem;
730
2.03M
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
731
2.03M
    const int bx4 = t->bx & 31, by4 = t->by & 31;
732
2.03M
    const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
733
2.03M
    const int ss_hor = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
734
2.03M
    const int cbx4 = bx4 >> ss_hor, cby4 = by4 >> ss_ver;
735
2.03M
    const int bw4 = b_dim[0], bh4 = b_dim[1];
736
2.03M
    const int w4 = imin(bw4, f->bw - t->bx), h4 = imin(bh4, f->bh - t->by);
737
2.03M
    const int cbw4 = (bw4 + ss_hor) >> ss_hor, cbh4 = (bh4 + ss_ver) >> ss_ver;
738
2.03M
    const int have_left = t->bx > ts->tiling.col_start;
739
2.03M
    const int have_top = t->by > ts->tiling.row_start;
740
2.03M
    const int has_chroma = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 &&
741
1.56M
                           (bw4 > ss_hor || t->bx & 1) &&
742
1.50M
                           (bh4 > ss_ver || t->by & 1);
743
744
2.03M
    if (t->frame_thread.pass == 2) {
745
717k
        if (b->intra) {
746
585k
            f->bd_fn.recon_b_intra(t, bs, intra_edge_flags, b);
747
748
585k
            const enum IntraPredMode y_mode_nofilt =
749
585k
                b->y_mode == FILTER_PRED ? DC_PRED : b->y_mode;
750
585k
#define set_ctx(rep_macro) \
751
1.17M
            rep_macro(edge->mode, off, y_mode_nofilt); \
752
1.17M
            rep_macro(edge->intra, off, 1)
753
585k
            BlockContext *edge = t->a;
754
1.75M
            for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
755
1.17M
                case_set(b_dim[2 + i]);
756
1.17M
            }
757
585k
#undef set_ctx
758
585k
            if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
759
5.42k
                refmvs_block *const r = &t->rt.r[(t->by & 31) + 5 + bh4 - 1][t->bx];
760
41.2k
                for (int x = 0; x < bw4; x++) {
761
35.8k
                    r[x].ref.ref[0] = 0;
762
35.8k
                    r[x].bs = bs;
763
35.8k
                }
764
5.42k
                refmvs_block *const *rr = &t->rt.r[(t->by & 31) + 5];
765
5.42k
                const int bx = t->bx + bw4 - 1;
766
32.8k
                for (int y = 0; y < bh4 - 1; y++) {
767
27.4k
                    refmvs_block *d = &rr[y][bx];
768
27.4k
                    d->ref.ref[0] = 0;
769
27.4k
                    d->bs = bs;
770
27.4k
                }
771
5.42k
            }
772
773
585k
            if (has_chroma) {
774
431k
                uint8_t uv_mode = b->uv_mode;
775
431k
                dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], uv_mode);
776
431k
                dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], uv_mode);
777
431k
            }
778
585k
        } else {
779
131k
            if (IS_INTER_OR_SWITCH(f->frame_hdr) /* not intrabc */ &&
780
92.4k
                b->comp_type == COMP_INTER_NONE && b->motion_mode == MM_WARP)
781
353
            {
782
353
                if (b->matrix[0] == INT16_MIN) {
783
50
                    t->warpmv.type = DAV1D_WM_TYPE_IDENTITY;
784
303
                } else {
785
303
                    t->warpmv.type = DAV1D_WM_TYPE_AFFINE;
786
303
                    t->warpmv.matrix[2] = b->matrix[0] + 0x10000;
787
303
                    t->warpmv.matrix[3] = b->matrix[1];
788
303
                    t->warpmv.matrix[4] = b->matrix[2];
789
303
                    t->warpmv.matrix[5] = b->matrix[3] + 0x10000;
790
303
                    dav1d_set_affine_mv2d(bw4, bh4, b->mv2d, &t->warpmv,
791
303
                                          t->bx, t->by);
792
303
                    dav1d_get_shear_params(&t->warpmv);
793
303
#define signabs(v) v < 0 ? '-' : ' ', abs(v)
794
303
                    if (DEBUG_BLOCK_INFO)
795
0
                        printf("[ %c%x %c%x %c%x\n  %c%x %c%x %c%x ]\n"
796
0
                               "alpha=%c%x, beta=%c%x, gamma=%c%x, delta=%c%x, mv=y:%d,x:%d\n",
797
0
                               signabs(t->warpmv.matrix[0]),
798
0
                               signabs(t->warpmv.matrix[1]),
799
0
                               signabs(t->warpmv.matrix[2]),
800
0
                               signabs(t->warpmv.matrix[3]),
801
0
                               signabs(t->warpmv.matrix[4]),
802
0
                               signabs(t->warpmv.matrix[5]),
803
0
                               signabs(t->warpmv.u.p.alpha),
804
0
                               signabs(t->warpmv.u.p.beta),
805
0
                               signabs(t->warpmv.u.p.gamma),
806
0
                               signabs(t->warpmv.u.p.delta),
807
0
                               b->mv2d.y, b->mv2d.x);
808
303
#undef signabs
809
303
                }
810
353
            }
811
131k
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
812
813
131k
            const uint8_t *const filter = dav1d_filter_dir[b->filter2d];
814
131k
            BlockContext *edge = t->a;
815
394k
            for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
816
262k
#define set_ctx(rep_macro) \
817
262k
                rep_macro(edge->filter[0], off, filter[0]); \
818
262k
                rep_macro(edge->filter[1], off, filter[1]); \
819
262k
                rep_macro(edge->intra, off, 0)
820
262k
                case_set(b_dim[2 + i]);
821
262k
#undef set_ctx
822
262k
            }
823
824
131k
            if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
825
92.4k
                refmvs_block *const r = &t->rt.r[(t->by & 31) + 5 + bh4 - 1][t->bx];
826
92.4k
                const int ref1 = b->ref[0] + 1;
827
92.4k
                const union mv mv1 = b->mv[0];
828
573k
                for (int x = 0; x < bw4; x++) {
829
481k
                    r[x].ref.ref[0] = ref1;
830
481k
                    r[x].mv.mv[0] = mv1;
831
481k
                    r[x].bs = bs;
832
481k
                }
833
92.4k
                refmvs_block *const *rr = &t->rt.r[(t->by & 31) + 5];
834
92.4k
                const int bx = t->bx + bw4 - 1;
835
455k
                for (int y = 0; y < bh4 - 1; y++) {
836
363k
                    refmvs_block* d = &rr[y][bx];
837
363k
                    d->ref.ref[0] = ref1;
838
363k
                    d->mv.mv[0] = mv1;
839
363k
                    d->bs = bs;
840
363k
                }
841
92.4k
            }
842
843
131k
            if (has_chroma) {
844
94.8k
                dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], DC_PRED);
845
94.8k
                dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], DC_PRED);
846
94.8k
            }
847
131k
        }
848
717k
        return 0;
849
717k
    }
850
851
1.32M
    const int cw4 = (w4 + ss_hor) >> ss_hor, ch4 = (h4 + ss_ver) >> ss_ver;
852
853
1.32M
    b->bl = bl;
854
1.32M
    b->bp = bp;
855
1.32M
    b->bs = bs;
856
857
1.32M
    const Dav1dSegmentationData *seg = NULL;
858
859
    // segment_id (if seg_feature for skip/ref/gmv is enabled)
860
1.32M
    int seg_pred = 0;
861
1.32M
    if (f->frame_hdr->segmentation.enabled) {
862
785k
        if (!f->frame_hdr->segmentation.update_map) {
863
5.85k
            if (f->prev_segmap) {
864
2.69k
                unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
865
2.69k
                                                       f->prev_segmap,
866
2.69k
                                                       f->b4_stride);
867
2.69k
                if (seg_id >= 8) return -1;
868
2.69k
                b->seg_id = seg_id;
869
3.16k
            } else {
870
3.16k
                b->seg_id = 0;
871
3.16k
            }
872
5.85k
            seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
873
779k
        } else if (f->frame_hdr->segmentation.seg_data.preskip) {
874
760k
            if (f->frame_hdr->segmentation.temporal &&
875
4.17k
                (seg_pred = dav1d_msac_decode_bool_adapt(&ts->msac,
876
4.17k
                                ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
877
4.17k
                                t->l.seg_pred[by4]])))
878
2.23k
            {
879
                // temporal predicted seg_id
880
2.23k
                if (f->prev_segmap) {
881
702
                    unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx,
882
702
                                                           w4, h4,
883
702
                                                           f->prev_segmap,
884
702
                                                           f->b4_stride);
885
702
                    if (seg_id >= 8) return -1;
886
702
                    b->seg_id = seg_id;
887
1.53k
                } else {
888
1.53k
                    b->seg_id = 0;
889
1.53k
                }
890
757k
            } else {
891
757k
                int seg_ctx;
892
757k
                const unsigned pred_seg_id =
893
757k
                    get_cur_frame_segid(t->by, t->bx, have_top, have_left,
894
757k
                                        &seg_ctx, f->cur_segmap, f->b4_stride);
895
757k
                const unsigned diff = dav1d_msac_decode_symbol_adapt8(&ts->msac,
896
757k
                                          ts->cdf.m.seg_id[seg_ctx],
897
757k
                                          DAV1D_MAX_SEGMENTS - 1);
898
757k
                const unsigned last_active_seg_id =
899
757k
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
900
757k
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
901
757k
                                             last_active_seg_id + 1);
902
757k
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
903
757k
                if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
904
757k
            }
905
906
760k
            if (DEBUG_BLOCK_INFO)
907
0
                printf("Post-segid[preskip;%d]: r=%d\n",
908
0
                       b->seg_id, ts->msac.rng);
909
910
760k
            seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
911
760k
        }
912
785k
    } else {
913
534k
        b->seg_id = 0;
914
534k
    }
915
916
    // skip_mode
917
1.32M
    if ((!seg || (!seg->globalmv && seg->ref == -1 && !seg->skip)) &&
918
762k
        f->frame_hdr->skip_mode_enabled && imin(bw4, bh4) > 1)
919
590
    {
920
590
        const int smctx = t->a->skip_mode[bx4] + t->l.skip_mode[by4];
921
590
        b->skip_mode = dav1d_msac_decode_bool_adapt(&ts->msac,
922
590
                           ts->cdf.m.skip_mode[smctx]);
923
590
        if (DEBUG_BLOCK_INFO)
924
0
            printf("Post-skipmode[%d]: r=%d\n", b->skip_mode, ts->msac.rng);
925
1.31M
    } else {
926
1.31M
        b->skip_mode = 0;
927
1.31M
    }
928
929
    // skip
930
1.32M
    if (b->skip_mode || (seg && seg->skip)) {
931
438k
        b->skip = 1;
932
881k
    } else {
933
881k
        const int sctx = t->a->skip[bx4] + t->l.skip[by4];
934
881k
        b->skip = dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.skip[sctx]);
935
881k
        if (DEBUG_BLOCK_INFO)
936
0
            printf("Post-skip[%d]: r=%d\n", b->skip, ts->msac.rng);
937
881k
    }
938
939
    // segment_id
940
1.32M
    if (f->frame_hdr->segmentation.enabled &&
941
786k
        f->frame_hdr->segmentation.update_map &&
942
780k
        !f->frame_hdr->segmentation.seg_data.preskip)
943
19.6k
    {
944
19.6k
        if (!b->skip && f->frame_hdr->segmentation.temporal &&
945
952
            (seg_pred = dav1d_msac_decode_bool_adapt(&ts->msac,
946
952
                            ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
947
952
                            t->l.seg_pred[by4]])))
948
511
        {
949
            // temporal predicted seg_id
950
511
            if (f->prev_segmap) {
951
77
                unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
952
77
                                                       f->prev_segmap,
953
77
                                                       f->b4_stride);
954
77
                if (seg_id >= 8) return -1;
955
77
                b->seg_id = seg_id;
956
434
            } else {
957
434
                b->seg_id = 0;
958
434
            }
959
19.1k
        } else {
960
19.1k
            int seg_ctx;
961
19.1k
            const unsigned pred_seg_id =
962
19.1k
                get_cur_frame_segid(t->by, t->bx, have_top, have_left,
963
19.1k
                                    &seg_ctx, f->cur_segmap, f->b4_stride);
964
19.1k
            if (b->skip) {
965
7.00k
                b->seg_id = pred_seg_id;
966
12.1k
            } else {
967
12.1k
                const unsigned diff = dav1d_msac_decode_symbol_adapt8(&ts->msac,
968
12.1k
                                          ts->cdf.m.seg_id[seg_ctx],
969
12.1k
                                          DAV1D_MAX_SEGMENTS - 1);
970
12.1k
                const unsigned last_active_seg_id =
971
12.1k
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
972
12.1k
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
973
12.1k
                                             last_active_seg_id + 1);
974
12.1k
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
975
12.1k
            }
976
19.1k
            if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
977
19.1k
        }
978
979
19.6k
        seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
980
981
19.6k
        if (DEBUG_BLOCK_INFO)
982
0
            printf("Post-segid[postskip;%d]: r=%d\n",
983
0
                   b->seg_id, ts->msac.rng);
984
19.6k
    }
985
986
    // cdef index
987
1.32M
    if (!b->skip) {
988
579k
        const int idx = f->seq_hdr->sb128 ? ((t->bx & 16) >> 4) +
989
385k
                                           ((t->by & 16) >> 3) : 0;
990
579k
        if (t->cur_sb_cdef_idx_ptr[idx] == -1) {
991
140k
            const int v = dav1d_msac_decode_bools(&ts->msac,
992
140k
                              f->frame_hdr->cdef.n_bits);
993
140k
            t->cur_sb_cdef_idx_ptr[idx] = v;
994
140k
            if (bw4 > 16) t->cur_sb_cdef_idx_ptr[idx + 1] = v;
995
140k
            if (bh4 > 16) t->cur_sb_cdef_idx_ptr[idx + 2] = v;
996
140k
            if (bw4 == 32 && bh4 == 32) t->cur_sb_cdef_idx_ptr[idx + 3] = v;
997
998
140k
            if (DEBUG_BLOCK_INFO)
999
0
                printf("Post-cdef_idx[%d]: r=%d\n",
1000
0
                        *t->cur_sb_cdef_idx_ptr, ts->msac.rng);
1001
140k
        }
1002
579k
    }
1003
1004
    // delta-q/lf
1005
1.32M
    if (!((t->bx | t->by) & (31 >> !f->seq_hdr->sb128))) {
1006
187k
        const int prev_qidx = ts->last_qidx;
1007
187k
        const int have_delta_q = f->frame_hdr->delta.q.present &&
1008
66.8k
            (bs != (f->seq_hdr->sb128 ? BS_128x128 : BS_64x64) || !b->skip);
1009
1010
187k
        uint32_t prev_delta_lf = ts->last_delta_lf.u32;
1011
1012
187k
        if (have_delta_q) {
1013
63.2k
            int delta_q = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1014
63.2k
                                                          ts->cdf.m.delta_q, 3);
1015
63.2k
            if (delta_q == 3) {
1016
4.06k
                const int n_bits = 1 + dav1d_msac_decode_bools(&ts->msac, 3);
1017
4.06k
                delta_q = dav1d_msac_decode_bools(&ts->msac, n_bits) +
1018
4.06k
                          1 + (1 << n_bits);
1019
4.06k
            }
1020
63.2k
            if (delta_q) {
1021
11.7k
                if (dav1d_msac_decode_bool_equi(&ts->msac)) delta_q = -delta_q;
1022
11.7k
                delta_q *= 1 << f->frame_hdr->delta.q.res_log2;
1023
11.7k
            }
1024
63.2k
            ts->last_qidx = iclip(ts->last_qidx + delta_q, 1, 255);
1025
63.2k
            if (have_delta_q && DEBUG_BLOCK_INFO)
1026
0
                printf("Post-delta_q[%d->%d]: r=%d\n",
1027
0
                       delta_q, ts->last_qidx, ts->msac.rng);
1028
1029
63.2k
            if (f->frame_hdr->delta.lf.present) {
1030
38.0k
                const int n_lfs = f->frame_hdr->delta.lf.multi ?
1031
20.6k
                    f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 ? 4 : 2 : 1;
1032
1033
121k
                for (int i = 0; i < n_lfs; i++) {
1034
83.7k
                    int delta_lf = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1035
83.7k
                        ts->cdf.m.delta_lf[i + f->frame_hdr->delta.lf.multi], 3);
1036
83.7k
                    if (delta_lf == 3) {
1037
3.39k
                        const int n_bits = 1 + dav1d_msac_decode_bools(&ts->msac, 3);
1038
3.39k
                        delta_lf = dav1d_msac_decode_bools(&ts->msac, n_bits) +
1039
3.39k
                                   1 + (1 << n_bits);
1040
3.39k
                    }
1041
83.7k
                    if (delta_lf) {
1042
14.4k
                        if (dav1d_msac_decode_bool_equi(&ts->msac))
1043
8.72k
                            delta_lf = -delta_lf;
1044
14.4k
                        delta_lf *= 1 << f->frame_hdr->delta.lf.res_log2;
1045
14.4k
                    }
1046
83.7k
                    ts->last_delta_lf.i8[i] =
1047
83.7k
                        iclip(ts->last_delta_lf.i8[i] + delta_lf, -63, 63);
1048
83.7k
                    if (have_delta_q && DEBUG_BLOCK_INFO)
1049
0
                        printf("Post-delta_lf[%d:%d]: r=%d\n", i, delta_lf,
1050
0
                               ts->msac.rng);
1051
83.7k
                }
1052
38.0k
            }
1053
63.2k
        }
1054
187k
        if (ts->last_qidx == f->frame_hdr->quant.yac) {
1055
            // assign frame-wide q values to this sb
1056
143k
            ts->dq = f->dq;
1057
143k
        } else if (ts->last_qidx != prev_qidx) {
1058
            // find sb-specific quant parameters
1059
7.50k
            init_quant_tables(f->seq_hdr, f->frame_hdr, ts->last_qidx, ts->dqmem);
1060
7.50k
            ts->dq = ts->dqmem;
1061
7.50k
        }
1062
187k
        if (!ts->last_delta_lf.u32) {
1063
            // assign frame-wide lf values to this sb
1064
155k
            ts->lflvl = f->lf.lvl;
1065
155k
        } else if (ts->last_delta_lf.u32 != prev_delta_lf) {
1066
            // find sb-specific lf lvl parameters
1067
9.37k
            ts->lflvl = ts->lflvlmem;
1068
9.37k
            dav1d_calc_lf_values(ts->lflvlmem, f->frame_hdr, ts->last_delta_lf.i8);
1069
9.37k
        }
1070
187k
    }
1071
1072
1.32M
    if (b->skip_mode) {
1073
41
        b->intra = 0;
1074
1.32M
    } else if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
1075
312k
        if (seg && (seg->ref >= 0 || seg->globalmv)) {
1076
101k
            b->intra = !seg->ref;
1077
210k
        } else {
1078
210k
            const int ictx = get_intra_ctx(t->a, &t->l, by4, bx4,
1079
210k
                                           have_top, have_left);
1080
210k
            b->intra = !dav1d_msac_decode_bool_adapt(&ts->msac,
1081
210k
                            ts->cdf.m.intra[ictx]);
1082
210k
            if (DEBUG_BLOCK_INFO)
1083
0
                printf("Post-intra[%d]: r=%d\n", b->intra, ts->msac.rng);
1084
210k
        }
1085
1.00M
    } else if (f->frame_hdr->allow_intrabc) {
1086
515k
        b->intra = !dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.intrabc);
1087
515k
        if (DEBUG_BLOCK_INFO)
1088
0
            printf("Post-intrabcflag[%d]: r=%d\n", b->intra, ts->msac.rng);
1089
515k
    } else {
1090
492k
        b->intra = 1;
1091
492k
    }
1092
1093
    // intra/inter-specific stuff
1094
1.32M
    if (b->intra) {
1095
926k
        uint16_t *const ymode_cdf = IS_INTER_OR_SWITCH(f->frame_hdr) ?
1096
32.3k
            ts->cdf.m.y_mode[dav1d_ymode_size_context[bs]] :
1097
926k
            ts->cdf.kfym[dav1d_intra_mode_context[t->a->mode[bx4]]]
1098
893k
                        [dav1d_intra_mode_context[t->l.mode[by4]]];
1099
926k
        b->y_mode = dav1d_msac_decode_symbol_adapt16(&ts->msac, ymode_cdf,
1100
926k
                                                     N_INTRA_PRED_MODES - 1);
1101
926k
        if (DEBUG_BLOCK_INFO)
1102
0
            printf("Post-ymode[%d]: r=%d\n", b->y_mode, ts->msac.rng);
1103
1104
        // angle delta
1105
926k
        if (b_dim[2] + b_dim[3] >= 2 && b->y_mode >= VERT_PRED &&
1106
405k
            b->y_mode <= VERT_LEFT_PRED)
1107
236k
        {
1108
236k
            uint16_t *const acdf = ts->cdf.m.angle_delta[b->y_mode - VERT_PRED];
1109
236k
            const int angle = dav1d_msac_decode_symbol_adapt8(&ts->msac, acdf, 6);
1110
236k
            b->y_angle = angle - 3;
1111
689k
        } else {
1112
689k
            b->y_angle = 0;
1113
689k
        }
1114
1115
926k
        if (has_chroma) {
1116
680k
            const int cfl_allowed = f->frame_hdr->segmentation.lossless[b->seg_id] ?
1117
675k
                cbw4 == 1 && cbh4 == 1 : !!(cfl_allowed_mask & (1 << bs));
1118
680k
            uint16_t *const uvmode_cdf = ts->cdf.m.uv_mode[cfl_allowed][b->y_mode];
1119
680k
            b->uv_mode = dav1d_msac_decode_symbol_adapt16(&ts->msac, uvmode_cdf,
1120
680k
                             N_UV_INTRA_PRED_MODES - 1 - !cfl_allowed);
1121
680k
            if (DEBUG_BLOCK_INFO)
1122
0
                printf("Post-uvmode[%d]: r=%d\n", b->uv_mode, ts->msac.rng);
1123
1124
680k
            b->uv_angle = 0;
1125
680k
            if (b->uv_mode == CFL_PRED) {
1126
135k
#define SIGN(a) (!!(a) + ((a) > 0))
1127
135k
                const int sign = dav1d_msac_decode_symbol_adapt8(&ts->msac,
1128
135k
                                     ts->cdf.m.cfl_sign, 7) + 1;
1129
135k
                const int sign_u = sign * 0x56 >> 8, sign_v = sign - sign_u * 3;
1130
135k
                assert(sign_u == sign / 3);
1131
135k
                if (sign_u) {
1132
126k
                    const int ctx = (sign_u == 2) * 3 + sign_v;
1133
126k
                    b->cfl_alpha[0] = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1134
126k
                                          ts->cdf.m.cfl_alpha[ctx], 15) + 1;
1135
126k
                    if (sign_u == 1) b->cfl_alpha[0] = -b->cfl_alpha[0];
1136
126k
                } else {
1137
9.34k
                    b->cfl_alpha[0] = 0;
1138
9.34k
                }
1139
135k
                if (sign_v) {
1140
88.4k
                    const int ctx = (sign_v == 2) * 3 + sign_u;
1141
88.4k
                    b->cfl_alpha[1] = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1142
88.4k
                                          ts->cdf.m.cfl_alpha[ctx], 15) + 1;
1143
88.4k
                    if (sign_v == 1) b->cfl_alpha[1] = -b->cfl_alpha[1];
1144
88.4k
                } else {
1145
47.0k
                    b->cfl_alpha[1] = 0;
1146
47.0k
                }
1147
135k
#undef SIGN
1148
135k
                if (DEBUG_BLOCK_INFO)
1149
0
                    printf("Post-uvalphas[%d/%d]: r=%d\n",
1150
0
                           b->cfl_alpha[0], b->cfl_alpha[1], ts->msac.rng);
1151
544k
            } else if (b_dim[2] + b_dim[3] >= 2 && b->uv_mode >= VERT_PRED &&
1152
281k
                       b->uv_mode <= VERT_LEFT_PRED)
1153
148k
            {
1154
148k
                uint16_t *const acdf = ts->cdf.m.angle_delta[b->uv_mode - VERT_PRED];
1155
148k
                const int angle = dav1d_msac_decode_symbol_adapt8(&ts->msac, acdf, 6);
1156
148k
                b->uv_angle = angle - 3;
1157
148k
            }
1158
680k
        }
1159
1160
926k
        b->pal_sz[0] = b->pal_sz[1] = 0;
1161
926k
        if (f->frame_hdr->allow_screen_content_tools &&
1162
477k
            imax(bw4, bh4) <= 16 && bw4 + bh4 >= 4)
1163
374k
        {
1164
374k
            const int sz_ctx = b_dim[2] + b_dim[3] - 2;
1165
374k
            if (b->y_mode == DC_PRED) {
1166
158k
                const int pal_ctx = (t->a->pal_sz[bx4] > 0) + (t->l.pal_sz[by4] > 0);
1167
158k
                const int use_y_pal = dav1d_msac_decode_bool_adapt(&ts->msac,
1168
158k
                                          ts->cdf.m.pal_y[sz_ctx][pal_ctx]);
1169
158k
                if (DEBUG_BLOCK_INFO)
1170
0
                    printf("Post-y_pal[%d]: r=%d\n", use_y_pal, ts->msac.rng);
1171
158k
                if (use_y_pal)
1172
12.7k
                    f->bd_fn.read_pal_plane(t, b, 0, sz_ctx, bx4, by4);
1173
158k
            }
1174
1175
374k
            if (has_chroma && b->uv_mode == DC_PRED) {
1176
91.9k
                const int pal_ctx = b->pal_sz[0] > 0;
1177
91.9k
                const int use_uv_pal = dav1d_msac_decode_bool_adapt(&ts->msac,
1178
91.9k
                                           ts->cdf.m.pal_uv[pal_ctx]);
1179
91.9k
                if (DEBUG_BLOCK_INFO)
1180
0
                    printf("Post-uv_pal[%d]: r=%d\n", use_uv_pal, ts->msac.rng);
1181
91.9k
                if (use_uv_pal) // see aomedia bug 2183 for why we use luma coordinates
1182
3.40k
                    f->bd_fn.read_pal_uv(t, b, sz_ctx, bx4, by4);
1183
91.9k
            }
1184
374k
        }
1185
1186
926k
        if (b->y_mode == DC_PRED && !b->pal_sz[0] &&
1187
361k
            imax(b_dim[2], b_dim[3]) <= 3 && f->seq_hdr->filter_intra)
1188
102k
        {
1189
102k
            const int is_filter = dav1d_msac_decode_bool_adapt(&ts->msac,
1190
102k
                                      ts->cdf.m.use_filter_intra[bs]);
1191
102k
            if (is_filter) {
1192
67.9k
                b->y_mode = FILTER_PRED;
1193
67.9k
                b->y_angle = dav1d_msac_decode_symbol_adapt8(&ts->msac,
1194
67.9k
                                 ts->cdf.m.filter_intra, 4);
1195
67.9k
            }
1196
102k
            if (DEBUG_BLOCK_INFO)
1197
0
                printf("Post-filterintramode[%d/%d]: r=%d\n",
1198
0
                       b->y_mode, b->y_angle, ts->msac.rng);
1199
102k
        }
1200
1201
926k
        if (b->pal_sz[0]) {
1202
12.7k
            uint8_t *pal_idx;
1203
12.7k
            if (t->frame_thread.pass) {
1204
12.7k
                const int p = t->frame_thread.pass & 1;
1205
12.7k
                assert(ts->frame_thread[p].pal_idx);
1206
12.7k
                pal_idx = ts->frame_thread[p].pal_idx;
1207
12.7k
                ts->frame_thread[p].pal_idx += bw4 * bh4 * 8;
1208
12.7k
            } else
1209
0
                pal_idx = t->scratch.pal_idx_y;
1210
12.7k
            read_pal_indices(t, pal_idx, b->pal_sz[0], 0, w4, h4, bw4, bh4);
1211
12.7k
            if (DEBUG_BLOCK_INFO)
1212
0
                printf("Post-y-pal-indices: r=%d\n", ts->msac.rng);
1213
12.7k
        }
1214
1215
926k
        if (has_chroma && b->pal_sz[1]) {
1216
3.40k
            uint8_t *pal_idx;
1217
3.40k
            if (t->frame_thread.pass) {
1218
3.40k
                const int p = t->frame_thread.pass & 1;
1219
3.40k
                assert(ts->frame_thread[p].pal_idx);
1220
3.40k
                pal_idx = ts->frame_thread[p].pal_idx;
1221
3.40k
                ts->frame_thread[p].pal_idx += cbw4 * cbh4 * 8;
1222
3.40k
            } else
1223
0
                pal_idx = t->scratch.pal_idx_uv;
1224
3.40k
            read_pal_indices(t, pal_idx, b->pal_sz[1], 1, cw4, ch4, cbw4, cbh4);
1225
3.40k
            if (DEBUG_BLOCK_INFO)
1226
0
                printf("Post-uv-pal-indices: r=%d\n", ts->msac.rng);
1227
3.40k
        }
1228
1229
926k
        const TxfmInfo *t_dim;
1230
926k
        if (f->frame_hdr->segmentation.lossless[b->seg_id]) {
1231
10.8k
            b->tx = b->uvtx = (int) TX_4X4;
1232
10.8k
            t_dim = &dav1d_txfm_dimensions[TX_4X4];
1233
915k
        } else {
1234
915k
            b->tx = dav1d_max_txfm_size_for_bs[bs][0];
1235
915k
            b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
1236
915k
            t_dim = &dav1d_txfm_dimensions[b->tx];
1237
915k
            if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE && t_dim->max > TX_4X4) {
1238
210k
                const int tctx = get_tx_ctx(t->a, &t->l, t_dim, by4, bx4);
1239
210k
                uint16_t *const tx_cdf = ts->cdf.m.txsz[t_dim->max - 1][tctx];
1240
210k
                int depth = dav1d_msac_decode_symbol_adapt4(&ts->msac, tx_cdf,
1241
210k
                                imin(t_dim->max, 2));
1242
1243
380k
                while (depth--) {
1244
169k
                    b->tx = t_dim->sub;
1245
169k
                    t_dim = &dav1d_txfm_dimensions[b->tx];
1246
169k
                }
1247
210k
            }
1248
915k
            if (DEBUG_BLOCK_INFO)
1249
0
                printf("Post-tx[%d]: r=%d\n", b->tx, ts->msac.rng);
1250
915k
        }
1251
1252
        // reconstruction
1253
926k
        if (t->frame_thread.pass == 1) {
1254
926k
            f->bd_fn.read_coef_blocks(t, bs, b);
1255
18.4E
        } else {
1256
18.4E
            f->bd_fn.recon_b_intra(t, bs, intra_edge_flags, b);
1257
18.4E
        }
1258
1259
926k
        if (f->frame_hdr->loopfilter.level_y[0] ||
1260
481k
            f->frame_hdr->loopfilter.level_y[1])
1261
490k
        {
1262
490k
            dav1d_create_lf_mask_intra(t->lf_mask, f->lf.level, f->b4_stride,
1263
490k
                                       (const uint8_t (*)[8][2])
1264
490k
                                       &ts->lflvl[b->seg_id][0][0][0],
1265
490k
                                       t->bx, t->by, f->w4, f->h4, bs,
1266
490k
                                       b->tx, b->uvtx, f->cur.p.layout,
1267
490k
                                       &t->a->tx_lpf_y[bx4], &t->l.tx_lpf_y[by4],
1268
490k
                                       has_chroma ? &t->a->tx_lpf_uv[cbx4] : NULL,
1269
490k
                                       has_chroma ? &t->l.tx_lpf_uv[cby4] : NULL);
1270
490k
        }
1271
        // update contexts
1272
926k
        const enum IntraPredMode y_mode_nofilt =
1273
926k
            b->y_mode == FILTER_PRED ? DC_PRED : b->y_mode;
1274
926k
        BlockContext *edge = t->a;
1275
2.77M
        for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
1276
1.85M
            int t_lsz = ((uint8_t *) &t_dim->lw)[i]; // lw then lh
1277
1.85M
#define set_ctx(rep_macro) \
1278
1.85M
            rep_macro(edge->tx_intra, off, t_lsz); \
1279
1.85M
            rep_macro(edge->tx, off, t_lsz); \
1280
1.85M
            rep_macro(edge->mode, off, y_mode_nofilt); \
1281
1.85M
            rep_macro(edge->pal_sz, off, b->pal_sz[0]); \
1282
1.85M
            rep_macro(edge->seg_pred, off, seg_pred); \
1283
1.85M
            rep_macro(edge->skip_mode, off, 0); \
1284
1.85M
            rep_macro(edge->intra, off, 1); \
1285
1.85M
            rep_macro(edge->skip, off, b->skip); \
1286
            /* see aomedia bug 2183 for why we use luma coordinates here */ \
1287
1.85M
            rep_macro(t->pal_sz_uv[i], off, (has_chroma ? b->pal_sz[1] : 0)); \
1288
1.85M
            if (IS_INTER_OR_SWITCH(f->frame_hdr)) { \
1289
64.6k
                rep_macro(edge->comp_type, off, COMP_INTER_NONE); \
1290
64.6k
                rep_macro(edge->ref[0], off, ((uint8_t) -1)); \
1291
64.6k
                rep_macro(edge->ref[1], off, ((uint8_t) -1)); \
1292
64.6k
                rep_macro(edge->filter[0], off, DAV1D_N_SWITCHABLE_FILTERS); \
1293
64.6k
                rep_macro(edge->filter[1], off, DAV1D_N_SWITCHABLE_FILTERS); \
1294
64.6k
            }
1295
1.85M
            case_set(b_dim[2 + i]);
1296
1.85M
#undef set_ctx
1297
1.85M
        }
1298
926k
        if (b->pal_sz[0])
1299
12.7k
            f->bd_fn.copy_pal_block_y(t, bx4, by4, bw4, bh4);
1300
926k
        if (has_chroma) {
1301
680k
            uint8_t uv_mode = b->uv_mode;
1302
680k
            dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], uv_mode);
1303
680k
            dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], uv_mode);
1304
680k
            if (b->pal_sz[1])
1305
3.40k
                f->bd_fn.copy_pal_block_uv(t, bx4, by4, bw4, bh4);
1306
680k
        }
1307
926k
        if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc)
1308
431k
            splat_intraref(f->c, t, bs, bw4, bh4);
1309
926k
    } else if (IS_KEY_OR_INTRA(f->frame_hdr)) {
1310
        // intra block copy
1311
115k
        refmvs_candidate mvstack[8];
1312
115k
        int n_mvs, ctx;
1313
115k
        dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1314
115k
                          (union refmvs_refpair) { .ref = { 0, -1 }},
1315
115k
                          bs, intra_edge_flags, t->by, t->bx);
1316
1317
115k
        if (mvstack[0].mv.mv[0].n)
1318
100k
            b->mv[0] = mvstack[0].mv.mv[0];
1319
15.3k
        else if (mvstack[1].mv.mv[0].n)
1320
0
            b->mv[0] = mvstack[1].mv.mv[0];
1321
15.3k
        else {
1322
15.3k
            if (t->by - (16 << f->seq_hdr->sb128) < ts->tiling.row_start) {
1323
9.51k
                b->mv[0].y = 0;
1324
9.51k
                b->mv[0].x = -(512 << f->seq_hdr->sb128) - 2048;
1325
9.51k
            } else {
1326
5.81k
                b->mv[0].y = -(512 << f->seq_hdr->sb128);
1327
5.81k
                b->mv[0].x = 0;
1328
5.81k
            }
1329
15.3k
        }
1330
1331
115k
        const union mv ref = b->mv[0];
1332
115k
        read_mv_residual(ts, &b->mv[0], -1);
1333
1334
        // clip intrabc motion vector to decoded parts of current tile
1335
115k
        int border_left = ts->tiling.col_start * 4;
1336
115k
        int border_top  = ts->tiling.row_start * 4;
1337
115k
        if (has_chroma) {
1338
103k
            if (bw4 < 2 &&  ss_hor)
1339
2.23k
                border_left += 4;
1340
103k
            if (bh4 < 2 &&  ss_ver)
1341
1.93k
                border_top  += 4;
1342
103k
        }
1343
115k
        int src_left   = t->bx * 4 + (b->mv[0].x >> 3);
1344
115k
        int src_top    = t->by * 4 + (b->mv[0].y >> 3);
1345
115k
        int src_right  = src_left + bw4 * 4;
1346
115k
        int src_bottom = src_top  + bh4 * 4;
1347
115k
        const int border_right = ((ts->tiling.col_end + (bw4 - 1)) & ~(bw4 - 1)) * 4;
1348
1349
        // check against left or right tile boundary and adjust if necessary
1350
115k
        if (src_left < border_left) {
1351
27.8k
            src_right += border_left - src_left;
1352
27.8k
            src_left  += border_left - src_left;
1353
87.8k
        } else if (src_right > border_right) {
1354
12.1k
            src_left  -= src_right - border_right;
1355
12.1k
            src_right -= src_right - border_right;
1356
12.1k
        }
1357
        // check against top tile boundary and adjust if necessary
1358
115k
        if (src_top < border_top) {
1359
50.1k
            src_bottom += border_top - src_top;
1360
50.1k
            src_top    += border_top - src_top;
1361
50.1k
        }
1362
1363
115k
        const int sbx = (t->bx >> (4 + f->seq_hdr->sb128)) << (6 + f->seq_hdr->sb128);
1364
115k
        const int sby = (t->by >> (4 + f->seq_hdr->sb128)) << (6 + f->seq_hdr->sb128);
1365
115k
        const int sb_size = 1 << (6 + f->seq_hdr->sb128);
1366
        // check for overlap with current superblock
1367
115k
        if (src_bottom > sby && src_right > sbx) {
1368
9.58k
            if (src_top - border_top >= src_bottom - sby) {
1369
                // if possible move src up into the previous suberblock row
1370
1.77k
                src_top    -= src_bottom - sby;
1371
1.77k
                src_bottom -= src_bottom - sby;
1372
7.81k
            } else if (src_left - border_left >= src_right - sbx) {
1373
                // if possible move src left into the previous suberblock
1374
7.76k
                src_left  -= src_right - sbx;
1375
7.76k
                src_right -= src_right - sbx;
1376
7.76k
            }
1377
9.58k
        }
1378
        // move src up if it is below current superblock row
1379
115k
        if (src_bottom > sby + sb_size) {
1380
3.91k
            src_top    -= src_bottom - (sby + sb_size);
1381
3.91k
            src_bottom -= src_bottom - (sby + sb_size);
1382
3.91k
        }
1383
        // error out if mv still overlaps with the current superblock
1384
115k
        if (src_bottom > sby && src_right > sbx)
1385
47
            return -1;
1386
1387
115k
        b->mv[0].x = (src_left - t->bx * 4) * 8;
1388
115k
        b->mv[0].y = (src_top  - t->by * 4) * 8;
1389
1390
115k
        if (DEBUG_BLOCK_INFO)
1391
0
            printf("Post-dmv[%d/%d,ref=%d/%d|%d/%d]: r=%d\n",
1392
0
                   b->mv[0].y, b->mv[0].x, ref.y, ref.x,
1393
0
                   mvstack[0].mv.mv[0].y, mvstack[0].mv.mv[0].x, ts->msac.rng);
1394
115k
        read_vartx_tree(t, b, bs, bx4, by4);
1395
1396
        // reconstruction
1397
115k
        if (t->frame_thread.pass == 1) {
1398
115k
            f->bd_fn.read_coef_blocks(t, bs, b);
1399
115k
            b->filter2d = FILTER_2D_BILINEAR;
1400
18.4E
        } else {
1401
18.4E
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
1402
18.4E
        }
1403
1404
115k
        splat_intrabc_mv(f->c, t, bs, b, bw4, bh4);
1405
115k
        BlockContext *edge = t->a;
1406
347k
        for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
1407
231k
#define set_ctx(rep_macro) \
1408
231k
            rep_macro(edge->tx_intra, off, b_dim[2 + i]); \
1409
231k
            rep_macro(edge->mode, off, DC_PRED); \
1410
231k
            rep_macro(edge->pal_sz, off, 0); \
1411
            /* see aomedia bug 2183 for why this is outside if (has_chroma) */ \
1412
231k
            rep_macro(t->pal_sz_uv[i], off, 0); \
1413
231k
            rep_macro(edge->seg_pred, off, seg_pred); \
1414
231k
            rep_macro(edge->skip_mode, off, 0); \
1415
231k
            rep_macro(edge->intra, off, 0); \
1416
231k
            rep_macro(edge->skip, off, b->skip)
1417
231k
            case_set(b_dim[2 + i]);
1418
231k
#undef set_ctx
1419
231k
        }
1420
115k
        if (has_chroma) {
1421
103k
            dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], DC_PRED);
1422
103k
            dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], DC_PRED);
1423
103k
        }
1424
278k
    } else {
1425
        // inter-specific mode/mv coding
1426
278k
        int is_comp, has_subpel_filter;
1427
1428
278k
        if (b->skip_mode) {
1429
41
            is_comp = 1;
1430
278k
        } else if ((!seg || (seg->ref == -1 && !seg->globalmv && !seg->skip)) &&
1431
177k
                   f->frame_hdr->switchable_comp_refs && imin(bw4, bh4) > 1)
1432
75.6k
        {
1433
75.6k
            const int ctx = get_comp_ctx(t->a, &t->l, by4, bx4,
1434
75.6k
                                         have_top, have_left);
1435
75.6k
            is_comp = dav1d_msac_decode_bool_adapt(&ts->msac,
1436
75.6k
                          ts->cdf.m.comp[ctx]);
1437
75.6k
            if (DEBUG_BLOCK_INFO)
1438
0
                printf("Post-compflag[%d]: r=%d\n", is_comp, ts->msac.rng);
1439
202k
        } else {
1440
202k
            is_comp = 0;
1441
202k
        }
1442
1443
278k
        if (b->skip_mode) {
1444
41
            b->ref[0] = f->frame_hdr->skip_mode_refs[0];
1445
41
            b->ref[1] = f->frame_hdr->skip_mode_refs[1];
1446
41
            b->comp_type = COMP_INTER_AVG;
1447
41
            b->inter_mode = NEARESTMV_NEARESTMV;
1448
41
            b->drl_idx = NEAREST_DRL;
1449
41
            has_subpel_filter = 0;
1450
1451
41
            refmvs_candidate mvstack[8];
1452
41
            int n_mvs, ctx;
1453
41
            dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1454
41
                              (union refmvs_refpair) { .ref = {
1455
41
                                    b->ref[0] + 1, b->ref[1] + 1 }},
1456
41
                              bs, intra_edge_flags, t->by, t->bx);
1457
1458
41
            b->mv[0] = mvstack[0].mv.mv[0];
1459
41
            b->mv[1] = mvstack[0].mv.mv[1];
1460
41
            fix_mv_precision(f->frame_hdr, &b->mv[0]);
1461
41
            fix_mv_precision(f->frame_hdr, &b->mv[1]);
1462
41
            if (DEBUG_BLOCK_INFO)
1463
0
                printf("Post-skipmodeblock[mv=1:y=%d,x=%d,2:y=%d,x=%d,refs=%d+%d\n",
1464
0
                       b->mv[0].y, b->mv[0].x, b->mv[1].y, b->mv[1].x,
1465
0
                       b->ref[0], b->ref[1]);
1466
278k
        } else if (is_comp) {
1467
41.0k
            const int dir_ctx = get_comp_dir_ctx(t->a, &t->l, by4, bx4,
1468
41.0k
                                                 have_top, have_left);
1469
41.0k
            if (dav1d_msac_decode_bool_adapt(&ts->msac,
1470
41.0k
                    ts->cdf.m.comp_dir[dir_ctx]))
1471
33.9k
            {
1472
                // bidir - first reference (fw)
1473
33.9k
                const int ctx1 = av1_get_fwd_ref_ctx(t->a, &t->l, by4, bx4,
1474
33.9k
                                                     have_top, have_left);
1475
33.9k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1476
33.9k
                        ts->cdf.m.comp_fwd_ref[0][ctx1]))
1477
11.8k
                {
1478
11.8k
                    const int ctx2 = av1_get_fwd_ref_2_ctx(t->a, &t->l, by4, bx4,
1479
11.8k
                                                           have_top, have_left);
1480
11.8k
                    b->ref[0] = 2 + dav1d_msac_decode_bool_adapt(&ts->msac,
1481
11.8k
                                        ts->cdf.m.comp_fwd_ref[2][ctx2]);
1482
22.0k
                } else {
1483
22.0k
                    const int ctx2 = av1_get_fwd_ref_1_ctx(t->a, &t->l, by4, bx4,
1484
22.0k
                                                           have_top, have_left);
1485
22.0k
                    b->ref[0] = dav1d_msac_decode_bool_adapt(&ts->msac,
1486
22.0k
                                    ts->cdf.m.comp_fwd_ref[1][ctx2]);
1487
22.0k
                }
1488
1489
                // second reference (bw)
1490
33.9k
                const int ctx3 = av1_get_bwd_ref_ctx(t->a, &t->l, by4, bx4,
1491
33.9k
                                                     have_top, have_left);
1492
33.9k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1493
33.9k
                        ts->cdf.m.comp_bwd_ref[0][ctx3]))
1494
17.1k
                {
1495
17.1k
                    b->ref[1] = 6;
1496
17.1k
                } else {
1497
16.8k
                    const int ctx4 = av1_get_bwd_ref_1_ctx(t->a, &t->l, by4, bx4,
1498
16.8k
                                                           have_top, have_left);
1499
16.8k
                    b->ref[1] = 4 + dav1d_msac_decode_bool_adapt(&ts->msac,
1500
16.8k
                                        ts->cdf.m.comp_bwd_ref[1][ctx4]);
1501
16.8k
                }
1502
33.9k
            } else {
1503
                // unidir
1504
7.08k
                const int uctx_p = av1_get_uni_p_ctx(t->a, &t->l, by4, bx4,
1505
7.08k
                                                     have_top, have_left);
1506
7.08k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1507
7.08k
                        ts->cdf.m.comp_uni_ref[0][uctx_p]))
1508
1.85k
                {
1509
1.85k
                    b->ref[0] = 4;
1510
1.85k
                    b->ref[1] = 6;
1511
5.22k
                } else {
1512
5.22k
                    const int uctx_p1 = av1_get_uni_p1_ctx(t->a, &t->l, by4, bx4,
1513
5.22k
                                                           have_top, have_left);
1514
5.22k
                    b->ref[0] = 0;
1515
5.22k
                    b->ref[1] = 1 + dav1d_msac_decode_bool_adapt(&ts->msac,
1516
5.22k
                                        ts->cdf.m.comp_uni_ref[1][uctx_p1]);
1517
5.22k
                    if (b->ref[1] == 2) {
1518
3.33k
                        const int uctx_p2 = av1_get_uni_p2_ctx(t->a, &t->l, by4, bx4,
1519
3.33k
                                                               have_top, have_left);
1520
3.33k
                        b->ref[1] += dav1d_msac_decode_bool_adapt(&ts->msac,
1521
3.33k
                                         ts->cdf.m.comp_uni_ref[2][uctx_p2]);
1522
3.33k
                    }
1523
5.22k
                }
1524
7.08k
            }
1525
41.0k
            if (DEBUG_BLOCK_INFO)
1526
0
                printf("Post-refs[%d/%d]: r=%d\n",
1527
0
                       b->ref[0], b->ref[1], ts->msac.rng);
1528
1529
41.0k
            refmvs_candidate mvstack[8];
1530
41.0k
            int n_mvs, ctx;
1531
41.0k
            dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1532
41.0k
                              (union refmvs_refpair) { .ref = {
1533
41.0k
                                    b->ref[0] + 1, b->ref[1] + 1 }},
1534
41.0k
                              bs, intra_edge_flags, t->by, t->bx);
1535
1536
41.0k
            b->inter_mode = dav1d_msac_decode_symbol_adapt8(&ts->msac,
1537
41.0k
                                ts->cdf.m.comp_inter_mode[ctx],
1538
41.0k
                                N_COMP_INTER_PRED_MODES - 1);
1539
41.0k
            if (DEBUG_BLOCK_INFO)
1540
0
                printf("Post-compintermode[%d,ctx=%d,n_mvs=%d]: r=%d\n",
1541
0
                       b->inter_mode, ctx, n_mvs, ts->msac.rng);
1542
1543
41.0k
            const uint8_t *const im = dav1d_comp_inter_pred_modes[b->inter_mode];
1544
41.0k
            b->drl_idx = NEAREST_DRL;
1545
41.0k
            if (b->inter_mode == NEWMV_NEWMV) {
1546
8.83k
                if (n_mvs > 1) { // NEARER, NEAR or NEARISH
1547
8.83k
                    const int drl_ctx_v1 = get_drl_context(mvstack, 0);
1548
8.83k
                    b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1549
8.83k
                                      ts->cdf.m.drl_bit[drl_ctx_v1]);
1550
8.83k
                    if (b->drl_idx == NEARER_DRL && n_mvs > 2) {
1551
1.91k
                        const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1552
1.91k
                        b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1553
1.91k
                                          ts->cdf.m.drl_bit[drl_ctx_v2]);
1554
1.91k
                    }
1555
8.83k
                    if (DEBUG_BLOCK_INFO)
1556
0
                        printf("Post-drlidx[%d,n_mvs=%d]: r=%d\n",
1557
0
                               b->drl_idx, n_mvs, ts->msac.rng);
1558
8.83k
                }
1559
32.2k
            } else if (im[0] == NEARMV || im[1] == NEARMV) {
1560
9.50k
                b->drl_idx = NEARER_DRL;
1561
9.50k
                if (n_mvs > 2) { // NEAR or NEARISH
1562
906
                    const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1563
906
                    b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1564
906
                                      ts->cdf.m.drl_bit[drl_ctx_v2]);
1565
906
                    if (b->drl_idx == NEAR_DRL && n_mvs > 3) {
1566
110
                        const int drl_ctx_v3 = get_drl_context(mvstack, 2);
1567
110
                        b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1568
110
                                          ts->cdf.m.drl_bit[drl_ctx_v3]);
1569
110
                    }
1570
906
                    if (DEBUG_BLOCK_INFO)
1571
0
                        printf("Post-drlidx[%d,n_mvs=%d]: r=%d\n",
1572
0
                               b->drl_idx, n_mvs, ts->msac.rng);
1573
906
                }
1574
9.50k
            }
1575
41.0k
            assert(b->drl_idx >= NEAREST_DRL && b->drl_idx <= NEARISH_DRL);
1576
1577
41.0k
#define assign_comp_mv(idx) \
1578
82.0k
            switch (im[idx]) { \
1579
16.6k
            case NEARMV: \
1580
49.2k
            case NEARESTMV: \
1581
49.2k
                b->mv[idx] = mvstack[b->drl_idx].mv.mv[idx]; \
1582
49.2k
                fix_mv_precision(f->frame_hdr, &b->mv[idx]); \
1583
49.2k
                break; \
1584
16.6k
            case GLOBALMV: \
1585
8.24k
                has_subpel_filter |= \
1586
8.24k
                    f->frame_hdr->gmv[b->ref[idx]].type == DAV1D_WM_TYPE_TRANSLATION; \
1587
8.24k
                b->mv[idx] = get_gmv_2d(&f->frame_hdr->gmv[b->ref[idx]], \
1588
8.24k
                                        t->bx, t->by, bw4, bh4, f->frame_hdr); \
1589
8.24k
                break; \
1590
24.5k
            case NEWMV: \
1591
24.5k
                b->mv[idx] = mvstack[b->drl_idx].mv.mv[idx]; \
1592
24.5k
                const int mv_prec = f->frame_hdr->hp - f->frame_hdr->force_integer_mv; \
1593
24.5k
                read_mv_residual(ts, &b->mv[idx], mv_prec); \
1594
24.5k
                break; \
1595
82.0k
            }
1596
41.0k
            has_subpel_filter = imin(bw4, bh4) == 1 ||
1597
41.0k
                                b->inter_mode != GLOBALMV_GLOBALMV;
1598
41.0k
            assign_comp_mv(0);
1599
41.0k
            assign_comp_mv(1);
1600
41.0k
#undef assign_comp_mv
1601
41.0k
            if (DEBUG_BLOCK_INFO)
1602
0
                printf("Post-residual_mv[1:y=%d,x=%d,2:y=%d,x=%d]: r=%d\n",
1603
0
                       b->mv[0].y, b->mv[0].x, b->mv[1].y, b->mv[1].x,
1604
0
                       ts->msac.rng);
1605
1606
            // jnt_comp vs. seg vs. wedge
1607
41.0k
            int is_segwedge = 0;
1608
41.0k
            if (f->seq_hdr->masked_compound) {
1609
35.1k
                const int mask_ctx = get_mask_comp_ctx(t->a, &t->l, by4, bx4);
1610
1611
35.1k
                is_segwedge = dav1d_msac_decode_bool_adapt(&ts->msac,
1612
35.1k
                                  ts->cdf.m.mask_comp[mask_ctx]);
1613
35.1k
                if (DEBUG_BLOCK_INFO)
1614
0
                    printf("Post-segwedge_vs_jntavg[%d,ctx=%d]: r=%d\n",
1615
0
                           is_segwedge, mask_ctx, ts->msac.rng);
1616
35.1k
            }
1617
1618
41.0k
            if (!is_segwedge) {
1619
30.1k
                if (f->seq_hdr->jnt_comp) {
1620
2.28k
                    const int jnt_ctx =
1621
2.28k
                        get_jnt_comp_ctx(f->seq_hdr->order_hint_n_bits,
1622
2.28k
                                         f->cur.frame_hdr->frame_offset,
1623
2.28k
                                         f->refp[b->ref[0]].p.frame_hdr->frame_offset,
1624
2.28k
                                         f->refp[b->ref[1]].p.frame_hdr->frame_offset,
1625
2.28k
                                         t->a, &t->l, by4, bx4);
1626
2.28k
                    b->comp_type = COMP_INTER_WEIGHTED_AVG +
1627
2.28k
                                   dav1d_msac_decode_bool_adapt(&ts->msac,
1628
2.28k
                                       ts->cdf.m.jnt_comp[jnt_ctx]);
1629
2.28k
                    if (DEBUG_BLOCK_INFO)
1630
0
                        printf("Post-jnt_comp[%d,ctx=%d[ac:%d,ar:%d,lc:%d,lr:%d]]: r=%d\n",
1631
0
                               b->comp_type == COMP_INTER_AVG,
1632
0
                               jnt_ctx, t->a->comp_type[bx4], t->a->ref[0][bx4],
1633
0
                               t->l.comp_type[by4], t->l.ref[0][by4],
1634
0
                               ts->msac.rng);
1635
27.8k
                } else {
1636
27.8k
                    b->comp_type = COMP_INTER_AVG;
1637
27.8k
                }
1638
30.1k
            } else {
1639
10.8k
                if (wedge_allowed_mask & (1 << bs)) {
1640
8.55k
                    const int ctx = dav1d_wedge_ctx_lut[bs];
1641
8.55k
                    b->comp_type = COMP_INTER_WEDGE -
1642
8.55k
                                   dav1d_msac_decode_bool_adapt(&ts->msac,
1643
8.55k
                                       ts->cdf.m.wedge_comp[ctx]);
1644
8.55k
                    if (b->comp_type == COMP_INTER_WEDGE)
1645
2.80k
                        b->wedge_idx = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1646
2.80k
                                           ts->cdf.m.wedge_idx[ctx], 15);
1647
8.55k
                } else {
1648
2.32k
                    b->comp_type = COMP_INTER_SEG;
1649
2.32k
                }
1650
10.8k
                b->mask_sign = dav1d_msac_decode_bool_equi(&ts->msac);
1651
10.8k
                if (DEBUG_BLOCK_INFO)
1652
0
                    printf("Post-seg/wedge[%d,wedge_idx=%d,sign=%d]: r=%d\n",
1653
0
                           b->comp_type == COMP_INTER_WEDGE,
1654
0
                           b->wedge_idx, b->mask_sign, ts->msac.rng);
1655
10.8k
            }
1656
237k
        } else {
1657
237k
            b->comp_type = COMP_INTER_NONE;
1658
1659
            // ref
1660
237k
            if (seg && seg->ref > 0) {
1661
59.0k
                b->ref[0] = seg->ref - 1;
1662
178k
            } else if (seg && (seg->globalmv || seg->skip)) {
1663
43.4k
                b->ref[0] = 0;
1664
135k
            } else {
1665
135k
                const int ctx1 = av1_get_ref_ctx(t->a, &t->l, by4, bx4,
1666
135k
                                                 have_top, have_left);
1667
135k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1668
135k
                                                 ts->cdf.m.ref[0][ctx1]))
1669
52.0k
                {
1670
52.0k
                    const int ctx2 = av1_get_ref_2_ctx(t->a, &t->l, by4, bx4,
1671
52.0k
                                                       have_top, have_left);
1672
52.0k
                    if (dav1d_msac_decode_bool_adapt(&ts->msac,
1673
52.0k
                                                     ts->cdf.m.ref[1][ctx2]))
1674
31.4k
                    {
1675
31.4k
                        b->ref[0] = 6;
1676
31.4k
                    } else {
1677
20.5k
                        const int ctx3 = av1_get_ref_6_ctx(t->a, &t->l, by4, bx4,
1678
20.5k
                                                           have_top, have_left);
1679
20.5k
                        b->ref[0] = 4 + dav1d_msac_decode_bool_adapt(&ts->msac,
1680
20.5k
                                            ts->cdf.m.ref[5][ctx3]);
1681
20.5k
                    }
1682
82.9k
                } else {
1683
82.9k
                    const int ctx2 = av1_get_ref_3_ctx(t->a, &t->l, by4, bx4,
1684
82.9k
                                                       have_top, have_left);
1685
82.9k
                    if (dav1d_msac_decode_bool_adapt(&ts->msac,
1686
82.9k
                                                     ts->cdf.m.ref[2][ctx2]))
1687
25.0k
                    {
1688
25.0k
                        const int ctx3 = av1_get_ref_5_ctx(t->a, &t->l, by4, bx4,
1689
25.0k
                                                           have_top, have_left);
1690
25.0k
                        b->ref[0] = 2 + dav1d_msac_decode_bool_adapt(&ts->msac,
1691
25.0k
                                            ts->cdf.m.ref[4][ctx3]);
1692
57.9k
                    } else {
1693
57.9k
                        const int ctx3 = av1_get_ref_4_ctx(t->a, &t->l, by4, bx4,
1694
57.9k
                                                           have_top, have_left);
1695
57.9k
                        b->ref[0] = dav1d_msac_decode_bool_adapt(&ts->msac,
1696
57.9k
                                        ts->cdf.m.ref[3][ctx3]);
1697
57.9k
                    }
1698
82.9k
                }
1699
135k
                if (DEBUG_BLOCK_INFO)
1700
0
                    printf("Post-ref[%d]: r=%d\n", b->ref[0], ts->msac.rng);
1701
135k
            }
1702
237k
            b->ref[1] = -1;
1703
1704
237k
            refmvs_candidate mvstack[8];
1705
237k
            int n_mvs, ctx;
1706
237k
            dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1707
237k
                              (union refmvs_refpair) { .ref = { b->ref[0] + 1, -1 }},
1708
237k
                              bs, intra_edge_flags, t->by, t->bx);
1709
1710
            // mode parsing and mv derivation from ref_mvs
1711
237k
            if ((seg && (seg->skip || seg->globalmv)) ||
1712
139k
                dav1d_msac_decode_bool_adapt(&ts->msac,
1713
139k
                                             ts->cdf.m.newmv_mode[ctx & 7]))
1714
183k
            {
1715
183k
                if ((seg && (seg->skip || seg->globalmv)) ||
1716
84.5k
                    !dav1d_msac_decode_bool_adapt(&ts->msac,
1717
84.5k
                         ts->cdf.m.globalmv_mode[(ctx >> 3) & 1]))
1718
105k
                {
1719
105k
                    b->inter_mode = GLOBALMV;
1720
105k
                    b->mv[0] = get_gmv_2d(&f->frame_hdr->gmv[b->ref[0]],
1721
105k
                                          t->bx, t->by, bw4, bh4, f->frame_hdr);
1722
105k
                    has_subpel_filter = imin(bw4, bh4) == 1 ||
1723
67.8k
                        f->frame_hdr->gmv[b->ref[0]].type == DAV1D_WM_TYPE_TRANSLATION;
1724
105k
                } else {
1725
78.6k
                    has_subpel_filter = 1;
1726
78.6k
                    if (dav1d_msac_decode_bool_adapt(&ts->msac,
1727
78.6k
                            ts->cdf.m.refmv_mode[(ctx >> 4) & 15]))
1728
30.2k
                    { // NEAREST, NEARER, NEAR or NEARISH
1729
30.2k
                        b->inter_mode = NEARMV;
1730
30.2k
                        b->drl_idx = NEARER_DRL;
1731
30.2k
                        if (n_mvs > 2) { // NEARER, NEAR or NEARISH
1732
7.90k
                            const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1733
7.90k
                            b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1734
7.90k
                                              ts->cdf.m.drl_bit[drl_ctx_v2]);
1735
7.90k
                            if (b->drl_idx == NEAR_DRL && n_mvs > 3) { // NEAR or NEARISH
1736
2.06k
                                const int drl_ctx_v3 =
1737
2.06k
                                    get_drl_context(mvstack, 2);
1738
2.06k
                                b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1739
2.06k
                                                  ts->cdf.m.drl_bit[drl_ctx_v3]);
1740
2.06k
                            }
1741
7.90k
                        }
1742
48.4k
                    } else {
1743
48.4k
                        b->inter_mode = NEARESTMV;
1744
48.4k
                        b->drl_idx = NEAREST_DRL;
1745
48.4k
                    }
1746
78.6k
                    assert(b->drl_idx >= NEAREST_DRL && b->drl_idx <= NEARISH_DRL);
1747
78.6k
                    b->mv[0] = mvstack[b->drl_idx].mv.mv[0];
1748
78.6k
                    if (b->drl_idx < NEAR_DRL)
1749
74.4k
                        fix_mv_precision(f->frame_hdr, &b->mv[0]);
1750
78.6k
                }
1751
1752
183k
                if (DEBUG_BLOCK_INFO)
1753
0
                    printf("Post-intermode[%d,drl=%d,mv=y:%d,x:%d,n_mvs=%d]: r=%d\n",
1754
0
                           b->inter_mode, b->drl_idx, b->mv[0].y, b->mv[0].x, n_mvs,
1755
0
                           ts->msac.rng);
1756
183k
            } else {
1757
53.4k
                has_subpel_filter = 1;
1758
53.4k
                b->inter_mode = NEWMV;
1759
53.4k
                b->drl_idx = NEAREST_DRL;
1760
53.4k
                if (n_mvs > 1) { // NEARER, NEAR or NEARISH
1761
30.0k
                    const int drl_ctx_v1 = get_drl_context(mvstack, 0);
1762
30.0k
                    b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1763
30.0k
                                      ts->cdf.m.drl_bit[drl_ctx_v1]);
1764
30.0k
                    if (b->drl_idx == NEARER_DRL && n_mvs > 2) { // NEAR or NEARISH
1765
5.58k
                        const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1766
5.58k
                        b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1767
5.58k
                                          ts->cdf.m.drl_bit[drl_ctx_v2]);
1768
5.58k
                    }
1769
30.0k
                }
1770
53.4k
                assert(b->drl_idx >= NEAREST_DRL && b->drl_idx <= NEARISH_DRL);
1771
53.4k
                if (n_mvs > 1) {
1772
30.0k
                    b->mv[0] = mvstack[b->drl_idx].mv.mv[0];
1773
30.0k
                } else {
1774
23.4k
                    assert(!b->drl_idx);
1775
23.4k
                    b->mv[0] = mvstack[0].mv.mv[0];
1776
23.4k
                    fix_mv_precision(f->frame_hdr, &b->mv[0]);
1777
23.4k
                }
1778
53.4k
                if (DEBUG_BLOCK_INFO)
1779
0
                    printf("Post-intermode[%d,drl=%d]: r=%d\n",
1780
0
                           b->inter_mode, b->drl_idx, ts->msac.rng);
1781
53.4k
                const int mv_prec = f->frame_hdr->hp - f->frame_hdr->force_integer_mv;
1782
53.4k
                read_mv_residual(ts, &b->mv[0], mv_prec);
1783
53.4k
                if (DEBUG_BLOCK_INFO)
1784
0
                    printf("Post-residualmv[mv=y:%d,x:%d]: r=%d\n",
1785
0
                           b->mv[0].y, b->mv[0].x, ts->msac.rng);
1786
53.4k
            }
1787
1788
            // interintra flags
1789
237k
            const int ii_sz_grp = dav1d_ymode_size_context[bs];
1790
237k
            if (f->seq_hdr->inter_intra &&
1791
68.2k
                interintra_allowed_mask & (1 << bs) &&
1792
31.5k
                dav1d_msac_decode_bool_adapt(&ts->msac,
1793
31.5k
                                             ts->cdf.m.interintra[ii_sz_grp]))
1794
6.03k
            {
1795
6.03k
                b->interintra_mode = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1796
6.03k
                                         ts->cdf.m.interintra_mode[ii_sz_grp],
1797
6.03k
                                         N_INTER_INTRA_PRED_MODES - 1);
1798
6.03k
                const int wedge_ctx = dav1d_wedge_ctx_lut[bs];
1799
6.03k
                b->interintra_type = INTER_INTRA_BLEND +
1800
6.03k
                                     dav1d_msac_decode_bool_adapt(&ts->msac,
1801
6.03k
                                         ts->cdf.m.interintra_wedge[wedge_ctx]);
1802
6.03k
                if (b->interintra_type == INTER_INTRA_WEDGE)
1803
1.56k
                    b->wedge_idx = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1804
1.56k
                                       ts->cdf.m.wedge_idx[wedge_ctx], 15);
1805
231k
            } else {
1806
231k
                b->interintra_type = INTER_INTRA_NONE;
1807
231k
            }
1808
237k
            if (DEBUG_BLOCK_INFO && f->seq_hdr->inter_intra &&
1809
0
                interintra_allowed_mask & (1 << bs))
1810
0
            {
1811
0
                printf("Post-interintra[t=%d,m=%d,w=%d]: r=%d\n",
1812
0
                       b->interintra_type, b->interintra_mode,
1813
0
                       b->wedge_idx, ts->msac.rng);
1814
0
            }
1815
1816
            // motion variation
1817
237k
            if (f->frame_hdr->switchable_motion_mode &&
1818
215k
                b->interintra_type == INTER_INTRA_NONE && imin(bw4, bh4) >= 2 &&
1819
                // is not warped global motion
1820
123k
                !(!f->frame_hdr->force_integer_mv && b->inter_mode == GLOBALMV &&
1821
3.80k
                  f->frame_hdr->gmv[b->ref[0]].type > DAV1D_WM_TYPE_TRANSLATION) &&
1822
                // has overlappable neighbours
1823
121k
                ((have_left && findoddzero(&t->l.intra[by4 + 1], h4 >> 1)) ||
1824
14.4k
                 (have_top && findoddzero(&t->a->intra[bx4 + 1], w4 >> 1))))
1825
113k
            {
1826
                // reaching here means the block allows obmc - check warp by
1827
                // finding matching-ref blocks in top/left edges
1828
113k
                uint64_t mask[2] = { 0, 0 };
1829
113k
                find_matching_ref(t, intra_edge_flags, bw4, bh4, w4, h4,
1830
113k
                                  have_left, have_top, b->ref[0], mask);
1831
113k
                const int allow_warp = !f->svc[b->ref[0]][0].scale &&
1832
11.0k
                    !f->frame_hdr->force_integer_mv &&
1833
10.7k
                    f->frame_hdr->warp_motion && (mask[0] | mask[1]);
1834
1835
113k
                b->motion_mode = allow_warp ?
1836
5.97k
                    dav1d_msac_decode_symbol_adapt4(&ts->msac,
1837
5.97k
                        ts->cdf.m.motion_mode[bs], 2) :
1838
113k
                    dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.obmc[bs]);
1839
113k
                if (b->motion_mode == MM_WARP) {
1840
1.82k
                    has_subpel_filter = 0;
1841
1.82k
                    derive_warpmv(t, bw4, bh4, mask, b->mv[0], &t->warpmv);
1842
1.82k
#define signabs(v) v < 0 ? '-' : ' ', abs(v)
1843
1.82k
                    if (DEBUG_BLOCK_INFO)
1844
0
                        printf("[ %c%x %c%x %c%x\n  %c%x %c%x %c%x ]\n"
1845
0
                               "alpha=%c%x, beta=%c%x, gamma=%c%x, delta=%c%x, "
1846
0
                               "mv=y:%d,x:%d\n",
1847
0
                               signabs(t->warpmv.matrix[0]),
1848
0
                               signabs(t->warpmv.matrix[1]),
1849
0
                               signabs(t->warpmv.matrix[2]),
1850
0
                               signabs(t->warpmv.matrix[3]),
1851
0
                               signabs(t->warpmv.matrix[4]),
1852
0
                               signabs(t->warpmv.matrix[5]),
1853
0
                               signabs(t->warpmv.u.p.alpha),
1854
0
                               signabs(t->warpmv.u.p.beta),
1855
0
                               signabs(t->warpmv.u.p.gamma),
1856
0
                               signabs(t->warpmv.u.p.delta),
1857
0
                               b->mv[0].y, b->mv[0].x);
1858
1.82k
#undef signabs
1859
1.82k
                    if (t->frame_thread.pass) {
1860
1.82k
                        if (t->warpmv.type == DAV1D_WM_TYPE_AFFINE) {
1861
1.57k
                            b->matrix[0] = t->warpmv.matrix[2] - 0x10000;
1862
1.57k
                            b->matrix[1] = t->warpmv.matrix[3];
1863
1.57k
                            b->matrix[2] = t->warpmv.matrix[4];
1864
1.57k
                            b->matrix[3] = t->warpmv.matrix[5] - 0x10000;
1865
1.57k
                        } else {
1866
248
                            b->matrix[0] = INT16_MIN;
1867
248
                        }
1868
1.82k
                    }
1869
1.82k
                }
1870
1871
113k
                if (DEBUG_BLOCK_INFO)
1872
0
                    printf("Post-motionmode[%d]: r=%d [mask: 0x%" PRIx64 "/0x%"
1873
0
                           PRIx64 "]\n", b->motion_mode, ts->msac.rng, mask[0],
1874
0
                            mask[1]);
1875
123k
            } else {
1876
123k
                b->motion_mode = MM_TRANSLATION;
1877
123k
            }
1878
237k
        }
1879
1880
        // subpel filter
1881
278k
        enum Dav1dFilterMode filter[2];
1882
278k
        if (f->frame_hdr->subpel_filter_mode == DAV1D_FILTER_SWITCHABLE) {
1883
41.6k
            if (has_subpel_filter) {
1884
36.9k
                const int comp = b->comp_type != COMP_INTER_NONE;
1885
36.9k
                const int ctx1 = get_filter_ctx(t->a, &t->l, comp, 0, b->ref[0],
1886
36.9k
                                                by4, bx4);
1887
36.9k
                filter[0] = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1888
36.9k
                               ts->cdf.m.filter[0][ctx1],
1889
36.9k
                               DAV1D_N_SWITCHABLE_FILTERS - 1);
1890
36.9k
                if (f->seq_hdr->dual_filter) {
1891
22.5k
                    const int ctx2 = get_filter_ctx(t->a, &t->l, comp, 1,
1892
22.5k
                                                    b->ref[0], by4, bx4);
1893
22.5k
                    if (DEBUG_BLOCK_INFO)
1894
0
                        printf("Post-subpel_filter1[%d,ctx=%d]: r=%d\n",
1895
0
                               filter[0], ctx1, ts->msac.rng);
1896
22.5k
                    filter[1] = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1897
22.5k
                                    ts->cdf.m.filter[1][ctx2],
1898
22.5k
                                    DAV1D_N_SWITCHABLE_FILTERS - 1);
1899
22.5k
                    if (DEBUG_BLOCK_INFO)
1900
0
                        printf("Post-subpel_filter2[%d,ctx=%d]: r=%d\n",
1901
0
                               filter[1], ctx2, ts->msac.rng);
1902
22.5k
                } else {
1903
14.4k
                    filter[1] = filter[0];
1904
14.4k
                    if (DEBUG_BLOCK_INFO)
1905
0
                        printf("Post-subpel_filter[%d,ctx=%d]: r=%d\n",
1906
0
                               filter[0], ctx1, ts->msac.rng);
1907
14.4k
                }
1908
36.9k
            } else {
1909
4.73k
                filter[0] = filter[1] = DAV1D_FILTER_8TAP_REGULAR;
1910
4.73k
            }
1911
236k
        } else {
1912
236k
            filter[0] = filter[1] = f->frame_hdr->subpel_filter_mode;
1913
236k
        }
1914
278k
        b->filter2d = dav1d_filter_2d[filter[1]][filter[0]];
1915
1916
278k
        read_vartx_tree(t, b, bs, bx4, by4);
1917
1918
        // reconstruction
1919
279k
        if (t->frame_thread.pass == 1) {
1920
279k
            f->bd_fn.read_coef_blocks(t, bs, b);
1921
18.4E
        } else {
1922
18.4E
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
1923
18.4E
        }
1924
1925
278k
        if (f->frame_hdr->loopfilter.level_y[0] ||
1926
67.0k
            f->frame_hdr->loopfilter.level_y[1])
1927
226k
        {
1928
226k
            const int is_globalmv =
1929
226k
                b->inter_mode == (is_comp ? GLOBALMV_GLOBALMV : GLOBALMV);
1930
226k
            const uint8_t (*const lf_lvls)[8][2] = (const uint8_t (*)[8][2])
1931
226k
                &ts->lflvl[b->seg_id][0][b->ref[0] + 1][!is_globalmv];
1932
226k
            const uint16_t tx_split[2] = { b->tx_split0, b->tx_split1 };
1933
226k
            enum RectTxfmSize ytx = b->max_ytx, uvtx = b->uvtx;
1934
226k
            if (f->frame_hdr->segmentation.lossless[b->seg_id]) {
1935
14.0k
                ytx  = (enum RectTxfmSize) TX_4X4;
1936
14.0k
                uvtx = (enum RectTxfmSize) TX_4X4;
1937
14.0k
            }
1938
226k
            dav1d_create_lf_mask_inter(t->lf_mask, f->lf.level, f->b4_stride, lf_lvls,
1939
226k
                                       t->bx, t->by, f->w4, f->h4, b->skip, bs,
1940
226k
                                       ytx, tx_split, uvtx, f->cur.p.layout,
1941
226k
                                       &t->a->tx_lpf_y[bx4], &t->l.tx_lpf_y[by4],
1942
226k
                                       has_chroma ? &t->a->tx_lpf_uv[cbx4] : NULL,
1943
226k
                                       has_chroma ? &t->l.tx_lpf_uv[cby4] : NULL);
1944
226k
        }
1945
1946
        // context updates
1947
278k
        if (is_comp)
1948
41.0k
            splat_tworef_mv(f->c, t, bs, b, bw4, bh4);
1949
237k
        else
1950
237k
            splat_oneref_mv(f->c, t, bs, b, bw4, bh4);
1951
278k
        BlockContext *edge = t->a;
1952
838k
        for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
1953
559k
#define set_ctx(rep_macro) \
1954
559k
            rep_macro(edge->seg_pred, off, seg_pred); \
1955
559k
            rep_macro(edge->skip_mode, off, b->skip_mode); \
1956
559k
            rep_macro(edge->intra, off, 0); \
1957
559k
            rep_macro(edge->skip, off, b->skip); \
1958
559k
            rep_macro(edge->pal_sz, off, 0); \
1959
            /* see aomedia bug 2183 for why this is outside if (has_chroma) */ \
1960
559k
            rep_macro(t->pal_sz_uv[i], off, 0); \
1961
559k
            rep_macro(edge->tx_intra, off, b_dim[2 + i]); \
1962
559k
            rep_macro(edge->comp_type, off, b->comp_type); \
1963
559k
            rep_macro(edge->filter[0], off, filter[0]); \
1964
559k
            rep_macro(edge->filter[1], off, filter[1]); \
1965
559k
            rep_macro(edge->mode, off, b->inter_mode); \
1966
559k
            rep_macro(edge->ref[0], off, b->ref[0]); \
1967
559k
            rep_macro(edge->ref[1], off, ((uint8_t) b->ref[1]))
1968
559k
            case_set(b_dim[2 + i]);
1969
559k
#undef set_ctx
1970
559k
        }
1971
278k
        if (has_chroma) {
1972
147k
            dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], DC_PRED);
1973
147k
            dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], DC_PRED);
1974
147k
        }
1975
278k
    }
1976
1977
    // update contexts
1978
1.32M
    if (f->frame_hdr->segmentation.enabled &&
1979
786k
        f->frame_hdr->segmentation.update_map)
1980
780k
    {
1981
780k
        uint8_t *seg_ptr = &f->cur_segmap[t->by * f->b4_stride + t->bx];
1982
780k
#define set_ctx(rep_macro) \
1983
4.77M
        for (int y = 0; y < bh4; y++) { \
1984
3.99M
            rep_macro(seg_ptr, 0, b->seg_id); \
1985
3.99M
            seg_ptr += f->b4_stride; \
1986
3.99M
        }
1987
780k
        case_set(b_dim[2]);
1988
779k
#undef set_ctx
1989
779k
    }
1990
1.31M
    if (!b->skip) {
1991
579k
        uint16_t (*noskip_mask)[2] = &t->lf_mask->noskip_mask[by4 >> 1];
1992
579k
        const unsigned mask = (~0U >> (32 - bw4)) << (bx4 & 15);
1993
579k
        const int bx_idx = (bx4 & 16) >> 4;
1994
2.10M
        for (int y = 0; y < bh4; y += 2, noskip_mask++) {
1995
1.52M
            (*noskip_mask)[bx_idx] |= mask;
1996
1.52M
            if (bw4 == 32) // this should be mask >> 16, but it's 0xffffffff anyway
1997
257k
                (*noskip_mask)[1] |= mask;
1998
1.52M
        }
1999
579k
    }
2000
2001
1.32M
    if (t->frame_thread.pass == 1 && !b->intra && IS_INTER_OR_SWITCH(f->frame_hdr)) {
2002
279k
        const int sby = (t->by - ts->tiling.row_start) >> f->sb_shift;
2003
279k
        int (*const lowest_px)[2] = ts->lowest_pixel[sby];
2004
2005
        // keep track of motion vectors for each reference
2006
279k
        if (b->comp_type == COMP_INTER_NONE) {
2007
            // y
2008
238k
            if (imin(bw4, bh4) > 1 &&
2009
143k
                ((b->inter_mode == GLOBALMV && f->gmv_warp_allowed[b->ref[0]]) ||
2010
142k
                 (b->motion_mode == MM_WARP && t->warpmv.type > DAV1D_WM_TYPE_TRANSLATION)))
2011
3.11k
            {
2012
3.11k
                affine_lowest_px_luma(t, &lowest_px[b->ref[0]][0], b_dim,
2013
3.11k
                                      b->motion_mode == MM_WARP ? &t->warpmv :
2014
3.11k
                                      &f->frame_hdr->gmv[b->ref[0]]);
2015
235k
            } else {
2016
235k
                mc_lowest_px(&lowest_px[b->ref[0]][0], t->by, bh4, b->mv[0].y,
2017
235k
                             0, &f->svc[b->ref[0]][1]);
2018
235k
                if (b->motion_mode == MM_OBMC) {
2019
61.5k
                    obmc_lowest_px(t, lowest_px, 0, b_dim, bx4, by4, w4, h4);
2020
61.5k
                }
2021
235k
            }
2022
2023
            // uv
2024
238k
            if (has_chroma) {
2025
                // sub8x8 derivation
2026
129k
                int is_sub8x8 = bw4 == ss_hor || bh4 == ss_ver;
2027
129k
                refmvs_block *const *r;
2028
129k
                if (is_sub8x8) {
2029
22.0k
                    assert(ss_hor == 1);
2030
22.0k
                    r = &t->rt.r[(t->by & 31) + 5];
2031
22.0k
                    if (bw4 == 1) is_sub8x8 &= r[0][t->bx - 1].ref.ref[0] > 0;
2032
22.0k
                    if (bh4 == ss_ver) is_sub8x8 &= r[-1][t->bx].ref.ref[0] > 0;
2033
22.0k
                    if (bw4 == 1 && bh4 == ss_ver)
2034
3.36k
                        is_sub8x8 &= r[-1][t->bx - 1].ref.ref[0] > 0;
2035
22.0k
                }
2036
2037
                // chroma prediction
2038
129k
                if (is_sub8x8) {
2039
20.8k
                    assert(ss_hor == 1);
2040
20.8k
                    if (bw4 == 1 && bh4 == ss_ver) {
2041
2.72k
                        const refmvs_block *const rr = &r[-1][t->bx - 1];
2042
2.72k
                        mc_lowest_px(&lowest_px[rr->ref.ref[0] - 1][1],
2043
2.72k
                                     t->by - 1, bh4, rr->mv.mv[0].y, ss_ver,
2044
2.72k
                                     &f->svc[rr->ref.ref[0] - 1][1]);
2045
2.72k
                    }
2046
20.8k
                    if (bw4 == 1) {
2047
10.5k
                        const refmvs_block *const rr = &r[0][t->bx - 1];
2048
10.5k
                        mc_lowest_px(&lowest_px[rr->ref.ref[0] - 1][1],
2049
10.5k
                                     t->by, bh4, rr->mv.mv[0].y, ss_ver,
2050
10.5k
                                     &f->svc[rr->ref.ref[0] - 1][1]);
2051
10.5k
                    }
2052
20.8k
                    if (bh4 == ss_ver) {
2053
13.0k
                        const refmvs_block *const rr = &r[-1][t->bx];
2054
13.0k
                        mc_lowest_px(&lowest_px[rr->ref.ref[0] - 1][1],
2055
13.0k
                                     t->by - 1, bh4, rr->mv.mv[0].y, ss_ver,
2056
13.0k
                                     &f->svc[rr->ref.ref[0] - 1][1]);
2057
13.0k
                    }
2058
20.8k
                    mc_lowest_px(&lowest_px[b->ref[0]][1], t->by, bh4,
2059
20.8k
                                 b->mv[0].y, ss_ver, &f->svc[b->ref[0]][1]);
2060
108k
                } else {
2061
108k
                    if (imin(cbw4, cbh4) > 1 &&
2062
46.1k
                        ((b->inter_mode == GLOBALMV && f->gmv_warp_allowed[b->ref[0]]) ||
2063
45.4k
                         (b->motion_mode == MM_WARP && t->warpmv.type > DAV1D_WM_TYPE_TRANSLATION)))
2064
859
                    {
2065
859
                        affine_lowest_px_chroma(t, &lowest_px[b->ref[0]][1], b_dim,
2066
859
                                                b->motion_mode == MM_WARP ? &t->warpmv :
2067
859
                                                &f->frame_hdr->gmv[b->ref[0]]);
2068
108k
                    } else {
2069
108k
                        mc_lowest_px(&lowest_px[b->ref[0]][1],
2070
108k
                                     t->by & ~ss_ver, bh4 << (bh4 == ss_ver),
2071
108k
                                     b->mv[0].y, ss_ver, &f->svc[b->ref[0]][1]);
2072
108k
                        if (b->motion_mode == MM_OBMC) {
2073
42.9k
                            obmc_lowest_px(t, lowest_px, 1, b_dim, bx4, by4, w4, h4);
2074
42.9k
                        }
2075
108k
                    }
2076
108k
                }
2077
129k
            }
2078
238k
        } else {
2079
            // y
2080
123k
            for (int i = 0; i < 2; i++) {
2081
82.1k
                if (b->inter_mode == GLOBALMV_GLOBALMV && f->gmv_warp_allowed[b->ref[i]]) {
2082
276
                    affine_lowest_px_luma(t, &lowest_px[b->ref[i]][0], b_dim,
2083
276
                                          &f->frame_hdr->gmv[b->ref[i]]);
2084
81.9k
                } else {
2085
81.9k
                    mc_lowest_px(&lowest_px[b->ref[i]][0], t->by, bh4,
2086
81.9k
                                 b->mv[i].y, 0, &f->svc[b->ref[i]][1]);
2087
81.9k
                }
2088
82.1k
            }
2089
2090
            // uv
2091
53.6k
            if (has_chroma) for (int i = 0; i < 2; i++) {
2092
35.7k
                if (b->inter_mode == GLOBALMV_GLOBALMV &&
2093
3.91k
                    imin(cbw4, cbh4) > 1 && f->gmv_warp_allowed[b->ref[i]])
2094
83
                {
2095
83
                    affine_lowest_px_chroma(t, &lowest_px[b->ref[i]][1], b_dim,
2096
83
                                            &f->frame_hdr->gmv[b->ref[i]]);
2097
35.6k
                } else {
2098
35.6k
                    mc_lowest_px(&lowest_px[b->ref[i]][1], t->by, bh4,
2099
35.6k
                                 b->mv[i].y, ss_ver, &f->svc[b->ref[i]][1]);
2100
35.6k
                }
2101
35.7k
            }
2102
41.0k
        }
2103
279k
    }
2104
2105
1.31M
    return 0;
2106
1.31M
}
2107
2108
#if __has_feature(memory_sanitizer)
2109
2110
#include <sanitizer/msan_interface.h>
2111
2112
static int checked_decode_b(Dav1dTaskContext *const t,
2113
                            const enum BlockLevel bl,
2114
                            const enum BlockSize bs,
2115
                            const enum BlockPartition bp,
2116
                            const enum EdgeFlags intra_edge_flags)
2117
{
2118
    const Dav1dFrameContext *const f = t->f;
2119
    const int err = decode_b(t, bl, bs, bp, intra_edge_flags);
2120
2121
    if (err == 0 && !(t->frame_thread.pass & 1)) {
2122
        const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
2123
        const int ss_hor = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
2124
        const uint8_t *const b_dim = dav1d_block_dimensions[bs];
2125
        const int bw4 = b_dim[0], bh4 = b_dim[1];
2126
        const int w4 = imin(bw4, f->bw - t->bx), h4 = imin(bh4, f->bh - t->by);
2127
        const int has_chroma = f->seq_hdr->layout != DAV1D_PIXEL_LAYOUT_I400 &&
2128
                               (bw4 > ss_hor || t->bx & 1) &&
2129
                               (bh4 > ss_ver || t->by & 1);
2130
2131
        for (int p = 0; p < 1 + 2 * has_chroma; p++) {
2132
            const int ss_ver = p && f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
2133
            const int ss_hor = p && f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
2134
            const ptrdiff_t stride = f->cur.stride[!!p];
2135
            const int bx = t->bx & ~ss_hor;
2136
            const int by = t->by & ~ss_ver;
2137
            const int width  = w4 << (2 - ss_hor + (bw4 == ss_hor));
2138
            const int height = h4 << (2 - ss_ver + (bh4 == ss_ver));
2139
2140
            const uint8_t *data = f->cur.data[p] + (by << (2 - ss_ver)) * stride +
2141
                                  (bx << (2 - ss_hor + !!f->seq_hdr->hbd));
2142
2143
            for (int y = 0; y < height; data += stride, y++) {
2144
                const size_t line_sz = width << !!f->seq_hdr->hbd;
2145
                if (__msan_test_shadow(data, line_sz) != -1) {
2146
                    fprintf(stderr, "B[%d](%d, %d) w4:%d, h4:%d, row:%d\n",
2147
                            p, bx, by, w4, h4, y);
2148
                    __msan_check_mem_is_initialized(data, line_sz);
2149
                }
2150
            }
2151
        }
2152
    }
2153
2154
    return err;
2155
}
2156
2157
#define decode_b checked_decode_b
2158
2159
#endif /* defined(__has_feature) */
2160
2161
static int decode_sb(Dav1dTaskContext *const t, const enum BlockLevel bl,
2162
                     const EdgeNode *const node)
2163
1.90M
{
2164
1.90M
    const Dav1dFrameContext *const f = t->f;
2165
1.90M
    Dav1dTileState *const ts = t->ts;
2166
1.90M
    const int hsz = 16 >> bl;
2167
1.90M
    const int have_h_split = f->bw > t->bx + hsz;
2168
1.90M
    const int have_v_split = f->bh > t->by + hsz;
2169
2170
1.90M
    if (!have_h_split && !have_v_split) {
2171
69.4k
        assert(bl < BL_8X8);
2172
69.4k
        return decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0));
2173
69.4k
    }
2174
2175
1.83M
    uint16_t *pc;
2176
1.83M
    enum BlockPartition bp;
2177
1.83M
    int ctx, bx8, by8;
2178
1.83M
    if (t->frame_thread.pass != 2) {
2179
1.12M
        if (0 && bl == BL_64X64)
2180
0
            printf("poc=%d,y=%d,x=%d,bl=%d,r=%d\n",
2181
0
                   f->frame_hdr->frame_offset, t->by, t->bx, bl, ts->msac.rng);
2182
1.12M
        bx8 = (t->bx & 31) >> 1;
2183
1.12M
        by8 = (t->by & 31) >> 1;
2184
1.12M
        ctx = get_partition_ctx(t->a, &t->l, bl, by8, bx8);
2185
1.12M
        pc = ts->cdf.m.partition[bl][ctx];
2186
1.12M
    }
2187
2188
1.83M
    if (have_h_split && have_v_split) {
2189
1.09M
        if (t->frame_thread.pass == 2) {
2190
369k
            const Av1Block *const b = &f->frame_thread.b[t->by * f->b4_stride + t->bx];
2191
369k
            bp = b->bl == bl ? b->bp : PARTITION_SPLIT;
2192
723k
        } else {
2193
723k
            bp = dav1d_msac_decode_symbol_adapt16(&ts->msac, pc,
2194
723k
                                                  dav1d_partition_type_count[bl]);
2195
723k
            if (f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I422 &&
2196
5.18k
                (bp == PARTITION_V || bp == PARTITION_V4 ||
2197
5.16k
                 bp == PARTITION_T_LEFT_SPLIT || bp == PARTITION_T_RIGHT_SPLIT))
2198
29
            {
2199
29
                return 1;
2200
29
            }
2201
722k
            if (DEBUG_BLOCK_INFO)
2202
0
                printf("poc=%d,y=%d,x=%d,bl=%d,ctx=%d,bp=%d: r=%d\n",
2203
0
                       f->frame_hdr->frame_offset, t->by, t->bx, bl, ctx, bp,
2204
0
                       ts->msac.rng);
2205
722k
        }
2206
1.09M
        const uint8_t *const b = dav1d_block_sizes[bl][bp];
2207
2208
1.09M
        switch (bp) {
2209
464k
        case PARTITION_NONE:
2210
464k
            if (decode_b(t, bl, b[0], PARTITION_NONE, node->o))
2211
2
                return -1;
2212
464k
            break;
2213
464k
        case PARTITION_H:
2214
146k
            if (decode_b(t, bl, b[0], PARTITION_H, node->h[0]))
2215
2
                return -1;
2216
146k
            t->by += hsz;
2217
146k
            if (decode_b(t, bl, b[0], PARTITION_H, node->h[1]))
2218
4
                return -1;
2219
146k
            t->by -= hsz;
2220
146k
            break;
2221
101k
        case PARTITION_V:
2222
101k
            if (decode_b(t, bl, b[0], PARTITION_V, node->v[0]))
2223
2
                return -1;
2224
101k
            t->bx += hsz;
2225
101k
            if (decode_b(t, bl, b[0], PARTITION_V, node->v[1]))
2226
3
                return -1;
2227
101k
            t->bx -= hsz;
2228
101k
            break;
2229
231k
        case PARTITION_SPLIT:
2230
231k
            if (bl == BL_8X8) {
2231
53.0k
                const EdgeTip *const tip = (const EdgeTip *) node;
2232
53.0k
                assert(hsz == 1);
2233
53.0k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, EDGE_ALL_TR_AND_BL))
2234
1
                    return -1;
2235
53.0k
                const enum Filter2d tl_filter = t->tl_4x4_filter;
2236
53.0k
                t->bx++;
2237
53.0k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, tip->split[0]))
2238
4
                    return -1;
2239
53.0k
                t->bx--;
2240
53.0k
                t->by++;
2241
53.0k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, tip->split[1]))
2242
1
                    return -1;
2243
53.0k
                t->bx++;
2244
53.0k
                t->tl_4x4_filter = tl_filter;
2245
53.0k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, tip->split[2]))
2246
1
                    return -1;
2247
53.0k
                t->bx--;
2248
53.0k
                t->by--;
2249
53.0k
#if ARCH_X86_64
2250
53.0k
                if (t->frame_thread.pass) {
2251
                    /* In 8-bit mode with 2-pass decoding the coefficient buffer
2252
                     * can end up misaligned due to skips here. Work around
2253
                     * the issue by explicitly realigning the buffer. */
2254
53.0k
                    const int p = t->frame_thread.pass & 1;
2255
53.0k
                    ts->frame_thread[p].cf =
2256
53.0k
                        (void*)(((uintptr_t)ts->frame_thread[p].cf + 63) & ~63);
2257
53.0k
                }
2258
53.0k
#endif
2259
178k
            } else {
2260
178k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0)))
2261
17
                    return 1;
2262
178k
                t->bx += hsz;
2263
178k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 1)))
2264
19
                    return 1;
2265
178k
                t->bx -= hsz;
2266
178k
                t->by += hsz;
2267
178k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 2)))
2268
21
                    return 1;
2269
178k
                t->bx += hsz;
2270
178k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 3)))
2271
25
                    return 1;
2272
178k
                t->bx -= hsz;
2273
178k
                t->by -= hsz;
2274
178k
            }
2275
231k
            break;
2276
231k
        case PARTITION_T_TOP_SPLIT: {
2277
18.0k
            if (decode_b(t, bl, b[0], PARTITION_T_TOP_SPLIT, EDGE_ALL_TR_AND_BL))
2278
1
                return -1;
2279
18.0k
            t->bx += hsz;
2280
18.0k
            if (decode_b(t, bl, b[0], PARTITION_T_TOP_SPLIT, node->v[1]))
2281
1
                return -1;
2282
18.0k
            t->bx -= hsz;
2283
18.0k
            t->by += hsz;
2284
18.0k
            if (decode_b(t, bl, b[1], PARTITION_T_TOP_SPLIT, node->h[1]))
2285
1
                return -1;
2286
18.0k
            t->by -= hsz;
2287
18.0k
            break;
2288
18.0k
        }
2289
20.0k
        case PARTITION_T_BOTTOM_SPLIT: {
2290
20.0k
            if (decode_b(t, bl, b[0], PARTITION_T_BOTTOM_SPLIT, node->h[0]))
2291
1
                return -1;
2292
20.0k
            t->by += hsz;
2293
20.0k
            if (decode_b(t, bl, b[1], PARTITION_T_BOTTOM_SPLIT, node->v[0]))
2294
1
                return -1;
2295
20.0k
            t->bx += hsz;
2296
20.0k
            if (decode_b(t, bl, b[1], PARTITION_T_BOTTOM_SPLIT, 0))
2297
1
                return -1;
2298
20.0k
            t->bx -= hsz;
2299
20.0k
            t->by -= hsz;
2300
20.0k
            break;
2301
20.0k
        }
2302
13.7k
        case PARTITION_T_LEFT_SPLIT: {
2303
13.7k
            if (decode_b(t, bl, b[0], PARTITION_T_LEFT_SPLIT, EDGE_ALL_TR_AND_BL))
2304
1
                return -1;
2305
13.7k
            t->by += hsz;
2306
13.7k
            if (decode_b(t, bl, b[0], PARTITION_T_LEFT_SPLIT, node->h[1]))
2307
1
                return -1;
2308
13.7k
            t->by -= hsz;
2309
13.7k
            t->bx += hsz;
2310
13.7k
            if (decode_b(t, bl, b[1], PARTITION_T_LEFT_SPLIT, node->v[1]))
2311
1
                return -1;
2312
13.7k
            t->bx -= hsz;
2313
13.7k
            break;
2314
13.7k
        }
2315
20.7k
        case PARTITION_T_RIGHT_SPLIT: {
2316
20.7k
            if (decode_b(t, bl, b[0], PARTITION_T_RIGHT_SPLIT, node->v[0]))
2317
2
                return -1;
2318
20.7k
            t->bx += hsz;
2319
20.7k
            if (decode_b(t, bl, b[1], PARTITION_T_RIGHT_SPLIT, node->h[0]))
2320
1
                return -1;
2321
20.7k
            t->by += hsz;
2322
20.7k
            if (decode_b(t, bl, b[1], PARTITION_T_RIGHT_SPLIT, 0))
2323
1
                return -1;
2324
20.7k
            t->by -= hsz;
2325
20.7k
            t->bx -= hsz;
2326
20.7k
            break;
2327
20.7k
        }
2328
42.0k
        case PARTITION_H4: {
2329
42.0k
            const EdgeBranch *const branch = (const EdgeBranch *) node;
2330
42.0k
            if (decode_b(t, bl, b[0], PARTITION_H4, node->h[0]))
2331
1
                return -1;
2332
42.0k
            t->by += hsz >> 1;
2333
42.0k
            if (decode_b(t, bl, b[0], PARTITION_H4, branch->h4))
2334
1
                return -1;
2335
42.0k
            t->by += hsz >> 1;
2336
42.0k
            if (decode_b(t, bl, b[0], PARTITION_H4, EDGE_ALL_LEFT_HAS_BOTTOM))
2337
1
                return -1;
2338
42.0k
            t->by += hsz >> 1;
2339
42.0k
            if (t->by < f->bh)
2340
41.2k
                if (decode_b(t, bl, b[0], PARTITION_H4, node->h[1]))
2341
1
                    return -1;
2342
42.0k
            t->by -= hsz * 3 >> 1;
2343
42.0k
            break;
2344
42.0k
        }
2345
34.7k
        case PARTITION_V4: {
2346
34.7k
            const EdgeBranch *const branch = (const EdgeBranch *) node;
2347
34.7k
            if (decode_b(t, bl, b[0], PARTITION_V4, node->v[0]))
2348
1
                return -1;
2349
34.7k
            t->bx += hsz >> 1;
2350
34.7k
            if (decode_b(t, bl, b[0], PARTITION_V4, branch->v4))
2351
2
                return -1;
2352
34.7k
            t->bx += hsz >> 1;
2353
34.7k
            if (decode_b(t, bl, b[0], PARTITION_V4, EDGE_ALL_TOP_HAS_RIGHT))
2354
2
                return -1;
2355
34.7k
            t->bx += hsz >> 1;
2356
34.7k
            if (t->bx < f->bw)
2357
33.0k
                if (decode_b(t, bl, b[0], PARTITION_V4, node->v[1]))
2358
1
                    return -1;
2359
34.7k
            t->bx -= hsz * 3 >> 1;
2360
34.7k
            break;
2361
34.7k
        }
2362
0
        default: assert(0);
2363
1.09M
        }
2364
1.09M
    } else if (have_h_split) {
2365
175k
        unsigned is_split;
2366
175k
        if (t->frame_thread.pass == 2) {
2367
70.6k
            const Av1Block *const b = &f->frame_thread.b[t->by * f->b4_stride + t->bx];
2368
70.6k
            is_split = b->bl != bl;
2369
104k
        } else {
2370
104k
            is_split = dav1d_msac_decode_bool(&ts->msac,
2371
104k
                           gather_top_partition_prob(pc, bl));
2372
104k
            if (DEBUG_BLOCK_INFO)
2373
0
                printf("poc=%d,y=%d,x=%d,bl=%d,ctx=%d,bp=%d: r=%d\n",
2374
0
                       f->frame_hdr->frame_offset, t->by, t->bx, bl, ctx,
2375
0
                       is_split ? PARTITION_SPLIT : PARTITION_H, ts->msac.rng);
2376
104k
        }
2377
2378
175k
        assert(bl < BL_8X8);
2379
175k
        if (is_split) {
2380
93.7k
            bp = PARTITION_SPLIT;
2381
93.7k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0))) return 1;
2382
93.6k
            t->bx += hsz;
2383
93.6k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 1))) return 1;
2384
93.6k
            t->bx -= hsz;
2385
93.6k
        } else {
2386
81.5k
            bp = PARTITION_H;
2387
81.5k
            if (decode_b(t, bl, dav1d_block_sizes[bl][PARTITION_H][0],
2388
81.5k
                         PARTITION_H, node->h[0]))
2389
3
                return -1;
2390
81.5k
        }
2391
563k
    } else {
2392
563k
        assert(have_v_split);
2393
563k
        unsigned is_split;
2394
563k
        if (t->frame_thread.pass == 2) {
2395
264k
            const Av1Block *const b = &f->frame_thread.b[t->by * f->b4_stride + t->bx];
2396
264k
            is_split = b->bl != bl;
2397
298k
        } else {
2398
298k
            is_split = dav1d_msac_decode_bool(&ts->msac,
2399
298k
                           gather_left_partition_prob(pc, bl));
2400
298k
            if (f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I422 && !is_split)
2401
8
                return 1;
2402
298k
            if (DEBUG_BLOCK_INFO)
2403
0
                printf("poc=%d,y=%d,x=%d,bl=%d,ctx=%d,bp=%d: r=%d\n",
2404
0
                       f->frame_hdr->frame_offset, t->by, t->bx, bl, ctx,
2405
0
                       is_split ? PARTITION_SPLIT : PARTITION_V, ts->msac.rng);
2406
298k
        }
2407
2408
563k
        assert(bl < BL_8X8);
2409
563k
        if (is_split) {
2410
301k
            bp = PARTITION_SPLIT;
2411
301k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0))) return 1;
2412
301k
            t->by += hsz;
2413
301k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 2))) return 1;
2414
301k
            t->by -= hsz;
2415
301k
        } else {
2416
261k
            bp = PARTITION_V;
2417
261k
            if (decode_b(t, bl, dav1d_block_sizes[bl][PARTITION_V][0],
2418
261k
                         PARTITION_V, node->v[0]))
2419
1
                return -1;
2420
261k
        }
2421
563k
    }
2422
2423
1.83M
    if (t->frame_thread.pass != 2 && (bp != PARTITION_SPLIT || bl == BL_8X8)) {
2424
783k
#define set_ctx(rep_macro) \
2425
783k
        rep_macro(t->a->partition, bx8, dav1d_al_part_ctx[0][bl][bp]); \
2426
783k
        rep_macro(t->l.partition, by8, dav1d_al_part_ctx[1][bl][bp])
2427
783k
        case_set_upto16(ulog2(hsz));
2428
783k
#undef set_ctx
2429
783k
    }
2430
2431
1.83M
    return 0;
2432
1.83M
}
2433
2434
358k
static void reset_context(BlockContext *const ctx, const int keyframe, const int pass) {
2435
358k
    memset(ctx->intra, keyframe, sizeof(ctx->intra));
2436
358k
    memset(ctx->uvmode, DC_PRED, sizeof(ctx->uvmode));
2437
358k
    if (keyframe)
2438
266k
        memset(ctx->mode, DC_PRED, sizeof(ctx->mode));
2439
2440
358k
    if (pass == 2) return;
2441
2442
185k
    memset(ctx->partition, 0, sizeof(ctx->partition));
2443
185k
    memset(ctx->skip, 0, sizeof(ctx->skip));
2444
185k
    memset(ctx->skip_mode, 0, sizeof(ctx->skip_mode));
2445
185k
    memset(ctx->tx_lpf_y, 2, sizeof(ctx->tx_lpf_y));
2446
185k
    memset(ctx->tx_lpf_uv, 1, sizeof(ctx->tx_lpf_uv));
2447
185k
    memset(ctx->tx_intra, -1, sizeof(ctx->tx_intra));
2448
185k
    memset(ctx->tx, TX_64X64, sizeof(ctx->tx));
2449
185k
    if (!keyframe) {
2450
46.5k
        memset(ctx->ref, -1, sizeof(ctx->ref));
2451
46.5k
        memset(ctx->comp_type, 0, sizeof(ctx->comp_type));
2452
46.5k
        memset(ctx->mode, NEARESTMV, sizeof(ctx->mode));
2453
46.5k
    }
2454
185k
    memset(ctx->lcoef, 0x40, sizeof(ctx->lcoef));
2455
185k
    memset(ctx->ccoef, 0x40, sizeof(ctx->ccoef));
2456
185k
    memset(ctx->filter, DAV1D_N_SWITCHABLE_FILTERS, sizeof(ctx->filter));
2457
185k
    memset(ctx->seg_pred, 0, sizeof(ctx->seg_pred));
2458
185k
    memset(ctx->pal_sz, 0, sizeof(ctx->pal_sz));
2459
185k
}
2460
2461
// { Y+U+V, Y+U } * 4
2462
static const uint8_t ss_size_mul[4][2] = {
2463
    [DAV1D_PIXEL_LAYOUT_I400] = {  4, 4 },
2464
    [DAV1D_PIXEL_LAYOUT_I420] = {  6, 5 },
2465
    [DAV1D_PIXEL_LAYOUT_I422] = {  8, 6 },
2466
    [DAV1D_PIXEL_LAYOUT_I444] = { 12, 8 },
2467
};
2468
2469
static void setup_tile(Dav1dTileState *const ts,
2470
                       const Dav1dFrameContext *const f,
2471
                       const uint8_t *const data, const size_t sz,
2472
                       const int tile_row, const int tile_col,
2473
                       const unsigned tile_start_off)
2474
33.1k
{
2475
33.1k
    const int col_sb_start = f->frame_hdr->tiling.col_start_sb[tile_col];
2476
33.1k
    const int col_sb128_start = col_sb_start >> !f->seq_hdr->sb128;
2477
33.1k
    const int col_sb_end = f->frame_hdr->tiling.col_start_sb[tile_col + 1];
2478
33.1k
    const int row_sb_start = f->frame_hdr->tiling.row_start_sb[tile_row];
2479
33.1k
    const int row_sb_end = f->frame_hdr->tiling.row_start_sb[tile_row + 1];
2480
33.1k
    const int sb_shift = f->sb_shift;
2481
2482
33.1k
    const uint8_t *const size_mul = ss_size_mul[f->cur.p.layout];
2483
99.3k
    for (int p = 0; p < 2; p++) {
2484
66.2k
        ts->frame_thread[p].pal_idx = f->frame_thread.pal_idx ?
2485
21.7k
            &f->frame_thread.pal_idx[(size_t)tile_start_off * size_mul[1] / 8] :
2486
66.2k
            NULL;
2487
66.2k
        ts->frame_thread[p].cbi = f->frame_thread.cbi ?
2488
66.2k
            &f->frame_thread.cbi[(size_t)tile_start_off * size_mul[0] / 64] :
2489
66.2k
            NULL;
2490
66.2k
        ts->frame_thread[p].cf = f->frame_thread.cf ?
2491
66.2k
            (uint8_t*)f->frame_thread.cf +
2492
66.2k
                (((size_t)tile_start_off * size_mul[0]) >> !f->seq_hdr->hbd) :
2493
66.2k
            NULL;
2494
66.2k
    }
2495
2496
33.1k
    dav1d_cdf_thread_copy(&ts->cdf, &f->in_cdf);
2497
33.1k
    ts->last_qidx = f->frame_hdr->quant.yac;
2498
33.1k
    ts->last_delta_lf.u32 = 0;
2499
2500
33.1k
    dav1d_msac_init(&ts->msac, data, sz, f->frame_hdr->disable_cdf_update);
2501
2502
33.1k
    ts->tiling.row = tile_row;
2503
33.1k
    ts->tiling.col = tile_col;
2504
33.1k
    ts->tiling.col_start = col_sb_start << sb_shift;
2505
33.1k
    ts->tiling.col_end = imin(col_sb_end << sb_shift, f->bw);
2506
33.1k
    ts->tiling.row_start = row_sb_start << sb_shift;
2507
33.1k
    ts->tiling.row_end = imin(row_sb_end << sb_shift, f->bh);
2508
2509
    // Reference Restoration Unit (used for exp coding)
2510
33.1k
    int sb_idx, unit_idx;
2511
33.1k
    if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
2512
        // vertical components only
2513
10.0k
        sb_idx = (ts->tiling.row_start >> 5) * f->sr_sb128w;
2514
10.0k
        unit_idx = (ts->tiling.row_start & 16) >> 3;
2515
23.0k
    } else {
2516
23.0k
        sb_idx = (ts->tiling.row_start >> 5) * f->sb128w + col_sb128_start;
2517
23.0k
        unit_idx = ((ts->tiling.row_start & 16) >> 3) +
2518
23.0k
                   ((ts->tiling.col_start & 16) >> 4);
2519
23.0k
    }
2520
132k
    for (int p = 0; p < 3; p++) {
2521
99.3k
        if (!((f->lf.restore_planes >> p) & 1U))
2522
79.0k
            continue;
2523
2524
20.2k
        if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
2525
8.97k
            const int ss_hor = p && f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
2526
8.97k
            const int d = f->frame_hdr->super_res.width_scale_denominator;
2527
8.97k
            const int unit_size_log2 = f->frame_hdr->restoration.unit_size[!!p];
2528
8.97k
            const int rnd = (8 << unit_size_log2) - 1, shift = unit_size_log2 + 3;
2529
8.97k
            const int x = ((4 * ts->tiling.col_start * d >> ss_hor) + rnd) >> shift;
2530
8.97k
            const int px_x = x << (unit_size_log2 + ss_hor);
2531
8.97k
            const int u_idx = unit_idx + ((px_x & 64) >> 6);
2532
8.97k
            const int sb128x = px_x >> 7;
2533
8.97k
            if (sb128x >= f->sr_sb128w) continue;
2534
8.86k
            ts->lr_ref[p] = &f->lf.lr_mask[sb_idx + sb128x].lr[p][u_idx];
2535
11.2k
        } else {
2536
11.2k
            ts->lr_ref[p] = &f->lf.lr_mask[sb_idx].lr[p][unit_idx];
2537
11.2k
        }
2538
2539
20.1k
        ts->lr_ref[p]->filter_v[0] = 3;
2540
20.1k
        ts->lr_ref[p]->filter_v[1] = -7;
2541
20.1k
        ts->lr_ref[p]->filter_v[2] = 15;
2542
20.1k
        ts->lr_ref[p]->filter_h[0] = 3;
2543
20.1k
        ts->lr_ref[p]->filter_h[1] = -7;
2544
20.1k
        ts->lr_ref[p]->filter_h[2] = 15;
2545
20.1k
        ts->lr_ref[p]->sgr_weights[0] = -32;
2546
20.1k
        ts->lr_ref[p]->sgr_weights[1] = 31;
2547
20.1k
    }
2548
2549
33.1k
    if (f->c->n_tc > 1) {
2550
99.3k
        for (int p = 0; p < 2; p++)
2551
66.2k
            atomic_init(&ts->progress[p], row_sb_start);
2552
33.1k
    }
2553
33.1k
}
2554
2555
static void read_restoration_info(Dav1dTaskContext *const t,
2556
                                  Av1RestorationUnit *const lr, const int p,
2557
                                  const enum Dav1dRestorationType frame_type)
2558
102k
{
2559
102k
    const Dav1dFrameContext *const f = t->f;
2560
102k
    Dav1dTileState *const ts = t->ts;
2561
102k
    const Av1RestorationUnit *const lr_ref = ts->lr_ref[p];
2562
2563
102k
    if (frame_type == DAV1D_RESTORATION_SWITCHABLE) {
2564
27.1k
        const int filter = dav1d_msac_decode_symbol_adapt4(&ts->msac,
2565
27.1k
                               ts->cdf.m.restore_switchable, 2);
2566
27.1k
        lr->type = filter + !!filter; /* NONE/WIENER/SGRPROJ */
2567
75.7k
    } else {
2568
75.7k
        const unsigned type =
2569
75.7k
            dav1d_msac_decode_bool_adapt(&ts->msac,
2570
75.7k
                frame_type == DAV1D_RESTORATION_WIENER ?
2571
47.6k
                ts->cdf.m.restore_wiener : ts->cdf.m.restore_sgrproj);
2572
75.7k
        lr->type = type ? frame_type : DAV1D_RESTORATION_NONE;
2573
75.7k
    }
2574
2575
102k
    if (lr->type == DAV1D_RESTORATION_WIENER) {
2576
27.7k
        lr->filter_v[0] = p ? 0 :
2577
27.7k
            dav1d_msac_decode_subexp(&ts->msac,
2578
9.84k
                lr_ref->filter_v[0] + 5, 16, 1) - 5;
2579
27.7k
        lr->filter_v[1] =
2580
27.7k
            dav1d_msac_decode_subexp(&ts->msac,
2581
27.7k
                lr_ref->filter_v[1] + 23, 32, 2) - 23;
2582
27.7k
        lr->filter_v[2] =
2583
27.7k
            dav1d_msac_decode_subexp(&ts->msac,
2584
27.7k
                lr_ref->filter_v[2] + 17, 64, 3) - 17;
2585
2586
27.7k
        lr->filter_h[0] = p ? 0 :
2587
27.7k
            dav1d_msac_decode_subexp(&ts->msac,
2588
9.84k
                lr_ref->filter_h[0] + 5, 16, 1) - 5;
2589
27.7k
        lr->filter_h[1] =
2590
27.7k
            dav1d_msac_decode_subexp(&ts->msac,
2591
27.7k
                lr_ref->filter_h[1] + 23, 32, 2) - 23;
2592
27.7k
        lr->filter_h[2] =
2593
27.7k
            dav1d_msac_decode_subexp(&ts->msac,
2594
27.7k
                lr_ref->filter_h[2] + 17, 64, 3) - 17;
2595
27.7k
        memcpy(lr->sgr_weights, lr_ref->sgr_weights, sizeof(lr->sgr_weights));
2596
27.7k
        ts->lr_ref[p] = lr;
2597
27.7k
        if (DEBUG_BLOCK_INFO)
2598
0
            printf("Post-lr_wiener[pl=%d,v[%d,%d,%d],h[%d,%d,%d]]: r=%d\n",
2599
0
                   p, lr->filter_v[0], lr->filter_v[1],
2600
0
                   lr->filter_v[2], lr->filter_h[0],
2601
0
                   lr->filter_h[1], lr->filter_h[2], ts->msac.rng);
2602
75.2k
    } else if (lr->type == DAV1D_RESTORATION_SGRPROJ) {
2603
29.7k
        const unsigned idx = dav1d_msac_decode_bools(&ts->msac, 4);
2604
29.7k
        const uint16_t *const sgr_params = dav1d_sgr_params[idx];
2605
29.7k
        lr->type += idx;
2606
29.7k
        lr->sgr_weights[0] = sgr_params[0] ? dav1d_msac_decode_subexp(&ts->msac,
2607
23.7k
            lr_ref->sgr_weights[0] + 96, 128, 4) - 96 : 0;
2608
29.7k
        lr->sgr_weights[1] = sgr_params[1] ? dav1d_msac_decode_subexp(&ts->msac,
2609
22.9k
            lr_ref->sgr_weights[1] + 32, 128, 4) - 32 : 95;
2610
29.7k
        memcpy(lr->filter_v, lr_ref->filter_v, sizeof(lr->filter_v));
2611
29.7k
        memcpy(lr->filter_h, lr_ref->filter_h, sizeof(lr->filter_h));
2612
29.7k
        ts->lr_ref[p] = lr;
2613
29.7k
        if (DEBUG_BLOCK_INFO)
2614
0
            printf("Post-lr_sgrproj[pl=%d,idx=%d,w[%d,%d]]: r=%d\n",
2615
0
                   p, idx, lr->sgr_weights[0],
2616
0
                   lr->sgr_weights[1], ts->msac.rng);
2617
29.7k
    }
2618
102k
}
2619
2620
// modeled after the equivalent function in aomdec:decodeframe.c
2621
0
static int check_trailing_bits_after_symbol_coder(const MsacContext *const msac) {
2622
    // check marker bit (single 1), followed by zeroes
2623
0
    const int n_bits = -(msac->cnt + 14);
2624
0
    assert(n_bits <= 0); // this assumes we errored out when cnt <= -15 in caller
2625
0
    const int n_bytes = (n_bits + 7) >> 3;
2626
0
    const uint8_t *p = &msac->buf_pos[n_bytes];
2627
0
    const int pattern = 128 >> ((n_bits - 1) & 7);
2628
0
    if ((p[-1] & (2 * pattern - 1)) != pattern)
2629
0
        return 1;
2630
2631
    // check remainder zero bytes
2632
0
    for (; p < msac->buf_end; p++)
2633
0
        if (*p)
2634
0
            return 1;
2635
2636
0
    return 0;
2637
0
}
2638
2639
208k
int dav1d_decode_tile_sbrow(Dav1dTaskContext *const t) {
2640
208k
    const Dav1dFrameContext *const f = t->f;
2641
208k
    const enum BlockLevel root_bl = f->seq_hdr->sb128 ? BL_128X128 : BL_64X64;
2642
208k
    Dav1dTileState *const ts = t->ts;
2643
208k
    const Dav1dContext *const c = f->c;
2644
208k
    const int sb_step = f->sb_step;
2645
208k
    const int tile_row = ts->tiling.row, tile_col = ts->tiling.col;
2646
208k
    const int col_sb_start = f->frame_hdr->tiling.col_start_sb[tile_col];
2647
208k
    const int col_sb128_start = col_sb_start >> !f->seq_hdr->sb128;
2648
2649
208k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc) {
2650
53.9k
        dav1d_refmvs_tile_sbrow_init(&t->rt, &f->rf, ts->tiling.col_start,
2651
53.9k
                                     ts->tiling.col_end, ts->tiling.row_start,
2652
53.9k
                                     ts->tiling.row_end, t->by >> f->sb_shift,
2653
53.9k
                                     ts->tiling.row, t->frame_thread.pass);
2654
53.9k
    }
2655
2656
208k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) && c->n_fc > 1) {
2657
37.5k
        const int sby = (t->by - ts->tiling.row_start) >> f->sb_shift;
2658
37.5k
        int (*const lowest_px)[2] = ts->lowest_pixel[sby];
2659
300k
        for (int n = 0; n < 7; n++)
2660
788k
            for (int m = 0; m < 2; m++)
2661
525k
                lowest_px[n][m] = INT_MIN;
2662
37.5k
    }
2663
2664
208k
    reset_context(&t->l, IS_KEY_OR_INTRA(f->frame_hdr), t->frame_thread.pass);
2665
208k
    if (t->frame_thread.pass == 2) {
2666
98.5k
        const int off_2pass = c->n_tc > 1 ? f->sb128w * f->frame_hdr->tiling.rows : 0;
2667
98.5k
        for (t->bx = ts->tiling.col_start,
2668
98.5k
             t->a = f->a + off_2pass + col_sb128_start + tile_row * f->sb128w;
2669
239k
             t->bx < ts->tiling.col_end; t->bx += sb_step)
2670
140k
        {
2671
140k
            if (atomic_load_explicit(c->flush, memory_order_acquire))
2672
12
                return 1;
2673
140k
            if (decode_sb(t, root_bl, dav1d_intra_edge_tree[root_bl]))
2674
0
                return 1;
2675
140k
            if (t->bx & 16 || f->seq_hdr->sb128)
2676
77.9k
                t->a++;
2677
140k
        }
2678
98.4k
        f->bd_fn.backup_ipred_edge(t);
2679
98.4k
        return 0;
2680
98.5k
    }
2681
2682
110k
    if (f->c->n_tc > 1 && f->frame_hdr->use_ref_frame_mvs) {
2683
2.71k
        f->c->refmvs_dsp.load_tmvs(&f->rf, ts->tiling.row,
2684
2.71k
                                   ts->tiling.col_start >> 1, ts->tiling.col_end >> 1,
2685
2.71k
                                   t->by >> 1, (t->by + sb_step) >> 1);
2686
2.71k
    }
2687
110k
    memset(t->pal_sz_uv[1], 0, sizeof(*t->pal_sz_uv));
2688
110k
    const int sb128y = t->by >> 5;
2689
110k
    for (t->bx = ts->tiling.col_start, t->a = f->a + col_sb128_start + tile_row * f->sb128w,
2690
110k
         t->lf_mask = f->lf.mask + sb128y * f->sb128w + col_sb128_start;
2691
298k
         t->bx < ts->tiling.col_end; t->bx += sb_step)
2692
187k
    {
2693
187k
        if (atomic_load_explicit(c->flush, memory_order_acquire))
2694
19
            return 1;
2695
187k
        if (root_bl == BL_128X128) {
2696
93.8k
            t->cur_sb_cdef_idx_ptr = t->lf_mask->cdef_idx;
2697
93.8k
            t->cur_sb_cdef_idx_ptr[0] = -1;
2698
93.8k
            t->cur_sb_cdef_idx_ptr[1] = -1;
2699
93.8k
            t->cur_sb_cdef_idx_ptr[2] = -1;
2700
93.8k
            t->cur_sb_cdef_idx_ptr[3] = -1;
2701
94.1k
        } else {
2702
94.1k
            t->cur_sb_cdef_idx_ptr =
2703
94.1k
                &t->lf_mask->cdef_idx[((t->bx & 16) >> 4) +
2704
94.1k
                                      ((t->by & 16) >> 3)];
2705
94.1k
            t->cur_sb_cdef_idx_ptr[0] = -1;
2706
94.1k
        }
2707
        // Restoration filter
2708
751k
        for (int p = 0; p < 3; p++) {
2709
563k
            if (!((f->lf.restore_planes >> p) & 1U))
2710
431k
                continue;
2711
2712
131k
            const int ss_ver = p && f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
2713
131k
            const int ss_hor = p && f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
2714
131k
            const int unit_size_log2 = f->frame_hdr->restoration.unit_size[!!p];
2715
131k
            const int y = t->by * 4 >> ss_ver;
2716
131k
            const int h = (f->cur.p.h + ss_ver) >> ss_ver;
2717
2718
131k
            const int unit_size = 1 << unit_size_log2;
2719
131k
            const unsigned mask = unit_size - 1;
2720
131k
            if (y & mask) continue;
2721
105k
            const int half_unit = unit_size >> 1;
2722
            // Round half up at frame boundaries, if there's more than one
2723
            // restoration unit
2724
105k
            if (y && y + half_unit > h) continue;
2725
2726
103k
            const enum Dav1dRestorationType frame_type = f->frame_hdr->restoration.type[p];
2727
2728
103k
            if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
2729
33.1k
                const int w = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
2730
33.1k
                const int n_units = imax(1, (w + half_unit) >> unit_size_log2);
2731
2732
33.1k
                const int d = f->frame_hdr->super_res.width_scale_denominator;
2733
33.1k
                const int rnd = unit_size * 8 - 1, shift = unit_size_log2 + 3;
2734
33.1k
                const int x0 = ((4 *  t->bx            * d >> ss_hor) + rnd) >> shift;
2735
33.1k
                const int x1 = ((4 * (t->bx + sb_step) * d >> ss_hor) + rnd) >> shift;
2736
2737
71.5k
                for (int x = x0; x < imin(x1, n_units); x++) {
2738
38.4k
                    const int px_x = x << (unit_size_log2 + ss_hor);
2739
38.4k
                    const int sb_idx = (t->by >> 5) * f->sr_sb128w + (px_x >> 7);
2740
38.4k
                    const int unit_idx = ((t->by & 16) >> 3) + ((px_x & 64) >> 6);
2741
38.4k
                    Av1RestorationUnit *const lr = &f->lf.lr_mask[sb_idx].lr[p][unit_idx];
2742
2743
38.4k
                    read_restoration_info(t, lr, p, frame_type);
2744
38.4k
                }
2745
70.6k
            } else {
2746
70.6k
                const int x = 4 * t->bx >> ss_hor;
2747
70.6k
                if (x & mask) continue;
2748
66.0k
                const int w = (f->cur.p.w + ss_hor) >> ss_hor;
2749
                // Round half up at frame boundaries, if there's more than one
2750
                // restoration unit
2751
66.0k
                if (x && x + half_unit > w) continue;
2752
64.4k
                const int sb_idx = (t->by >> 5) * f->sr_sb128w + (t->bx >> 5);
2753
64.4k
                const int unit_idx = ((t->by & 16) >> 3) + ((t->bx & 16) >> 4);
2754
64.4k
                Av1RestorationUnit *const lr = &f->lf.lr_mask[sb_idx].lr[p][unit_idx];
2755
2756
64.4k
                read_restoration_info(t, lr, p, frame_type);
2757
64.4k
            }
2758
103k
        }
2759
187k
        if (decode_sb(t, root_bl, dav1d_intra_edge_tree[root_bl]))
2760
84
            return 1;
2761
187k
        if (t->bx & 16 || f->seq_hdr->sb128) {
2762
111k
            t->a++;
2763
111k
            t->lf_mask++;
2764
111k
        }
2765
187k
    }
2766
2767
110k
    if (f->seq_hdr->ref_frame_mvs && f->c->n_tc > 1 && IS_INTER_OR_SWITCH(f->frame_hdr)) {
2768
5.19k
        dav1d_refmvs_save_tmvs(&f->c->refmvs_dsp, &t->rt,
2769
5.19k
                               ts->tiling.col_start >> 1, ts->tiling.col_end >> 1,
2770
5.19k
                               t->by >> 1, (t->by + sb_step) >> 1);
2771
5.19k
    }
2772
2773
    // backup pre-loopfilter pixels for intra prediction of the next sbrow
2774
110k
    if (t->frame_thread.pass != 1)
2775
0
        f->bd_fn.backup_ipred_edge(t);
2776
2777
    // backup t->a/l.tx_lpf_y/uv at tile boundaries to use them to "fix"
2778
    // up the initial value in neighbour tiles when running the loopfilter
2779
110k
    int align_h = (f->bh + 31) & ~31;
2780
110k
    memcpy(&f->lf.tx_lpf_right_edge[0][align_h * tile_col + t->by],
2781
110k
           &t->l.tx_lpf_y[t->by & 16], sb_step);
2782
110k
    const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
2783
110k
    align_h >>= ss_ver;
2784
110k
    memcpy(&f->lf.tx_lpf_right_edge[1][align_h * tile_col + (t->by >> ss_ver)],
2785
110k
           &t->l.tx_lpf_uv[(t->by & 16) >> ss_ver], sb_step >> ss_ver);
2786
2787
    // error out on symbol decoder overread
2788
110k
    if (ts->msac.cnt <= -15) return 1;
2789
2790
108k
    return c->strict_std_compliance &&
2791
0
           (t->by >> f->sb_shift) + 1 >= f->frame_hdr->tiling.row_start_sb[tile_row + 1] &&
2792
0
           check_trailing_bits_after_symbol_coder(&ts->msac);
2793
110k
}
2794
2795
30.5k
int dav1d_decode_frame_init(Dav1dFrameContext *const f) {
2796
30.5k
    const Dav1dContext *const c = f->c;
2797
30.5k
    int retval = DAV1D_ERR(ENOMEM);
2798
2799
30.5k
    if (f->sbh > f->lf.start_of_tile_row_sz) {
2800
16.7k
        dav1d_free(f->lf.start_of_tile_row);
2801
16.7k
        f->lf.start_of_tile_row = dav1d_malloc(ALLOC_TILE, f->sbh * sizeof(uint8_t));
2802
16.7k
        if (!f->lf.start_of_tile_row) {
2803
0
            f->lf.start_of_tile_row_sz = 0;
2804
0
            goto error;
2805
0
        }
2806
16.7k
        f->lf.start_of_tile_row_sz = f->sbh;
2807
16.7k
    }
2808
30.5k
    int sby = 0;
2809
62.7k
    for (int tile_row = 0; tile_row < f->frame_hdr->tiling.rows; tile_row++) {
2810
32.2k
        f->lf.start_of_tile_row[sby++] = tile_row;
2811
170k
        while (sby < f->frame_hdr->tiling.row_start_sb[tile_row + 1])
2812
138k
            f->lf.start_of_tile_row[sby++] = 0;
2813
32.2k
    }
2814
2815
30.5k
    const int n_ts = f->frame_hdr->tiling.cols * f->frame_hdr->tiling.rows;
2816
30.5k
    if (n_ts != f->n_ts) {
2817
16.8k
        if (c->n_fc > 1) {
2818
16.8k
            dav1d_free(f->frame_thread.tile_start_off);
2819
16.8k
            f->frame_thread.tile_start_off =
2820
16.8k
                dav1d_malloc(ALLOC_TILE, sizeof(*f->frame_thread.tile_start_off) * n_ts);
2821
16.8k
            if (!f->frame_thread.tile_start_off) {
2822
0
                f->n_ts = 0;
2823
0
                goto error;
2824
0
            }
2825
16.8k
        }
2826
16.8k
        dav1d_free_aligned(f->ts);
2827
16.8k
        f->ts = dav1d_alloc_aligned(ALLOC_TILE, sizeof(*f->ts) * n_ts, 32);
2828
16.8k
        if (!f->ts) goto error;
2829
16.8k
        f->n_ts = n_ts;
2830
16.8k
    }
2831
2832
30.5k
    const int a_sz = f->sb128w * f->frame_hdr->tiling.rows * (1 + (c->n_fc > 1 && c->n_tc > 1));
2833
30.5k
    if (a_sz != f->a_sz) {
2834
16.8k
        dav1d_free(f->a);
2835
16.8k
        f->a = dav1d_malloc(ALLOC_TILE, sizeof(*f->a) * a_sz);
2836
16.8k
        if (!f->a) {
2837
0
            f->a_sz = 0;
2838
0
            goto error;
2839
0
        }
2840
16.8k
        f->a_sz = a_sz;
2841
16.8k
    }
2842
2843
30.5k
    const int num_sb128 = f->sb128w * f->sb128h;
2844
30.5k
    const uint8_t *const size_mul = ss_size_mul[f->cur.p.layout];
2845
30.5k
    const int hbd = !!f->seq_hdr->hbd;
2846
30.5k
    if (c->n_fc > 1) {
2847
30.5k
        const unsigned sb_step4 = f->sb_step * 4;
2848
30.5k
        int tile_idx = 0;
2849
62.7k
        for (int tile_row = 0; tile_row < f->frame_hdr->tiling.rows; tile_row++) {
2850
32.2k
            const unsigned row_off = f->frame_hdr->tiling.row_start_sb[tile_row] *
2851
32.2k
                                     sb_step4 * f->sb128w * 128;
2852
32.2k
            const unsigned b_diff = (f->frame_hdr->tiling.row_start_sb[tile_row + 1] -
2853
32.2k
                                     f->frame_hdr->tiling.row_start_sb[tile_row]) * sb_step4;
2854
68.8k
            for (int tile_col = 0; tile_col < f->frame_hdr->tiling.cols; tile_col++) {
2855
36.6k
                f->frame_thread.tile_start_off[tile_idx++] = row_off + b_diff *
2856
36.6k
                    f->frame_hdr->tiling.col_start_sb[tile_col] * sb_step4;
2857
36.6k
            }
2858
32.2k
        }
2859
2860
30.5k
        const int lowest_pixel_mem_sz = f->frame_hdr->tiling.cols * f->sbh;
2861
30.5k
        if (lowest_pixel_mem_sz != f->tile_thread.lowest_pixel_mem_sz) {
2862
16.8k
            dav1d_free(f->tile_thread.lowest_pixel_mem);
2863
16.8k
            f->tile_thread.lowest_pixel_mem =
2864
16.8k
                dav1d_malloc(ALLOC_TILE, lowest_pixel_mem_sz *
2865
16.8k
                             sizeof(*f->tile_thread.lowest_pixel_mem));
2866
16.8k
            if (!f->tile_thread.lowest_pixel_mem) {
2867
0
                f->tile_thread.lowest_pixel_mem_sz = 0;
2868
0
                goto error;
2869
0
            }
2870
16.8k
            f->tile_thread.lowest_pixel_mem_sz = lowest_pixel_mem_sz;
2871
16.8k
        }
2872
30.5k
        int (*lowest_pixel_ptr)[7][2] = f->tile_thread.lowest_pixel_mem;
2873
62.7k
        for (int tile_row = 0, tile_row_base = 0; tile_row < f->frame_hdr->tiling.rows;
2874
32.2k
             tile_row++, tile_row_base += f->frame_hdr->tiling.cols)
2875
32.2k
        {
2876
32.2k
            const int tile_row_sb_h = f->frame_hdr->tiling.row_start_sb[tile_row + 1] -
2877
32.2k
                                      f->frame_hdr->tiling.row_start_sb[tile_row];
2878
68.8k
            for (int tile_col = 0; tile_col < f->frame_hdr->tiling.cols; tile_col++) {
2879
36.6k
                f->ts[tile_row_base + tile_col].lowest_pixel = lowest_pixel_ptr;
2880
36.6k
                lowest_pixel_ptr += tile_row_sb_h;
2881
36.6k
            }
2882
32.2k
        }
2883
2884
30.5k
        const int cbi_sz = num_sb128 * size_mul[0];
2885
30.5k
        if (cbi_sz != f->frame_thread.cbi_sz) {
2886
16.9k
            dav1d_free_aligned(f->frame_thread.cbi);
2887
16.9k
            f->frame_thread.cbi =
2888
16.9k
                dav1d_alloc_aligned(ALLOC_BLOCK, sizeof(*f->frame_thread.cbi) *
2889
16.9k
                                    cbi_sz * 32 * 32 / 4, 64);
2890
16.9k
            if (!f->frame_thread.cbi) {
2891
0
                f->frame_thread.cbi_sz = 0;
2892
0
                goto error;
2893
0
            }
2894
16.9k
            f->frame_thread.cbi_sz = cbi_sz;
2895
16.9k
        }
2896
2897
30.5k
        const int cf_sz = (num_sb128 * size_mul[0]) << hbd;
2898
30.5k
        if (cf_sz != f->frame_thread.cf_sz) {
2899
16.9k
            dav1d_free_aligned(f->frame_thread.cf);
2900
16.9k
            f->frame_thread.cf =
2901
16.9k
                dav1d_alloc_aligned(ALLOC_COEF, (size_t)cf_sz * 128 * 128 / 2, 64);
2902
16.9k
            if (!f->frame_thread.cf) {
2903
0
                f->frame_thread.cf_sz = 0;
2904
0
                goto error;
2905
0
            }
2906
16.9k
            memset(f->frame_thread.cf, 0, (size_t)cf_sz * 128 * 128 / 2);
2907
16.9k
            f->frame_thread.cf_sz = cf_sz;
2908
16.9k
        }
2909
2910
30.5k
        if (f->frame_hdr->allow_screen_content_tools) {
2911
10.1k
            const int pal_sz = num_sb128 << hbd;
2912
10.1k
            if (pal_sz != f->frame_thread.pal_sz) {
2913
6.72k
                dav1d_free_aligned(f->frame_thread.pal);
2914
6.72k
                f->frame_thread.pal =
2915
6.72k
                    dav1d_alloc_aligned(ALLOC_PAL, sizeof(*f->frame_thread.pal) *
2916
6.72k
                                        pal_sz * 16 * 16, 64);
2917
6.72k
                if (!f->frame_thread.pal) {
2918
0
                    f->frame_thread.pal_sz = 0;
2919
0
                    goto error;
2920
0
                }
2921
6.72k
                f->frame_thread.pal_sz = pal_sz;
2922
6.72k
            }
2923
2924
10.1k
            const int pal_idx_sz = num_sb128 * size_mul[1];
2925
10.1k
            if (pal_idx_sz != f->frame_thread.pal_idx_sz) {
2926
6.72k
                dav1d_free_aligned(f->frame_thread.pal_idx);
2927
6.72k
                f->frame_thread.pal_idx =
2928
6.72k
                    dav1d_alloc_aligned(ALLOC_PAL, sizeof(*f->frame_thread.pal_idx) *
2929
6.72k
                                        pal_idx_sz * 128 * 128 / 8, 64);
2930
6.72k
                if (!f->frame_thread.pal_idx) {
2931
0
                    f->frame_thread.pal_idx_sz = 0;
2932
0
                    goto error;
2933
0
                }
2934
6.72k
                f->frame_thread.pal_idx_sz = pal_idx_sz;
2935
6.72k
            }
2936
20.4k
        } else if (f->frame_thread.pal) {
2937
150
            dav1d_freep_aligned(&f->frame_thread.pal);
2938
150
            dav1d_freep_aligned(&f->frame_thread.pal_idx);
2939
150
            f->frame_thread.pal_sz = f->frame_thread.pal_idx_sz = 0;
2940
150
        }
2941
30.5k
    }
2942
2943
    // update allocation of block contexts for above
2944
30.5k
    ptrdiff_t y_stride = f->cur.stride[0], uv_stride = f->cur.stride[1];
2945
30.5k
    const int has_resize = f->frame_hdr->width[0] != f->frame_hdr->width[1];
2946
30.5k
    const int need_cdef_lpf_copy = c->n_tc > 1 && has_resize;
2947
30.5k
    if (y_stride * f->sbh * 4 != f->lf.cdef_buf_plane_sz[0] ||
2948
13.5k
        uv_stride * f->sbh * 8 != f->lf.cdef_buf_plane_sz[1] ||
2949
13.5k
        need_cdef_lpf_copy != f->lf.need_cdef_lpf_copy ||
2950
12.8k
        f->sbh != f->lf.cdef_buf_sbh)
2951
17.6k
    {
2952
17.6k
        dav1d_free_aligned(f->lf.cdef_line_buf);
2953
17.6k
        size_t alloc_sz = 64;
2954
17.6k
        alloc_sz += (size_t)llabs(y_stride) * 4 * f->sbh << need_cdef_lpf_copy;
2955
17.6k
        alloc_sz += (size_t)llabs(uv_stride) * 8 * f->sbh << need_cdef_lpf_copy;
2956
17.6k
        uint8_t *ptr = f->lf.cdef_line_buf = dav1d_alloc_aligned(ALLOC_CDEF, alloc_sz, 32);
2957
17.6k
        if (!ptr) {
2958
0
            f->lf.cdef_buf_plane_sz[0] = f->lf.cdef_buf_plane_sz[1] = 0;
2959
0
            goto error;
2960
0
        }
2961
2962
17.6k
        ptr += 32;
2963
17.6k
        if (y_stride < 0) {
2964
0
            f->lf.cdef_line[0][0] = ptr - y_stride * (f->sbh * 4 - 1);
2965
0
            f->lf.cdef_line[1][0] = ptr - y_stride * (f->sbh * 4 - 3);
2966
17.6k
        } else {
2967
17.6k
            f->lf.cdef_line[0][0] = ptr + y_stride * 0;
2968
17.6k
            f->lf.cdef_line[1][0] = ptr + y_stride * 2;
2969
17.6k
        }
2970
17.6k
        ptr += llabs(y_stride) * f->sbh * 4;
2971
17.6k
        if (uv_stride < 0) {
2972
0
            f->lf.cdef_line[0][1] = ptr - uv_stride * (f->sbh * 8 - 1);
2973
0
            f->lf.cdef_line[0][2] = ptr - uv_stride * (f->sbh * 8 - 3);
2974
0
            f->lf.cdef_line[1][1] = ptr - uv_stride * (f->sbh * 8 - 5);
2975
0
            f->lf.cdef_line[1][2] = ptr - uv_stride * (f->sbh * 8 - 7);
2976
17.6k
        } else {
2977
17.6k
            f->lf.cdef_line[0][1] = ptr + uv_stride * 0;
2978
17.6k
            f->lf.cdef_line[0][2] = ptr + uv_stride * 2;
2979
17.6k
            f->lf.cdef_line[1][1] = ptr + uv_stride * 4;
2980
17.6k
            f->lf.cdef_line[1][2] = ptr + uv_stride * 6;
2981
17.6k
        }
2982
2983
17.6k
        if (need_cdef_lpf_copy) {
2984
4.22k
            ptr += llabs(uv_stride) * f->sbh * 8;
2985
4.22k
            if (y_stride < 0)
2986
0
                f->lf.cdef_lpf_line[0] = ptr - y_stride * (f->sbh * 4 - 1);
2987
4.22k
            else
2988
4.22k
                f->lf.cdef_lpf_line[0] = ptr;
2989
4.22k
            ptr += llabs(y_stride) * f->sbh * 4;
2990
4.22k
            if (uv_stride < 0) {
2991
0
                f->lf.cdef_lpf_line[1] = ptr - uv_stride * (f->sbh * 4 - 1);
2992
0
                f->lf.cdef_lpf_line[2] = ptr - uv_stride * (f->sbh * 8 - 1);
2993
4.22k
            } else {
2994
4.22k
                f->lf.cdef_lpf_line[1] = ptr;
2995
4.22k
                f->lf.cdef_lpf_line[2] = ptr + uv_stride * f->sbh * 4;
2996
4.22k
            }
2997
4.22k
        }
2998
2999
17.6k
        f->lf.cdef_buf_plane_sz[0] = (int) y_stride * f->sbh * 4;
3000
17.6k
        f->lf.cdef_buf_plane_sz[1] = (int) uv_stride * f->sbh * 8;
3001
17.6k
        f->lf.need_cdef_lpf_copy = need_cdef_lpf_copy;
3002
17.6k
        f->lf.cdef_buf_sbh = f->sbh;
3003
17.6k
    }
3004
3005
30.5k
    const int sb128 = f->seq_hdr->sb128;
3006
30.5k
    const int num_lines = c->n_tc > 1 ? f->sbh * 4 << sb128 : 12;
3007
30.5k
    y_stride = f->sr_cur.p.stride[0], uv_stride = f->sr_cur.p.stride[1];
3008
30.5k
    if (y_stride * num_lines != f->lf.lr_buf_plane_sz[0] ||
3009
13.5k
        uv_stride * num_lines * 2 != f->lf.lr_buf_plane_sz[1])
3010
17.0k
    {
3011
17.0k
        dav1d_free_aligned(f->lf.lr_line_buf);
3012
        // lr simd may overread the input, so slightly over-allocate the lpf buffer
3013
17.0k
        size_t alloc_sz = 128;
3014
17.0k
        alloc_sz += (size_t)llabs(y_stride) * num_lines;
3015
17.0k
        alloc_sz += (size_t)llabs(uv_stride) * num_lines * 2;
3016
17.0k
        uint8_t *ptr = f->lf.lr_line_buf = dav1d_alloc_aligned(ALLOC_LR, alloc_sz, 64);
3017
17.0k
        if (!ptr) {
3018
0
            f->lf.lr_buf_plane_sz[0] = f->lf.lr_buf_plane_sz[1] = 0;
3019
0
            goto error;
3020
0
        }
3021
3022
17.0k
        ptr += 64;
3023
17.0k
        if (y_stride < 0)
3024
0
            f->lf.lr_lpf_line[0] = ptr - y_stride * (num_lines - 1);
3025
17.0k
        else
3026
17.0k
            f->lf.lr_lpf_line[0] = ptr;
3027
17.0k
        ptr += llabs(y_stride) * num_lines;
3028
17.0k
        if (uv_stride < 0) {
3029
0
            f->lf.lr_lpf_line[1] = ptr - uv_stride * (num_lines * 1 - 1);
3030
0
            f->lf.lr_lpf_line[2] = ptr - uv_stride * (num_lines * 2 - 1);
3031
17.0k
        } else {
3032
17.0k
            f->lf.lr_lpf_line[1] = ptr;
3033
17.0k
            f->lf.lr_lpf_line[2] = ptr + uv_stride * num_lines;
3034
17.0k
        }
3035
3036
17.0k
        f->lf.lr_buf_plane_sz[0] = (int) y_stride * num_lines;
3037
17.0k
        f->lf.lr_buf_plane_sz[1] = (int) uv_stride * num_lines * 2;
3038
17.0k
    }
3039
3040
    // update allocation for loopfilter masks
3041
30.5k
    if (num_sb128 != f->lf.mask_sz) {
3042
16.8k
        dav1d_free(f->lf.mask);
3043
16.8k
        dav1d_free(f->lf.level);
3044
16.8k
        f->lf.mask = dav1d_malloc(ALLOC_LF, sizeof(*f->lf.mask) * num_sb128);
3045
        // over-allocate by 3 bytes since some of the SIMD implementations
3046
        // index this from the level type and can thus over-read by up to 3
3047
16.8k
        f->lf.level = dav1d_malloc(ALLOC_LF, sizeof(*f->lf.level) * num_sb128 * 32 * 32 + 3);
3048
16.8k
        if (!f->lf.mask || !f->lf.level) {
3049
0
            f->lf.mask_sz = 0;
3050
0
            goto error;
3051
0
        }
3052
16.8k
        if (c->n_fc > 1) {
3053
16.8k
            dav1d_free(f->frame_thread.b);
3054
16.8k
            f->frame_thread.b = dav1d_malloc(ALLOC_BLOCK, sizeof(*f->frame_thread.b) *
3055
16.8k
                                             num_sb128 * 32 * 32);
3056
16.8k
            if (!f->frame_thread.b) {
3057
0
                f->lf.mask_sz = 0;
3058
0
                goto error;
3059
0
            }
3060
16.8k
        }
3061
16.8k
        f->lf.mask_sz = num_sb128;
3062
16.8k
    }
3063
3064
30.5k
    f->sr_sb128w = (f->sr_cur.p.p.w + 127) >> 7;
3065
30.5k
    const int lr_mask_sz = f->sr_sb128w * f->sb128h;
3066
30.5k
    if (lr_mask_sz != f->lf.lr_mask_sz) {
3067
16.7k
        dav1d_free(f->lf.lr_mask);
3068
16.7k
        f->lf.lr_mask = dav1d_malloc(ALLOC_LR, sizeof(*f->lf.lr_mask) * lr_mask_sz);
3069
16.7k
        if (!f->lf.lr_mask) {
3070
0
            f->lf.lr_mask_sz = 0;
3071
0
            goto error;
3072
0
        }
3073
16.7k
        f->lf.lr_mask_sz = lr_mask_sz;
3074
16.7k
    }
3075
30.5k
    f->lf.restore_planes =
3076
30.5k
        ((f->frame_hdr->restoration.type[0] != DAV1D_RESTORATION_NONE) << 0) +
3077
30.5k
        ((f->frame_hdr->restoration.type[1] != DAV1D_RESTORATION_NONE) << 1) +
3078
30.5k
        ((f->frame_hdr->restoration.type[2] != DAV1D_RESTORATION_NONE) << 2);
3079
30.5k
    if (f->frame_hdr->loopfilter.sharpness != f->lf.last_sharpness) {
3080
21.3k
        dav1d_calc_eih(&f->lf.lim_lut, f->frame_hdr->loopfilter.sharpness);
3081
21.3k
        f->lf.last_sharpness = f->frame_hdr->loopfilter.sharpness;
3082
21.3k
    }
3083
30.5k
    dav1d_calc_lf_values(f->lf.lvl, f->frame_hdr, (int8_t[4]) { 0, 0, 0, 0 });
3084
30.5k
    memset(f->lf.mask, 0, sizeof(*f->lf.mask) * num_sb128);
3085
3086
30.5k
    const int ipred_edge_sz = f->sbh * f->sb128w << hbd;
3087
30.5k
    if (ipred_edge_sz != f->ipred_edge_sz) {
3088
16.9k
        dav1d_free_aligned(f->ipred_edge[0]);
3089
16.9k
        uint8_t *ptr = f->ipred_edge[0] =
3090
16.9k
            dav1d_alloc_aligned(ALLOC_IPRED, ipred_edge_sz * 128 * 3, 64);
3091
16.9k
        if (!ptr) {
3092
0
            f->ipred_edge_sz = 0;
3093
0
            goto error;
3094
0
        }
3095
16.9k
        f->ipred_edge[1] = ptr + ipred_edge_sz * 128 * 1;
3096
16.9k
        f->ipred_edge[2] = ptr + ipred_edge_sz * 128 * 2;
3097
16.9k
        f->ipred_edge_sz = ipred_edge_sz;
3098
16.9k
    }
3099
3100
30.5k
    const int re_sz = f->sb128h * f->frame_hdr->tiling.cols;
3101
30.5k
    if (re_sz != f->lf.re_sz) {
3102
16.8k
        dav1d_free(f->lf.tx_lpf_right_edge[0]);
3103
16.8k
        f->lf.tx_lpf_right_edge[0] = dav1d_malloc(ALLOC_LF, re_sz * 32 * 2);
3104
16.8k
        if (!f->lf.tx_lpf_right_edge[0]) {
3105
0
            f->lf.re_sz = 0;
3106
0
            goto error;
3107
0
        }
3108
16.8k
        f->lf.tx_lpf_right_edge[1] = f->lf.tx_lpf_right_edge[0] + re_sz * 32;
3109
16.8k
        f->lf.re_sz = re_sz;
3110
16.8k
    }
3111
3112
    // init ref mvs
3113
30.5k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc) {
3114
20.2k
        const int ret =
3115
20.2k
            dav1d_refmvs_init_frame(&f->rf, f->seq_hdr, f->frame_hdr,
3116
20.2k
                                    f->refpoc, f->mvs, f->refrefpoc, f->ref_mvs,
3117
20.2k
                                    f->c->n_tc, f->c->n_fc);
3118
20.2k
        if (ret < 0) goto error;
3119
20.2k
    }
3120
3121
    // setup dequant tables
3122
30.5k
    init_quant_tables(f->seq_hdr, f->frame_hdr, f->frame_hdr->quant.yac, f->dq);
3123
30.5k
    if (f->frame_hdr->quant.qm)
3124
411k
        for (int i = 0; i < N_RECT_TX_SIZES; i++) {
3125
391k
            f->qm[i][0] = dav1d_qm_tbl[f->frame_hdr->quant.qm_y][0][i];
3126
391k
            f->qm[i][1] = dav1d_qm_tbl[f->frame_hdr->quant.qm_u][1][i];
3127
391k
            f->qm[i][2] = dav1d_qm_tbl[f->frame_hdr->quant.qm_v][1][i];
3128
391k
        }
3129
9.93k
    else
3130
9.93k
        memset(f->qm, 0, sizeof(f->qm));
3131
3132
    // setup jnt_comp weights
3133
30.5k
    if (f->frame_hdr->switchable_comp_refs) {
3134
78.1k
        for (int i = 0; i < 7; i++) {
3135
68.3k
            const unsigned ref0poc = f->refp[i].p.frame_hdr->frame_offset;
3136
3137
273k
            for (int j = i + 1; j < 7; j++) {
3138
204k
                const unsigned ref1poc = f->refp[j].p.frame_hdr->frame_offset;
3139
3140
204k
                const unsigned d1 =
3141
204k
                    imin(abs(get_poc_diff(f->seq_hdr->order_hint_n_bits, ref0poc,
3142
204k
                                          f->cur.frame_hdr->frame_offset)), 31);
3143
204k
                const unsigned d0 =
3144
204k
                    imin(abs(get_poc_diff(f->seq_hdr->order_hint_n_bits, ref1poc,
3145
204k
                                          f->cur.frame_hdr->frame_offset)), 31);
3146
204k
                const int order = d0 <= d1;
3147
3148
204k
                static const uint8_t quant_dist_weight[3][2] = {
3149
204k
                    { 2, 3 }, { 2, 5 }, { 2, 7 }
3150
204k
                };
3151
204k
                static const uint8_t quant_dist_lookup_table[4][2] = {
3152
204k
                    { 9, 7 }, { 11, 5 }, { 12, 4 }, { 13, 3 }
3153
204k
                };
3154
3155
204k
                int k;
3156
688k
                for (k = 0; k < 3; k++) {
3157
528k
                    const int c0 = quant_dist_weight[k][order];
3158
528k
                    const int c1 = quant_dist_weight[k][!order];
3159
528k
                    const int d0_c0 = d0 * c0;
3160
528k
                    const int d1_c1 = d1 * c1;
3161
528k
                    if ((d0 > d1 && d0_c0 < d1_c1) || (d0 <= d1 && d0_c0 > d1_c1)) break;
3162
528k
                }
3163
3164
204k
                f->jnt_weights[i][j] = quant_dist_lookup_table[k][order];
3165
204k
            }
3166
68.3k
        }
3167
9.77k
    }
3168
3169
    /* Init loopfilter pointers. Increasing NULL pointers is technically UB,
3170
     * so just point the chroma pointers in 4:0:0 to the luma plane here to
3171
     * avoid having additional in-loop branches in various places. We never
3172
     * dereference those pointers so it doesn't really matter what they
3173
     * point at, as long as the pointers are valid. */
3174
30.5k
    const int has_chroma = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400;
3175
30.5k
    f->lf.p[0] = f->cur.data[0];
3176
30.5k
    f->lf.p[1] = f->cur.data[has_chroma ? 1 : 0];
3177
30.5k
    f->lf.p[2] = f->cur.data[has_chroma ? 2 : 0];
3178
30.5k
    f->lf.sr_p[0] = f->sr_cur.p.data[0];
3179
30.5k
    f->lf.sr_p[1] = f->sr_cur.p.data[has_chroma ? 1 : 0];
3180
30.5k
    f->lf.sr_p[2] = f->sr_cur.p.data[has_chroma ? 2 : 0];
3181
3182
30.5k
    retval = 0;
3183
30.5k
error:
3184
30.5k
    return retval;
3185
30.5k
}
3186
3187
29.5k
int dav1d_decode_frame_init_cdf(Dav1dFrameContext *const f) {
3188
29.5k
    const Dav1dContext *const c = f->c;
3189
29.5k
    int retval = DAV1D_ERR(EINVAL);
3190
3191
29.5k
    if (f->frame_hdr->refresh_context)
3192
12.5k
        dav1d_cdf_thread_copy(f->out_cdf.data.cdf, &f->in_cdf);
3193
3194
    // parse individual tiles per tile group
3195
29.5k
    int tile_row = 0, tile_col = 0;
3196
29.5k
    f->task_thread.update_set = 0;
3197
58.9k
    for (int i = 0; i < f->n_tile_data; i++) {
3198
29.5k
        const uint8_t *data = f->tile[i].data.data;
3199
29.5k
        size_t size = f->tile[i].data.sz;
3200
3201
62.6k
        for (int j = f->tile[i].start; j <= f->tile[i].end; j++) {
3202
33.2k
            size_t tile_sz;
3203
33.2k
            if (j == f->tile[i].end) {
3204
29.4k
                tile_sz = size;
3205
29.4k
            } else {
3206
3.77k
                if (f->frame_hdr->tiling.n_bytes > size) goto error;
3207
3.77k
                tile_sz = 0;
3208
7.88k
                for (unsigned k = 0; k < f->frame_hdr->tiling.n_bytes; k++)
3209
4.11k
                    tile_sz |= (unsigned)*data++ << (k * 8);
3210
3.77k
                tile_sz++;
3211
3.77k
                size -= f->frame_hdr->tiling.n_bytes;
3212
3.77k
                if (tile_sz > size) goto error;
3213
3.77k
            }
3214
3215
33.1k
            setup_tile(&f->ts[j], f, data, tile_sz, tile_row, tile_col++,
3216
33.1k
                       c->n_fc > 1 ? f->frame_thread.tile_start_off[j] : 0);
3217
3218
33.1k
            if (tile_col == f->frame_hdr->tiling.cols) {
3219
30.2k
                tile_col = 0;
3220
30.2k
                tile_row++;
3221
30.2k
            }
3222
33.1k
            if (j == f->frame_hdr->tiling.update && f->frame_hdr->refresh_context)
3223
12.5k
                f->task_thread.update_set = 1;
3224
33.1k
            data += tile_sz;
3225
33.1k
            size -= tile_sz;
3226
33.1k
        }
3227
29.5k
    }
3228
3229
29.4k
    if (c->n_tc > 1) {
3230
29.4k
        const int uses_2pass = c->n_fc > 1;
3231
179k
        for (int n = 0; n < f->sb128w * f->frame_hdr->tiling.rows * (1 + uses_2pass); n++)
3232
149k
            reset_context(&f->a[n], IS_KEY_OR_INTRA(f->frame_hdr),
3233
18.4E
                          uses_2pass ? 1 + (n >= f->sb128w * f->frame_hdr->tiling.rows) : 0);
3234
29.4k
    }
3235
3236
29.4k
    retval = 0;
3237
29.5k
error:
3238
29.5k
    return retval;
3239
29.4k
}
3240
3241
0
int dav1d_decode_frame_main(Dav1dFrameContext *const f) {
3242
0
    const Dav1dContext *const c = f->c;
3243
0
    int retval = DAV1D_ERR(EINVAL);
3244
3245
0
    assert(f->c->n_tc == 1);
3246
3247
0
    Dav1dTaskContext *const t = &c->tc[f - c->fc];
3248
0
    t->f = f;
3249
0
    t->frame_thread.pass = 0;
3250
3251
0
    for (int n = 0; n < f->sb128w * f->frame_hdr->tiling.rows; n++)
3252
0
        reset_context(&f->a[n], IS_KEY_OR_INTRA(f->frame_hdr), 0);
3253
3254
    // no threading - we explicitly interleave tile/sbrow decoding
3255
    // and post-filtering, so that the full process runs in-line
3256
0
    for (int tile_row = 0; tile_row < f->frame_hdr->tiling.rows; tile_row++) {
3257
0
        const int sbh_end =
3258
0
            imin(f->frame_hdr->tiling.row_start_sb[tile_row + 1], f->sbh);
3259
0
        for (int sby = f->frame_hdr->tiling.row_start_sb[tile_row];
3260
0
             sby < sbh_end; sby++)
3261
0
        {
3262
0
            t->by = sby << (4 + f->seq_hdr->sb128);
3263
0
            const int by_end = (t->by + f->sb_step) >> 1;
3264
0
            if (f->frame_hdr->use_ref_frame_mvs) {
3265
0
                f->c->refmvs_dsp.load_tmvs(&f->rf, tile_row,
3266
0
                                           0, f->bw >> 1, t->by >> 1, by_end);
3267
0
            }
3268
0
            for (int tile_col = 0; tile_col < f->frame_hdr->tiling.cols; tile_col++) {
3269
0
                t->ts = &f->ts[tile_row * f->frame_hdr->tiling.cols + tile_col];
3270
0
                if (dav1d_decode_tile_sbrow(t)) goto error;
3271
0
            }
3272
0
            if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
3273
0
                dav1d_refmvs_save_tmvs(&f->c->refmvs_dsp, &t->rt,
3274
0
                                       0, f->bw >> 1, t->by >> 1, by_end);
3275
0
            }
3276
3277
            // loopfilter + cdef + restoration
3278
0
            f->bd_fn.filter_sbrow(f, sby);
3279
0
        }
3280
0
    }
3281
3282
0
    retval = 0;
3283
0
error:
3284
0
    return retval;
3285
0
}
3286
3287
78.9k
void dav1d_decode_frame_exit(Dav1dFrameContext *const f, int retval) {
3288
78.9k
    const Dav1dContext *const c = f->c;
3289
3290
78.9k
    if (f->sr_cur.p.data[0])
3291
78.9k
        atomic_init(&f->task_thread.error, 0);
3292
3293
78.9k
    if (c->n_fc > 1 && retval && f->frame_thread.cf) {
3294
19.7k
        memset(f->frame_thread.cf, 0,
3295
19.7k
               (size_t)f->frame_thread.cf_sz * 128 * 128 / 2);
3296
19.7k
    }
3297
631k
    for (int i = 0; i < 7; i++) {
3298
552k
        if (f->refp[i].p.frame_hdr) {
3299
136k
            if (!retval && c->n_fc > 1 && c->strict_std_compliance &&
3300
136k
                atomic_load(&f->refp[i].progress[1]) == FRAME_ERROR)
3301
0
            {
3302
0
                retval = DAV1D_ERR(EINVAL);
3303
0
                atomic_store(&f->task_thread.error, 1);
3304
0
                atomic_store(&f->sr_cur.progress[1], FRAME_ERROR);
3305
0
            }
3306
136k
            dav1d_thread_picture_unref(&f->refp[i]);
3307
136k
        }
3308
552k
        dav1d_ref_dec(&f->ref_mvs_ref[i]);
3309
552k
    }
3310
3311
78.9k
    dav1d_picture_unref_internal(&f->cur);
3312
78.9k
    dav1d_thread_picture_unref(&f->sr_cur);
3313
78.9k
    dav1d_cdf_thread_unref(&f->in_cdf);
3314
78.9k
    if (f->frame_hdr && f->frame_hdr->refresh_context) {
3315
18.6k
        if (f->out_cdf.progress)
3316
18.6k
            atomic_store(f->out_cdf.progress, retval == 0 ? 1 : TILE_ERROR);
3317
18.6k
        dav1d_cdf_thread_unref(&f->out_cdf);
3318
18.6k
    }
3319
78.9k
    dav1d_ref_dec(&f->cur_segmap_ref);
3320
78.9k
    dav1d_ref_dec(&f->prev_segmap_ref);
3321
78.9k
    dav1d_ref_dec(&f->mvs_ref);
3322
78.9k
    dav1d_ref_dec(&f->seq_hdr_ref);
3323
78.9k
    dav1d_ref_dec(&f->frame_hdr_ref);
3324
3325
111k
    for (int i = 0; i < f->n_tile_data; i++)
3326
32.2k
        dav1d_data_unref_internal(&f->tile[i].data);
3327
78.9k
    f->task_thread.retval = retval;
3328
78.9k
}
3329
3330
0
int dav1d_decode_frame(Dav1dFrameContext *const f) {
3331
0
    assert(f->c->n_fc == 1);
3332
    // if n_tc > 1 (but n_fc == 1), we could run init/exit in the task
3333
    // threads also. Not sure it makes a measurable difference.
3334
0
    int res = dav1d_decode_frame_init(f);
3335
0
    if (!res) res = dav1d_decode_frame_init_cdf(f);
3336
    // wait until all threads have completed
3337
0
    if (!res) {
3338
0
        if (f->c->n_tc > 1) {
3339
0
            res = dav1d_task_create_tile_sbrow(f, 0, 1);
3340
0
            pthread_mutex_lock(&f->task_thread.ttd->lock);
3341
0
            pthread_cond_signal(&f->task_thread.ttd->cond);
3342
0
            if (!res) {
3343
0
                while (!f->task_thread.done[0] ||
3344
0
                       atomic_load(&f->task_thread.task_counter) > 0)
3345
0
                {
3346
0
                    pthread_cond_wait(&f->task_thread.cond,
3347
0
                                      &f->task_thread.ttd->lock);
3348
0
                }
3349
0
            }
3350
0
            pthread_mutex_unlock(&f->task_thread.ttd->lock);
3351
0
            res = f->task_thread.retval;
3352
0
        } else {
3353
0
            res = dav1d_decode_frame_main(f);
3354
0
            if (!res && f->frame_hdr->refresh_context && f->task_thread.update_set) {
3355
0
                dav1d_cdf_thread_update(f->frame_hdr, f->out_cdf.data.cdf,
3356
0
                                        &f->ts[f->frame_hdr->tiling.update].cdf);
3357
0
            }
3358
0
        }
3359
0
    }
3360
0
    dav1d_decode_frame_exit(f, res);
3361
0
    res = f->task_thread.retval;
3362
0
    f->n_tile_data = 0;
3363
0
    return res;
3364
0
}
3365
3366
17.7k
static int get_upscale_x0(const int in_w, const int out_w, const int step) {
3367
17.7k
    const int err = out_w * step - (in_w << 14);
3368
17.7k
    const int x0 = (-((out_w - in_w) << 13) + (out_w >> 1)) / out_w + 128 - (err / 2);
3369
17.7k
    return x0 & 0x3fff;
3370
17.7k
}
3371
3372
32.3k
int dav1d_submit_frame(Dav1dContext *const c) {
3373
32.3k
    Dav1dFrameContext *f;
3374
32.3k
    int res = -1;
3375
3376
    // wait for c->out_delayed[next] and move into c->out if visible
3377
32.3k
    Dav1dThreadPicture *out_delayed;
3378
32.3k
    if (c->n_fc > 1) {
3379
32.3k
        pthread_mutex_lock(&c->task_thread.lock);
3380
32.3k
        const unsigned next = c->frame_thread.next++;
3381
32.3k
        if (c->frame_thread.next == c->n_fc)
3382
3.16k
            c->frame_thread.next = 0;
3383
3384
32.3k
        f = &c->fc[next];
3385
34.6k
        while (f->n_tile_data > 0)
3386
2.33k
            pthread_cond_wait(&f->task_thread.cond,
3387
2.33k
                              &c->task_thread.lock);
3388
32.3k
        out_delayed = &c->frame_thread.out_delayed[next];
3389
32.3k
        if (out_delayed->p.data[0] || atomic_load(&f->task_thread.error)) {
3390
3.93k
            unsigned first = atomic_load(&c->task_thread.first);
3391
3.93k
            if (first + 1U < c->n_fc)
3392
3.93k
                atomic_fetch_add(&c->task_thread.first, 1U);
3393
195
            else
3394
3.93k
                atomic_store(&c->task_thread.first, 0);
3395
3.93k
            atomic_compare_exchange_strong(&c->task_thread.reset_task_cur,
3396
3.93k
                                           &first, UINT_MAX);
3397
3.93k
            if (c->task_thread.cur && c->task_thread.cur < c->n_fc)
3398
1.12k
                c->task_thread.cur--;
3399
3.93k
        }
3400
32.3k
        const int error = f->task_thread.retval;
3401
32.3k
        if (error) {
3402
6
            f->task_thread.retval = 0;
3403
6
            c->cached_error = error;
3404
6
            dav1d_data_props_copy(&c->cached_error_props, &out_delayed->p.m);
3405
6
            dav1d_thread_picture_unref(out_delayed);
3406
32.3k
        } else if (out_delayed->p.data[0]) {
3407
3.92k
            const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
3408
3.92k
                                                           memory_order_relaxed);
3409
3.92k
            if ((out_delayed->visible || c->output_invisible_frames) &&
3410
3.87k
                progress != FRAME_ERROR)
3411
3.87k
            {
3412
3.87k
                dav1d_thread_picture_ref(&c->out, out_delayed);
3413
3.87k
                c->event_flags |= dav1d_picture_get_event_flags(out_delayed);
3414
3.87k
            }
3415
3.92k
            dav1d_thread_picture_unref(out_delayed);
3416
3.92k
        }
3417
32.3k
    } else {
3418
0
        f = c->fc;
3419
0
    }
3420
3421
32.3k
    f->seq_hdr = c->seq_hdr;
3422
32.3k
    f->seq_hdr_ref = c->seq_hdr_ref;
3423
32.3k
    dav1d_ref_inc(f->seq_hdr_ref);
3424
32.3k
    f->frame_hdr = c->frame_hdr;
3425
32.3k
    f->frame_hdr_ref = c->frame_hdr_ref;
3426
32.3k
    c->frame_hdr = NULL;
3427
32.3k
    c->frame_hdr_ref = NULL;
3428
32.3k
    f->dsp = &c->dsp[f->seq_hdr->hbd];
3429
3430
32.3k
    const int bpc = 8 + 2 * f->seq_hdr->hbd;
3431
3432
32.3k
    if (!f->dsp->ipred.intra_pred[DC_PRED]) {
3433
8.20k
        Dav1dDSPContext *const dsp = &c->dsp[f->seq_hdr->hbd];
3434
3435
8.20k
        switch (bpc) {
3436
0
#define assign_bitdepth_case(bd) \
3437
8.20k
            dav1d_cdef_dsp_init_##bd##bpc(&dsp->cdef); \
3438
8.20k
            dav1d_intra_pred_dsp_init_##bd##bpc(&dsp->ipred); \
3439
8.20k
            dav1d_itx_dsp_init_##bd##bpc(&dsp->itx, bpc); \
3440
8.20k
            dav1d_loop_filter_dsp_init_##bd##bpc(&dsp->lf); \
3441
8.20k
            dav1d_loop_restoration_dsp_init_##bd##bpc(&dsp->lr, bpc); \
3442
8.20k
            dav1d_mc_dsp_init_##bd##bpc(&dsp->mc); \
3443
8.20k
            dav1d_film_grain_dsp_init_##bd##bpc(&dsp->fg); \
3444
8.20k
            break
3445
0
#if CONFIG_8BPC
3446
3.55k
        case 8:
3447
3.55k
            assign_bitdepth_case(8);
3448
0
#endif
3449
0
#if CONFIG_16BPC
3450
3.20k
        case 10:
3451
4.64k
        case 12:
3452
4.64k
            assign_bitdepth_case(16);
3453
0
#endif
3454
0
#undef assign_bitdepth_case
3455
0
        default:
3456
0
            dav1d_log(c, "Compiled without support for %d-bit decoding\n",
3457
0
                    8 + 2 * f->seq_hdr->hbd);
3458
0
            res = DAV1D_ERR(ENOPROTOOPT);
3459
0
            goto error;
3460
8.20k
        }
3461
8.20k
    }
3462
3463
32.3k
#define assign_bitdepth_case(bd) \
3464
32.3k
        f->bd_fn.recon_b_inter = dav1d_recon_b_inter_##bd##bpc; \
3465
32.3k
        f->bd_fn.recon_b_intra = dav1d_recon_b_intra_##bd##bpc; \
3466
32.3k
        f->bd_fn.filter_sbrow = dav1d_filter_sbrow_##bd##bpc; \
3467
32.3k
        f->bd_fn.filter_sbrow_deblock_cols = dav1d_filter_sbrow_deblock_cols_##bd##bpc; \
3468
32.3k
        f->bd_fn.filter_sbrow_deblock_rows = dav1d_filter_sbrow_deblock_rows_##bd##bpc; \
3469
32.3k
        f->bd_fn.filter_sbrow_cdef = dav1d_filter_sbrow_cdef_##bd##bpc; \
3470
32.3k
        f->bd_fn.filter_sbrow_resize = dav1d_filter_sbrow_resize_##bd##bpc; \
3471
32.3k
        f->bd_fn.filter_sbrow_lr = dav1d_filter_sbrow_lr_##bd##bpc; \
3472
32.3k
        f->bd_fn.backup_ipred_edge = dav1d_backup_ipred_edge_##bd##bpc; \
3473
32.3k
        f->bd_fn.read_coef_blocks = dav1d_read_coef_blocks_##bd##bpc; \
3474
32.3k
        f->bd_fn.copy_pal_block_y = dav1d_copy_pal_block_y_##bd##bpc; \
3475
32.3k
        f->bd_fn.copy_pal_block_uv = dav1d_copy_pal_block_uv_##bd##bpc; \
3476
32.3k
        f->bd_fn.read_pal_plane = dav1d_read_pal_plane_##bd##bpc; \
3477
32.3k
        f->bd_fn.read_pal_uv = dav1d_read_pal_uv_##bd##bpc
3478
32.3k
    if (!f->seq_hdr->hbd) {
3479
13.2k
#if CONFIG_8BPC
3480
13.2k
        assign_bitdepth_case(8);
3481
13.2k
#endif
3482
19.0k
    } else {
3483
19.0k
#if CONFIG_16BPC
3484
19.0k
        assign_bitdepth_case(16);
3485
19.0k
#endif
3486
19.0k
    }
3487
32.3k
#undef assign_bitdepth_case
3488
3489
32.3k
    int ref_coded_width[7];
3490
32.3k
    if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
3491
19.5k
        if (f->frame_hdr->primary_ref_frame != DAV1D_PRIMARY_REF_NONE) {
3492
17.5k
            const int pri_ref = f->frame_hdr->refidx[f->frame_hdr->primary_ref_frame];
3493
17.5k
            if (!c->refs[pri_ref].p.p.data[0]) {
3494
1
                res = DAV1D_ERR(EINVAL);
3495
1
                goto error;
3496
1
            }
3497
17.5k
        }
3498
156k
        for (int i = 0; i < 7; i++) {
3499
136k
            const int refidx = f->frame_hdr->refidx[i];
3500
136k
            if (!c->refs[refidx].p.p.data[0] ||
3501
136k
                f->frame_hdr->width[0] * 2 < c->refs[refidx].p.p.p.w ||
3502
136k
                f->frame_hdr->height * 2 < c->refs[refidx].p.p.p.h ||
3503
136k
                f->frame_hdr->width[0] > c->refs[refidx].p.p.p.w * 16 ||
3504
136k
                f->frame_hdr->height > c->refs[refidx].p.p.p.h * 16 ||
3505
136k
                f->seq_hdr->layout != c->refs[refidx].p.p.p.layout ||
3506
136k
                bpc != c->refs[refidx].p.p.p.bpc)
3507
73
            {
3508
126
                for (int j = 0; j < i; j++)
3509
53
                    dav1d_thread_picture_unref(&f->refp[j]);
3510
73
                res = DAV1D_ERR(EINVAL);
3511
73
                goto error;
3512
73
            }
3513
136k
            dav1d_thread_picture_ref(&f->refp[i], &c->refs[refidx].p);
3514
136k
            ref_coded_width[i] = c->refs[refidx].p.p.frame_hdr->width[0];
3515
136k
            if (f->frame_hdr->width[0] != c->refs[refidx].p.p.p.w ||
3516
91.5k
                f->frame_hdr->height != c->refs[refidx].p.p.p.h)
3517
48.3k
            {
3518
48.3k
#define scale_fac(ref_sz, this_sz) \
3519
114k
    ((((ref_sz) << 14) + ((this_sz) >> 1)) / (this_sz))
3520
48.3k
                f->svc[i][0].scale = scale_fac(c->refs[refidx].p.p.p.w,
3521
48.3k
                                               f->frame_hdr->width[0]);
3522
48.3k
                f->svc[i][1].scale = scale_fac(c->refs[refidx].p.p.p.h,
3523
48.3k
                                               f->frame_hdr->height);
3524
48.3k
                f->svc[i][0].step = (f->svc[i][0].scale + 8) >> 4;
3525
48.3k
                f->svc[i][1].step = (f->svc[i][1].scale + 8) >> 4;
3526
88.2k
            } else {
3527
88.2k
                f->svc[i][0].scale = f->svc[i][1].scale = 0;
3528
88.2k
            }
3529
136k
            f->gmv_warp_allowed[i] = f->frame_hdr->gmv[i].type > DAV1D_WM_TYPE_TRANSLATION &&
3530
32.0k
                                     !f->frame_hdr->force_integer_mv &&
3531
30.6k
                                     !dav1d_get_shear_params(&f->frame_hdr->gmv[i]) &&
3532
30.2k
                                     !f->svc[i][0].scale;
3533
136k
        }
3534
19.5k
    }
3535
3536
    // setup entropy
3537
32.2k
    if (f->frame_hdr->primary_ref_frame == DAV1D_PRIMARY_REF_NONE) {
3538
14.7k
        dav1d_cdf_thread_init_static(&f->in_cdf, f->frame_hdr->quant.yac);
3539
17.5k
    } else {
3540
17.5k
        const int pri_ref = f->frame_hdr->refidx[f->frame_hdr->primary_ref_frame];
3541
17.5k
        dav1d_cdf_thread_ref(&f->in_cdf, &c->cdf[pri_ref]);
3542
17.5k
    }
3543
32.2k
    if (f->frame_hdr->refresh_context) {
3544
13.9k
        res = dav1d_cdf_thread_alloc(c, &f->out_cdf, c->n_fc > 1);
3545
13.9k
        if (res < 0) goto error;
3546
13.9k
    }
3547
3548
    // FIXME qsort so tiles are in order (for frame threading)
3549
32.2k
    if (f->n_tile_data_alloc < c->n_tile_data) {
3550
17.6k
        dav1d_free(f->tile);
3551
17.6k
        assert(c->n_tile_data < INT_MAX / (int)sizeof(*f->tile));
3552
17.6k
        f->tile = dav1d_malloc(ALLOC_TILE, c->n_tile_data * sizeof(*f->tile));
3553
17.6k
        if (!f->tile) {
3554
0
            f->n_tile_data_alloc = f->n_tile_data = 0;
3555
0
            res = DAV1D_ERR(ENOMEM);
3556
0
            goto error;
3557
0
        }
3558
17.6k
        f->n_tile_data_alloc = c->n_tile_data;
3559
17.6k
    }
3560
32.2k
    memcpy(f->tile, c->tile, c->n_tile_data * sizeof(*f->tile));
3561
32.2k
    memset(c->tile, 0, c->n_tile_data * sizeof(*c->tile));
3562
32.2k
    f->n_tile_data = c->n_tile_data;
3563
32.2k
    c->n_tile_data = 0;
3564
3565
    // allocate frame
3566
32.2k
    res = dav1d_thread_picture_alloc(c, f, bpc);
3567
32.2k
    if (res < 0) goto error;
3568
3569
32.2k
    if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
3570
8.86k
        res = dav1d_picture_alloc_copy(c, &f->cur, f->frame_hdr->width[0], &f->sr_cur.p);
3571
8.86k
        if (res < 0) goto error;
3572
23.4k
    } else {
3573
23.4k
        dav1d_picture_ref(&f->cur, &f->sr_cur.p);
3574
23.4k
    }
3575
3576
32.2k
    if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
3577
8.86k
        f->resize_step[0] = scale_fac(f->cur.p.w, f->sr_cur.p.p.w);
3578
8.86k
        const int ss_hor = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
3579
8.86k
        const int in_cw = (f->cur.p.w + ss_hor) >> ss_hor;
3580
8.86k
        const int out_cw = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
3581
8.86k
        f->resize_step[1] = scale_fac(in_cw, out_cw);
3582
8.86k
#undef scale_fac
3583
8.86k
        f->resize_start[0] = get_upscale_x0(f->cur.p.w, f->sr_cur.p.p.w, f->resize_step[0]);
3584
8.86k
        f->resize_start[1] = get_upscale_x0(in_cw, out_cw, f->resize_step[1]);
3585
8.86k
    }
3586
3587
    // move f->cur into output queue
3588
32.2k
    if (c->n_fc == 1) {
3589
0
        if (f->frame_hdr->show_frame || c->output_invisible_frames) {
3590
0
            dav1d_thread_picture_ref(&c->out, &f->sr_cur);
3591
0
            c->event_flags |= dav1d_picture_get_event_flags(&f->sr_cur);
3592
0
        }
3593
32.2k
    } else {
3594
32.2k
        dav1d_thread_picture_ref(out_delayed, &f->sr_cur);
3595
32.2k
    }
3596
3597
32.2k
    f->w4 = (f->frame_hdr->width[0] + 3) >> 2;
3598
32.2k
    f->h4 = (f->frame_hdr->height + 3) >> 2;
3599
32.2k
    f->bw = ((f->frame_hdr->width[0] + 7) >> 3) << 1;
3600
32.2k
    f->bh = ((f->frame_hdr->height + 7) >> 3) << 1;
3601
32.2k
    f->sb128w = (f->bw + 31) >> 5;
3602
32.2k
    f->sb128h = (f->bh + 31) >> 5;
3603
32.2k
    f->sb_shift = 4 + f->seq_hdr->sb128;
3604
32.2k
    f->sb_step = 16 << f->seq_hdr->sb128;
3605
32.2k
    f->sbh = (f->bh + f->sb_step - 1) >> f->sb_shift;
3606
32.2k
    f->b4_stride = (f->bw + 31) & ~31;
3607
32.2k
    f->bitdepth_max = (1 << f->cur.p.bpc) - 1;
3608
32.2k
    atomic_init(&f->task_thread.error, 0);
3609
32.2k
    const int uses_2pass = c->n_fc > 1;
3610
32.2k
    const int cols = f->frame_hdr->tiling.cols;
3611
32.2k
    const int rows = f->frame_hdr->tiling.rows;
3612
32.2k
    atomic_store(&f->task_thread.task_counter,
3613
32.2k
                 (cols * rows + f->sbh) << uses_2pass);
3614
3615
    // ref_mvs
3616
32.2k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc) {
3617
21.3k
        f->mvs_ref = dav1d_ref_create_using_pool(c->refmvs_pool,
3618
21.3k
            sizeof(*f->mvs) * f->sb128h * 16 * (f->b4_stride >> 1));
3619
21.3k
        if (!f->mvs_ref) {
3620
0
            res = DAV1D_ERR(ENOMEM);
3621
0
            goto error;
3622
0
        }
3623
21.3k
        f->mvs = f->mvs_ref->data;
3624
21.3k
        if (!f->frame_hdr->allow_intrabc) {
3625
155k
            for (int i = 0; i < 7; i++)
3626
136k
                f->refpoc[i] = f->refp[i].p.frame_hdr->frame_offset;
3627
19.4k
        } else {
3628
1.85k
            memset(f->refpoc, 0, sizeof(f->refpoc));
3629
1.85k
        }
3630
21.3k
        if (f->frame_hdr->use_ref_frame_mvs) {
3631
24.5k
            for (int i = 0; i < 7; i++) {
3632
21.5k
                const int refidx = f->frame_hdr->refidx[i];
3633
21.5k
                const int ref_w = ((ref_coded_width[i] + 7) >> 3) << 1;
3634
21.5k
                const int ref_h = ((f->refp[i].p.p.h + 7) >> 3) << 1;
3635
21.5k
                if (c->refs[refidx].refmvs != NULL &&
3636
9.93k
                    ref_w == f->bw && ref_h == f->bh)
3637
9.76k
                {
3638
9.76k
                    f->ref_mvs_ref[i] = c->refs[refidx].refmvs;
3639
9.76k
                    dav1d_ref_inc(f->ref_mvs_ref[i]);
3640
9.76k
                    f->ref_mvs[i] = c->refs[refidx].refmvs->data;
3641
11.7k
                } else {
3642
11.7k
                    f->ref_mvs[i] = NULL;
3643
11.7k
                    f->ref_mvs_ref[i] = NULL;
3644
11.7k
                }
3645
21.5k
                memcpy(f->refrefpoc[i], c->refs[refidx].refpoc,
3646
21.5k
                       sizeof(*f->refrefpoc));
3647
21.5k
            }
3648
18.2k
        } else {
3649
18.2k
            memset(f->ref_mvs_ref, 0, sizeof(f->ref_mvs_ref));
3650
18.2k
        }
3651
21.3k
    } else {
3652
10.9k
        f->mvs_ref = NULL;
3653
10.9k
        memset(f->ref_mvs_ref, 0, sizeof(f->ref_mvs_ref));
3654
10.9k
    }
3655
3656
    // segmap
3657
32.2k
    if (f->frame_hdr->segmentation.enabled) {
3658
        // By default, the previous segmentation map is not initialised.
3659
12.4k
        f->prev_segmap_ref = NULL;
3660
12.4k
        f->prev_segmap = NULL;
3661
3662
        // We might need a previous frame's segmentation map. This
3663
        // happens if there is either no update or a temporal update.
3664
12.4k
        if (f->frame_hdr->segmentation.temporal || !f->frame_hdr->segmentation.update_map) {
3665
4.84k
            const int pri_ref = f->frame_hdr->primary_ref_frame;
3666
4.84k
            assert(pri_ref != DAV1D_PRIMARY_REF_NONE);
3667
4.84k
            const int ref_w = ((ref_coded_width[pri_ref] + 7) >> 3) << 1;
3668
4.84k
            const int ref_h = ((f->refp[pri_ref].p.p.h + 7) >> 3) << 1;
3669
4.84k
            if (ref_w == f->bw && ref_h == f->bh) {
3670
3.61k
                f->prev_segmap_ref = c->refs[f->frame_hdr->refidx[pri_ref]].segmap;
3671
3.61k
                if (f->prev_segmap_ref) {
3672
2.37k
                    dav1d_ref_inc(f->prev_segmap_ref);
3673
2.37k
                    f->prev_segmap = f->prev_segmap_ref->data;
3674
2.37k
                }
3675
3.61k
            }
3676
4.84k
        }
3677
3678
12.4k
        if (f->frame_hdr->segmentation.update_map) {
3679
            // We're updating an existing map, but need somewhere to
3680
            // put the new values. Allocate them here (the data
3681
            // actually gets set elsewhere)
3682
7.93k
            f->cur_segmap_ref = dav1d_ref_create_using_pool(c->segmap_pool,
3683
7.93k
                sizeof(*f->cur_segmap) * f->b4_stride * 32 * f->sb128h);
3684
7.93k
            if (!f->cur_segmap_ref) {
3685
0
                dav1d_ref_dec(&f->prev_segmap_ref);
3686
0
                res = DAV1D_ERR(ENOMEM);
3687
0
                goto error;
3688
0
            }
3689
7.93k
            f->cur_segmap = f->cur_segmap_ref->data;
3690
7.93k
        } else if (f->prev_segmap_ref) {
3691
            // We're not updating an existing map, and we have a valid
3692
            // reference. Use that.
3693
2.26k
            f->cur_segmap_ref = f->prev_segmap_ref;
3694
2.26k
            dav1d_ref_inc(f->cur_segmap_ref);
3695
2.26k
            f->cur_segmap = f->prev_segmap_ref->data;
3696
2.27k
        } else {
3697
            // We need to make a new map. Allocate one here and zero it out.
3698
2.27k
            const size_t segmap_size = sizeof(*f->cur_segmap) * f->b4_stride * 32 * f->sb128h;
3699
2.27k
            f->cur_segmap_ref = dav1d_ref_create_using_pool(c->segmap_pool, segmap_size);
3700
2.27k
            if (!f->cur_segmap_ref) {
3701
0
                res = DAV1D_ERR(ENOMEM);
3702
0
                goto error;
3703
0
            }
3704
2.27k
            f->cur_segmap = f->cur_segmap_ref->data;
3705
2.27k
            memset(f->cur_segmap, 0, segmap_size);
3706
2.27k
        }
3707
19.8k
    } else {
3708
19.8k
        f->cur_segmap = NULL;
3709
19.8k
        f->cur_segmap_ref = NULL;
3710
19.8k
        f->prev_segmap_ref = NULL;
3711
19.8k
    }
3712
3713
    // update references etc.
3714
32.2k
    const unsigned refresh_frame_flags = f->frame_hdr->refresh_frame_flags;
3715
290k
    for (int i = 0; i < 8; i++) {
3716
258k
        if (refresh_frame_flags & (1 << i)) {
3717
149k
            if (c->refs[i].p.p.frame_hdr)
3718
91.1k
                dav1d_thread_picture_unref(&c->refs[i].p);
3719
149k
            dav1d_thread_picture_ref(&c->refs[i].p, &f->sr_cur);
3720
3721
149k
            dav1d_cdf_thread_unref(&c->cdf[i]);
3722
149k
            if (f->frame_hdr->refresh_context) {
3723
41.1k
                dav1d_cdf_thread_ref(&c->cdf[i], &f->out_cdf);
3724
108k
            } else {
3725
108k
                dav1d_cdf_thread_ref(&c->cdf[i], &f->in_cdf);
3726
108k
            }
3727
3728
149k
            dav1d_ref_dec(&c->refs[i].segmap);
3729
149k
            c->refs[i].segmap = f->cur_segmap_ref;
3730
149k
            if (f->cur_segmap_ref)
3731
61.3k
                dav1d_ref_inc(f->cur_segmap_ref);
3732
149k
            dav1d_ref_dec(&c->refs[i].refmvs);
3733
149k
            if (!f->frame_hdr->allow_intrabc) {
3734
136k
                c->refs[i].refmvs = f->mvs_ref;
3735
136k
                if (f->mvs_ref)
3736
57.2k
                    dav1d_ref_inc(f->mvs_ref);
3737
136k
            }
3738
149k
            memcpy(c->refs[i].refpoc, f->refpoc, sizeof(f->refpoc));
3739
149k
        }
3740
258k
    }
3741
3742
32.2k
    if (c->n_fc == 1) {
3743
0
        if ((res = dav1d_decode_frame(f)) < 0) {
3744
0
            dav1d_thread_picture_unref(&c->out);
3745
0
            for (int i = 0; i < 8; i++) {
3746
0
                if (refresh_frame_flags & (1 << i)) {
3747
0
                    if (c->refs[i].p.p.frame_hdr)
3748
0
                        dav1d_thread_picture_unref(&c->refs[i].p);
3749
0
                    dav1d_cdf_thread_unref(&c->cdf[i]);
3750
0
                    dav1d_ref_dec(&c->refs[i].segmap);
3751
0
                    dav1d_ref_dec(&c->refs[i].refmvs);
3752
0
                }
3753
0
            }
3754
0
            goto error;
3755
0
        }
3756
32.2k
    } else {
3757
32.2k
        dav1d_task_frame_init(f);
3758
32.2k
        pthread_mutex_unlock(&c->task_thread.lock);
3759
32.2k
    }
3760
3761
32.2k
    return 0;
3762
74
error:
3763
74
    atomic_init(&f->task_thread.error, 1);
3764
74
    dav1d_cdf_thread_unref(&f->in_cdf);
3765
74
    if (f->frame_hdr->refresh_context)
3766
42
        dav1d_cdf_thread_unref(&f->out_cdf);
3767
592
    for (int i = 0; i < 7; i++) {
3768
518
        if (f->refp[i].p.frame_hdr)
3769
0
            dav1d_thread_picture_unref(&f->refp[i]);
3770
518
        dav1d_ref_dec(&f->ref_mvs_ref[i]);
3771
518
    }
3772
74
    if (c->n_fc == 1)
3773
0
        dav1d_thread_picture_unref(&c->out);
3774
74
    else
3775
74
        dav1d_thread_picture_unref(out_delayed);
3776
74
    dav1d_picture_unref_internal(&f->cur);
3777
74
    dav1d_thread_picture_unref(&f->sr_cur);
3778
74
    dav1d_ref_dec(&f->mvs_ref);
3779
74
    dav1d_ref_dec(&f->seq_hdr_ref);
3780
74
    dav1d_ref_dec(&f->frame_hdr_ref);
3781
74
    dav1d_data_props_copy(&c->cached_error_props, &c->in.m);
3782
3783
74
    for (int i = 0; i < f->n_tile_data; i++)
3784
0
        dav1d_data_unref_internal(&f->tile[i].data);
3785
74
    f->n_tile_data = 0;
3786
3787
74
    if (c->n_fc > 1)
3788
74
        pthread_mutex_unlock(&c->task_thread.lock);
3789
3790
74
    return res;
3791
32.2k
}