Coverage Report

Created: 2026-10-28 06:18

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.8k
{
58
191k
    for (int i = 0; i < (frame_hdr->segmentation.enabled ? 8 : 1); i++) {
59
152k
        const int yac = frame_hdr->segmentation.enabled ?
60
129k
            iclip_u8(qidx + frame_hdr->segmentation.seg_data.d[i].delta_q) : qidx;
61
152k
        const int ydc = iclip_u8(yac + frame_hdr->quant.ydc_delta);
62
152k
        const int uac = iclip_u8(yac + frame_hdr->quant.uac_delta);
63
152k
        const int udc = iclip_u8(yac + frame_hdr->quant.udc_delta);
64
152k
        const int vac = iclip_u8(yac + frame_hdr->quant.vac_delta);
65
152k
        const int vdc = iclip_u8(yac + frame_hdr->quant.vdc_delta);
66
67
152k
        dq[i][0][0] = dav1d_dq_tbl[seq_hdr->hbd][ydc][0];
68
152k
        dq[i][0][1] = dav1d_dq_tbl[seq_hdr->hbd][yac][1];
69
152k
        dq[i][1][0] = dav1d_dq_tbl[seq_hdr->hbd][udc][0];
70
152k
        dq[i][1][1] = dav1d_dq_tbl[seq_hdr->hbd][uac][1];
71
152k
        dq[i][2][0] = dav1d_dq_tbl[seq_hdr->hbd][vdc][0];
72
152k
        dq[i][2][1] = dav1d_dq_tbl[seq_hdr->hbd][vac][1];
73
152k
    }
74
38.8k
}
75
76
static int read_mv_component_diff(MsacContext *const msac,
77
                                  CdfMvComponent *const mv_comp,
78
                                  const int mv_prec)
79
610k
{
80
610k
    const int sign = dav1d_msac_decode_bool_adapt(msac, mv_comp->sign);
81
610k
    const int cl = dav1d_msac_decode_symbol_adapt16(msac, mv_comp->classes, 10);
82
610k
    int up, fp = 3, hp = 1;
83
84
610k
    if (!cl) {
85
421k
        up = dav1d_msac_decode_bool_adapt(msac, mv_comp->class0);
86
421k
        if (mv_prec >= 0) {  // !force_integer_mv
87
65.1k
            fp = dav1d_msac_decode_symbol_adapt4(msac, mv_comp->class0_fp[up], 3);
88
65.1k
            if (mv_prec > 0) // allow_high_precision_mv
89
21.0k
                hp = dav1d_msac_decode_bool_adapt(msac, mv_comp->class0_hp);
90
65.1k
        }
91
421k
    } else {
92
189k
        up = 1 << cl;
93
1.58M
        for (int n = 0; n < cl; n++)
94
1.39M
            up |= dav1d_msac_decode_bool_adapt(msac, mv_comp->classN[n]) << n;
95
189k
        if (mv_prec >= 0) {  // !force_integer_mv
96
17.8k
            fp = dav1d_msac_decode_symbol_adapt4(msac, mv_comp->classN_fp, 3);
97
17.8k
            if (mv_prec > 0) // allow_high_precision_mv
98
4.96k
                hp = dav1d_msac_decode_bool_adapt(msac, mv_comp->classN_hp);
99
17.8k
        }
100
189k
    }
101
102
610k
    const int diff = ((up << 3) | (fp << 1) | hp) + 1;
103
104
610k
    return sign ? -diff : diff;
105
610k
}
106
107
static void read_mv_residual(Dav1dTileState *const ts, mv *const ref_mv,
108
                             const int mv_prec)
109
457k
{
110
457k
    MsacContext *const msac = &ts->msac;
111
457k
    const enum MVJoint mv_joint =
112
457k
        dav1d_msac_decode_symbol_adapt4(msac, ts->cdf.mv.joint, N_MV_JOINTS - 1);
113
457k
    if (mv_joint & MV_JOINT_V)
114
306k
        ref_mv->y += read_mv_component_diff(msac, &ts->cdf.mv.comp[0], mv_prec);
115
457k
    if (mv_joint & MV_JOINT_H)
116
304k
        ref_mv->x += read_mv_component_diff(msac, &ts->cdf.mv.comp[1], mv_prec);
117
457k
}
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
207k
{
124
207k
    const Dav1dFrameContext *const f = t->f;
125
207k
    const int bx4 = t->bx & 31, by4 = t->by & 31;
126
207k
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];
127
207k
    const int txw = t_dim->lw, txh = t_dim->lh;
128
207k
    int is_split;
129
130
207k
    if (depth < 2 && from > (int) TX_4X4) {
131
174k
        const int cat = 2 * (TX_64X64 - t_dim->max) - depth;
132
174k
        const int a = t->a->tx[bx4] < txw;
133
174k
        const int l = t->l.tx[by4] < txh;
134
135
174k
        is_split = dav1d_msac_decode_bool_adapt(&t->ts->msac,
136
174k
                       t->ts->cdf.m.txpart[cat][a + l]);
137
174k
        if (is_split)
138
51.2k
            masks[depth] |= 1 << (y_off * 4 + x_off);
139
174k
    } else {
140
32.8k
        is_split = 0;
141
32.8k
    }
142
143
207k
    if (is_split && t_dim->max > TX_8X8) {
144
35.8k
        const enum RectTxfmSize sub = t_dim->sub;
145
35.8k
        const TxfmInfo *const sub_t_dim = &dav1d_txfm_dimensions[sub];
146
35.8k
        const int txsw = sub_t_dim->w, txsh = sub_t_dim->h;
147
148
35.8k
        read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 0);
149
35.8k
        t->bx += txsw;
150
35.8k
        if (txw >= txh && t->bx < f->bw)
151
28.0k
            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 1, y_off * 2 + 0);
152
35.8k
        t->bx -= txsw;
153
35.8k
        t->by += txsh;
154
35.8k
        if (txh >= txw && t->by < f->bh) {
155
22.7k
            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 1);
156
22.7k
            t->bx += txsw;
157
22.7k
            if (txw >= txh && t->bx < f->bw)
158
14.9k
                read_tx_tree(t, sub, depth + 1, masks,
159
14.9k
                             x_off * 2 + 1, y_off * 2 + 1);
160
22.7k
            t->bx -= txsw;
161
22.7k
        }
162
35.8k
        t->by -= txsh;
163
171k
    } else {
164
171k
        dav1d_memset_pow2[t_dim->lw](&t->a->tx[bx4], is_split ? TX_4X4 : txw);
165
171k
        dav1d_memset_pow2[t_dim->lh](&t->l.tx[by4], is_split ? TX_4X4 : txh);
166
171k
    }
167
207k
}
168
169
1.44M
static int neg_deinterleave(int diff, int ref, int max) {
170
1.44M
    if (!ref) return diff;
171
1.09M
    if (ref >= (max - 1)) return max - diff - 1;
172
985k
    if (2 * ref < max) {
173
589k
        if (diff <= 2 * ref) {
174
500k
            if (diff & 1)
175
70.7k
                return ref + ((diff + 1) >> 1);
176
429k
            else
177
429k
                return ref - (diff >> 1);
178
500k
        }
179
88.7k
        return diff;
180
589k
    } else {
181
395k
        if (diff <= 2 * (max - ref - 1)) {
182
341k
            if (diff & 1)
183
52.3k
                return ref + ((diff + 1) >> 1);
184
289k
            else
185
289k
                return ref - (diff >> 1);
186
341k
        }
187
54.3k
        return max - (diff + 1);
188
395k
    }
189
985k
}
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
31.8k
{
198
31.8k
    /*const*/ refmvs_block *const *r = &t->rt.r[(t->by & 31) + 5];
199
31.8k
    int count = 0;
200
31.8k
    int have_topleft = have_top && have_left;
201
31.8k
    int have_topright = imax(bw4, bh4) < 32 &&
202
31.6k
                        have_top && t->bx + bw4 < t->ts->tiling.col_end &&
203
21.5k
                        (intra_edge_flags & EDGE_I444_TOP_HAS_RIGHT);
204
205
83.4k
#define bs(rp) dav1d_block_dimensions[(rp)->bs]
206
88.4k
#define matches(rp) ((rp)->ref.ref[0] == ref + 1 && (rp)->ref.ref[1] == -1)
207
208
31.8k
    if (have_top) {
209
25.2k
        const refmvs_block *r2 = &r[-1][t->bx];
210
25.2k
        if (matches(r2)) {
211
14.4k
            masks[0] |= 1;
212
14.4k
            count = 1;
213
14.4k
        }
214
25.2k
        int aw4 = bs(r2)[0];
215
25.2k
        if (aw4 >= bw4) {
216
21.1k
            const int off = t->bx & (aw4 - 1);
217
21.1k
            if (off) have_topleft = 0;
218
21.1k
            if (aw4 - off > bw4) have_topright = 0;
219
21.1k
        } else {
220
4.12k
            unsigned mask = 1 << aw4;
221
9.57k
            for (int x = aw4; x < w4; x += aw4) {
222
5.46k
                r2 += aw4;
223
5.46k
                if (matches(r2)) {
224
2.52k
                    masks[0] |= mask;
225
2.52k
                    if (++count >= 8) return;
226
2.52k
                }
227
5.45k
                aw4 = bs(r2)[0];
228
5.45k
                mask <<= aw4;
229
5.45k
            }
230
4.12k
        }
231
25.2k
    }
232
31.8k
    if (have_left) {
233
27.9k
        /*const*/ refmvs_block *const *r2 = r;
234
27.9k
        if (matches(&r2[0][t->bx - 1])) {
235
16.0k
            masks[1] |= 1;
236
16.0k
            if (++count >= 8) return;
237
16.0k
        }
238
27.9k
        int lh4 = bs(&r2[0][t->bx - 1])[1];
239
27.9k
        if (lh4 >= bh4) {
240
23.3k
            if (t->by & (lh4 - 1)) have_topleft = 0;
241
23.3k
        } else {
242
4.55k
            unsigned mask = 1 << lh4;
243
11.2k
            for (int y = lh4; y < h4; y += lh4) {
244
6.76k
                r2 += lh4;
245
6.76k
                if (matches(&r2[0][t->bx - 1])) {
246
2.86k
                    masks[1] |= mask;
247
2.86k
                    if (++count >= 8) return;
248
2.86k
                }
249
6.74k
                lh4 = bs(&r2[0][t->bx - 1])[1];
250
6.74k
                mask <<= lh4;
251
6.74k
            }
252
4.55k
        }
253
27.9k
    }
254
31.8k
    if (have_topleft && matches(&r[-1][t->bx - 1])) {
255
6.55k
        masks[1] |= 1ULL << 32;
256
6.55k
        if (++count >= 8) return;
257
6.55k
    }
258
31.7k
    if (have_topright && matches(&r[-1][t->bx + bw4])) {
259
3.67k
        masks[0] |= 1ULL << 32;
260
3.67k
    }
261
31.7k
#undef matches
262
31.7k
}
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
3.34k
{
269
3.34k
    int pts[8][2 /* in, out */][2 /* x, y */], np = 0;
270
3.34k
    /*const*/ refmvs_block *const *r = &t->rt.r[(t->by & 31) + 5];
271
272
7.94k
#define add_sample(dx, dy, sx, sy, rp) do { \
273
7.94k
    pts[np][0][0] = 16 * (2 * dx + sx * bs(rp)[0]) - 8; \
274
7.94k
    pts[np][0][1] = 16 * (2 * dy + sy * bs(rp)[1]) - 8; \
275
7.94k
    pts[np][1][0] = pts[np][0][0] + (rp)->mv.mv[0].x; \
276
7.94k
    pts[np][1][1] = pts[np][0][1] + (rp)->mv.mv[0].y; \
277
7.94k
    np++; \
278
7.94k
} while (0)
279
280
    // use masks[] to find the projectable motion vectors in the edges
281
3.34k
    if ((unsigned) masks[0] == 1 && !(masks[1] >> 32)) {
282
972
        const int off = t->bx & (bs(&r[-1][t->bx])[0] - 1);
283
972
        add_sample(-off, 0, 1, -1, &r[-1][t->bx]);
284
4.14k
    } else for (unsigned off = 0, xmask = (uint32_t) masks[0]; np < 8 && xmask;) { // top
285
1.77k
        const int tz = ctz(xmask);
286
1.77k
        off += tz;
287
1.77k
        xmask >>= tz;
288
1.77k
        add_sample(off, 0, 1, -1, &r[-1][t->bx + off]);
289
1.77k
        xmask &= ~1;
290
1.77k
    }
291
3.34k
    if (np < 8 && masks[1] == 1) {
292
1.25k
        const int off = t->by & (bs(&r[0][t->bx - 1])[1] - 1);
293
1.25k
        add_sample(0, -off, -1, 1, &r[-off][t->bx - 1]);
294
3.77k
    } else for (unsigned off = 0, ymask = (uint32_t) masks[1]; np < 8 && ymask;) { // left
295
1.68k
        const int tz = ctz(ymask);
296
1.68k
        off += tz;
297
1.68k
        ymask >>= tz;
298
1.68k
        add_sample(0, off, -1, 1, &r[off][t->bx - 1]);
299
1.68k
        ymask &= ~1;
300
1.68k
    }
301
3.34k
    if (np < 8 && masks[1] >> 32) // top/left
302
1.25k
        add_sample(0, 0, -1, -1, &r[-1][t->bx - 1]);
303
3.34k
    if (np < 8 && masks[0] >> 32) // top/right
304
996
        add_sample(bw4, 0, 1, -1, &r[-1][t->bx + bw4]);
305
3.34k
    assert(np > 0 && np <= 8);
306
3.34k
#undef bs
307
308
    // select according to motion vector difference against a threshold
309
3.34k
    int mvd[8], ret = 0;
310
3.34k
    const int thresh = 4 * iclip(imax(bw4, bh4), 4, 28);
311
11.2k
    for (int i = 0; i < np; i++) {
312
7.94k
        mvd[i] = abs(pts[i][1][0] - pts[i][0][0] - mv.x) +
313
7.94k
                 abs(pts[i][1][1] - pts[i][0][1] - mv.y);
314
7.94k
        if (mvd[i] > thresh)
315
2.57k
            mvd[i] = -1;
316
5.36k
        else
317
5.36k
            ret++;
318
7.94k
    }
319
3.34k
    if (!ret) {
320
636
        ret = 1;
321
3.26k
    } else for (int i = 0, j = np - 1, k = 0; k < np - ret; k++, i++, j--) {
322
1.86k
        while (mvd[i] != -1) i++;
323
1.85k
        while (mvd[j] == -1) j--;
324
1.09k
        assert(i != j);
325
1.09k
        if (i > j) break;
326
        // replace the discarded samples;
327
561
        mvd[i] = mvd[j];
328
561
        memcpy(pts[i], pts[j], sizeof(*pts));
329
561
    }
330
331
3.34k
    if (!dav1d_find_affine_int(pts, ret, bw4, bh4, mv, wmp, t->bx, t->by) &&
332
3.16k
        !dav1d_get_shear_params(wmp))
333
2.90k
    {
334
2.90k
        wmp->type = DAV1D_WM_TYPE_AFFINE;
335
2.90k
    } else
336
433
        wmp->type = DAV1D_WM_TYPE_IDENTITY;
337
3.34k
}
338
339
33.0k
static inline int findoddzero(const uint8_t *buf, int len) {
340
35.4k
    for (int n = 0; n < len; n++)
341
34.2k
        if (!buf[n * 2]) return 1;
342
1.20k
    return 0;
343
33.0k
}
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
4.76M
{
353
4.76M
    if (color_idx < prio_count)
354
4.02M
        return p[color_idx];
355
738k
    unsigned rank = color_idx - prio_count + (mask & 1);
356
738k
    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
738k
    static const uint8_t free_offsets2[] = {
361
738k
        0x00, 0x00, 0x50, 0x15, 0x40, 0x15, 0xa0, 0x0a, 0x00, 0x15, 0x90, 0x0a,
362
738k
        0x80, 0x0a, 0xf0, 0x03, 0x00, 0x14, 0x50, 0x0a, 0x40, 0x0a, 0xe0, 0x03,
363
738k
        0x00, 0x0a, 0xd0, 0x03, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x10, 0x50, 0x09,
364
738k
        0x40, 0x09, 0xa0, 0x03, 0x00, 0x09, 0x90, 0x03, 0x80, 0x03, 0x00, 0x00,
365
738k
        0x00, 0x08, 0x50, 0x03, 0x40, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
366
738k
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x40, 0x05, 0xa0, 0x02,
367
738k
        0x00, 0x05, 0x90, 0x02, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x50, 0x02,
368
738k
        0x40, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369
738k
        0x00, 0x00, 0x50, 0x01, 0x40, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
370
738k
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371
738k
    };
372
738k
    const unsigned byte_idx = 2 * (mask >> 2) + (rank >> 2);
373
738k
    assert(byte_idx < sizeof(free_offsets2));
374
738k
    return rank + ((free_offsets2[byte_idx] >> (2 * (rank & 3))) & 3);
375
738k
}
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
37.9k
{
383
37.9k
    Dav1dTileState *const ts = t->ts;
384
37.9k
    const ptrdiff_t stride = bw4 * 4;
385
37.9k
    assert(pal_idx);
386
37.9k
    uint8_t *const pal_tmp = t->scratch.pal_idx_uv;
387
37.9k
    pal_tmp[0] = dav1d_msac_decode_uniform(&ts->msac, pal_sz);
388
37.9k
    uint16_t (*const color_map_cdf)[8] =
389
37.9k
        ts->cdf.m.color_map[pl][pal_sz - 2];
390
391
37.9k
    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
226k
        for (int i = 1; i < 4 * (w4 + h4) - 1; i++) {
397
217k
            const int first = imin(i, w4 * 4 - 1);
398
217k
            const int last = imax(0, i - h4 * 4 + 1);
399
217k
            int have_top = i > first;
400
217k
            const uint8_t *pal_row = pal_tmp + first + (i - first) * stride;
401
2.16M
            for (int j = first; j >= last; have_top = 1, j--, pal_row += stride - 1) {
402
1.94M
                const int have_left = j > 0;
403
1.94M
                int ctx, p0;
404
1.94M
                if (!have_left) {
405
101k
                    ctx = 0;
406
101k
                    p0 = pal_row[-stride];
407
1.84M
                } else if (!have_top) {
408
116k
                    ctx = 0;
409
116k
                    p0 = pal_row[-1];
410
1.72M
                } else {
411
1.72M
                    const int l = pal_row[-1], tp = pal_row[-stride];
412
1.72M
                    const int tl = pal_row[-(stride + 1)];
413
1.72M
                    const int same_t_l = tp == l;
414
1.72M
                    const int same_t_tl = tp == tl;
415
1.72M
                    ctx = 2 + same_t_l + (same_t_l & same_t_tl);
416
1.72M
                    p0 = same_t_l ? tp : tl;
417
1.72M
                }
418
1.94M
                const int bit = dav1d_msac_decode_bool_adapt(
419
1.94M
                    &ts->msac, color_map_cdf[ctx]);
420
1.94M
                pal_tmp[(i - j) * stride + j] = bit ^ p0;
421
1.94M
            }
422
217k
        }
423
8.89k
        t->c->pal_dsp.pal_idx_finish(pal_idx, pal_tmp, bw4 * 4, bh4 * 4,
424
8.89k
                                     w4 * 4, h4 * 4);
425
8.89k
        return;
426
8.89k
    }
427
428
29.0k
    unsigned (*const symbol_adapt)(MsacContext *, uint16_t *, size_t) =
429
29.0k
        pal_sz <= 4 ? dav1d_msac_decode_symbol_adapt4 : dav1d_msac_decode_symbol_adapt8;
430
431
674k
    for (int i = 1; i < 4 * (w4 + h4) - 1; i++) {
432
        // top/left-to-bottom/right diagonals ("wave-front")
433
645k
        const int first = imin(i, w4 * 4 - 1);
434
645k
        const int last = imax(0, i - h4 * 4 + 1);
435
645k
        int have_top = i > first;
436
645k
        const uint8_t *pal_row = pal_tmp + first + (i - first) * stride;
437
5.41M
        for (int j = first; j >= last; have_top = 1, j--, pal_row += stride - 1) {
438
4.76M
            const int have_left = j > 0;
439
4.76M
            uint8_t p[3];
440
4.76M
            unsigned mask;
441
4.76M
            int ctx, prio_count;
442
4.76M
            if (!have_left) {
443
295k
                ctx = 0; prio_count = 1;
444
295k
                p[0] = pal_row[-stride];
445
295k
                mask = 1u << p[0];
446
4.47M
            } else if (!have_top) {
447
350k
                ctx = 0; prio_count = 1;
448
350k
                p[0] = pal_row[-1];
449
350k
                mask = 1u << p[0];
450
4.12M
            } else {
451
4.12M
                const int l = pal_row[-1], tp = pal_row[-stride];
452
4.12M
                const int tl = pal_row[-(stride + 1)];
453
4.12M
                const int same_t_l = tp == l;
454
4.12M
                const int same_t_tl = tp == tl;
455
4.12M
                const int same_l_tl = l == tl;
456
4.12M
                if (same_t_l & same_t_tl) {
457
1.95M
                    ctx = 4; prio_count = 1;
458
1.95M
                    p[0] = tp; mask = 1u << tp;
459
2.16M
                } else if (same_t_l) {
460
133k
                    ctx = 3; prio_count = 2;
461
133k
                    p[0] = tp; p[1] = tl;
462
133k
                    mask = (1u << tp) | (1u << tl);
463
2.02M
                } else if (same_t_tl | same_l_tl) {
464
1.61M
                    ctx = 2; prio_count = 2;
465
1.61M
                    p[0] = tl; p[1] = same_t_tl ? l : tp;
466
1.61M
                    mask = (1u << tl) | (1u << p[1]);
467
1.61M
                } else {
468
417k
                    ctx = 1; prio_count = 3;
469
417k
                    p[0] = imin(tp, l); p[1] = imax(tp, l); p[2] = tl;
470
417k
                    mask = (1u << tp) | (1u << l) | (1u << tl);
471
417k
                }
472
4.12M
            }
473
4.76M
            const int color_idx = symbol_adapt(&ts->msac, color_map_cdf[ctx], pal_sz - 1);
474
4.76M
            pal_tmp[(i - j) * stride + j] =
475
4.76M
                resolve_pal_color(color_idx, p, prio_count, mask);
476
4.76M
        }
477
645k
    }
478
479
29.0k
    t->c->pal_dsp.pal_idx_finish(pal_idx, pal_tmp, bw4 * 4, bh4 * 4,
480
29.0k
                                 w4 * 4, h4 * 4);
481
29.0k
}
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
585k
{
487
585k
    const Dav1dFrameContext *const f = t->f;
488
585k
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
489
585k
    const int bw4 = b_dim[0], bh4 = b_dim[1];
490
491
    // var-tx tree coding
492
585k
    uint16_t tx_split[2] = { 0 };
493
585k
    b->max_ytx = dav1d_max_txfm_size_for_bs[bs][0];
494
585k
    if (!b->skip && (f->frame_hdr->segmentation.lossless[b->seg_id] ||
495
392k
                     b->max_ytx == TX_4X4))
496
32.4k
    {
497
32.4k
        b->max_ytx = b->uvtx = TX_4X4;
498
32.4k
        if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE) {
499
8.13k
            dav1d_memset_pow2[b_dim[2]](&t->a->tx[bx4], TX_4X4);
500
8.13k
            dav1d_memset_pow2[b_dim[3]](&t->l.tx[by4], TX_4X4);
501
8.13k
        }
502
553k
    } else if (f->frame_hdr->txfm_mode != DAV1D_TX_SWITCHABLE || b->skip) {
503
450k
        if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE) {
504
53.8k
            dav1d_memset_pow2[b_dim[2]](&t->a->tx[bx4], b_dim[2 + 0]);
505
53.8k
            dav1d_memset_pow2[b_dim[3]](&t->l.tx[by4], b_dim[2 + 1]);
506
53.8k
        }
507
450k
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
508
450k
    } else {
509
102k
        assert(bw4 <= 16 || bh4 <= 16 || b->max_ytx == TX_64X64);
510
102k
        int y, x, y_off, x_off;
511
102k
        const TxfmInfo *const ytx = &dav1d_txfm_dimensions[b->max_ytx];
512
205k
        for (y = 0, y_off = 0; y < bh4; y += ytx->h, y_off++) {
513
208k
            for (x = 0, x_off = 0; x < bw4; x += ytx->w, x_off++) {
514
105k
                read_tx_tree(t, b->max_ytx, 0, tx_split, x_off, y_off);
515
                // contexts are updated inside read_tx_tree()
516
105k
                t->bx += ytx->w;
517
105k
            }
518
103k
            t->bx -= x;
519
103k
            t->by += ytx->h;
520
103k
        }
521
102k
        t->by -= y;
522
102k
        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
102k
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
526
102k
    }
527
585k
    assert(!(tx_split[0] & ~0x33));
528
585k
    b->tx_split0 = (uint8_t)tx_split[0];
529
585k
    b->tx_split1 = tx_split[1];
530
585k
}
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
11.5k
{
538
11.5k
    assert(f->frame_hdr->primary_ref_frame != DAV1D_PRIMARY_REF_NONE);
539
540
11.5k
    unsigned seg_id = 8;
541
11.5k
    ref_seg_map += by * stride + bx;
542
101k
    do {
543
1.66M
        for (int x = 0; x < w4; x++)
544
1.56M
            seg_id = imin(seg_id, ref_seg_map[x]);
545
101k
        ref_seg_map += stride;
546
101k
    } while (--h4 > 0 && seg_id);
547
11.5k
    assert(seg_id < 8);
548
549
11.5k
    return seg_id;
550
11.5k
}
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
148k
{
558
148k
    const enum InterPredMode mode = b->inter_mode;
559
148k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
560
148k
        .ref.ref = { b->ref[0] + 1, b->interintra_type ? 0 : -1 },
561
148k
        .mv.mv[0] = b->mv[0],
562
148k
        .bs = bs,
563
148k
        .mf = (mode == GLOBALMV && imin(bw4, bh4) >= 2) | ((mode == NEWMV) * 2),
564
148k
    };
565
148k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
566
148k
}
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
390k
{
574
390k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
575
390k
        .ref.ref = { 0, -1 },
576
390k
        .mv.mv[0] = b->mv[0],
577
390k
        .bs = bs,
578
390k
        .mf = 0,
579
390k
    };
580
390k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
581
390k
}
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
46.8k
{
589
46.8k
    assert(bw4 >= 2 && bh4 >= 2);
590
46.8k
    const enum CompInterPredMode mode = b->inter_mode;
591
46.8k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
592
46.8k
        .ref.ref = { b->ref[0] + 1, b->ref[1] + 1 },
593
46.8k
        .mv.mv = { b->mv[0], b->mv[1] },
594
46.8k
        .bs = bs,
595
46.8k
        .mf = (mode == GLOBALMV_GLOBALMV) | !!((1 << mode) & (0xbc)) * 2,
596
46.8k
    };
597
46.8k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
598
46.8k
}
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
822k
{
605
822k
    const refmvs_block ALIGN(tmpl, 16) = (refmvs_block) {
606
822k
        .ref.ref = { 0, -1 },
607
822k
        .mv.mv[0].n = INVALID_MV,
608
822k
        .bs = bs,
609
822k
        .mf = 0,
610
822k
    };
611
822k
    c->refmvs_dsp.splat_mv(&t->rt.r[(t->by & 31) + 5], &tmpl, t->bx, bw4, bh4);
612
822k
}
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
334k
{
618
334k
    const int v_mul = 4 >> ss_ver;
619
334k
    if (!smp->scale) {
620
156k
        const int my = mvy >> (3 + ss_ver), dy = mvy & (15 >> !ss_ver);
621
156k
        *dst = imax(*dst, (by4 + bh4) * v_mul + my + 4 * !!dy);
622
177k
    } else {
623
177k
        int y = (by4 * v_mul << 4) + mvy * (1 << !ss_ver);
624
177k
        const int64_t tmp = (int64_t)(y) * smp->scale + (smp->scale - 0x4000) * 8;
625
177k
        y = apply_sign64((int)((llabs(tmp) + 128) >> 8), tmp) + 32;
626
177k
        const int bottom = ((y + (bh4 * v_mul - 1) * smp->step) >> 10) + 1 + 4;
627
177k
        *dst = imax(*dst, bottom);
628
177k
    }
629
334k
}
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
12.7k
{
636
12.7k
    const int h_mul = 4 >> ss_hor, v_mul = 4 >> ss_ver;
637
12.7k
    assert(!((b_dim[0] * h_mul) & 7) && !((b_dim[1] * v_mul) & 7));
638
12.7k
    const int32_t *const mat = wmp->matrix;
639
12.7k
    const int y = b_dim[1] * v_mul - 8; // lowest y
640
641
12.7k
    const int src_y = t->by * 4 + ((y + 4) << ss_ver);
642
12.7k
    const int64_t mat5_y = (int64_t) mat[5] * src_y + mat[1];
643
    // check left- and right-most blocks
644
34.0k
    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
21.3k
        const int src_x = t->bx * 4 + ((x + 4) << ss_hor);
648
21.3k
        const int64_t mvy = ((int64_t) mat[4] * src_x + mat5_y) >> ss_ver;
649
21.3k
        const int dy = (int) (mvy >> 16) - 4;
650
21.3k
        *dst = imax(*dst, dy + 4 + 8);
651
21.3k
    }
652
12.7k
}
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
12.5k
{
658
12.5k
    affine_lowest_px(t, dst, b_dim, wmp, 0, 0);
659
12.5k
}
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
957
{
665
957
    const Dav1dFrameContext *const f = t->f;
666
957
    assert(f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400);
667
957
    if (f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I444)
668
746
        affine_lowest_px_luma(t, dst, b_dim, wmp);
669
211
    else
670
211
        affine_lowest_px(t, dst, b_dim, wmp, f->cur.p.layout & DAV1D_PIXEL_LAYOUT_I420, 1);
671
957
}
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
23.4k
{
678
23.4k
    assert(!(t->bx & 1) && !(t->by & 1));
679
23.4k
    const Dav1dFrameContext *const f = t->f;
680
23.4k
    /*const*/ refmvs_block **r = &t->rt.r[(t->by & 31) + 5];
681
23.4k
    const int ss_ver = is_chroma && f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
682
23.4k
    const int ss_hor = is_chroma && f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
683
23.4k
    const int h_mul = 4 >> ss_hor, v_mul = 4 >> ss_ver;
684
685
23.4k
    if (t->by > t->ts->tiling.row_start &&
686
18.8k
        (!is_chroma || b_dim[0] * h_mul + b_dim[1] * v_mul >= 16))
687
17.1k
    {
688
36.3k
        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
19.1k
            const refmvs_block *const a_r = &r[-1][t->bx + x + 1];
691
19.1k
            const uint8_t *const a_b_dim = dav1d_block_dimensions[a_r->bs];
692
693
19.1k
            if (a_r->ref.ref[0] > 0) {
694
18.6k
                const int oh4 = imin(b_dim[1], 16) >> 1;
695
18.6k
                mc_lowest_px(&dst[a_r->ref.ref[0] - 1][is_chroma], t->by,
696
18.6k
                             (oh4 * 3 + 3) >> 2, a_r->mv.mv[0].y, ss_ver,
697
18.6k
                             &f->svc[a_r->ref.ref[0] - 1][1]);
698
18.6k
                i++;
699
18.6k
            }
700
19.1k
            x += imax(a_b_dim[0], 2);
701
19.1k
        }
702
17.1k
    }
703
704
23.4k
    if (t->bx > t->ts->tiling.col_start)
705
41.9k
        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
21.9k
            const refmvs_block *const l_r = &r[y + 1][t->bx - 1];
708
21.9k
            const uint8_t *const l_b_dim = dav1d_block_dimensions[l_r->bs];
709
710
21.9k
            if (l_r->ref.ref[0] > 0) {
711
21.3k
                const int oh4 = iclip(l_b_dim[1], 2, b_dim[1]);
712
21.3k
                mc_lowest_px(&dst[l_r->ref.ref[0] - 1][is_chroma],
713
21.3k
                             t->by + y, oh4, l_r->mv.mv[0].y, ss_ver,
714
21.3k
                             &f->svc[l_r->ref.ref[0] - 1][1]);
715
21.3k
                i++;
716
21.3k
            }
717
21.9k
            y += imax(l_b_dim[1], 2);
718
21.9k
        }
719
23.4k
}
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
5.28M
                    const enum EdgeFlags intra_edge_flags) {
726
5.28M
    Dav1dTileState *const ts = t->ts;
727
5.28M
    const Dav1dFrameContext *const f = t->f;
728
5.28M
    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
5.28M
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
731
5.28M
    const int bx4 = t->bx & 31, by4 = t->by & 31;
732
5.28M
    const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
733
5.28M
    const int ss_hor = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
734
5.28M
    const int cbx4 = bx4 >> ss_hor, cby4 = by4 >> ss_ver;
735
5.28M
    const int bw4 = b_dim[0], bh4 = b_dim[1];
736
5.28M
    const int w4 = imin(bw4, f->bw - t->bx), h4 = imin(bh4, f->bh - t->by);
737
5.28M
    const int cbw4 = (bw4 + ss_hor) >> ss_hor, cbh4 = (bh4 + ss_ver) >> ss_ver;
738
5.28M
    const int have_left = t->bx > ts->tiling.col_start;
739
5.28M
    const int have_top = t->by > ts->tiling.row_start;
740
5.28M
    const int has_chroma = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 &&
741
3.90M
                           (bw4 > ss_hor || t->bx & 1) &&
742
3.60M
                           (bh4 > ss_ver || t->by & 1);
743
744
5.28M
    if (t->frame_thread.pass == 2) {
745
2.12M
        if (b->intra) {
746
1.85M
            f->bd_fn.recon_b_intra(t, bs, intra_edge_flags, b);
747
748
1.85M
            const enum IntraPredMode y_mode_nofilt =
749
1.85M
                b->y_mode == FILTER_PRED ? DC_PRED : b->y_mode;
750
1.85M
#define set_ctx(rep_macro) \
751
3.70M
            rep_macro(edge->mode, off, y_mode_nofilt); \
752
3.70M
            rep_macro(edge->intra, off, 1)
753
1.85M
            BlockContext *edge = t->a;
754
5.55M
            for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
755
3.70M
                case_set(b_dim[2 + i]);
756
3.70M
            }
757
1.85M
#undef set_ctx
758
1.85M
            if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
759
4.61k
                refmvs_block *const r = &t->rt.r[(t->by & 31) + 5 + bh4 - 1][t->bx];
760
31.0k
                for (int x = 0; x < bw4; x++) {
761
26.4k
                    r[x].ref.ref[0] = 0;
762
26.4k
                    r[x].bs = bs;
763
26.4k
                }
764
4.61k
                refmvs_block *const *rr = &t->rt.r[(t->by & 31) + 5];
765
4.61k
                const int bx = t->bx + bw4 - 1;
766
28.6k
                for (int y = 0; y < bh4 - 1; y++) {
767
23.9k
                    refmvs_block *d = &rr[y][bx];
768
23.9k
                    d->ref.ref[0] = 0;
769
23.9k
                    d->bs = bs;
770
23.9k
                }
771
4.61k
            }
772
773
1.85M
            if (has_chroma) {
774
1.15M
                uint8_t uv_mode = b->uv_mode;
775
1.15M
                dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], uv_mode);
776
1.15M
                dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], uv_mode);
777
1.15M
            }
778
1.85M
        } else {
779
276k
            if (IS_INTER_OR_SWITCH(f->frame_hdr) /* not intrabc */ &&
780
64.0k
                b->comp_type == COMP_INTER_NONE && b->motion_mode == MM_WARP)
781
334
            {
782
334
                if (b->matrix[0] == INT16_MIN) {
783
55
                    t->warpmv.type = DAV1D_WM_TYPE_IDENTITY;
784
279
                } else {
785
279
                    t->warpmv.type = DAV1D_WM_TYPE_AFFINE;
786
279
                    t->warpmv.matrix[2] = b->matrix[0] + 0x10000;
787
279
                    t->warpmv.matrix[3] = b->matrix[1];
788
279
                    t->warpmv.matrix[4] = b->matrix[2];
789
279
                    t->warpmv.matrix[5] = b->matrix[3] + 0x10000;
790
279
                    dav1d_set_affine_mv2d(bw4, bh4, b->mv2d, &t->warpmv,
791
279
                                          t->bx, t->by);
792
279
                    dav1d_get_shear_params(&t->warpmv);
793
279
#define signabs(v) v < 0 ? '-' : ' ', abs(v)
794
279
                    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
279
#undef signabs
809
279
                }
810
334
            }
811
276k
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
812
813
276k
            const uint8_t *const filter = dav1d_filter_dir[b->filter2d];
814
276k
            BlockContext *edge = t->a;
815
828k
            for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
816
552k
#define set_ctx(rep_macro) \
817
552k
                rep_macro(edge->filter[0], off, filter[0]); \
818
552k
                rep_macro(edge->filter[1], off, filter[1]); \
819
552k
                rep_macro(edge->intra, off, 0)
820
552k
                case_set(b_dim[2 + i]);
821
552k
#undef set_ctx
822
552k
            }
823
824
276k
            if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
825
64.0k
                refmvs_block *const r = &t->rt.r[(t->by & 31) + 5 + bh4 - 1][t->bx];
826
64.0k
                const int ref1 = b->ref[0] + 1;
827
64.0k
                const union mv mv1 = b->mv[0];
828
433k
                for (int x = 0; x < bw4; x++) {
829
369k
                    r[x].ref.ref[0] = ref1;
830
369k
                    r[x].mv.mv[0] = mv1;
831
369k
                    r[x].bs = bs;
832
369k
                }
833
64.0k
                refmvs_block *const *rr = &t->rt.r[(t->by & 31) + 5];
834
64.0k
                const int bx = t->bx + bw4 - 1;
835
352k
                for (int y = 0; y < bh4 - 1; y++) {
836
288k
                    refmvs_block* d = &rr[y][bx];
837
288k
                    d->ref.ref[0] = ref1;
838
288k
                    d->mv.mv[0] = mv1;
839
288k
                    d->bs = bs;
840
288k
                }
841
64.0k
            }
842
843
276k
            if (has_chroma) {
844
186k
                dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], DC_PRED);
845
186k
                dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], DC_PRED);
846
186k
            }
847
276k
        }
848
2.12M
        return 0;
849
2.12M
    }
850
851
3.16M
    const int cw4 = (w4 + ss_hor) >> ss_hor, ch4 = (h4 + ss_ver) >> ss_ver;
852
853
3.16M
    b->bl = bl;
854
3.16M
    b->bp = bp;
855
3.16M
    b->bs = bs;
856
857
3.16M
    const Dav1dSegmentationData *seg = NULL;
858
859
    // segment_id (if seg_feature for skip/ref/gmv is enabled)
860
3.16M
    int seg_pred = 0;
861
3.16M
    if (f->frame_hdr->segmentation.enabled) {
862
1.57M
        if (!f->frame_hdr->segmentation.update_map) {
863
18.0k
            if (f->prev_segmap) {
864
10.7k
                unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
865
10.7k
                                                       f->prev_segmap,
866
10.7k
                                                       f->b4_stride);
867
10.7k
                if (seg_id >= 8) return -1;
868
10.7k
                b->seg_id = seg_id;
869
10.7k
            } else {
870
7.27k
                b->seg_id = 0;
871
7.27k
            }
872
18.0k
            seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
873
1.56M
        } else if (f->frame_hdr->segmentation.seg_data.preskip) {
874
1.38M
            if (f->frame_hdr->segmentation.temporal &&
875
2.80k
                (seg_pred = dav1d_msac_decode_bool_adapt(&ts->msac,
876
2.80k
                                ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
877
2.80k
                                t->l.seg_pred[by4]])))
878
1.58k
            {
879
                // temporal predicted seg_id
880
1.58k
                if (f->prev_segmap) {
881
701
                    unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx,
882
701
                                                           w4, h4,
883
701
                                                           f->prev_segmap,
884
701
                                                           f->b4_stride);
885
701
                    if (seg_id >= 8) return -1;
886
701
                    b->seg_id = seg_id;
887
888
                } else {
888
888
                    b->seg_id = 0;
889
888
                }
890
1.38M
            } else {
891
1.38M
                int seg_ctx;
892
1.38M
                const unsigned pred_seg_id =
893
1.38M
                    get_cur_frame_segid(t->by, t->bx, have_top, have_left,
894
1.38M
                                        &seg_ctx, f->cur_segmap, f->b4_stride);
895
1.38M
                const unsigned diff = dav1d_msac_decode_symbol_adapt8(&ts->msac,
896
1.38M
                                          ts->cdf.m.seg_id[seg_ctx],
897
1.38M
                                          DAV1D_MAX_SEGMENTS - 1);
898
1.38M
                const unsigned last_active_seg_id =
899
1.38M
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
900
1.38M
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
901
1.38M
                                             last_active_seg_id + 1);
902
1.38M
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
903
1.38M
                if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
904
1.38M
            }
905
906
1.38M
            if (DEBUG_BLOCK_INFO)
907
0
                printf("Post-segid[preskip;%d]: r=%d\n",
908
0
                       b->seg_id, ts->msac.rng);
909
910
1.38M
            seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
911
1.38M
        }
912
1.58M
    } else {
913
1.58M
        b->seg_id = 0;
914
1.58M
    }
915
916
    // skip_mode
917
3.16M
    if ((!seg || (!seg->globalmv && seg->ref == -1 && !seg->skip)) &&
918
1.94M
        f->frame_hdr->skip_mode_enabled && imin(bw4, bh4) > 1)
919
8.49k
    {
920
8.49k
        const int smctx = t->a->skip_mode[bx4] + t->l.skip_mode[by4];
921
8.49k
        b->skip_mode = dav1d_msac_decode_bool_adapt(&ts->msac,
922
8.49k
                           ts->cdf.m.skip_mode[smctx]);
923
8.49k
        if (DEBUG_BLOCK_INFO)
924
0
            printf("Post-skipmode[%d]: r=%d\n", b->skip_mode, ts->msac.rng);
925
3.15M
    } else {
926
3.15M
        b->skip_mode = 0;
927
3.15M
    }
928
929
    // skip
930
3.16M
    if (b->skip_mode || (seg && seg->skip)) {
931
957k
        b->skip = 1;
932
2.20M
    } else {
933
2.20M
        const int sctx = t->a->skip[bx4] + t->l.skip[by4];
934
2.20M
        b->skip = dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.skip[sctx]);
935
2.20M
        if (DEBUG_BLOCK_INFO)
936
0
            printf("Post-skip[%d]: r=%d\n", b->skip, ts->msac.rng);
937
2.20M
    }
938
939
    // segment_id
940
3.16M
    if (f->frame_hdr->segmentation.enabled &&
941
1.57M
        f->frame_hdr->segmentation.update_map &&
942
1.56M
        !f->frame_hdr->segmentation.seg_data.preskip)
943
178k
    {
944
178k
        if (!b->skip && f->frame_hdr->segmentation.temporal &&
945
14.4k
            (seg_pred = dav1d_msac_decode_bool_adapt(&ts->msac,
946
14.4k
                            ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
947
14.4k
                            t->l.seg_pred[by4]])))
948
7.00k
        {
949
            // temporal predicted seg_id
950
7.00k
            if (f->prev_segmap) {
951
126
                unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
952
126
                                                       f->prev_segmap,
953
126
                                                       f->b4_stride);
954
126
                if (seg_id >= 8) return -1;
955
126
                b->seg_id = seg_id;
956
6.88k
            } else {
957
6.88k
                b->seg_id = 0;
958
6.88k
            }
959
171k
        } else {
960
171k
            int seg_ctx;
961
171k
            const unsigned pred_seg_id =
962
171k
                get_cur_frame_segid(t->by, t->bx, have_top, have_left,
963
171k
                                    &seg_ctx, f->cur_segmap, f->b4_stride);
964
171k
            if (b->skip) {
965
104k
                b->seg_id = pred_seg_id;
966
104k
            } else {
967
67.1k
                const unsigned diff = dav1d_msac_decode_symbol_adapt8(&ts->msac,
968
67.1k
                                          ts->cdf.m.seg_id[seg_ctx],
969
67.1k
                                          DAV1D_MAX_SEGMENTS - 1);
970
67.1k
                const unsigned last_active_seg_id =
971
67.1k
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
972
67.1k
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
973
67.1k
                                             last_active_seg_id + 1);
974
67.1k
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
975
67.1k
            }
976
171k
            if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
977
171k
        }
978
979
178k
        seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
980
981
178k
        if (DEBUG_BLOCK_INFO)
982
0
            printf("Post-segid[postskip;%d]: r=%d\n",
983
0
                   b->seg_id, ts->msac.rng);
984
178k
    }
985
986
    // cdef index
987
3.16M
    if (!b->skip) {
988
1.44M
        const int idx = f->seq_hdr->sb128 ? ((t->bx & 16) >> 4) +
989
1.04M
                                           ((t->by & 16) >> 3) : 0;
990
1.44M
        if (t->cur_sb_cdef_idx_ptr[idx] == -1) {
991
268k
            const int v = dav1d_msac_decode_bools(&ts->msac,
992
268k
                              f->frame_hdr->cdef.n_bits);
993
268k
            t->cur_sb_cdef_idx_ptr[idx] = v;
994
268k
            if (bw4 > 16) t->cur_sb_cdef_idx_ptr[idx + 1] = v;
995
268k
            if (bh4 > 16) t->cur_sb_cdef_idx_ptr[idx + 2] = v;
996
268k
            if (bw4 == 32 && bh4 == 32) t->cur_sb_cdef_idx_ptr[idx + 3] = v;
997
998
268k
            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
268k
        }
1002
1.44M
    }
1003
1004
    // delta-q/lf
1005
3.16M
    if (!((t->bx | t->by) & (31 >> !f->seq_hdr->sb128))) {
1006
413k
        const int prev_qidx = ts->last_qidx;
1007
413k
        const int have_delta_q = f->frame_hdr->delta.q.present &&
1008
129k
            (bs != (f->seq_hdr->sb128 ? BS_128x128 : BS_64x64) || !b->skip);
1009
1010
413k
        uint32_t prev_delta_lf = ts->last_delta_lf.u32;
1011
1012
413k
        if (have_delta_q) {
1013
113k
            int delta_q = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1014
113k
                                                          ts->cdf.m.delta_q, 3);
1015
113k
            if (delta_q == 3) {
1016
7.84k
                const int n_bits = 1 + dav1d_msac_decode_bools(&ts->msac, 3);
1017
7.84k
                delta_q = dav1d_msac_decode_bools(&ts->msac, n_bits) +
1018
7.84k
                          1 + (1 << n_bits);
1019
7.84k
            }
1020
113k
            if (delta_q) {
1021
18.7k
                if (dav1d_msac_decode_bool_equi(&ts->msac)) delta_q = -delta_q;
1022
18.7k
                delta_q *= 1 << f->frame_hdr->delta.q.res_log2;
1023
18.7k
            }
1024
113k
            ts->last_qidx = iclip(ts->last_qidx + delta_q, 1, 255);
1025
113k
            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
113k
            if (f->frame_hdr->delta.lf.present) {
1030
41.8k
                const int n_lfs = f->frame_hdr->delta.lf.multi ?
1031
27.0k
                    f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 ? 4 : 2 : 1;
1032
1033
148k
                for (int i = 0; i < n_lfs; i++) {
1034
107k
                    int delta_lf = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1035
107k
                        ts->cdf.m.delta_lf[i + f->frame_hdr->delta.lf.multi], 3);
1036
107k
                    if (delta_lf == 3) {
1037
5.49k
                        const int n_bits = 1 + dav1d_msac_decode_bools(&ts->msac, 3);
1038
5.49k
                        delta_lf = dav1d_msac_decode_bools(&ts->msac, n_bits) +
1039
5.49k
                                   1 + (1 << n_bits);
1040
5.49k
                    }
1041
107k
                    if (delta_lf) {
1042
19.0k
                        if (dav1d_msac_decode_bool_equi(&ts->msac))
1043
10.6k
                            delta_lf = -delta_lf;
1044
19.0k
                        delta_lf *= 1 << f->frame_hdr->delta.lf.res_log2;
1045
19.0k
                    }
1046
107k
                    ts->last_delta_lf.i8[i] =
1047
107k
                        iclip(ts->last_delta_lf.i8[i] + delta_lf, -63, 63);
1048
107k
                    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
107k
                }
1052
41.8k
            }
1053
113k
        }
1054
413k
        if (ts->last_qidx == f->frame_hdr->quant.yac) {
1055
            // assign frame-wide q values to this sb
1056
313k
            ts->dq = f->dq;
1057
313k
        } else if (ts->last_qidx != prev_qidx) {
1058
            // find sb-specific quant parameters
1059
12.0k
            init_quant_tables(f->seq_hdr, f->frame_hdr, ts->last_qidx, ts->dqmem);
1060
12.0k
            ts->dq = ts->dqmem;
1061
12.0k
        }
1062
413k
        if (!ts->last_delta_lf.u32) {
1063
            // assign frame-wide lf values to this sb
1064
369k
            ts->lflvl = f->lf.lvl;
1065
369k
        } else if (ts->last_delta_lf.u32 != prev_delta_lf) {
1066
            // find sb-specific lf lvl parameters
1067
12.2k
            ts->lflvl = ts->lflvlmem;
1068
12.2k
            dav1d_calc_lf_values(ts->lflvlmem, f->frame_hdr, ts->last_delta_lf.i8);
1069
12.2k
        }
1070
413k
    }
1071
1072
3.16M
    if (b->skip_mode) {
1073
669
        b->intra = 0;
1074
3.16M
    } else if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
1075
212k
        if (seg && (seg->ref >= 0 || seg->globalmv)) {
1076
32.4k
            b->intra = !seg->ref;
1077
180k
        } else {
1078
180k
            const int ictx = get_intra_ctx(t->a, &t->l, by4, bx4,
1079
180k
                                           have_top, have_left);
1080
180k
            b->intra = !dav1d_msac_decode_bool_adapt(&ts->msac,
1081
180k
                            ts->cdf.m.intra[ictx]);
1082
180k
            if (DEBUG_BLOCK_INFO)
1083
0
                printf("Post-intra[%d]: r=%d\n", b->intra, ts->msac.rng);
1084
180k
        }
1085
2.94M
    } else if (f->frame_hdr->allow_intrabc) {
1086
1.19M
        b->intra = !dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.intrabc);
1087
1.19M
        if (DEBUG_BLOCK_INFO)
1088
0
            printf("Post-intrabcflag[%d]: r=%d\n", b->intra, ts->msac.rng);
1089
1.75M
    } else {
1090
1.75M
        b->intra = 1;
1091
1.75M
    }
1092
1093
    // intra/inter-specific stuff
1094
3.16M
    if (b->intra) {
1095
2.58M
        uint16_t *const ymode_cdf = IS_INTER_OR_SWITCH(f->frame_hdr) ?
1096
17.6k
            ts->cdf.m.y_mode[dav1d_ymode_size_context[bs]] :
1097
2.58M
            ts->cdf.kfym[dav1d_intra_mode_context[t->a->mode[bx4]]]
1098
2.56M
                        [dav1d_intra_mode_context[t->l.mode[by4]]];
1099
2.58M
        b->y_mode = dav1d_msac_decode_symbol_adapt16(&ts->msac, ymode_cdf,
1100
2.58M
                                                     N_INTRA_PRED_MODES - 1);
1101
2.58M
        if (DEBUG_BLOCK_INFO)
1102
0
            printf("Post-ymode[%d]: r=%d\n", b->y_mode, ts->msac.rng);
1103
1104
        // angle delta
1105
2.58M
        if (b_dim[2] + b_dim[3] >= 2 && b->y_mode >= VERT_PRED &&
1106
1.22M
            b->y_mode <= VERT_LEFT_PRED)
1107
611k
        {
1108
611k
            uint16_t *const acdf = ts->cdf.m.angle_delta[b->y_mode - VERT_PRED];
1109
611k
            const int angle = dav1d_msac_decode_symbol_adapt8(&ts->msac, acdf, 6);
1110
611k
            b->y_angle = angle - 3;
1111
1.97M
        } else {
1112
1.97M
            b->y_angle = 0;
1113
1.97M
        }
1114
1115
2.58M
        if (has_chroma) {
1116
1.61M
            const int cfl_allowed = f->frame_hdr->segmentation.lossless[b->seg_id] ?
1117
1.59M
                cbw4 == 1 && cbh4 == 1 : !!(cfl_allowed_mask & (1 << bs));
1118
1.61M
            uint16_t *const uvmode_cdf = ts->cdf.m.uv_mode[cfl_allowed][b->y_mode];
1119
1.61M
            b->uv_mode = dav1d_msac_decode_symbol_adapt16(&ts->msac, uvmode_cdf,
1120
1.61M
                             N_UV_INTRA_PRED_MODES - 1 - !cfl_allowed);
1121
1.61M
            if (DEBUG_BLOCK_INFO)
1122
0
                printf("Post-uvmode[%d]: r=%d\n", b->uv_mode, ts->msac.rng);
1123
1124
1.61M
            b->uv_angle = 0;
1125
1.61M
            if (b->uv_mode == CFL_PRED) {
1126
328k
#define SIGN(a) (!!(a) + ((a) > 0))
1127
328k
                const int sign = dav1d_msac_decode_symbol_adapt8(&ts->msac,
1128
328k
                                     ts->cdf.m.cfl_sign, 7) + 1;
1129
328k
                const int sign_u = sign * 0x56 >> 8, sign_v = sign - sign_u * 3;
1130
328k
                assert(sign_u == sign / 3);
1131
328k
                if (sign_u) {
1132
308k
                    const int ctx = (sign_u == 2) * 3 + sign_v;
1133
308k
                    b->cfl_alpha[0] = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1134
308k
                                          ts->cdf.m.cfl_alpha[ctx], 15) + 1;
1135
308k
                    if (sign_u == 1) b->cfl_alpha[0] = -b->cfl_alpha[0];
1136
308k
                } else {
1137
20.5k
                    b->cfl_alpha[0] = 0;
1138
20.5k
                }
1139
328k
                if (sign_v) {
1140
224k
                    const int ctx = (sign_v == 2) * 3 + sign_u;
1141
224k
                    b->cfl_alpha[1] = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1142
224k
                                          ts->cdf.m.cfl_alpha[ctx], 15) + 1;
1143
224k
                    if (sign_v == 1) b->cfl_alpha[1] = -b->cfl_alpha[1];
1144
224k
                } else {
1145
104k
                    b->cfl_alpha[1] = 0;
1146
104k
                }
1147
328k
#undef SIGN
1148
328k
                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
1.28M
            } else if (b_dim[2] + b_dim[3] >= 2 && b->uv_mode >= VERT_PRED &&
1152
703k
                       b->uv_mode <= VERT_LEFT_PRED)
1153
361k
            {
1154
361k
                uint16_t *const acdf = ts->cdf.m.angle_delta[b->uv_mode - VERT_PRED];
1155
361k
                const int angle = dav1d_msac_decode_symbol_adapt8(&ts->msac, acdf, 6);
1156
361k
                b->uv_angle = angle - 3;
1157
361k
            }
1158
1.61M
        }
1159
1160
2.58M
        b->pal_sz[0] = b->pal_sz[1] = 0;
1161
2.58M
        if (f->frame_hdr->allow_screen_content_tools &&
1162
836k
            imax(bw4, bh4) <= 16 && bw4 + bh4 >= 4)
1163
657k
        {
1164
657k
            const int sz_ctx = b_dim[2] + b_dim[3] - 2;
1165
657k
            if (b->y_mode == DC_PRED) {
1166
310k
                const int pal_ctx = (t->a->pal_sz[bx4] > 0) + (t->l.pal_sz[by4] > 0);
1167
310k
                const int use_y_pal = dav1d_msac_decode_bool_adapt(&ts->msac,
1168
310k
                                          ts->cdf.m.pal_y[sz_ctx][pal_ctx]);
1169
310k
                if (DEBUG_BLOCK_INFO)
1170
0
                    printf("Post-y_pal[%d]: r=%d\n", use_y_pal, ts->msac.rng);
1171
310k
                if (use_y_pal)
1172
28.9k
                    f->bd_fn.read_pal_plane(t, b, 0, sz_ctx, bx4, by4);
1173
310k
            }
1174
1175
657k
            if (has_chroma && b->uv_mode == DC_PRED) {
1176
161k
                const int pal_ctx = b->pal_sz[0] > 0;
1177
161k
                const int use_uv_pal = dav1d_msac_decode_bool_adapt(&ts->msac,
1178
161k
                                           ts->cdf.m.pal_uv[pal_ctx]);
1179
161k
                if (DEBUG_BLOCK_INFO)
1180
0
                    printf("Post-uv_pal[%d]: r=%d\n", use_uv_pal, ts->msac.rng);
1181
161k
                if (use_uv_pal) // see aomedia bug 2183 for why we use luma coordinates
1182
8.92k
                    f->bd_fn.read_pal_uv(t, b, sz_ctx, bx4, by4);
1183
161k
            }
1184
657k
        }
1185
1186
2.58M
        if (b->y_mode == DC_PRED && !b->pal_sz[0] &&
1187
959k
            imax(b_dim[2], b_dim[3]) <= 3 && f->seq_hdr->filter_intra)
1188
548k
        {
1189
548k
            const int is_filter = dav1d_msac_decode_bool_adapt(&ts->msac,
1190
548k
                                      ts->cdf.m.use_filter_intra[bs]);
1191
548k
            if (is_filter) {
1192
367k
                b->y_mode = FILTER_PRED;
1193
367k
                b->y_angle = dav1d_msac_decode_symbol_adapt8(&ts->msac,
1194
367k
                                 ts->cdf.m.filter_intra, 4);
1195
367k
            }
1196
548k
            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
548k
        }
1200
1201
2.58M
        if (b->pal_sz[0]) {
1202
28.9k
            uint8_t *pal_idx;
1203
28.9k
            if (t->frame_thread.pass) {
1204
28.9k
                const int p = t->frame_thread.pass & 1;
1205
28.9k
                assert(ts->frame_thread[p].pal_idx);
1206
28.9k
                pal_idx = ts->frame_thread[p].pal_idx;
1207
28.9k
                ts->frame_thread[p].pal_idx += bw4 * bh4 * 8;
1208
28.9k
            } else
1209
0
                pal_idx = t->scratch.pal_idx_y;
1210
28.9k
            read_pal_indices(t, pal_idx, b->pal_sz[0], 0, w4, h4, bw4, bh4);
1211
28.9k
            if (DEBUG_BLOCK_INFO)
1212
0
                printf("Post-y-pal-indices: r=%d\n", ts->msac.rng);
1213
28.9k
        }
1214
1215
2.58M
        if (has_chroma && b->pal_sz[1]) {
1216
8.92k
            uint8_t *pal_idx;
1217
8.92k
            if (t->frame_thread.pass) {
1218
8.92k
                const int p = t->frame_thread.pass & 1;
1219
8.92k
                assert(ts->frame_thread[p].pal_idx);
1220
8.92k
                pal_idx = ts->frame_thread[p].pal_idx;
1221
8.92k
                ts->frame_thread[p].pal_idx += cbw4 * cbh4 * 8;
1222
8.92k
            } else
1223
0
                pal_idx = t->scratch.pal_idx_uv;
1224
8.92k
            read_pal_indices(t, pal_idx, b->pal_sz[1], 1, cw4, ch4, cbw4, cbh4);
1225
8.92k
            if (DEBUG_BLOCK_INFO)
1226
0
                printf("Post-uv-pal-indices: r=%d\n", ts->msac.rng);
1227
8.92k
        }
1228
1229
2.58M
        const TxfmInfo *t_dim;
1230
2.58M
        if (f->frame_hdr->segmentation.lossless[b->seg_id]) {
1231
37.2k
            b->tx = b->uvtx = (int) TX_4X4;
1232
37.2k
            t_dim = &dav1d_txfm_dimensions[TX_4X4];
1233
2.54M
        } else {
1234
2.54M
            b->tx = dav1d_max_txfm_size_for_bs[bs][0];
1235
2.54M
            b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
1236
2.54M
            t_dim = &dav1d_txfm_dimensions[b->tx];
1237
2.54M
            if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE && t_dim->max > TX_4X4) {
1238
662k
                const int tctx = get_tx_ctx(t->a, &t->l, t_dim, by4, bx4);
1239
662k
                uint16_t *const tx_cdf = ts->cdf.m.txsz[t_dim->max - 1][tctx];
1240
662k
                int depth = dav1d_msac_decode_symbol_adapt4(&ts->msac, tx_cdf,
1241
662k
                                imin(t_dim->max, 2));
1242
1243
1.12M
                while (depth--) {
1244
460k
                    b->tx = t_dim->sub;
1245
460k
                    t_dim = &dav1d_txfm_dimensions[b->tx];
1246
460k
                }
1247
662k
            }
1248
2.54M
            if (DEBUG_BLOCK_INFO)
1249
0
                printf("Post-tx[%d]: r=%d\n", b->tx, ts->msac.rng);
1250
2.54M
        }
1251
1252
        // reconstruction
1253
2.58M
        if (t->frame_thread.pass == 1) {
1254
2.58M
            f->bd_fn.read_coef_blocks(t, bs, b);
1255
2.58M
        } else {
1256
44
            f->bd_fn.recon_b_intra(t, bs, intra_edge_flags, b);
1257
44
        }
1258
1259
2.58M
        if (f->frame_hdr->loopfilter.level_y[0] ||
1260
1.04M
            f->frame_hdr->loopfilter.level_y[1])
1261
1.65M
        {
1262
1.65M
            dav1d_create_lf_mask_intra(t->lf_mask, f->lf.level, f->b4_stride,
1263
1.65M
                                       (const uint8_t (*)[8][2])
1264
1.65M
                                       &ts->lflvl[b->seg_id][0][0][0],
1265
1.65M
                                       t->bx, t->by, f->w4, f->h4, bs,
1266
1.65M
                                       b->tx, b->uvtx, f->cur.p.layout,
1267
1.65M
                                       &t->a->tx_lpf_y[bx4], &t->l.tx_lpf_y[by4],
1268
1.65M
                                       has_chroma ? &t->a->tx_lpf_uv[cbx4] : NULL,
1269
1.65M
                                       has_chroma ? &t->l.tx_lpf_uv[cby4] : NULL);
1270
1.65M
        }
1271
        // update contexts
1272
2.58M
        const enum IntraPredMode y_mode_nofilt =
1273
2.58M
            b->y_mode == FILTER_PRED ? DC_PRED : b->y_mode;
1274
2.58M
        BlockContext *edge = t->a;
1275
7.75M
        for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
1276
5.17M
            int t_lsz = ((uint8_t *) &t_dim->lw)[i]; // lw then lh
1277
5.17M
#define set_ctx(rep_macro) \
1278
5.17M
            rep_macro(edge->tx_intra, off, t_lsz); \
1279
5.17M
            rep_macro(edge->tx, off, t_lsz); \
1280
5.17M
            rep_macro(edge->mode, off, y_mode_nofilt); \
1281
5.17M
            rep_macro(edge->pal_sz, off, b->pal_sz[0]); \
1282
5.17M
            rep_macro(edge->seg_pred, off, seg_pred); \
1283
5.17M
            rep_macro(edge->skip_mode, off, 0); \
1284
5.17M
            rep_macro(edge->intra, off, 1); \
1285
5.17M
            rep_macro(edge->skip, off, b->skip); \
1286
            /* see aomedia bug 2183 for why we use luma coordinates here */ \
1287
5.17M
            rep_macro(t->pal_sz_uv[i], off, (has_chroma ? b->pal_sz[1] : 0)); \
1288
5.17M
            if (IS_INTER_OR_SWITCH(f->frame_hdr)) { \
1289
35.3k
                rep_macro(edge->comp_type, off, COMP_INTER_NONE); \
1290
35.3k
                rep_macro(edge->ref[0], off, ((uint8_t) -1)); \
1291
35.3k
                rep_macro(edge->ref[1], off, ((uint8_t) -1)); \
1292
35.3k
                rep_macro(edge->filter[0], off, DAV1D_N_SWITCHABLE_FILTERS); \
1293
35.3k
                rep_macro(edge->filter[1], off, DAV1D_N_SWITCHABLE_FILTERS); \
1294
35.3k
            }
1295
5.17M
            case_set(b_dim[2 + i]);
1296
5.17M
#undef set_ctx
1297
5.17M
        }
1298
2.58M
        if (b->pal_sz[0])
1299
28.9k
            f->bd_fn.copy_pal_block_y(t, bx4, by4, bw4, bh4);
1300
2.58M
        if (has_chroma) {
1301
1.61M
            uint8_t uv_mode = b->uv_mode;
1302
1.61M
            dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], uv_mode);
1303
1.61M
            dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], uv_mode);
1304
1.61M
            if (b->pal_sz[1])
1305
8.92k
                f->bd_fn.copy_pal_block_uv(t, bx4, by4, bw4, bh4);
1306
1.61M
        }
1307
2.58M
        if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc)
1308
822k
            splat_intraref(f->c, t, bs, bw4, bh4);
1309
2.58M
    } else if (IS_KEY_OR_INTRA(f->frame_hdr)) {
1310
        // intra block copy
1311
390k
        refmvs_candidate mvstack[8];
1312
390k
        int n_mvs, ctx;
1313
390k
        dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1314
390k
                          (union refmvs_refpair) { .ref = { 0, -1 }},
1315
390k
                          bs, intra_edge_flags, t->by, t->bx);
1316
1317
390k
        if (mvstack[0].mv.mv[0].n)
1318
346k
            b->mv[0] = mvstack[0].mv.mv[0];
1319
43.4k
        else if (mvstack[1].mv.mv[0].n)
1320
0
            b->mv[0] = mvstack[1].mv.mv[0];
1321
43.4k
        else {
1322
43.4k
            if (t->by - (16 << f->seq_hdr->sb128) < ts->tiling.row_start) {
1323
13.6k
                b->mv[0].y = 0;
1324
13.6k
                b->mv[0].x = -(512 << f->seq_hdr->sb128) - 2048;
1325
29.7k
            } else {
1326
29.7k
                b->mv[0].y = -(512 << f->seq_hdr->sb128);
1327
29.7k
                b->mv[0].x = 0;
1328
29.7k
            }
1329
43.4k
        }
1330
1331
390k
        const union mv ref = b->mv[0];
1332
390k
        read_mv_residual(ts, &b->mv[0], -1);
1333
1334
        // clip intrabc motion vector to decoded parts of current tile
1335
390k
        int border_left = ts->tiling.col_start * 4;
1336
390k
        int border_top  = ts->tiling.row_start * 4;
1337
390k
        if (has_chroma) {
1338
297k
            if (bw4 < 2 &&  ss_hor)
1339
22.9k
                border_left += 4;
1340
297k
            if (bh4 < 2 &&  ss_ver)
1341
33.8k
                border_top  += 4;
1342
297k
        }
1343
390k
        int src_left   = t->bx * 4 + (b->mv[0].x >> 3);
1344
390k
        int src_top    = t->by * 4 + (b->mv[0].y >> 3);
1345
390k
        int src_right  = src_left + bw4 * 4;
1346
390k
        int src_bottom = src_top  + bh4 * 4;
1347
390k
        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
390k
        if (src_left < border_left) {
1351
78.3k
            src_right += border_left - src_left;
1352
78.3k
            src_left  += border_left - src_left;
1353
311k
        } else if (src_right > border_right) {
1354
14.7k
            src_left  -= src_right - border_right;
1355
14.7k
            src_right -= src_right - border_right;
1356
14.7k
        }
1357
        // check against top tile boundary and adjust if necessary
1358
390k
        if (src_top < border_top) {
1359
50.3k
            src_bottom += border_top - src_top;
1360
50.3k
            src_top    += border_top - src_top;
1361
50.3k
        }
1362
1363
390k
        const int sbx = (t->bx >> (4 + f->seq_hdr->sb128)) << (6 + f->seq_hdr->sb128);
1364
390k
        const int sby = (t->by >> (4 + f->seq_hdr->sb128)) << (6 + f->seq_hdr->sb128);
1365
390k
        const int sb_size = 1 << (6 + f->seq_hdr->sb128);
1366
        // check for overlap with current superblock
1367
390k
        if (src_bottom > sby && src_right > sbx) {
1368
15.6k
            if (src_top - border_top >= src_bottom - sby) {
1369
                // if possible move src up into the previous suberblock row
1370
14.7k
                src_top    -= src_bottom - sby;
1371
14.7k
                src_bottom -= src_bottom - sby;
1372
14.7k
            } else if (src_left - border_left >= src_right - sbx) {
1373
                // if possible move src left into the previous suberblock
1374
707
                src_left  -= src_right - sbx;
1375
707
                src_right -= src_right - sbx;
1376
707
            }
1377
15.6k
        }
1378
        // move src up if it is below current superblock row
1379
390k
        if (src_bottom > sby + sb_size) {
1380
16.0k
            src_top    -= src_bottom - (sby + sb_size);
1381
16.0k
            src_bottom -= src_bottom - (sby + sb_size);
1382
16.0k
        }
1383
        // error out if mv still overlaps with the current superblock
1384
390k
        if (src_bottom > sby && src_right > sbx)
1385
243
            return -1;
1386
1387
390k
        b->mv[0].x = (src_left - t->bx * 4) * 8;
1388
390k
        b->mv[0].y = (src_top  - t->by * 4) * 8;
1389
1390
390k
        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
390k
        read_vartx_tree(t, b, bs, bx4, by4);
1395
1396
        // reconstruction
1397
390k
        if (t->frame_thread.pass == 1) {
1398
390k
            f->bd_fn.read_coef_blocks(t, bs, b);
1399
390k
            b->filter2d = FILTER_2D_BILINEAR;
1400
390k
        } else {
1401
0
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
1402
0
        }
1403
1404
390k
        splat_intrabc_mv(f->c, t, bs, b, bw4, bh4);
1405
390k
        BlockContext *edge = t->a;
1406
1.17M
        for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
1407
780k
#define set_ctx(rep_macro) \
1408
780k
            rep_macro(edge->tx_intra, off, b_dim[2 + i]); \
1409
780k
            rep_macro(edge->mode, off, DC_PRED); \
1410
780k
            rep_macro(edge->pal_sz, off, 0); \
1411
            /* see aomedia bug 2183 for why this is outside if (has_chroma) */ \
1412
780k
            rep_macro(t->pal_sz_uv[i], off, 0); \
1413
780k
            rep_macro(edge->seg_pred, off, seg_pred); \
1414
780k
            rep_macro(edge->skip_mode, off, 0); \
1415
780k
            rep_macro(edge->intra, off, 0); \
1416
780k
            rep_macro(edge->skip, off, b->skip)
1417
780k
            case_set(b_dim[2 + i]);
1418
780k
#undef set_ctx
1419
780k
        }
1420
390k
        if (has_chroma) {
1421
296k
            dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], DC_PRED);
1422
296k
            dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], DC_PRED);
1423
296k
        }
1424
390k
    } else {
1425
        // inter-specific mode/mv coding
1426
186k
        int is_comp, has_subpel_filter;
1427
1428
186k
        if (b->skip_mode) {
1429
669
            is_comp = 1;
1430
185k
        } else if ((!seg || (seg->ref == -1 && !seg->globalmv && !seg->skip)) &&
1431
163k
                   f->frame_hdr->switchable_comp_refs && imin(bw4, bh4) > 1)
1432
85.1k
        {
1433
85.1k
            const int ctx = get_comp_ctx(t->a, &t->l, by4, bx4,
1434
85.1k
                                         have_top, have_left);
1435
85.1k
            is_comp = dav1d_msac_decode_bool_adapt(&ts->msac,
1436
85.1k
                          ts->cdf.m.comp[ctx]);
1437
85.1k
            if (DEBUG_BLOCK_INFO)
1438
0
                printf("Post-compflag[%d]: r=%d\n", is_comp, ts->msac.rng);
1439
100k
        } else {
1440
100k
            is_comp = 0;
1441
100k
        }
1442
1443
186k
        if (b->skip_mode) {
1444
669
            b->ref[0] = f->frame_hdr->skip_mode_refs[0];
1445
669
            b->ref[1] = f->frame_hdr->skip_mode_refs[1];
1446
669
            b->comp_type = COMP_INTER_AVG;
1447
669
            b->inter_mode = NEARESTMV_NEARESTMV;
1448
669
            b->drl_idx = NEAREST_DRL;
1449
669
            has_subpel_filter = 0;
1450
1451
669
            refmvs_candidate mvstack[8];
1452
669
            int n_mvs, ctx;
1453
669
            dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1454
669
                              (union refmvs_refpair) { .ref = {
1455
669
                                    b->ref[0] + 1, b->ref[1] + 1 }},
1456
669
                              bs, intra_edge_flags, t->by, t->bx);
1457
1458
669
            b->mv[0] = mvstack[0].mv.mv[0];
1459
669
            b->mv[1] = mvstack[0].mv.mv[1];
1460
669
            fix_mv_precision(f->frame_hdr, &b->mv[0]);
1461
669
            fix_mv_precision(f->frame_hdr, &b->mv[1]);
1462
669
            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
185k
        } else if (is_comp) {
1467
46.1k
            const int dir_ctx = get_comp_dir_ctx(t->a, &t->l, by4, bx4,
1468
46.1k
                                                 have_top, have_left);
1469
46.1k
            if (dav1d_msac_decode_bool_adapt(&ts->msac,
1470
46.1k
                    ts->cdf.m.comp_dir[dir_ctx]))
1471
37.7k
            {
1472
                // bidir - first reference (fw)
1473
37.7k
                const int ctx1 = av1_get_fwd_ref_ctx(t->a, &t->l, by4, bx4,
1474
37.7k
                                                     have_top, have_left);
1475
37.7k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1476
37.7k
                        ts->cdf.m.comp_fwd_ref[0][ctx1]))
1477
12.6k
                {
1478
12.6k
                    const int ctx2 = av1_get_fwd_ref_2_ctx(t->a, &t->l, by4, bx4,
1479
12.6k
                                                           have_top, have_left);
1480
12.6k
                    b->ref[0] = 2 + dav1d_msac_decode_bool_adapt(&ts->msac,
1481
12.6k
                                        ts->cdf.m.comp_fwd_ref[2][ctx2]);
1482
25.1k
                } else {
1483
25.1k
                    const int ctx2 = av1_get_fwd_ref_1_ctx(t->a, &t->l, by4, bx4,
1484
25.1k
                                                           have_top, have_left);
1485
25.1k
                    b->ref[0] = dav1d_msac_decode_bool_adapt(&ts->msac,
1486
25.1k
                                    ts->cdf.m.comp_fwd_ref[1][ctx2]);
1487
25.1k
                }
1488
1489
                // second reference (bw)
1490
37.7k
                const int ctx3 = av1_get_bwd_ref_ctx(t->a, &t->l, by4, bx4,
1491
37.7k
                                                     have_top, have_left);
1492
37.7k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1493
37.7k
                        ts->cdf.m.comp_bwd_ref[0][ctx3]))
1494
18.6k
                {
1495
18.6k
                    b->ref[1] = 6;
1496
19.0k
                } else {
1497
19.0k
                    const int ctx4 = av1_get_bwd_ref_1_ctx(t->a, &t->l, by4, bx4,
1498
19.0k
                                                           have_top, have_left);
1499
19.0k
                    b->ref[1] = 4 + dav1d_msac_decode_bool_adapt(&ts->msac,
1500
19.0k
                                        ts->cdf.m.comp_bwd_ref[1][ctx4]);
1501
19.0k
                }
1502
37.7k
            } else {
1503
                // unidir
1504
8.37k
                const int uctx_p = av1_get_uni_p_ctx(t->a, &t->l, by4, bx4,
1505
8.37k
                                                     have_top, have_left);
1506
8.37k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1507
8.37k
                        ts->cdf.m.comp_uni_ref[0][uctx_p]))
1508
2.61k
                {
1509
2.61k
                    b->ref[0] = 4;
1510
2.61k
                    b->ref[1] = 6;
1511
5.76k
                } else {
1512
5.76k
                    const int uctx_p1 = av1_get_uni_p1_ctx(t->a, &t->l, by4, bx4,
1513
5.76k
                                                           have_top, have_left);
1514
5.76k
                    b->ref[0] = 0;
1515
5.76k
                    b->ref[1] = 1 + dav1d_msac_decode_bool_adapt(&ts->msac,
1516
5.76k
                                        ts->cdf.m.comp_uni_ref[1][uctx_p1]);
1517
5.76k
                    if (b->ref[1] == 2) {
1518
3.43k
                        const int uctx_p2 = av1_get_uni_p2_ctx(t->a, &t->l, by4, bx4,
1519
3.43k
                                                               have_top, have_left);
1520
3.43k
                        b->ref[1] += dav1d_msac_decode_bool_adapt(&ts->msac,
1521
3.43k
                                         ts->cdf.m.comp_uni_ref[2][uctx_p2]);
1522
3.43k
                    }
1523
5.76k
                }
1524
8.37k
            }
1525
46.1k
            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
46.1k
            refmvs_candidate mvstack[8];
1530
46.1k
            int n_mvs, ctx;
1531
46.1k
            dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1532
46.1k
                              (union refmvs_refpair) { .ref = {
1533
46.1k
                                    b->ref[0] + 1, b->ref[1] + 1 }},
1534
46.1k
                              bs, intra_edge_flags, t->by, t->bx);
1535
1536
46.1k
            b->inter_mode = dav1d_msac_decode_symbol_adapt8(&ts->msac,
1537
46.1k
                                ts->cdf.m.comp_inter_mode[ctx],
1538
46.1k
                                N_COMP_INTER_PRED_MODES - 1);
1539
46.1k
            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
46.1k
            const uint8_t *const im = dav1d_comp_inter_pred_modes[b->inter_mode];
1544
46.1k
            b->drl_idx = NEAREST_DRL;
1545
46.1k
            if (b->inter_mode == NEWMV_NEWMV) {
1546
7.98k
                if (n_mvs > 1) { // NEARER, NEAR or NEARISH
1547
7.98k
                    const int drl_ctx_v1 = get_drl_context(mvstack, 0);
1548
7.98k
                    b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1549
7.98k
                                      ts->cdf.m.drl_bit[drl_ctx_v1]);
1550
7.98k
                    if (b->drl_idx == NEARER_DRL && n_mvs > 2) {
1551
1.07k
                        const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1552
1.07k
                        b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1553
1.07k
                                          ts->cdf.m.drl_bit[drl_ctx_v2]);
1554
1.07k
                    }
1555
7.98k
                    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
7.98k
                }
1559
38.1k
            } else if (im[0] == NEARMV || im[1] == NEARMV) {
1560
11.2k
                b->drl_idx = NEARER_DRL;
1561
11.2k
                if (n_mvs > 2) { // NEAR or NEARISH
1562
1.09k
                    const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1563
1.09k
                    b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1564
1.09k
                                      ts->cdf.m.drl_bit[drl_ctx_v2]);
1565
1.09k
                    if (b->drl_idx == NEAR_DRL && n_mvs > 3) {
1566
164
                        const int drl_ctx_v3 = get_drl_context(mvstack, 2);
1567
164
                        b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1568
164
                                          ts->cdf.m.drl_bit[drl_ctx_v3]);
1569
164
                    }
1570
1.09k
                    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
1.09k
                }
1574
11.2k
            }
1575
46.1k
            assert(b->drl_idx >= NEAREST_DRL && b->drl_idx <= NEARISH_DRL);
1576
1577
46.1k
#define assign_comp_mv(idx) \
1578
92.3k
            switch (im[idx]) { \
1579
19.4k
            case NEARMV: \
1580
57.3k
            case NEARESTMV: \
1581
57.3k
                b->mv[idx] = mvstack[b->drl_idx].mv.mv[idx]; \
1582
57.3k
                fix_mv_precision(f->frame_hdr, &b->mv[idx]); \
1583
57.3k
                break; \
1584
19.4k
            case GLOBALMV: \
1585
10.6k
                has_subpel_filter |= \
1586
10.6k
                    f->frame_hdr->gmv[b->ref[idx]].type == DAV1D_WM_TYPE_TRANSLATION; \
1587
10.6k
                b->mv[idx] = get_gmv_2d(&f->frame_hdr->gmv[b->ref[idx]], \
1588
10.6k
                                        t->bx, t->by, bw4, bh4, f->frame_hdr); \
1589
10.6k
                break; \
1590
24.3k
            case NEWMV: \
1591
24.3k
                b->mv[idx] = mvstack[b->drl_idx].mv.mv[idx]; \
1592
24.3k
                const int mv_prec = f->frame_hdr->hp - f->frame_hdr->force_integer_mv; \
1593
24.3k
                read_mv_residual(ts, &b->mv[idx], mv_prec); \
1594
24.3k
                break; \
1595
92.3k
            }
1596
46.1k
            has_subpel_filter = imin(bw4, bh4) == 1 ||
1597
46.1k
                                b->inter_mode != GLOBALMV_GLOBALMV;
1598
46.1k
            assign_comp_mv(0);
1599
46.1k
            assign_comp_mv(1);
1600
46.1k
#undef assign_comp_mv
1601
46.1k
            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
46.1k
            int is_segwedge = 0;
1608
46.1k
            if (f->seq_hdr->masked_compound) {
1609
40.3k
                const int mask_ctx = get_mask_comp_ctx(t->a, &t->l, by4, bx4);
1610
1611
40.3k
                is_segwedge = dav1d_msac_decode_bool_adapt(&ts->msac,
1612
40.3k
                                  ts->cdf.m.mask_comp[mask_ctx]);
1613
40.3k
                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
40.3k
            }
1617
1618
46.1k
            if (!is_segwedge) {
1619
35.8k
                if (f->seq_hdr->jnt_comp) {
1620
8.51k
                    const int jnt_ctx =
1621
8.51k
                        get_jnt_comp_ctx(f->seq_hdr->order_hint_n_bits,
1622
8.51k
                                         f->cur.frame_hdr->frame_offset,
1623
8.51k
                                         f->refp[b->ref[0]].p.frame_hdr->frame_offset,
1624
8.51k
                                         f->refp[b->ref[1]].p.frame_hdr->frame_offset,
1625
8.51k
                                         t->a, &t->l, by4, bx4);
1626
8.51k
                    b->comp_type = COMP_INTER_WEIGHTED_AVG +
1627
8.51k
                                   dav1d_msac_decode_bool_adapt(&ts->msac,
1628
8.51k
                                       ts->cdf.m.jnt_comp[jnt_ctx]);
1629
8.51k
                    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.3k
                } else {
1636
27.3k
                    b->comp_type = COMP_INTER_AVG;
1637
27.3k
                }
1638
35.8k
            } else {
1639
10.3k
                if (wedge_allowed_mask & (1 << bs)) {
1640
9.03k
                    const int ctx = dav1d_wedge_ctx_lut[bs];
1641
9.03k
                    b->comp_type = COMP_INTER_WEDGE -
1642
9.03k
                                   dav1d_msac_decode_bool_adapt(&ts->msac,
1643
9.03k
                                       ts->cdf.m.wedge_comp[ctx]);
1644
9.03k
                    if (b->comp_type == COMP_INTER_WEDGE)
1645
3.40k
                        b->wedge_idx = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1646
3.40k
                                           ts->cdf.m.wedge_idx[ctx], 15);
1647
9.03k
                } else {
1648
1.26k
                    b->comp_type = COMP_INTER_SEG;
1649
1.26k
                }
1650
10.3k
                b->mask_sign = dav1d_msac_decode_bool_equi(&ts->msac);
1651
10.3k
                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.3k
            }
1656
139k
        } else {
1657
139k
            b->comp_type = COMP_INTER_NONE;
1658
1659
            // ref
1660
139k
            if (seg && seg->ref > 0) {
1661
25.4k
                b->ref[0] = seg->ref - 1;
1662
114k
            } else if (seg && (seg->globalmv || seg->skip)) {
1663
5.78k
                b->ref[0] = 0;
1664
108k
            } else {
1665
108k
                const int ctx1 = av1_get_ref_ctx(t->a, &t->l, by4, bx4,
1666
108k
                                                 have_top, have_left);
1667
108k
                if (dav1d_msac_decode_bool_adapt(&ts->msac,
1668
108k
                                                 ts->cdf.m.ref[0][ctx1]))
1669
55.5k
                {
1670
55.5k
                    const int ctx2 = av1_get_ref_2_ctx(t->a, &t->l, by4, bx4,
1671
55.5k
                                                       have_top, have_left);
1672
55.5k
                    if (dav1d_msac_decode_bool_adapt(&ts->msac,
1673
55.5k
                                                     ts->cdf.m.ref[1][ctx2]))
1674
36.9k
                    {
1675
36.9k
                        b->ref[0] = 6;
1676
36.9k
                    } else {
1677
18.6k
                        const int ctx3 = av1_get_ref_6_ctx(t->a, &t->l, by4, bx4,
1678
18.6k
                                                           have_top, have_left);
1679
18.6k
                        b->ref[0] = 4 + dav1d_msac_decode_bool_adapt(&ts->msac,
1680
18.6k
                                            ts->cdf.m.ref[5][ctx3]);
1681
18.6k
                    }
1682
55.5k
                } else {
1683
52.6k
                    const int ctx2 = av1_get_ref_3_ctx(t->a, &t->l, by4, bx4,
1684
52.6k
                                                       have_top, have_left);
1685
52.6k
                    if (dav1d_msac_decode_bool_adapt(&ts->msac,
1686
52.6k
                                                     ts->cdf.m.ref[2][ctx2]))
1687
20.6k
                    {
1688
20.6k
                        const int ctx3 = av1_get_ref_5_ctx(t->a, &t->l, by4, bx4,
1689
20.6k
                                                           have_top, have_left);
1690
20.6k
                        b->ref[0] = 2 + dav1d_msac_decode_bool_adapt(&ts->msac,
1691
20.6k
                                            ts->cdf.m.ref[4][ctx3]);
1692
31.9k
                    } else {
1693
31.9k
                        const int ctx3 = av1_get_ref_4_ctx(t->a, &t->l, by4, bx4,
1694
31.9k
                                                           have_top, have_left);
1695
31.9k
                        b->ref[0] = dav1d_msac_decode_bool_adapt(&ts->msac,
1696
31.9k
                                        ts->cdf.m.ref[3][ctx3]);
1697
31.9k
                    }
1698
52.6k
                }
1699
108k
                if (DEBUG_BLOCK_INFO)
1700
0
                    printf("Post-ref[%d]: r=%d\n", b->ref[0], ts->msac.rng);
1701
108k
            }
1702
139k
            b->ref[1] = -1;
1703
1704
139k
            refmvs_candidate mvstack[8];
1705
139k
            int n_mvs, ctx;
1706
139k
            dav1d_refmvs_find(&t->rt, mvstack, &n_mvs, &ctx,
1707
139k
                              (union refmvs_refpair) { .ref = { b->ref[0] + 1, -1 }},
1708
139k
                              bs, intra_edge_flags, t->by, t->bx);
1709
1710
            // mode parsing and mv derivation from ref_mvs
1711
139k
            if ((seg && (seg->skip || seg->globalmv)) ||
1712
119k
                dav1d_msac_decode_bool_adapt(&ts->msac,
1713
119k
                                             ts->cdf.m.newmv_mode[ctx & 7]))
1714
106k
            {
1715
106k
                if ((seg && (seg->skip || seg->globalmv)) ||
1716
76.6k
                    !dav1d_msac_decode_bool_adapt(&ts->msac,
1717
76.6k
                         ts->cdf.m.globalmv_mode[(ctx >> 3) & 1]))
1718
33.3k
                {
1719
33.3k
                    b->inter_mode = GLOBALMV;
1720
33.3k
                    b->mv[0] = get_gmv_2d(&f->frame_hdr->gmv[b->ref[0]],
1721
33.3k
                                          t->bx, t->by, bw4, bh4, f->frame_hdr);
1722
33.3k
                    has_subpel_filter = imin(bw4, bh4) == 1 ||
1723
22.5k
                        f->frame_hdr->gmv[b->ref[0]].type == DAV1D_WM_TYPE_TRANSLATION;
1724
72.8k
                } else {
1725
72.8k
                    has_subpel_filter = 1;
1726
72.8k
                    if (dav1d_msac_decode_bool_adapt(&ts->msac,
1727
72.8k
                            ts->cdf.m.refmv_mode[(ctx >> 4) & 15]))
1728
31.7k
                    { // NEAREST, NEARER, NEAR or NEARISH
1729
31.7k
                        b->inter_mode = NEARMV;
1730
31.7k
                        b->drl_idx = NEARER_DRL;
1731
31.7k
                        if (n_mvs > 2) { // NEARER, NEAR or NEARISH
1732
10.3k
                            const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1733
10.3k
                            b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1734
10.3k
                                              ts->cdf.m.drl_bit[drl_ctx_v2]);
1735
10.3k
                            if (b->drl_idx == NEAR_DRL && n_mvs > 3) { // NEAR or NEARISH
1736
3.47k
                                const int drl_ctx_v3 =
1737
3.47k
                                    get_drl_context(mvstack, 2);
1738
3.47k
                                b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1739
3.47k
                                                  ts->cdf.m.drl_bit[drl_ctx_v3]);
1740
3.47k
                            }
1741
10.3k
                        }
1742
41.0k
                    } else {
1743
41.0k
                        b->inter_mode = NEARESTMV;
1744
41.0k
                        b->drl_idx = NEAREST_DRL;
1745
41.0k
                    }
1746
72.8k
                    assert(b->drl_idx >= NEAREST_DRL && b->drl_idx <= NEARISH_DRL);
1747
72.8k
                    b->mv[0] = mvstack[b->drl_idx].mv.mv[0];
1748
72.8k
                    if (b->drl_idx < NEAR_DRL)
1749
65.4k
                        fix_mv_precision(f->frame_hdr, &b->mv[0]);
1750
72.8k
                }
1751
1752
106k
                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
106k
            } else {
1757
33.2k
                has_subpel_filter = 1;
1758
33.2k
                b->inter_mode = NEWMV;
1759
33.2k
                b->drl_idx = NEAREST_DRL;
1760
33.2k
                if (n_mvs > 1) { // NEARER, NEAR or NEARISH
1761
27.7k
                    const int drl_ctx_v1 = get_drl_context(mvstack, 0);
1762
27.7k
                    b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1763
27.7k
                                      ts->cdf.m.drl_bit[drl_ctx_v1]);
1764
27.7k
                    if (b->drl_idx == NEARER_DRL && n_mvs > 2) { // NEAR or NEARISH
1765
4.76k
                        const int drl_ctx_v2 = get_drl_context(mvstack, 1);
1766
4.76k
                        b->drl_idx += dav1d_msac_decode_bool_adapt(&ts->msac,
1767
4.76k
                                          ts->cdf.m.drl_bit[drl_ctx_v2]);
1768
4.76k
                    }
1769
27.7k
                }
1770
33.2k
                assert(b->drl_idx >= NEAREST_DRL && b->drl_idx <= NEARISH_DRL);
1771
33.2k
                if (n_mvs > 1) {
1772
27.7k
                    b->mv[0] = mvstack[b->drl_idx].mv.mv[0];
1773
27.7k
                } else {
1774
5.51k
                    assert(!b->drl_idx);
1775
5.51k
                    b->mv[0] = mvstack[0].mv.mv[0];
1776
5.51k
                    fix_mv_precision(f->frame_hdr, &b->mv[0]);
1777
5.51k
                }
1778
33.2k
                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
33.2k
                const int mv_prec = f->frame_hdr->hp - f->frame_hdr->force_integer_mv;
1782
33.2k
                read_mv_residual(ts, &b->mv[0], mv_prec);
1783
33.2k
                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
33.2k
            }
1787
1788
            // interintra flags
1789
139k
            const int ii_sz_grp = dav1d_ymode_size_context[bs];
1790
139k
            if (f->seq_hdr->inter_intra &&
1791
104k
                interintra_allowed_mask & (1 << bs) &&
1792
40.4k
                dav1d_msac_decode_bool_adapt(&ts->msac,
1793
40.4k
                                             ts->cdf.m.interintra[ii_sz_grp]))
1794
7.00k
            {
1795
7.00k
                b->interintra_mode = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1796
7.00k
                                         ts->cdf.m.interintra_mode[ii_sz_grp],
1797
7.00k
                                         N_INTER_INTRA_PRED_MODES - 1);
1798
7.00k
                const int wedge_ctx = dav1d_wedge_ctx_lut[bs];
1799
7.00k
                b->interintra_type = INTER_INTRA_BLEND +
1800
7.00k
                                     dav1d_msac_decode_bool_adapt(&ts->msac,
1801
7.00k
                                         ts->cdf.m.interintra_wedge[wedge_ctx]);
1802
7.00k
                if (b->interintra_type == INTER_INTRA_WEDGE)
1803
1.78k
                    b->wedge_idx = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1804
1.78k
                                       ts->cdf.m.wedge_idx[wedge_ctx], 15);
1805
132k
            } else {
1806
132k
                b->interintra_type = INTER_INTRA_NONE;
1807
132k
            }
1808
139k
            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
139k
            if (f->frame_hdr->switchable_motion_mode &&
1818
82.4k
                b->interintra_type == INTER_INTRA_NONE && imin(bw4, bh4) >= 2 &&
1819
                // is not warped global motion
1820
35.9k
                !(!f->frame_hdr->force_integer_mv && b->inter_mode == GLOBALMV &&
1821
4.57k
                  f->frame_hdr->gmv[b->ref[0]].type > DAV1D_WM_TYPE_TRANSLATION) &&
1822
                // has overlappable neighbours
1823
34.8k
                ((have_left && findoddzero(&t->l.intra[by4 + 1], h4 >> 1)) ||
1824
7.38k
                 (have_top && findoddzero(&t->a->intra[bx4 + 1], w4 >> 1))))
1825
31.8k
            {
1826
                // reaching here means the block allows obmc - check warp by
1827
                // finding matching-ref blocks in top/left edges
1828
31.8k
                uint64_t mask[2] = { 0, 0 };
1829
31.8k
                find_matching_ref(t, intra_edge_flags, bw4, bh4, w4, h4,
1830
31.8k
                                  have_left, have_top, b->ref[0], mask);
1831
31.8k
                const int allow_warp = !f->svc[b->ref[0]][0].scale &&
1832
20.3k
                    !f->frame_hdr->force_integer_mv &&
1833
20.2k
                    f->frame_hdr->warp_motion && (mask[0] | mask[1]);
1834
1835
31.8k
                b->motion_mode = allow_warp ?
1836
10.2k
                    dav1d_msac_decode_symbol_adapt4(&ts->msac,
1837
10.2k
                        ts->cdf.m.motion_mode[bs], 2) :
1838
31.8k
                    dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.obmc[bs]);
1839
31.8k
                if (b->motion_mode == MM_WARP) {
1840
3.34k
                    has_subpel_filter = 0;
1841
3.34k
                    derive_warpmv(t, bw4, bh4, mask, b->mv[0], &t->warpmv);
1842
3.34k
#define signabs(v) v < 0 ? '-' : ' ', abs(v)
1843
3.34k
                    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
3.34k
#undef signabs
1859
3.34k
                    if (t->frame_thread.pass) {
1860
3.34k
                        if (t->warpmv.type == DAV1D_WM_TYPE_AFFINE) {
1861
2.90k
                            b->matrix[0] = t->warpmv.matrix[2] - 0x10000;
1862
2.90k
                            b->matrix[1] = t->warpmv.matrix[3];
1863
2.90k
                            b->matrix[2] = t->warpmv.matrix[4];
1864
2.90k
                            b->matrix[3] = t->warpmv.matrix[5] - 0x10000;
1865
2.90k
                        } else {
1866
433
                            b->matrix[0] = INT16_MIN;
1867
433
                        }
1868
3.34k
                    }
1869
3.34k
                }
1870
1871
31.8k
                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
107k
            } else {
1876
107k
                b->motion_mode = MM_TRANSLATION;
1877
107k
            }
1878
139k
        }
1879
1880
        // subpel filter
1881
186k
        enum Dav1dFilterMode filter[2];
1882
186k
        if (f->frame_hdr->subpel_filter_mode == DAV1D_FILTER_SWITCHABLE) {
1883
123k
            if (has_subpel_filter) {
1884
107k
                const int comp = b->comp_type != COMP_INTER_NONE;
1885
107k
                const int ctx1 = get_filter_ctx(t->a, &t->l, comp, 0, b->ref[0],
1886
107k
                                                by4, bx4);
1887
107k
                filter[0] = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1888
107k
                               ts->cdf.m.filter[0][ctx1],
1889
107k
                               DAV1D_N_SWITCHABLE_FILTERS - 1);
1890
107k
                if (f->seq_hdr->dual_filter) {
1891
85.6k
                    const int ctx2 = get_filter_ctx(t->a, &t->l, comp, 1,
1892
85.6k
                                                    b->ref[0], by4, bx4);
1893
85.6k
                    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
85.6k
                    filter[1] = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1897
85.6k
                                    ts->cdf.m.filter[1][ctx2],
1898
85.6k
                                    DAV1D_N_SWITCHABLE_FILTERS - 1);
1899
85.6k
                    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
85.6k
                } else {
1903
21.9k
                    filter[1] = filter[0];
1904
21.9k
                    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
21.9k
                }
1908
107k
            } else {
1909
15.9k
                filter[0] = filter[1] = DAV1D_FILTER_8TAP_REGULAR;
1910
15.9k
            }
1911
123k
        } else {
1912
62.7k
            filter[0] = filter[1] = f->frame_hdr->subpel_filter_mode;
1913
62.7k
        }
1914
186k
        b->filter2d = dav1d_filter_2d[filter[1]][filter[0]];
1915
1916
186k
        read_vartx_tree(t, b, bs, bx4, by4);
1917
1918
        // reconstruction
1919
195k
        if (t->frame_thread.pass == 1) {
1920
195k
            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
186k
        if (f->frame_hdr->loopfilter.level_y[0] ||
1926
28.2k
            f->frame_hdr->loopfilter.level_y[1])
1927
185k
        {
1928
185k
            const int is_globalmv =
1929
185k
                b->inter_mode == (is_comp ? GLOBALMV_GLOBALMV : GLOBALMV);
1930
185k
            const uint8_t (*const lf_lvls)[8][2] = (const uint8_t (*)[8][2])
1931
185k
                &ts->lflvl[b->seg_id][0][b->ref[0] + 1][!is_globalmv];
1932
185k
            const uint16_t tx_split[2] = { b->tx_split0, b->tx_split1 };
1933
185k
            enum RectTxfmSize ytx = b->max_ytx, uvtx = b->uvtx;
1934
185k
            if (f->frame_hdr->segmentation.lossless[b->seg_id]) {
1935
1.87k
                ytx  = (enum RectTxfmSize) TX_4X4;
1936
1.87k
                uvtx = (enum RectTxfmSize) TX_4X4;
1937
1.87k
            }
1938
185k
            dav1d_create_lf_mask_inter(t->lf_mask, f->lf.level, f->b4_stride, lf_lvls,
1939
185k
                                       t->bx, t->by, f->w4, f->h4, b->skip, bs,
1940
185k
                                       ytx, tx_split, uvtx, f->cur.p.layout,
1941
185k
                                       &t->a->tx_lpf_y[bx4], &t->l.tx_lpf_y[by4],
1942
185k
                                       has_chroma ? &t->a->tx_lpf_uv[cbx4] : NULL,
1943
185k
                                       has_chroma ? &t->l.tx_lpf_uv[cby4] : NULL);
1944
185k
        }
1945
1946
        // context updates
1947
186k
        if (is_comp)
1948
46.8k
            splat_tworef_mv(f->c, t, bs, b, bw4, bh4);
1949
139k
        else
1950
139k
            splat_oneref_mv(f->c, t, bs, b, bw4, bh4);
1951
186k
        BlockContext *edge = t->a;
1952
577k
        for (int i = 0, off = bx4; i < 2; i++, off = by4, edge = &t->l) {
1953
391k
#define set_ctx(rep_macro) \
1954
391k
            rep_macro(edge->seg_pred, off, seg_pred); \
1955
391k
            rep_macro(edge->skip_mode, off, b->skip_mode); \
1956
391k
            rep_macro(edge->intra, off, 0); \
1957
391k
            rep_macro(edge->skip, off, b->skip); \
1958
391k
            rep_macro(edge->pal_sz, off, 0); \
1959
            /* see aomedia bug 2183 for why this is outside if (has_chroma) */ \
1960
391k
            rep_macro(t->pal_sz_uv[i], off, 0); \
1961
391k
            rep_macro(edge->tx_intra, off, b_dim[2 + i]); \
1962
391k
            rep_macro(edge->comp_type, off, b->comp_type); \
1963
391k
            rep_macro(edge->filter[0], off, filter[0]); \
1964
391k
            rep_macro(edge->filter[1], off, filter[1]); \
1965
391k
            rep_macro(edge->mode, off, b->inter_mode); \
1966
391k
            rep_macro(edge->ref[0], off, b->ref[0]); \
1967
391k
            rep_macro(edge->ref[1], off, ((uint8_t) b->ref[1]))
1968
391k
            case_set(b_dim[2 + i]);
1969
391k
#undef set_ctx
1970
391k
        }
1971
186k
        if (has_chroma) {
1972
48.4k
            dav1d_memset_pow2[ulog2(cbw4)](&t->a->uvmode[cbx4], DC_PRED);
1973
48.4k
            dav1d_memset_pow2[ulog2(cbh4)](&t->l.uvmode[cby4], DC_PRED);
1974
48.4k
        }
1975
186k
    }
1976
1977
    // update contexts
1978
3.16M
    if (f->frame_hdr->segmentation.enabled &&
1979
1.57M
        f->frame_hdr->segmentation.update_map)
1980
1.56M
    {
1981
1.56M
        uint8_t *seg_ptr = &f->cur_segmap[t->by * f->b4_stride + t->bx];
1982
1.56M
#define set_ctx(rep_macro) \
1983
9.20M
        for (int y = 0; y < bh4; y++) { \
1984
7.64M
            rep_macro(seg_ptr, 0, b->seg_id); \
1985
7.64M
            seg_ptr += f->b4_stride; \
1986
7.64M
        }
1987
1.56M
        case_set(b_dim[2]);
1988
1.56M
#undef set_ctx
1989
1.56M
    }
1990
3.16M
    if (!b->skip) {
1991
1.44M
        uint16_t (*noskip_mask)[2] = &t->lf_mask->noskip_mask[by4 >> 1];
1992
1.44M
        const unsigned mask = (~0U >> (32 - bw4)) << (bx4 & 15);
1993
1.44M
        const int bx_idx = (bx4 & 16) >> 4;
1994
4.83M
        for (int y = 0; y < bh4; y += 2, noskip_mask++) {
1995
3.38M
            (*noskip_mask)[bx_idx] |= mask;
1996
3.38M
            if (bw4 == 32) // this should be mask >> 16, but it's 0xffffffff anyway
1997
309k
                (*noskip_mask)[1] |= mask;
1998
3.38M
        }
1999
1.44M
    }
2000
2001
3.17M
    if (t->frame_thread.pass == 1 && !b->intra && IS_INTER_OR_SWITCH(f->frame_hdr)) {
2002
195k
        const int sby = (t->by - ts->tiling.row_start) >> f->sb_shift;
2003
195k
        int (*const lowest_px)[2] = ts->lowest_pixel[sby];
2004
2005
        // keep track of motion vectors for each reference
2006
195k
        if (b->comp_type == COMP_INTER_NONE) {
2007
            // y
2008
148k
            if (imin(bw4, bh4) > 1 &&
2009
76.7k
                ((b->inter_mode == GLOBALMV && f->gmv_warp_allowed[b->ref[0]]) ||
2010
69.9k
                 (b->motion_mode == MM_WARP && t->warpmv.type > DAV1D_WM_TYPE_TRANSLATION)))
2011
9.73k
            {
2012
9.73k
                affine_lowest_px_luma(t, &lowest_px[b->ref[0]][0], b_dim,
2013
9.73k
                                      b->motion_mode == MM_WARP ? &t->warpmv :
2014
9.73k
                                      &f->frame_hdr->gmv[b->ref[0]]);
2015
138k
            } else {
2016
138k
                mc_lowest_px(&lowest_px[b->ref[0]][0], t->by, bh4, b->mv[0].y,
2017
138k
                             0, &f->svc[b->ref[0]][1]);
2018
138k
                if (b->motion_mode == MM_OBMC) {
2019
16.4k
                    obmc_lowest_px(t, lowest_px, 0, b_dim, bx4, by4, w4, h4);
2020
16.4k
                }
2021
138k
            }
2022
2023
            // uv
2024
148k
            if (has_chroma) {
2025
                // sub8x8 derivation
2026
36.5k
                int is_sub8x8 = bw4 == ss_hor || bh4 == ss_ver;
2027
36.5k
                refmvs_block *const *r;
2028
36.5k
                if (is_sub8x8) {
2029
3.26k
                    assert(ss_hor == 1);
2030
3.26k
                    r = &t->rt.r[(t->by & 31) + 5];
2031
3.26k
                    if (bw4 == 1) is_sub8x8 &= r[0][t->bx - 1].ref.ref[0] > 0;
2032
3.26k
                    if (bh4 == ss_ver) is_sub8x8 &= r[-1][t->bx].ref.ref[0] > 0;
2033
3.26k
                    if (bw4 == 1 && bh4 == ss_ver)
2034
821
                        is_sub8x8 &= r[-1][t->bx - 1].ref.ref[0] > 0;
2035
3.26k
                }
2036
2037
                // chroma prediction
2038
36.5k
                if (is_sub8x8) {
2039
3.11k
                    assert(ss_hor == 1);
2040
3.11k
                    if (bw4 == 1 && bh4 == ss_ver) {
2041
747
                        const refmvs_block *const rr = &r[-1][t->bx - 1];
2042
747
                        mc_lowest_px(&lowest_px[rr->ref.ref[0] - 1][1],
2043
747
                                     t->by - 1, bh4, rr->mv.mv[0].y, ss_ver,
2044
747
                                     &f->svc[rr->ref.ref[0] - 1][1]);
2045
747
                    }
2046
3.11k
                    if (bw4 == 1) {
2047
1.75k
                        const refmvs_block *const rr = &r[0][t->bx - 1];
2048
1.75k
                        mc_lowest_px(&lowest_px[rr->ref.ref[0] - 1][1],
2049
1.75k
                                     t->by, bh4, rr->mv.mv[0].y, ss_ver,
2050
1.75k
                                     &f->svc[rr->ref.ref[0] - 1][1]);
2051
1.75k
                    }
2052
3.11k
                    if (bh4 == ss_ver) {
2053
2.11k
                        const refmvs_block *const rr = &r[-1][t->bx];
2054
2.11k
                        mc_lowest_px(&lowest_px[rr->ref.ref[0] - 1][1],
2055
2.11k
                                     t->by - 1, bh4, rr->mv.mv[0].y, ss_ver,
2056
2.11k
                                     &f->svc[rr->ref.ref[0] - 1][1]);
2057
2.11k
                    }
2058
3.11k
                    mc_lowest_px(&lowest_px[b->ref[0]][1], t->by, bh4,
2059
3.11k
                                 b->mv[0].y, ss_ver, &f->svc[b->ref[0]][1]);
2060
33.3k
                } else {
2061
33.3k
                    if (imin(cbw4, cbh4) > 1 &&
2062
15.3k
                        ((b->inter_mode == GLOBALMV && f->gmv_warp_allowed[b->ref[0]]) ||
2063
14.9k
                         (b->motion_mode == MM_WARP && t->warpmv.type > DAV1D_WM_TYPE_TRANSLATION)))
2064
727
                    {
2065
727
                        affine_lowest_px_chroma(t, &lowest_px[b->ref[0]][1], b_dim,
2066
727
                                                b->motion_mode == MM_WARP ? &t->warpmv :
2067
727
                                                &f->frame_hdr->gmv[b->ref[0]]);
2068
32.6k
                    } else {
2069
32.6k
                        mc_lowest_px(&lowest_px[b->ref[0]][1],
2070
32.6k
                                     t->by & ~ss_ver, bh4 << (bh4 == ss_ver),
2071
32.6k
                                     b->mv[0].y, ss_ver, &f->svc[b->ref[0]][1]);
2072
32.6k
                        if (b->motion_mode == MM_OBMC) {
2073
6.99k
                            obmc_lowest_px(t, lowest_px, 1, b_dim, bx4, by4, w4, h4);
2074
6.99k
                        }
2075
32.6k
                    }
2076
33.3k
                }
2077
36.5k
            }
2078
148k
        } else {
2079
            // y
2080
140k
            for (int i = 0; i < 2; i++) {
2081
93.6k
                if (b->inter_mode == GLOBALMV_GLOBALMV && f->gmv_warp_allowed[b->ref[i]]) {
2082
2.04k
                    affine_lowest_px_luma(t, &lowest_px[b->ref[i]][0], b_dim,
2083
2.04k
                                          &f->frame_hdr->gmv[b->ref[i]]);
2084
91.6k
                } else {
2085
91.6k
                    mc_lowest_px(&lowest_px[b->ref[i]][0], t->by, bh4,
2086
91.6k
                                 b->mv[i].y, 0, &f->svc[b->ref[i]][1]);
2087
91.6k
                }
2088
93.6k
            }
2089
2090
            // uv
2091
46.8k
            if (has_chroma) for (int i = 0; i < 2; i++) {
2092
23.7k
                if (b->inter_mode == GLOBALMV_GLOBALMV &&
2093
2.97k
                    imin(cbw4, cbh4) > 1 && f->gmv_warp_allowed[b->ref[i]])
2094
230
                {
2095
230
                    affine_lowest_px_chroma(t, &lowest_px[b->ref[i]][1], b_dim,
2096
230
                                            &f->frame_hdr->gmv[b->ref[i]]);
2097
23.5k
                } else {
2098
23.5k
                    mc_lowest_px(&lowest_px[b->ref[i]][1], t->by, bh4,
2099
23.5k
                                 b->mv[i].y, ss_ver, &f->svc[b->ref[i]][1]);
2100
23.5k
                }
2101
23.7k
            }
2102
46.8k
        }
2103
195k
    }
2104
2105
3.16M
    return 0;
2106
3.16M
}
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
4.03M
{
2164
4.03M
    const Dav1dFrameContext *const f = t->f;
2165
4.03M
    Dav1dTileState *const ts = t->ts;
2166
4.03M
    const int hsz = 16 >> bl;
2167
4.03M
    const int have_h_split = f->bw > t->bx + hsz;
2168
4.03M
    const int have_v_split = f->bh > t->by + hsz;
2169
2170
4.03M
    if (!have_h_split && !have_v_split) {
2171
47.6k
        assert(bl < BL_8X8);
2172
47.6k
        return decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0));
2173
47.6k
    }
2174
2175
3.98M
    uint16_t *pc;
2176
3.98M
    enum BlockPartition bp;
2177
3.98M
    int ctx, bx8, by8;
2178
3.98M
    if (t->frame_thread.pass != 2) {
2179
2.35M
        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
2.35M
        bx8 = (t->bx & 31) >> 1;
2183
2.35M
        by8 = (t->by & 31) >> 1;
2184
2.35M
        ctx = get_partition_ctx(t->a, &t->l, bl, by8, bx8);
2185
2.35M
        pc = ts->cdf.m.partition[bl][ctx];
2186
2.35M
    }
2187
2188
3.98M
    if (have_h_split && have_v_split) {
2189
3.08M
        if (t->frame_thread.pass == 2) {
2190
1.22M
            const Av1Block *const b = &f->frame_thread.b[t->by * f->b4_stride + t->bx];
2191
1.22M
            bp = b->bl == bl ? b->bp : PARTITION_SPLIT;
2192
1.85M
        } else {
2193
1.85M
            bp = dav1d_msac_decode_symbol_adapt16(&ts->msac, pc,
2194
1.85M
                                                  dav1d_partition_type_count[bl]);
2195
1.85M
            if (f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I422 &&
2196
3.40k
                (bp == PARTITION_V || bp == PARTITION_V4 ||
2197
3.26k
                 bp == PARTITION_T_LEFT_SPLIT || bp == PARTITION_T_RIGHT_SPLIT))
2198
185
            {
2199
185
                return 1;
2200
185
            }
2201
1.85M
            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
1.85M
        }
2206
3.08M
        const uint8_t *const b = dav1d_block_sizes[bl][bp];
2207
2208
3.08M
        switch (bp) {
2209
1.18M
        case PARTITION_NONE:
2210
1.18M
            if (decode_b(t, bl, b[0], PARTITION_NONE, node->o))
2211
7
                return -1;
2212
1.18M
            break;
2213
1.18M
        case PARTITION_H:
2214
402k
            if (decode_b(t, bl, b[0], PARTITION_H, node->h[0]))
2215
6
                return -1;
2216
402k
            t->by += hsz;
2217
402k
            if (decode_b(t, bl, b[0], PARTITION_H, node->h[1]))
2218
11
                return -1;
2219
402k
            t->by -= hsz;
2220
402k
            break;
2221
281k
        case PARTITION_V:
2222
281k
            if (decode_b(t, bl, b[0], PARTITION_V, node->v[0]))
2223
8
                return -1;
2224
281k
            t->bx += hsz;
2225
281k
            if (decode_b(t, bl, b[0], PARTITION_V, node->v[1]))
2226
10
                return -1;
2227
281k
            t->bx -= hsz;
2228
281k
            break;
2229
696k
        case PARTITION_SPLIT:
2230
696k
            if (bl == BL_8X8) {
2231
120k
                const EdgeTip *const tip = (const EdgeTip *) node;
2232
120k
                assert(hsz == 1);
2233
120k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, EDGE_ALL_TR_AND_BL))
2234
11
                    return -1;
2235
120k
                const enum Filter2d tl_filter = t->tl_4x4_filter;
2236
120k
                t->bx++;
2237
120k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, tip->split[0]))
2238
11
                    return -1;
2239
120k
                t->bx--;
2240
120k
                t->by++;
2241
120k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, tip->split[1]))
2242
8
                    return -1;
2243
120k
                t->bx++;
2244
120k
                t->tl_4x4_filter = tl_filter;
2245
120k
                if (decode_b(t, bl, BS_4x4, PARTITION_SPLIT, tip->split[2]))
2246
7
                    return -1;
2247
120k
                t->bx--;
2248
120k
                t->by--;
2249
120k
#if ARCH_X86_64
2250
120k
                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
120k
                    const int p = t->frame_thread.pass & 1;
2255
120k
                    ts->frame_thread[p].cf =
2256
120k
                        (void*)(((uintptr_t)ts->frame_thread[p].cf + 63) & ~63);
2257
120k
                }
2258
120k
#endif
2259
575k
            } else {
2260
575k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0)))
2261
115
                    return 1;
2262
575k
                t->bx += hsz;
2263
575k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 1)))
2264
124
                    return 1;
2265
575k
                t->bx -= hsz;
2266
575k
                t->by += hsz;
2267
575k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 2)))
2268
102
                    return 1;
2269
575k
                t->bx += hsz;
2270
575k
                if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 3)))
2271
84
                    return 1;
2272
575k
                t->bx -= hsz;
2273
575k
                t->by -= hsz;
2274
575k
            }
2275
695k
            break;
2276
695k
        case PARTITION_T_TOP_SPLIT: {
2277
63.2k
            if (decode_b(t, bl, b[0], PARTITION_T_TOP_SPLIT, EDGE_ALL_TR_AND_BL))
2278
8
                return -1;
2279
63.2k
            t->bx += hsz;
2280
63.2k
            if (decode_b(t, bl, b[0], PARTITION_T_TOP_SPLIT, node->v[1]))
2281
7
                return -1;
2282
63.2k
            t->bx -= hsz;
2283
63.2k
            t->by += hsz;
2284
63.2k
            if (decode_b(t, bl, b[1], PARTITION_T_TOP_SPLIT, node->h[1]))
2285
6
                return -1;
2286
63.2k
            t->by -= hsz;
2287
63.2k
            break;
2288
63.2k
        }
2289
63.3k
        case PARTITION_T_BOTTOM_SPLIT: {
2290
63.3k
            if (decode_b(t, bl, b[0], PARTITION_T_BOTTOM_SPLIT, node->h[0]))
2291
6
                return -1;
2292
63.3k
            t->by += hsz;
2293
63.3k
            if (decode_b(t, bl, b[1], PARTITION_T_BOTTOM_SPLIT, node->v[0]))
2294
6
                return -1;
2295
63.3k
            t->bx += hsz;
2296
63.3k
            if (decode_b(t, bl, b[1], PARTITION_T_BOTTOM_SPLIT, 0))
2297
6
                return -1;
2298
63.3k
            t->bx -= hsz;
2299
63.3k
            t->by -= hsz;
2300
63.3k
            break;
2301
63.3k
        }
2302
48.4k
        case PARTITION_T_LEFT_SPLIT: {
2303
48.4k
            if (decode_b(t, bl, b[0], PARTITION_T_LEFT_SPLIT, EDGE_ALL_TR_AND_BL))
2304
6
                return -1;
2305
48.4k
            t->by += hsz;
2306
48.4k
            if (decode_b(t, bl, b[0], PARTITION_T_LEFT_SPLIT, node->h[1]))
2307
6
                return -1;
2308
48.4k
            t->by -= hsz;
2309
48.4k
            t->bx += hsz;
2310
48.4k
            if (decode_b(t, bl, b[1], PARTITION_T_LEFT_SPLIT, node->v[1]))
2311
6
                return -1;
2312
48.4k
            t->bx -= hsz;
2313
48.4k
            break;
2314
48.4k
        }
2315
58.9k
        case PARTITION_T_RIGHT_SPLIT: {
2316
58.9k
            if (decode_b(t, bl, b[0], PARTITION_T_RIGHT_SPLIT, node->v[0]))
2317
8
                return -1;
2318
58.9k
            t->bx += hsz;
2319
58.9k
            if (decode_b(t, bl, b[1], PARTITION_T_RIGHT_SPLIT, node->h[0]))
2320
10
                return -1;
2321
58.8k
            t->by += hsz;
2322
58.8k
            if (decode_b(t, bl, b[1], PARTITION_T_RIGHT_SPLIT, 0))
2323
10
                return -1;
2324
58.8k
            t->by -= hsz;
2325
58.8k
            t->bx -= hsz;
2326
58.8k
            break;
2327
58.8k
        }
2328
140k
        case PARTITION_H4: {
2329
140k
            const EdgeBranch *const branch = (const EdgeBranch *) node;
2330
140k
            if (decode_b(t, bl, b[0], PARTITION_H4, node->h[0]))
2331
7
                return -1;
2332
140k
            t->by += hsz >> 1;
2333
140k
            if (decode_b(t, bl, b[0], PARTITION_H4, branch->h4))
2334
8
                return -1;
2335
140k
            t->by += hsz >> 1;
2336
140k
            if (decode_b(t, bl, b[0], PARTITION_H4, EDGE_ALL_LEFT_HAS_BOTTOM))
2337
6
                return -1;
2338
140k
            t->by += hsz >> 1;
2339
140k
            if (t->by < f->bh)
2340
139k
                if (decode_b(t, bl, b[0], PARTITION_H4, node->h[1]))
2341
8
                    return -1;
2342
140k
            t->by -= hsz * 3 >> 1;
2343
140k
            break;
2344
140k
        }
2345
146k
        case PARTITION_V4: {
2346
146k
            const EdgeBranch *const branch = (const EdgeBranch *) node;
2347
146k
            if (decode_b(t, bl, b[0], PARTITION_V4, node->v[0]))
2348
10
                return -1;
2349
146k
            t->bx += hsz >> 1;
2350
146k
            if (decode_b(t, bl, b[0], PARTITION_V4, branch->v4))
2351
12
                return -1;
2352
146k
            t->bx += hsz >> 1;
2353
146k
            if (decode_b(t, bl, b[0], PARTITION_V4, EDGE_ALL_TOP_HAS_RIGHT))
2354
6
                return -1;
2355
146k
            t->bx += hsz >> 1;
2356
146k
            if (t->bx < f->bw)
2357
130k
                if (decode_b(t, bl, b[0], PARTITION_V4, node->v[1]))
2358
7
                    return -1;
2359
146k
            t->bx -= hsz * 3 >> 1;
2360
146k
            break;
2361
146k
        }
2362
0
        default: assert(0);
2363
3.08M
        }
2364
3.08M
    } else if (have_h_split) {
2365
296k
        unsigned is_split;
2366
296k
        if (t->frame_thread.pass == 2) {
2367
126k
            const Av1Block *const b = &f->frame_thread.b[t->by * f->b4_stride + t->bx];
2368
126k
            is_split = b->bl != bl;
2369
169k
        } else {
2370
169k
            is_split = dav1d_msac_decode_bool(&ts->msac,
2371
169k
                           gather_top_partition_prob(pc, bl));
2372
169k
            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
169k
        }
2377
2378
296k
        assert(bl < BL_8X8);
2379
296k
        if (is_split) {
2380
157k
            bp = PARTITION_SPLIT;
2381
157k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0))) return 1;
2382
157k
            t->bx += hsz;
2383
157k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 1))) return 1;
2384
157k
            t->bx -= hsz;
2385
157k
        } else {
2386
138k
            bp = PARTITION_H;
2387
138k
            if (decode_b(t, bl, dav1d_block_sizes[bl][PARTITION_H][0],
2388
138k
                         PARTITION_H, node->h[0]))
2389
6
                return -1;
2390
138k
        }
2391
606k
    } else {
2392
606k
        assert(have_v_split);
2393
606k
        unsigned is_split;
2394
606k
        if (t->frame_thread.pass == 2) {
2395
282k
            const Av1Block *const b = &f->frame_thread.b[t->by * f->b4_stride + t->bx];
2396
282k
            is_split = b->bl != bl;
2397
323k
        } else {
2398
323k
            is_split = dav1d_msac_decode_bool(&ts->msac,
2399
323k
                           gather_left_partition_prob(pc, bl));
2400
323k
            if (f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I422 && !is_split)
2401
19
                return 1;
2402
323k
            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
323k
        }
2407
2408
606k
        assert(bl < BL_8X8);
2409
606k
        if (is_split) {
2410
316k
            bp = PARTITION_SPLIT;
2411
316k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 0))) return 1;
2412
316k
            t->by += hsz;
2413
316k
            if (decode_sb(t, bl + 1, INTRA_EDGE_SPLIT(node, 2))) return 1;
2414
316k
            t->by -= hsz;
2415
316k
        } else {
2416
290k
            bp = PARTITION_V;
2417
290k
            if (decode_b(t, bl, dav1d_block_sizes[bl][PARTITION_V][0],
2418
290k
                         PARTITION_V, node->v[0]))
2419
9
                return -1;
2420
290k
        }
2421
606k
    }
2422
2423
3.98M
    if (t->frame_thread.pass != 2 && (bp != PARTITION_SPLIT || bl == BL_8X8)) {
2424
1.73M
#define set_ctx(rep_macro) \
2425
1.73M
        rep_macro(t->a->partition, bx8, dav1d_al_part_ctx[0][bl][bp]); \
2426
1.73M
        rep_macro(t->l.partition, by8, dav1d_al_part_ctx[1][bl][bp])
2427
1.73M
        case_set_upto16(ulog2(hsz));
2428
1.73M
#undef set_ctx
2429
1.73M
    }
2430
2431
3.98M
    return 0;
2432
3.98M
}
2433
2434
482k
static void reset_context(BlockContext *const ctx, const int keyframe, const int pass) {
2435
482k
    memset(ctx->intra, keyframe, sizeof(ctx->intra));
2436
482k
    memset(ctx->uvmode, DC_PRED, sizeof(ctx->uvmode));
2437
482k
    if (keyframe)
2438
427k
        memset(ctx->mode, DC_PRED, sizeof(ctx->mode));
2439
2440
482k
    if (pass == 2) return;
2441
2442
251k
    memset(ctx->partition, 0, sizeof(ctx->partition));
2443
251k
    memset(ctx->skip, 0, sizeof(ctx->skip));
2444
251k
    memset(ctx->skip_mode, 0, sizeof(ctx->skip_mode));
2445
251k
    memset(ctx->tx_lpf_y, 2, sizeof(ctx->tx_lpf_y));
2446
251k
    memset(ctx->tx_lpf_uv, 1, sizeof(ctx->tx_lpf_uv));
2447
251k
    memset(ctx->tx_intra, -1, sizeof(ctx->tx_intra));
2448
251k
    memset(ctx->tx, TX_64X64, sizeof(ctx->tx));
2449
251k
    if (!keyframe) {
2450
28.9k
        memset(ctx->ref, -1, sizeof(ctx->ref));
2451
28.9k
        memset(ctx->comp_type, 0, sizeof(ctx->comp_type));
2452
28.9k
        memset(ctx->mode, NEARESTMV, sizeof(ctx->mode));
2453
28.9k
    }
2454
251k
    memset(ctx->lcoef, 0x40, sizeof(ctx->lcoef));
2455
251k
    memset(ctx->ccoef, 0x40, sizeof(ctx->ccoef));
2456
251k
    memset(ctx->filter, DAV1D_N_SWITCHABLE_FILTERS, sizeof(ctx->filter));
2457
251k
    memset(ctx->seg_pred, 0, sizeof(ctx->seg_pred));
2458
251k
    memset(ctx->pal_sz, 0, sizeof(ctx->pal_sz));
2459
251k
}
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
38.3k
{
2475
38.3k
    const int col_sb_start = f->frame_hdr->tiling.col_start_sb[tile_col];
2476
38.3k
    const int col_sb128_start = col_sb_start >> !f->seq_hdr->sb128;
2477
38.3k
    const int col_sb_end = f->frame_hdr->tiling.col_start_sb[tile_col + 1];
2478
38.3k
    const int row_sb_start = f->frame_hdr->tiling.row_start_sb[tile_row];
2479
38.3k
    const int row_sb_end = f->frame_hdr->tiling.row_start_sb[tile_row + 1];
2480
38.3k
    const int sb_shift = f->sb_shift;
2481
2482
38.3k
    const uint8_t *const size_mul = ss_size_mul[f->cur.p.layout];
2483
115k
    for (int p = 0; p < 2; p++) {
2484
76.7k
        ts->frame_thread[p].pal_idx = f->frame_thread.pal_idx ?
2485
16.7k
            &f->frame_thread.pal_idx[(size_t)tile_start_off * size_mul[1] / 8] :
2486
76.7k
            NULL;
2487
76.7k
        ts->frame_thread[p].cbi = f->frame_thread.cbi ?
2488
76.7k
            &f->frame_thread.cbi[(size_t)tile_start_off * size_mul[0] / 64] :
2489
76.7k
            NULL;
2490
76.7k
        ts->frame_thread[p].cf = f->frame_thread.cf ?
2491
76.7k
            (uint8_t*)f->frame_thread.cf +
2492
76.7k
                (((size_t)tile_start_off * size_mul[0]) >> !f->seq_hdr->hbd) :
2493
76.7k
            NULL;
2494
76.7k
    }
2495
2496
38.3k
    dav1d_cdf_thread_copy(&ts->cdf, &f->in_cdf);
2497
38.3k
    ts->last_qidx = f->frame_hdr->quant.yac;
2498
38.3k
    ts->last_delta_lf.u32 = 0;
2499
2500
38.3k
    dav1d_msac_init(&ts->msac, data, sz, f->frame_hdr->disable_cdf_update);
2501
2502
38.3k
    ts->tiling.row = tile_row;
2503
38.3k
    ts->tiling.col = tile_col;
2504
38.3k
    ts->tiling.col_start = col_sb_start << sb_shift;
2505
38.3k
    ts->tiling.col_end = imin(col_sb_end << sb_shift, f->bw);
2506
38.3k
    ts->tiling.row_start = row_sb_start << sb_shift;
2507
38.3k
    ts->tiling.row_end = imin(row_sb_end << sb_shift, f->bh);
2508
2509
    // Reference Restoration Unit (used for exp coding)
2510
38.3k
    int sb_idx, unit_idx;
2511
38.3k
    if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
2512
        // vertical components only
2513
6.22k
        sb_idx = (ts->tiling.row_start >> 5) * f->sr_sb128w;
2514
6.22k
        unit_idx = (ts->tiling.row_start & 16) >> 3;
2515
32.1k
    } else {
2516
32.1k
        sb_idx = (ts->tiling.row_start >> 5) * f->sb128w + col_sb128_start;
2517
32.1k
        unit_idx = ((ts->tiling.row_start & 16) >> 3) +
2518
32.1k
                   ((ts->tiling.col_start & 16) >> 4);
2519
32.1k
    }
2520
153k
    for (int p = 0; p < 3; p++) {
2521
115k
        if (!((f->lf.restore_planes >> p) & 1U))
2522
93.9k
            continue;
2523
2524
21.1k
        if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
2525
7.18k
            const int ss_hor = p && f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
2526
7.18k
            const int d = f->frame_hdr->super_res.width_scale_denominator;
2527
7.18k
            const int unit_size_log2 = f->frame_hdr->restoration.unit_size[!!p];
2528
7.18k
            const int rnd = (8 << unit_size_log2) - 1, shift = unit_size_log2 + 3;
2529
7.18k
            const int x = ((4 * ts->tiling.col_start * d >> ss_hor) + rnd) >> shift;
2530
7.18k
            const int px_x = x << (unit_size_log2 + ss_hor);
2531
7.18k
            const int u_idx = unit_idx + ((px_x & 64) >> 6);
2532
7.18k
            const int sb128x = px_x >> 7;
2533
7.18k
            if (sb128x >= f->sr_sb128w) continue;
2534
6.80k
            ts->lr_ref[p] = &f->lf.lr_mask[sb_idx + sb128x].lr[p][u_idx];
2535
13.9k
        } else {
2536
13.9k
            ts->lr_ref[p] = &f->lf.lr_mask[sb_idx].lr[p][unit_idx];
2537
13.9k
        }
2538
2539
20.7k
        ts->lr_ref[p]->filter_v[0] = 3;
2540
20.7k
        ts->lr_ref[p]->filter_v[1] = -7;
2541
20.7k
        ts->lr_ref[p]->filter_v[2] = 15;
2542
20.7k
        ts->lr_ref[p]->filter_h[0] = 3;
2543
20.7k
        ts->lr_ref[p]->filter_h[1] = -7;
2544
20.7k
        ts->lr_ref[p]->filter_h[2] = 15;
2545
20.7k
        ts->lr_ref[p]->sgr_weights[0] = -32;
2546
20.7k
        ts->lr_ref[p]->sgr_weights[1] = 31;
2547
20.7k
    }
2548
2549
38.3k
    if (f->c->n_tc > 1) {
2550
115k
        for (int p = 0; p < 2; p++)
2551
76.7k
            atomic_init(&ts->progress[p], row_sb_start);
2552
38.3k
    }
2553
38.3k
}
2554
2555
static void read_restoration_info(Dav1dTaskContext *const t,
2556
                                  Av1RestorationUnit *const lr, const int p,
2557
                                  const enum Dav1dRestorationType frame_type)
2558
190k
{
2559
190k
    const Dav1dFrameContext *const f = t->f;
2560
190k
    Dav1dTileState *const ts = t->ts;
2561
190k
    const Av1RestorationUnit *const lr_ref = ts->lr_ref[p];
2562
2563
190k
    if (frame_type == DAV1D_RESTORATION_SWITCHABLE) {
2564
68.7k
        const int filter = dav1d_msac_decode_symbol_adapt4(&ts->msac,
2565
68.7k
                               ts->cdf.m.restore_switchable, 2);
2566
68.7k
        lr->type = filter + !!filter; /* NONE/WIENER/SGRPROJ */
2567
121k
    } else {
2568
121k
        const unsigned type =
2569
121k
            dav1d_msac_decode_bool_adapt(&ts->msac,
2570
121k
                frame_type == DAV1D_RESTORATION_WIENER ?
2571
66.6k
                ts->cdf.m.restore_wiener : ts->cdf.m.restore_sgrproj);
2572
121k
        lr->type = type ? frame_type : DAV1D_RESTORATION_NONE;
2573
121k
    }
2574
2575
190k
    if (lr->type == DAV1D_RESTORATION_WIENER) {
2576
58.3k
        lr->filter_v[0] = p ? 0 :
2577
58.3k
            dav1d_msac_decode_subexp(&ts->msac,
2578
29.0k
                lr_ref->filter_v[0] + 5, 16, 1) - 5;
2579
58.3k
        lr->filter_v[1] =
2580
58.3k
            dav1d_msac_decode_subexp(&ts->msac,
2581
58.3k
                lr_ref->filter_v[1] + 23, 32, 2) - 23;
2582
58.3k
        lr->filter_v[2] =
2583
58.3k
            dav1d_msac_decode_subexp(&ts->msac,
2584
58.3k
                lr_ref->filter_v[2] + 17, 64, 3) - 17;
2585
2586
58.3k
        lr->filter_h[0] = p ? 0 :
2587
58.3k
            dav1d_msac_decode_subexp(&ts->msac,
2588
29.0k
                lr_ref->filter_h[0] + 5, 16, 1) - 5;
2589
58.3k
        lr->filter_h[1] =
2590
58.3k
            dav1d_msac_decode_subexp(&ts->msac,
2591
58.3k
                lr_ref->filter_h[1] + 23, 32, 2) - 23;
2592
58.3k
        lr->filter_h[2] =
2593
58.3k
            dav1d_msac_decode_subexp(&ts->msac,
2594
58.3k
                lr_ref->filter_h[2] + 17, 64, 3) - 17;
2595
58.3k
        memcpy(lr->sgr_weights, lr_ref->sgr_weights, sizeof(lr->sgr_weights));
2596
58.3k
        ts->lr_ref[p] = lr;
2597
58.3k
        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
131k
    } else if (lr->type == DAV1D_RESTORATION_SGRPROJ) {
2603
52.1k
        const unsigned idx = dav1d_msac_decode_bools(&ts->msac, 4);
2604
52.1k
        const uint16_t *const sgr_params = dav1d_sgr_params[idx];
2605
52.1k
        lr->type += idx;
2606
52.1k
        lr->sgr_weights[0] = sgr_params[0] ? dav1d_msac_decode_subexp(&ts->msac,
2607
41.2k
            lr_ref->sgr_weights[0] + 96, 128, 4) - 96 : 0;
2608
52.1k
        lr->sgr_weights[1] = sgr_params[1] ? dav1d_msac_decode_subexp(&ts->msac,
2609
37.7k
            lr_ref->sgr_weights[1] + 32, 128, 4) - 32 : 95;
2610
52.1k
        memcpy(lr->filter_v, lr_ref->filter_v, sizeof(lr->filter_v));
2611
52.1k
        memcpy(lr->filter_h, lr_ref->filter_h, sizeof(lr->filter_h));
2612
52.1k
        ts->lr_ref[p] = lr;
2613
52.1k
        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
52.1k
    }
2618
190k
}
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
295k
int dav1d_decode_tile_sbrow(Dav1dTaskContext *const t) {
2640
295k
    const Dav1dFrameContext *const f = t->f;
2641
295k
    const enum BlockLevel root_bl = f->seq_hdr->sb128 ? BL_128X128 : BL_64X64;
2642
295k
    Dav1dTileState *const ts = t->ts;
2643
295k
    const Dav1dContext *const c = f->c;
2644
295k
    const int sb_step = f->sb_step;
2645
295k
    const int tile_row = ts->tiling.row, tile_col = ts->tiling.col;
2646
295k
    const int col_sb_start = f->frame_hdr->tiling.col_start_sb[tile_col];
2647
295k
    const int col_sb128_start = col_sb_start >> !f->seq_hdr->sb128;
2648
2649
295k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc) {
2650
104k
        dav1d_refmvs_tile_sbrow_init(&t->rt, &f->rf, ts->tiling.col_start,
2651
104k
                                     ts->tiling.col_end, ts->tiling.row_start,
2652
104k
                                     ts->tiling.row_end, t->by >> f->sb_shift,
2653
104k
                                     ts->tiling.row, t->frame_thread.pass);
2654
104k
    }
2655
2656
295k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) && c->n_fc > 1) {
2657
21.5k
        const int sby = (t->by - ts->tiling.row_start) >> f->sb_shift;
2658
21.5k
        int (*const lowest_px)[2] = ts->lowest_pixel[sby];
2659
172k
        for (int n = 0; n < 7; n++)
2660
452k
            for (int m = 0; m < 2; m++)
2661
301k
                lowest_px[n][m] = INT_MIN;
2662
21.5k
    }
2663
2664
295k
    reset_context(&t->l, IS_KEY_OR_INTRA(f->frame_hdr), t->frame_thread.pass);
2665
295k
    if (t->frame_thread.pass == 2) {
2666
137k
        const int off_2pass = c->n_tc > 1 ? f->sb128w * f->frame_hdr->tiling.rows : 0;
2667
137k
        for (t->bx = ts->tiling.col_start,
2668
137k
             t->a = f->a + off_2pass + col_sb128_start + tile_row * f->sb128w;
2669
461k
             t->bx < ts->tiling.col_end; t->bx += sb_step)
2670
324k
        {
2671
324k
            if (atomic_load_explicit(c->flush, memory_order_acquire))
2672
11
                return 1;
2673
324k
            if (decode_sb(t, root_bl, dav1d_intra_edge_tree[root_bl]))
2674
0
                return 1;
2675
324k
            if (t->bx & 16 || f->seq_hdr->sb128)
2676
153k
                t->a++;
2677
324k
        }
2678
137k
        f->bd_fn.backup_ipred_edge(t);
2679
137k
        return 0;
2680
137k
    }
2681
2682
158k
    if (f->c->n_tc > 1 && f->frame_hdr->use_ref_frame_mvs) {
2683
1.63k
        f->c->refmvs_dsp.load_tmvs(&f->rf, ts->tiling.row,
2684
1.63k
                                   ts->tiling.col_start >> 1, ts->tiling.col_end >> 1,
2685
1.63k
                                   t->by >> 1, (t->by + sb_step) >> 1);
2686
1.63k
    }
2687
158k
    memset(t->pal_sz_uv[1], 0, sizeof(*t->pal_sz_uv));
2688
158k
    const int sb128y = t->by >> 5;
2689
158k
    for (t->bx = ts->tiling.col_start, t->a = f->a + col_sb128_start + tile_row * f->sb128w,
2690
158k
         t->lf_mask = f->lf.mask + sb128y * f->sb128w + col_sb128_start;
2691
571k
         t->bx < ts->tiling.col_end; t->bx += sb_step)
2692
413k
    {
2693
413k
        if (atomic_load_explicit(c->flush, memory_order_acquire))
2694
66
            return 1;
2695
413k
        if (root_bl == BL_128X128) {
2696
89.1k
            t->cur_sb_cdef_idx_ptr = t->lf_mask->cdef_idx;
2697
89.1k
            t->cur_sb_cdef_idx_ptr[0] = -1;
2698
89.1k
            t->cur_sb_cdef_idx_ptr[1] = -1;
2699
89.1k
            t->cur_sb_cdef_idx_ptr[2] = -1;
2700
89.1k
            t->cur_sb_cdef_idx_ptr[3] = -1;
2701
324k
        } else {
2702
324k
            t->cur_sb_cdef_idx_ptr =
2703
324k
                &t->lf_mask->cdef_idx[((t->bx & 16) >> 4) +
2704
324k
                                      ((t->by & 16) >> 3)];
2705
324k
            t->cur_sb_cdef_idx_ptr[0] = -1;
2706
324k
        }
2707
        // Restoration filter
2708
1.65M
        for (int p = 0; p < 3; p++) {
2709
1.24M
            if (!((f->lf.restore_planes >> p) & 1U))
2710
878k
                continue;
2711
2712
362k
            const int ss_ver = p && f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
2713
362k
            const int ss_hor = p && f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
2714
362k
            const int unit_size_log2 = f->frame_hdr->restoration.unit_size[!!p];
2715
362k
            const int y = t->by * 4 >> ss_ver;
2716
362k
            const int h = (f->cur.p.h + ss_ver) >> ss_ver;
2717
2718
362k
            const int unit_size = 1 << unit_size_log2;
2719
362k
            const unsigned mask = unit_size - 1;
2720
362k
            if (y & mask) continue;
2721
235k
            const int half_unit = unit_size >> 1;
2722
            // Round half up at frame boundaries, if there's more than one
2723
            // restoration unit
2724
235k
            if (y && y + half_unit > h) continue;
2725
2726
225k
            const enum Dav1dRestorationType frame_type = f->frame_hdr->restoration.type[p];
2727
2728
225k
            if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
2729
55.1k
                const int w = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
2730
55.1k
                const int n_units = imax(1, (w + half_unit) >> unit_size_log2);
2731
2732
55.1k
                const int d = f->frame_hdr->super_res.width_scale_denominator;
2733
55.1k
                const int rnd = unit_size * 8 - 1, shift = unit_size_log2 + 3;
2734
55.1k
                const int x0 = ((4 *  t->bx            * d >> ss_hor) + rnd) >> shift;
2735
55.1k
                const int x1 = ((4 * (t->bx + sb_step) * d >> ss_hor) + rnd) >> shift;
2736
2737
116k
                for (int x = x0; x < imin(x1, n_units); x++) {
2738
61.0k
                    const int px_x = x << (unit_size_log2 + ss_hor);
2739
61.0k
                    const int sb_idx = (t->by >> 5) * f->sr_sb128w + (px_x >> 7);
2740
61.0k
                    const int unit_idx = ((t->by & 16) >> 3) + ((px_x & 64) >> 6);
2741
61.0k
                    Av1RestorationUnit *const lr = &f->lf.lr_mask[sb_idx].lr[p][unit_idx];
2742
2743
61.0k
                    read_restoration_info(t, lr, p, frame_type);
2744
61.0k
                }
2745
170k
            } else {
2746
170k
                const int x = 4 * t->bx >> ss_hor;
2747
170k
                if (x & mask) continue;
2748
131k
                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
131k
                if (x && x + half_unit > w) continue;
2752
129k
                const int sb_idx = (t->by >> 5) * f->sr_sb128w + (t->bx >> 5);
2753
129k
                const int unit_idx = ((t->by & 16) >> 3) + ((t->bx & 16) >> 4);
2754
129k
                Av1RestorationUnit *const lr = &f->lf.lr_mask[sb_idx].lr[p][unit_idx];
2755
2756
129k
                read_restoration_info(t, lr, p, frame_type);
2757
129k
            }
2758
225k
        }
2759
413k
        if (decode_sb(t, root_bl, dav1d_intra_edge_tree[root_bl]))
2760
447
            return 1;
2761
413k
        if (t->bx & 16 || f->seq_hdr->sb128) {
2762
202k
            t->a++;
2763
202k
            t->lf_mask++;
2764
202k
        }
2765
413k
    }
2766
2767
157k
    if (f->seq_hdr->ref_frame_mvs && f->c->n_tc > 1 && IS_INTER_OR_SWITCH(f->frame_hdr)) {
2768
3.50k
        dav1d_refmvs_save_tmvs(&f->c->refmvs_dsp, &t->rt,
2769
3.50k
                               ts->tiling.col_start >> 1, ts->tiling.col_end >> 1,
2770
3.50k
                               t->by >> 1, (t->by + sb_step) >> 1);
2771
3.50k
    }
2772
2773
    // backup pre-loopfilter pixels for intra prediction of the next sbrow
2774
157k
    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
157k
    int align_h = (f->bh + 31) & ~31;
2780
157k
    memcpy(&f->lf.tx_lpf_right_edge[0][align_h * tile_col + t->by],
2781
157k
           &t->l.tx_lpf_y[t->by & 16], sb_step);
2782
157k
    const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
2783
157k
    align_h >>= ss_ver;
2784
157k
    memcpy(&f->lf.tx_lpf_right_edge[1][align_h * tile_col + (t->by >> ss_ver)],
2785
157k
           &t->l.tx_lpf_uv[(t->by & 16) >> ss_ver], sb_step >> ss_ver);
2786
2787
    // error out on symbol decoder overread
2788
157k
    if (ts->msac.cnt <= -15) return 1;
2789
2790
150k
    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
157k
}
2794
2795
26.8k
int dav1d_decode_frame_init(Dav1dFrameContext *const f) {
2796
26.8k
    const Dav1dContext *const c = f->c;
2797
26.8k
    int retval = DAV1D_ERR(ENOMEM);
2798
2799
26.8k
    if (f->sbh > f->lf.start_of_tile_row_sz) {
2800
26.4k
        dav1d_free(f->lf.start_of_tile_row);
2801
26.4k
        f->lf.start_of_tile_row = dav1d_malloc(ALLOC_TILE, f->sbh * sizeof(uint8_t));
2802
26.4k
        if (!f->lf.start_of_tile_row) {
2803
0
            f->lf.start_of_tile_row_sz = 0;
2804
0
            goto error;
2805
0
        }
2806
26.4k
        f->lf.start_of_tile_row_sz = f->sbh;
2807
26.4k
    }
2808
26.8k
    int sby = 0;
2809
58.1k
    for (int tile_row = 0; tile_row < f->frame_hdr->tiling.rows; tile_row++) {
2810
31.3k
        f->lf.start_of_tile_row[sby++] = tile_row;
2811
336k
        while (sby < f->frame_hdr->tiling.row_start_sb[tile_row + 1])
2812
304k
            f->lf.start_of_tile_row[sby++] = 0;
2813
31.3k
    }
2814
2815
26.8k
    const int n_ts = f->frame_hdr->tiling.cols * f->frame_hdr->tiling.rows;
2816
26.8k
    if (n_ts != f->n_ts) {
2817
26.5k
        if (c->n_fc > 1) {
2818
26.5k
            dav1d_free(f->frame_thread.tile_start_off);
2819
26.5k
            f->frame_thread.tile_start_off =
2820
26.5k
                dav1d_malloc(ALLOC_TILE, sizeof(*f->frame_thread.tile_start_off) * n_ts);
2821
26.5k
            if (!f->frame_thread.tile_start_off) {
2822
0
                f->n_ts = 0;
2823
0
                goto error;
2824
0
            }
2825
26.5k
        }
2826
26.5k
        dav1d_free_aligned(f->ts);
2827
26.5k
        f->ts = dav1d_alloc_aligned(ALLOC_TILE, sizeof(*f->ts) * n_ts, 32);
2828
26.5k
        if (!f->ts) goto error;
2829
26.5k
        f->n_ts = n_ts;
2830
26.5k
    }
2831
2832
26.8k
    const int a_sz = f->sb128w * f->frame_hdr->tiling.rows * (1 + (c->n_fc > 1 && c->n_tc > 1));
2833
26.8k
    if (a_sz != f->a_sz) {
2834
26.4k
        dav1d_free(f->a);
2835
26.4k
        f->a = dav1d_malloc(ALLOC_TILE, sizeof(*f->a) * a_sz);
2836
26.4k
        if (!f->a) {
2837
0
            f->a_sz = 0;
2838
0
            goto error;
2839
0
        }
2840
26.4k
        f->a_sz = a_sz;
2841
26.4k
    }
2842
2843
26.8k
    const int num_sb128 = f->sb128w * f->sb128h;
2844
26.8k
    const uint8_t *const size_mul = ss_size_mul[f->cur.p.layout];
2845
26.8k
    const int hbd = !!f->seq_hdr->hbd;
2846
26.8k
    if (c->n_fc > 1) {
2847
26.8k
        const unsigned sb_step4 = f->sb_step * 4;
2848
26.8k
        int tile_idx = 0;
2849
58.1k
        for (int tile_row = 0; tile_row < f->frame_hdr->tiling.rows; tile_row++) {
2850
31.3k
            const unsigned row_off = f->frame_hdr->tiling.row_start_sb[tile_row] *
2851
31.3k
                                     sb_step4 * f->sb128w * 128;
2852
31.3k
            const unsigned b_diff = (f->frame_hdr->tiling.row_start_sb[tile_row + 1] -
2853
31.3k
                                     f->frame_hdr->tiling.row_start_sb[tile_row]) * sb_step4;
2854
74.9k
            for (int tile_col = 0; tile_col < f->frame_hdr->tiling.cols; tile_col++) {
2855
43.6k
                f->frame_thread.tile_start_off[tile_idx++] = row_off + b_diff *
2856
43.6k
                    f->frame_hdr->tiling.col_start_sb[tile_col] * sb_step4;
2857
43.6k
            }
2858
31.3k
        }
2859
2860
26.8k
        const int lowest_pixel_mem_sz = f->frame_hdr->tiling.cols * f->sbh;
2861
26.8k
        if (lowest_pixel_mem_sz != f->tile_thread.lowest_pixel_mem_sz) {
2862
26.4k
            dav1d_free(f->tile_thread.lowest_pixel_mem);
2863
26.4k
            f->tile_thread.lowest_pixel_mem =
2864
26.4k
                dav1d_malloc(ALLOC_TILE, lowest_pixel_mem_sz *
2865
26.4k
                             sizeof(*f->tile_thread.lowest_pixel_mem));
2866
26.4k
            if (!f->tile_thread.lowest_pixel_mem) {
2867
0
                f->tile_thread.lowest_pixel_mem_sz = 0;
2868
0
                goto error;
2869
0
            }
2870
26.4k
            f->tile_thread.lowest_pixel_mem_sz = lowest_pixel_mem_sz;
2871
26.4k
        }
2872
26.8k
        int (*lowest_pixel_ptr)[7][2] = f->tile_thread.lowest_pixel_mem;
2873
58.1k
        for (int tile_row = 0, tile_row_base = 0; tile_row < f->frame_hdr->tiling.rows;
2874
31.3k
             tile_row++, tile_row_base += f->frame_hdr->tiling.cols)
2875
31.3k
        {
2876
31.3k
            const int tile_row_sb_h = f->frame_hdr->tiling.row_start_sb[tile_row + 1] -
2877
31.3k
                                      f->frame_hdr->tiling.row_start_sb[tile_row];
2878
74.9k
            for (int tile_col = 0; tile_col < f->frame_hdr->tiling.cols; tile_col++) {
2879
43.6k
                f->ts[tile_row_base + tile_col].lowest_pixel = lowest_pixel_ptr;
2880
43.6k
                lowest_pixel_ptr += tile_row_sb_h;
2881
43.6k
            }
2882
31.3k
        }
2883
2884
26.8k
        const int cbi_sz = num_sb128 * size_mul[0];
2885
26.8k
        if (cbi_sz != f->frame_thread.cbi_sz) {
2886
26.4k
            dav1d_free_aligned(f->frame_thread.cbi);
2887
26.4k
            f->frame_thread.cbi =
2888
26.4k
                dav1d_alloc_aligned(ALLOC_BLOCK, sizeof(*f->frame_thread.cbi) *
2889
26.4k
                                    cbi_sz * 32 * 32 / 4, 64);
2890
26.4k
            if (!f->frame_thread.cbi) {
2891
0
                f->frame_thread.cbi_sz = 0;
2892
0
                goto error;
2893
0
            }
2894
26.4k
            f->frame_thread.cbi_sz = cbi_sz;
2895
26.4k
        }
2896
2897
26.8k
        const int cf_sz = (num_sb128 * size_mul[0]) << hbd;
2898
26.8k
        if (cf_sz != f->frame_thread.cf_sz) {
2899
26.4k
            dav1d_free_aligned(f->frame_thread.cf);
2900
26.4k
            f->frame_thread.cf =
2901
26.4k
                dav1d_alloc_aligned(ALLOC_COEF, (size_t)cf_sz * 128 * 128 / 2, 64);
2902
26.4k
            if (!f->frame_thread.cf) {
2903
0
                f->frame_thread.cf_sz = 0;
2904
0
                goto error;
2905
0
            }
2906
26.4k
            memset(f->frame_thread.cf, 0, (size_t)cf_sz * 128 * 128 / 2);
2907
26.4k
            f->frame_thread.cf_sz = cf_sz;
2908
26.4k
        }
2909
2910
26.8k
        if (f->frame_hdr->allow_screen_content_tools) {
2911
7.72k
            const int pal_sz = num_sb128 << hbd;
2912
7.72k
            if (pal_sz != f->frame_thread.pal_sz) {
2913
7.69k
                dav1d_free_aligned(f->frame_thread.pal);
2914
7.69k
                f->frame_thread.pal =
2915
7.69k
                    dav1d_alloc_aligned(ALLOC_PAL, sizeof(*f->frame_thread.pal) *
2916
7.69k
                                        pal_sz * 16 * 16, 64);
2917
7.69k
                if (!f->frame_thread.pal) {
2918
0
                    f->frame_thread.pal_sz = 0;
2919
0
                    goto error;
2920
0
                }
2921
7.69k
                f->frame_thread.pal_sz = pal_sz;
2922
7.69k
            }
2923
2924
7.72k
            const int pal_idx_sz = num_sb128 * size_mul[1];
2925
7.72k
            if (pal_idx_sz != f->frame_thread.pal_idx_sz) {
2926
7.69k
                dav1d_free_aligned(f->frame_thread.pal_idx);
2927
7.69k
                f->frame_thread.pal_idx =
2928
7.69k
                    dav1d_alloc_aligned(ALLOC_PAL, sizeof(*f->frame_thread.pal_idx) *
2929
7.69k
                                        pal_idx_sz * 128 * 128 / 8, 64);
2930
7.69k
                if (!f->frame_thread.pal_idx) {
2931
0
                    f->frame_thread.pal_idx_sz = 0;
2932
0
                    goto error;
2933
0
                }
2934
7.69k
                f->frame_thread.pal_idx_sz = pal_idx_sz;
2935
7.69k
            }
2936
19.0k
        } else if (f->frame_thread.pal) {
2937
13
            dav1d_freep_aligned(&f->frame_thread.pal);
2938
13
            dav1d_freep_aligned(&f->frame_thread.pal_idx);
2939
13
            f->frame_thread.pal_sz = f->frame_thread.pal_idx_sz = 0;
2940
13
        }
2941
26.8k
    }
2942
2943
    // update allocation of block contexts for above
2944
26.8k
    ptrdiff_t y_stride = f->cur.stride[0], uv_stride = f->cur.stride[1];
2945
26.8k
    const int has_resize = f->frame_hdr->width[0] != f->frame_hdr->width[1];
2946
26.8k
    const int need_cdef_lpf_copy = c->n_tc > 1 && has_resize;
2947
26.8k
    if (y_stride * f->sbh * 4 != f->lf.cdef_buf_plane_sz[0] ||
2948
364
        uv_stride * f->sbh * 8 != f->lf.cdef_buf_plane_sz[1] ||
2949
340
        need_cdef_lpf_copy != f->lf.need_cdef_lpf_copy ||
2950
325
        f->sbh != f->lf.cdef_buf_sbh)
2951
26.4k
    {
2952
26.4k
        dav1d_free_aligned(f->lf.cdef_line_buf);
2953
26.4k
        size_t alloc_sz = 64;
2954
26.4k
        alloc_sz += (size_t)llabs(y_stride) * 4 * f->sbh << need_cdef_lpf_copy;
2955
26.4k
        alloc_sz += (size_t)llabs(uv_stride) * 8 * f->sbh << need_cdef_lpf_copy;
2956
26.4k
        uint8_t *ptr = f->lf.cdef_line_buf = dav1d_alloc_aligned(ALLOC_CDEF, alloc_sz, 32);
2957
26.4k
        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
26.4k
        ptr += 32;
2963
26.4k
        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
26.4k
        } else {
2967
26.4k
            f->lf.cdef_line[0][0] = ptr + y_stride * 0;
2968
26.4k
            f->lf.cdef_line[1][0] = ptr + y_stride * 2;
2969
26.4k
        }
2970
26.4k
        ptr += llabs(y_stride) * f->sbh * 4;
2971
26.4k
        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
26.4k
        } else {
2977
26.4k
            f->lf.cdef_line[0][1] = ptr + uv_stride * 0;
2978
26.4k
            f->lf.cdef_line[0][2] = ptr + uv_stride * 2;
2979
26.4k
            f->lf.cdef_line[1][1] = ptr + uv_stride * 4;
2980
26.4k
            f->lf.cdef_line[1][2] = ptr + uv_stride * 6;
2981
26.4k
        }
2982
2983
26.4k
        if (need_cdef_lpf_copy) {
2984
3.17k
            ptr += llabs(uv_stride) * f->sbh * 8;
2985
3.17k
            if (y_stride < 0)
2986
0
                f->lf.cdef_lpf_line[0] = ptr - y_stride * (f->sbh * 4 - 1);
2987
3.17k
            else
2988
3.17k
                f->lf.cdef_lpf_line[0] = ptr;
2989
3.17k
            ptr += llabs(y_stride) * f->sbh * 4;
2990
3.17k
            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
3.17k
            } else {
2994
3.17k
                f->lf.cdef_lpf_line[1] = ptr;
2995
3.17k
                f->lf.cdef_lpf_line[2] = ptr + uv_stride * f->sbh * 4;
2996
3.17k
            }
2997
3.17k
        }
2998
2999
26.4k
        f->lf.cdef_buf_plane_sz[0] = (int) y_stride * f->sbh * 4;
3000
26.4k
        f->lf.cdef_buf_plane_sz[1] = (int) uv_stride * f->sbh * 8;
3001
26.4k
        f->lf.need_cdef_lpf_copy = need_cdef_lpf_copy;
3002
26.4k
        f->lf.cdef_buf_sbh = f->sbh;
3003
26.4k
    }
3004
3005
26.8k
    const int sb128 = f->seq_hdr->sb128;
3006
26.8k
    const int num_lines = c->n_tc > 1 ? f->sbh * 4 << sb128 : 12;
3007
26.8k
    y_stride = f->sr_cur.p.stride[0], uv_stride = f->sr_cur.p.stride[1];
3008
26.8k
    if (y_stride * num_lines != f->lf.lr_buf_plane_sz[0] ||
3009
355
        uv_stride * num_lines * 2 != f->lf.lr_buf_plane_sz[1])
3010
26.4k
    {
3011
26.4k
        dav1d_free_aligned(f->lf.lr_line_buf);
3012
        // lr simd may overread the input, so slightly over-allocate the lpf buffer
3013
26.4k
        size_t alloc_sz = 128;
3014
26.4k
        alloc_sz += (size_t)llabs(y_stride) * num_lines;
3015
26.4k
        alloc_sz += (size_t)llabs(uv_stride) * num_lines * 2;
3016
26.4k
        uint8_t *ptr = f->lf.lr_line_buf = dav1d_alloc_aligned(ALLOC_LR, alloc_sz, 64);
3017
26.4k
        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
26.4k
        ptr += 64;
3023
26.4k
        if (y_stride < 0)
3024
0
            f->lf.lr_lpf_line[0] = ptr - y_stride * (num_lines - 1);
3025
26.4k
        else
3026
26.4k
            f->lf.lr_lpf_line[0] = ptr;
3027
26.4k
        ptr += llabs(y_stride) * num_lines;
3028
26.4k
        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
26.4k
        } else {
3032
26.4k
            f->lf.lr_lpf_line[1] = ptr;
3033
26.4k
            f->lf.lr_lpf_line[2] = ptr + uv_stride * num_lines;
3034
26.4k
        }
3035
3036
26.4k
        f->lf.lr_buf_plane_sz[0] = (int) y_stride * num_lines;
3037
26.4k
        f->lf.lr_buf_plane_sz[1] = (int) uv_stride * num_lines * 2;
3038
26.4k
    }
3039
3040
    // update allocation for loopfilter masks
3041
26.8k
    if (num_sb128 != f->lf.mask_sz) {
3042
26.4k
        dav1d_free(f->lf.mask);
3043
26.4k
        dav1d_free(f->lf.level);
3044
26.4k
        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
26.4k
        f->lf.level = dav1d_malloc(ALLOC_LF, sizeof(*f->lf.level) * num_sb128 * 32 * 32 + 3);
3048
26.4k
        if (!f->lf.mask || !f->lf.level) {
3049
0
            f->lf.mask_sz = 0;
3050
0
            goto error;
3051
0
        }
3052
26.4k
        if (c->n_fc > 1) {
3053
26.4k
            dav1d_free(f->frame_thread.b);
3054
26.4k
            f->frame_thread.b = dav1d_malloc(ALLOC_BLOCK, sizeof(*f->frame_thread.b) *
3055
26.4k
                                             num_sb128 * 32 * 32);
3056
26.4k
            if (!f->frame_thread.b) {
3057
0
                f->lf.mask_sz = 0;
3058
0
                goto error;
3059
0
            }
3060
26.4k
        }
3061
26.4k
        f->lf.mask_sz = num_sb128;
3062
26.4k
    }
3063
3064
26.8k
    f->sr_sb128w = (f->sr_cur.p.p.w + 127) >> 7;
3065
26.8k
    const int lr_mask_sz = f->sr_sb128w * f->sb128h;
3066
26.8k
    if (lr_mask_sz != f->lf.lr_mask_sz) {
3067
26.4k
        dav1d_free(f->lf.lr_mask);
3068
26.4k
        f->lf.lr_mask = dav1d_malloc(ALLOC_LR, sizeof(*f->lf.lr_mask) * lr_mask_sz);
3069
26.4k
        if (!f->lf.lr_mask) {
3070
0
            f->lf.lr_mask_sz = 0;
3071
0
            goto error;
3072
0
        }
3073
26.4k
        f->lf.lr_mask_sz = lr_mask_sz;
3074
26.4k
    }
3075
26.8k
    f->lf.restore_planes =
3076
26.8k
        ((f->frame_hdr->restoration.type[0] != DAV1D_RESTORATION_NONE) << 0) +
3077
26.8k
        ((f->frame_hdr->restoration.type[1] != DAV1D_RESTORATION_NONE) << 1) +
3078
26.8k
        ((f->frame_hdr->restoration.type[2] != DAV1D_RESTORATION_NONE) << 2);
3079
26.8k
    if (f->frame_hdr->loopfilter.sharpness != f->lf.last_sharpness) {
3080
26.6k
        dav1d_calc_eih(&f->lf.lim_lut, f->frame_hdr->loopfilter.sharpness);
3081
26.6k
        f->lf.last_sharpness = f->frame_hdr->loopfilter.sharpness;
3082
26.6k
    }
3083
26.8k
    dav1d_calc_lf_values(f->lf.lvl, f->frame_hdr, (int8_t[4]) { 0, 0, 0, 0 });
3084
26.8k
    memset(f->lf.mask, 0, sizeof(*f->lf.mask) * num_sb128);
3085
3086
26.8k
    const int ipred_edge_sz = f->sbh * f->sb128w << hbd;
3087
26.8k
    if (ipred_edge_sz != f->ipred_edge_sz) {
3088
26.4k
        dav1d_free_aligned(f->ipred_edge[0]);
3089
26.4k
        uint8_t *ptr = f->ipred_edge[0] =
3090
26.4k
            dav1d_alloc_aligned(ALLOC_IPRED, ipred_edge_sz * 128 * 3, 64);
3091
26.4k
        if (!ptr) {
3092
0
            f->ipred_edge_sz = 0;
3093
0
            goto error;
3094
0
        }
3095
26.4k
        f->ipred_edge[1] = ptr + ipred_edge_sz * 128 * 1;
3096
26.4k
        f->ipred_edge[2] = ptr + ipred_edge_sz * 128 * 2;
3097
26.4k
        f->ipred_edge_sz = ipred_edge_sz;
3098
26.4k
    }
3099
3100
26.8k
    const int re_sz = f->sb128h * f->frame_hdr->tiling.cols;
3101
26.8k
    if (re_sz != f->lf.re_sz) {
3102
26.4k
        dav1d_free(f->lf.tx_lpf_right_edge[0]);
3103
26.4k
        f->lf.tx_lpf_right_edge[0] = dav1d_malloc(ALLOC_LF, re_sz * 32 * 2);
3104
26.4k
        if (!f->lf.tx_lpf_right_edge[0]) {
3105
0
            f->lf.re_sz = 0;
3106
0
            goto error;
3107
0
        }
3108
26.4k
        f->lf.tx_lpf_right_edge[1] = f->lf.tx_lpf_right_edge[0] + re_sz * 32;
3109
26.4k
        f->lf.re_sz = re_sz;
3110
26.4k
    }
3111
3112
    // init ref mvs
3113
26.8k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc) {
3114
13.3k
        const int ret =
3115
13.3k
            dav1d_refmvs_init_frame(&f->rf, f->seq_hdr, f->frame_hdr,
3116
13.3k
                                    f->refpoc, f->mvs, f->refrefpoc, f->ref_mvs,
3117
13.3k
                                    f->c->n_tc, f->c->n_fc);
3118
13.3k
        if (ret < 0) goto error;
3119
13.3k
    }
3120
3121
    // setup dequant tables
3122
26.8k
    init_quant_tables(f->seq_hdr, f->frame_hdr, f->frame_hdr->quant.yac, f->dq);
3123
26.8k
    if (f->frame_hdr->quant.qm)
3124
294k
        for (int i = 0; i < N_RECT_TX_SIZES; i++) {
3125
279k
            f->qm[i][0] = dav1d_qm_tbl[f->frame_hdr->quant.qm_y][0][i];
3126
279k
            f->qm[i][1] = dav1d_qm_tbl[f->frame_hdr->quant.qm_u][1][i];
3127
279k
            f->qm[i][2] = dav1d_qm_tbl[f->frame_hdr->quant.qm_v][1][i];
3128
279k
        }
3129
12.1k
    else
3130
12.1k
        memset(f->qm, 0, sizeof(f->qm));
3131
3132
    // setup jnt_comp weights
3133
26.8k
    if (f->frame_hdr->switchable_comp_refs) {
3134
49.7k
        for (int i = 0; i < 7; i++) {
3135
43.5k
            const unsigned ref0poc = f->refp[i].p.frame_hdr->frame_offset;
3136
3137
173k
            for (int j = i + 1; j < 7; j++) {
3138
130k
                const unsigned ref1poc = f->refp[j].p.frame_hdr->frame_offset;
3139
3140
130k
                const unsigned d1 =
3141
130k
                    imin(abs(get_poc_diff(f->seq_hdr->order_hint_n_bits, ref0poc,
3142
130k
                                          f->cur.frame_hdr->frame_offset)), 31);
3143
130k
                const unsigned d0 =
3144
130k
                    imin(abs(get_poc_diff(f->seq_hdr->order_hint_n_bits, ref1poc,
3145
130k
                                          f->cur.frame_hdr->frame_offset)), 31);
3146
130k
                const int order = d0 <= d1;
3147
3148
130k
                static const uint8_t quant_dist_weight[3][2] = {
3149
130k
                    { 2, 3 }, { 2, 5 }, { 2, 7 }
3150
130k
                };
3151
130k
                static const uint8_t quant_dist_lookup_table[4][2] = {
3152
130k
                    { 9, 7 }, { 11, 5 }, { 12, 4 }, { 13, 3 }
3153
130k
                };
3154
3155
130k
                int k;
3156
412k
                for (k = 0; k < 3; k++) {
3157
320k
                    const int c0 = quant_dist_weight[k][order];
3158
320k
                    const int c1 = quant_dist_weight[k][!order];
3159
320k
                    const int d0_c0 = d0 * c0;
3160
320k
                    const int d1_c1 = d1 * c1;
3161
320k
                    if ((d0 > d1 && d0_c0 < d1_c1) || (d0 <= d1 && d0_c0 > d1_c1)) break;
3162
320k
                }
3163
3164
130k
                f->jnt_weights[i][j] = quant_dist_lookup_table[k][order];
3165
130k
            }
3166
43.5k
        }
3167
6.21k
    }
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
26.8k
    const int has_chroma = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400;
3175
26.8k
    f->lf.p[0] = f->cur.data[0];
3176
26.8k
    f->lf.p[1] = f->cur.data[has_chroma ? 1 : 0];
3177
26.8k
    f->lf.p[2] = f->cur.data[has_chroma ? 2 : 0];
3178
26.8k
    f->lf.sr_p[0] = f->sr_cur.p.data[0];
3179
26.8k
    f->lf.sr_p[1] = f->sr_cur.p.data[has_chroma ? 1 : 0];
3180
26.8k
    f->lf.sr_p[2] = f->sr_cur.p.data[has_chroma ? 2 : 0];
3181
3182
26.8k
    retval = 0;
3183
26.8k
error:
3184
26.8k
    return retval;
3185
26.8k
}
3186
3187
26.2k
int dav1d_decode_frame_init_cdf(Dav1dFrameContext *const f) {
3188
26.2k
    const Dav1dContext *const c = f->c;
3189
26.2k
    int retval = DAV1D_ERR(EINVAL);
3190
3191
26.2k
    if (f->frame_hdr->refresh_context)
3192
9.21k
        dav1d_cdf_thread_copy(f->out_cdf.data.cdf, &f->in_cdf);
3193
3194
    // parse individual tiles per tile group
3195
26.2k
    int tile_row = 0, tile_col = 0;
3196
26.2k
    f->task_thread.update_set = 0;
3197
52.1k
    for (int i = 0; i < f->n_tile_data; i++) {
3198
26.2k
        const uint8_t *data = f->tile[i].data.data;
3199
26.2k
        size_t size = f->tile[i].data.sz;
3200
3201
64.6k
        for (int j = f->tile[i].start; j <= f->tile[i].end; j++) {
3202
38.7k
            size_t tile_sz;
3203
38.7k
            if (j == f->tile[i].end) {
3204
25.9k
                tile_sz = size;
3205
25.9k
            } else {
3206
12.8k
                if (f->frame_hdr->tiling.n_bytes > size) goto error;
3207
12.8k
                tile_sz = 0;
3208
26.4k
                for (unsigned k = 0; k < f->frame_hdr->tiling.n_bytes; k++)
3209
13.6k
                    tile_sz |= (unsigned)*data++ << (k * 8);
3210
12.8k
                tile_sz++;
3211
12.8k
                size -= f->frame_hdr->tiling.n_bytes;
3212
12.8k
                if (tile_sz > size) goto error;
3213
12.8k
            }
3214
3215
38.3k
            setup_tile(&f->ts[j], f, data, tile_sz, tile_row, tile_col++,
3216
38.3k
                       c->n_fc > 1 ? f->frame_thread.tile_start_off[j] : 0);
3217
3218
38.3k
            if (tile_col == f->frame_hdr->tiling.cols) {
3219
28.9k
                tile_col = 0;
3220
28.9k
                tile_row++;
3221
28.9k
            }
3222
38.3k
            if (j == f->frame_hdr->tiling.update && f->frame_hdr->refresh_context)
3223
9.14k
                f->task_thread.update_set = 1;
3224
38.3k
            data += tile_sz;
3225
38.3k
            size -= tile_sz;
3226
38.3k
        }
3227
26.2k
    }
3228
3229
25.8k
    if (c->n_tc > 1) {
3230
25.8k
        const int uses_2pass = c->n_fc > 1;
3231
213k
        for (int n = 0; n < f->sb128w * f->frame_hdr->tiling.rows * (1 + uses_2pass); n++)
3232
187k
            reset_context(&f->a[n], IS_KEY_OR_INTRA(f->frame_hdr),
3233
187k
                          uses_2pass ? 1 + (n >= f->sb128w * f->frame_hdr->tiling.rows) : 0);
3234
25.8k
    }
3235
3236
25.8k
    retval = 0;
3237
26.2k
error:
3238
26.2k
    return retval;
3239
25.8k
}
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
127k
void dav1d_decode_frame_exit(Dav1dFrameContext *const f, int retval) {
3288
127k
    const Dav1dContext *const c = f->c;
3289
3290
127k
    if (f->sr_cur.p.data[0])
3291
127k
        atomic_init(&f->task_thread.error, 0);
3292
3293
127k
    if (c->n_fc > 1 && retval && f->frame_thread.cf) {
3294
34.0k
        memset(f->frame_thread.cf, 0,
3295
34.0k
               (size_t)f->frame_thread.cf_sz * 128 * 128 / 2);
3296
34.0k
    }
3297
1.02M
    for (int i = 0; i < 7; i++) {
3298
895k
        if (f->refp[i].p.frame_hdr) {
3299
71.1k
            if (!retval && c->n_fc > 1 && c->strict_std_compliance &&
3300
71.1k
                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
71.1k
            dav1d_thread_picture_unref(&f->refp[i]);
3307
71.1k
        }
3308
895k
        dav1d_ref_dec(&f->ref_mvs_ref[i]);
3309
895k
    }
3310
3311
127k
    dav1d_picture_unref_internal(&f->cur);
3312
127k
    dav1d_thread_picture_unref(&f->sr_cur);
3313
127k
    dav1d_cdf_thread_unref(&f->in_cdf);
3314
127k
    if (f->frame_hdr && f->frame_hdr->refresh_context) {
3315
19.1k
        if (f->out_cdf.progress)
3316
19.1k
            atomic_store(f->out_cdf.progress, retval == 0 ? 1 : TILE_ERROR);
3317
19.1k
        dav1d_cdf_thread_unref(&f->out_cdf);
3318
19.1k
    }
3319
127k
    dav1d_ref_dec(&f->cur_segmap_ref);
3320
127k
    dav1d_ref_dec(&f->prev_segmap_ref);
3321
127k
    dav1d_ref_dec(&f->mvs_ref);
3322
127k
    dav1d_ref_dec(&f->seq_hdr_ref);
3323
127k
    dav1d_ref_dec(&f->frame_hdr_ref);
3324
3325
155k
    for (int i = 0; i < f->n_tile_data; i++)
3326
27.5k
        dav1d_data_unref_internal(&f->tile[i].data);
3327
127k
    f->task_thread.retval = retval;
3328
127k
}
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
6.45k
static int get_upscale_x0(const int in_w, const int out_w, const int step) {
3367
6.45k
    const int err = out_w * step - (in_w << 14);
3368
6.45k
    const int x0 = (-((out_w - in_w) << 13) + (out_w >> 1)) / out_w + 128 - (err / 2);
3369
6.45k
    return x0 & 0x3fff;
3370
6.45k
}
3371
3372
27.6k
int dav1d_submit_frame(Dav1dContext *const c) {
3373
27.6k
    Dav1dFrameContext *f;
3374
27.6k
    int res = -1;
3375
3376
    // wait for c->out_delayed[next] and move into c->out if visible
3377
27.6k
    Dav1dThreadPicture *out_delayed;
3378
27.6k
    if (c->n_fc > 1) {
3379
27.6k
        pthread_mutex_lock(&c->task_thread.lock);
3380
27.6k
        const unsigned next = c->frame_thread.next++;
3381
27.6k
        if (c->frame_thread.next == c->n_fc)
3382
431
            c->frame_thread.next = 0;
3383
3384
27.6k
        f = &c->fc[next];
3385
27.9k
        while (f->n_tile_data > 0)
3386
296
            pthread_cond_wait(&f->task_thread.cond,
3387
296
                              &c->task_thread.lock);
3388
27.6k
        out_delayed = &c->frame_thread.out_delayed[next];
3389
27.6k
        if (out_delayed->p.data[0] || atomic_load(&f->task_thread.error)) {
3390
383
            unsigned first = atomic_load(&c->task_thread.first);
3391
383
            if (first + 1U < c->n_fc)
3392
383
                atomic_fetch_add(&c->task_thread.first, 1U);
3393
0
            else
3394
383
                atomic_store(&c->task_thread.first, 0);
3395
383
            atomic_compare_exchange_strong(&c->task_thread.reset_task_cur,
3396
383
                                           &first, UINT_MAX);
3397
383
            if (c->task_thread.cur && c->task_thread.cur < c->n_fc)
3398
113
                c->task_thread.cur--;
3399
383
        }
3400
27.6k
        const int error = f->task_thread.retval;
3401
27.6k
        if (error) {
3402
13
            f->task_thread.retval = 0;
3403
13
            c->cached_error = error;
3404
13
            dav1d_data_props_copy(&c->cached_error_props, &out_delayed->p.m);
3405
13
            dav1d_thread_picture_unref(out_delayed);
3406
27.6k
        } else if (out_delayed->p.data[0]) {
3407
370
            const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
3408
370
                                                           memory_order_relaxed);
3409
370
            if ((out_delayed->visible || c->output_invisible_frames) &&
3410
154
                progress != FRAME_ERROR)
3411
154
            {
3412
154
                dav1d_thread_picture_ref(&c->out, out_delayed);
3413
154
                c->event_flags |= dav1d_picture_get_event_flags(out_delayed);
3414
154
            }
3415
370
            dav1d_thread_picture_unref(out_delayed);
3416
370
        }
3417
27.6k
    } else {
3418
0
        f = c->fc;
3419
0
    }
3420
3421
27.6k
    f->seq_hdr = c->seq_hdr;
3422
27.6k
    f->seq_hdr_ref = c->seq_hdr_ref;
3423
27.6k
    dav1d_ref_inc(f->seq_hdr_ref);
3424
27.6k
    f->frame_hdr = c->frame_hdr;
3425
27.6k
    f->frame_hdr_ref = c->frame_hdr_ref;
3426
27.6k
    c->frame_hdr = NULL;
3427
27.6k
    c->frame_hdr_ref = NULL;
3428
27.6k
    f->dsp = &c->dsp[f->seq_hdr->hbd];
3429
3430
27.6k
    const int bpc = 8 + 2 * f->seq_hdr->hbd;
3431
3432
27.6k
    if (!f->dsp->ipred.intra_pred[DC_PRED]) {
3433
15.7k
        Dav1dDSPContext *const dsp = &c->dsp[f->seq_hdr->hbd];
3434
3435
15.7k
        switch (bpc) {
3436
0
#define assign_bitdepth_case(bd) \
3437
15.7k
            dav1d_cdef_dsp_init_##bd##bpc(&dsp->cdef); \
3438
15.7k
            dav1d_intra_pred_dsp_init_##bd##bpc(&dsp->ipred); \
3439
15.7k
            dav1d_itx_dsp_init_##bd##bpc(&dsp->itx, bpc); \
3440
15.7k
            dav1d_loop_filter_dsp_init_##bd##bpc(&dsp->lf); \
3441
15.7k
            dav1d_loop_restoration_dsp_init_##bd##bpc(&dsp->lr, bpc); \
3442
15.7k
            dav1d_mc_dsp_init_##bd##bpc(&dsp->mc); \
3443
15.7k
            dav1d_film_grain_dsp_init_##bd##bpc(&dsp->fg); \
3444
15.7k
            break
3445
0
#if CONFIG_8BPC
3446
7.66k
        case 8:
3447
7.66k
            assign_bitdepth_case(8);
3448
0
#endif
3449
0
#if CONFIG_16BPC
3450
6.49k
        case 10:
3451
8.08k
        case 12:
3452
8.08k
            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
15.7k
        }
3461
15.7k
    }
3462
3463
27.6k
#define assign_bitdepth_case(bd) \
3464
27.6k
        f->bd_fn.recon_b_inter = dav1d_recon_b_inter_##bd##bpc; \
3465
27.6k
        f->bd_fn.recon_b_intra = dav1d_recon_b_intra_##bd##bpc; \
3466
27.6k
        f->bd_fn.filter_sbrow = dav1d_filter_sbrow_##bd##bpc; \
3467
27.6k
        f->bd_fn.filter_sbrow_deblock_cols = dav1d_filter_sbrow_deblock_cols_##bd##bpc; \
3468
27.6k
        f->bd_fn.filter_sbrow_deblock_rows = dav1d_filter_sbrow_deblock_rows_##bd##bpc; \
3469
27.6k
        f->bd_fn.filter_sbrow_cdef = dav1d_filter_sbrow_cdef_##bd##bpc; \
3470
27.6k
        f->bd_fn.filter_sbrow_resize = dav1d_filter_sbrow_resize_##bd##bpc; \
3471
27.6k
        f->bd_fn.filter_sbrow_lr = dav1d_filter_sbrow_lr_##bd##bpc; \
3472
27.6k
        f->bd_fn.backup_ipred_edge = dav1d_backup_ipred_edge_##bd##bpc; \
3473
27.6k
        f->bd_fn.read_coef_blocks = dav1d_read_coef_blocks_##bd##bpc; \
3474
27.6k
        f->bd_fn.copy_pal_block_y = dav1d_copy_pal_block_y_##bd##bpc; \
3475
27.6k
        f->bd_fn.copy_pal_block_uv = dav1d_copy_pal_block_uv_##bd##bpc; \
3476
27.6k
        f->bd_fn.read_pal_plane = dav1d_read_pal_plane_##bd##bpc; \
3477
27.6k
        f->bd_fn.read_pal_uv = dav1d_read_pal_uv_##bd##bpc
3478
27.6k
    if (!f->seq_hdr->hbd) {
3479
14.8k
#if CONFIG_8BPC
3480
14.8k
        assign_bitdepth_case(8);
3481
14.8k
#endif
3482
14.8k
    } else {
3483
12.8k
#if CONFIG_16BPC
3484
12.8k
        assign_bitdepth_case(16);
3485
12.8k
#endif
3486
12.8k
    }
3487
27.6k
#undef assign_bitdepth_case
3488
3489
27.6k
    int ref_coded_width[7];
3490
27.6k
    if (IS_INTER_OR_SWITCH(f->frame_hdr)) {
3491
10.2k
        if (f->frame_hdr->primary_ref_frame != DAV1D_PRIMARY_REF_NONE) {
3492
8.49k
            const int pri_ref = f->frame_hdr->refidx[f->frame_hdr->primary_ref_frame];
3493
8.49k
            if (!c->refs[pri_ref].p.p.data[0]) {
3494
13
                res = DAV1D_ERR(EINVAL);
3495
13
                goto error;
3496
13
            }
3497
8.49k
        }
3498
81.4k
        for (int i = 0; i < 7; i++) {
3499
71.2k
            const int refidx = f->frame_hdr->refidx[i];
3500
71.2k
            if (!c->refs[refidx].p.p.data[0] ||
3501
71.2k
                f->frame_hdr->width[0] * 2 < c->refs[refidx].p.p.p.w ||
3502
71.1k
                f->frame_hdr->height * 2 < c->refs[refidx].p.p.p.h ||
3503
71.1k
                f->frame_hdr->width[0] > c->refs[refidx].p.p.p.w * 16 ||
3504
71.1k
                f->frame_hdr->height > c->refs[refidx].p.p.p.h * 16 ||
3505
71.1k
                f->seq_hdr->layout != c->refs[refidx].p.p.p.layout ||
3506
71.1k
                bpc != c->refs[refidx].p.p.p.bpc)
3507
114
            {
3508
164
                for (int j = 0; j < i; j++)
3509
50
                    dav1d_thread_picture_unref(&f->refp[j]);
3510
114
                res = DAV1D_ERR(EINVAL);
3511
114
                goto error;
3512
114
            }
3513
71.1k
            dav1d_thread_picture_ref(&f->refp[i], &c->refs[refidx].p);
3514
71.1k
            ref_coded_width[i] = c->refs[refidx].p.p.frame_hdr->width[0];
3515
71.1k
            if (f->frame_hdr->width[0] != c->refs[refidx].p.p.p.w ||
3516
51.9k
                f->frame_hdr->height != c->refs[refidx].p.p.p.h)
3517
20.5k
            {
3518
20.5k
#define scale_fac(ref_sz, this_sz) \
3519
47.6k
    ((((ref_sz) << 14) + ((this_sz) >> 1)) / (this_sz))
3520
20.5k
                f->svc[i][0].scale = scale_fac(c->refs[refidx].p.p.p.w,
3521
20.5k
                                               f->frame_hdr->width[0]);
3522
20.5k
                f->svc[i][1].scale = scale_fac(c->refs[refidx].p.p.p.h,
3523
20.5k
                                               f->frame_hdr->height);
3524
20.5k
                f->svc[i][0].step = (f->svc[i][0].scale + 8) >> 4;
3525
20.5k
                f->svc[i][1].step = (f->svc[i][1].scale + 8) >> 4;
3526
50.5k
            } else {
3527
50.5k
                f->svc[i][0].scale = f->svc[i][1].scale = 0;
3528
50.5k
            }
3529
71.1k
            f->gmv_warp_allowed[i] = f->frame_hdr->gmv[i].type > DAV1D_WM_TYPE_TRANSLATION &&
3530
21.4k
                                     !f->frame_hdr->force_integer_mv &&
3531
18.5k
                                     !dav1d_get_shear_params(&f->frame_hdr->gmv[i]) &&
3532
18.0k
                                     !f->svc[i][0].scale;
3533
71.1k
        }
3534
10.2k
    }
3535
3536
    // setup entropy
3537
27.5k
    if (f->frame_hdr->primary_ref_frame == DAV1D_PRIMARY_REF_NONE) {
3538
19.1k
        dav1d_cdf_thread_init_static(&f->in_cdf, f->frame_hdr->quant.yac);
3539
19.1k
    } else {
3540
8.42k
        const int pri_ref = f->frame_hdr->refidx[f->frame_hdr->primary_ref_frame];
3541
8.42k
        dav1d_cdf_thread_ref(&f->in_cdf, &c->cdf[pri_ref]);
3542
8.42k
    }
3543
27.5k
    if (f->frame_hdr->refresh_context) {
3544
9.98k
        res = dav1d_cdf_thread_alloc(c, &f->out_cdf, c->n_fc > 1);
3545
9.98k
        if (res < 0) goto error;
3546
9.98k
    }
3547
3548
    // FIXME qsort so tiles are in order (for frame threading)
3549
27.5k
    if (f->n_tile_data_alloc < c->n_tile_data) {
3550
27.1k
        dav1d_free(f->tile);
3551
27.1k
        assert(c->n_tile_data < INT_MAX / (int)sizeof(*f->tile));
3552
27.1k
        f->tile = dav1d_malloc(ALLOC_TILE, c->n_tile_data * sizeof(*f->tile));
3553
27.1k
        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
27.1k
        f->n_tile_data_alloc = c->n_tile_data;
3559
27.1k
    }
3560
27.5k
    memcpy(f->tile, c->tile, c->n_tile_data * sizeof(*f->tile));
3561
27.5k
    memset(c->tile, 0, c->n_tile_data * sizeof(*c->tile));
3562
27.5k
    f->n_tile_data = c->n_tile_data;
3563
27.5k
    c->n_tile_data = 0;
3564
3565
    // allocate frame
3566
27.5k
    res = dav1d_thread_picture_alloc(c, f, bpc);
3567
27.5k
    if (res < 0) goto error;
3568
3569
27.5k
    if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
3570
3.22k
        res = dav1d_picture_alloc_copy(c, &f->cur, f->frame_hdr->width[0], &f->sr_cur.p);
3571
3.22k
        if (res < 0) goto error;
3572
24.3k
    } else {
3573
24.3k
        dav1d_picture_ref(&f->cur, &f->sr_cur.p);
3574
24.3k
    }
3575
3576
27.5k
    if (f->frame_hdr->width[0] != f->frame_hdr->width[1]) {
3577
3.22k
        f->resize_step[0] = scale_fac(f->cur.p.w, f->sr_cur.p.p.w);
3578
3.22k
        const int ss_hor = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
3579
3.22k
        const int in_cw = (f->cur.p.w + ss_hor) >> ss_hor;
3580
3.22k
        const int out_cw = (f->sr_cur.p.p.w + ss_hor) >> ss_hor;
3581
3.22k
        f->resize_step[1] = scale_fac(in_cw, out_cw);
3582
3.22k
#undef scale_fac
3583
3.22k
        f->resize_start[0] = get_upscale_x0(f->cur.p.w, f->sr_cur.p.p.w, f->resize_step[0]);
3584
3.22k
        f->resize_start[1] = get_upscale_x0(in_cw, out_cw, f->resize_step[1]);
3585
3.22k
    }
3586
3587
    // move f->cur into output queue
3588
27.5k
    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
27.5k
    } else {
3594
27.5k
        dav1d_thread_picture_ref(out_delayed, &f->sr_cur);
3595
27.5k
    }
3596
3597
27.5k
    f->w4 = (f->frame_hdr->width[0] + 3) >> 2;
3598
27.5k
    f->h4 = (f->frame_hdr->height + 3) >> 2;
3599
27.5k
    f->bw = ((f->frame_hdr->width[0] + 7) >> 3) << 1;
3600
27.5k
    f->bh = ((f->frame_hdr->height + 7) >> 3) << 1;
3601
27.5k
    f->sb128w = (f->bw + 31) >> 5;
3602
27.5k
    f->sb128h = (f->bh + 31) >> 5;
3603
27.5k
    f->sb_shift = 4 + f->seq_hdr->sb128;
3604
27.5k
    f->sb_step = 16 << f->seq_hdr->sb128;
3605
27.5k
    f->sbh = (f->bh + f->sb_step - 1) >> f->sb_shift;
3606
27.5k
    f->b4_stride = (f->bw + 31) & ~31;
3607
27.5k
    f->bitdepth_max = (1 << f->cur.p.bpc) - 1;
3608
27.5k
    atomic_init(&f->task_thread.error, 0);
3609
27.5k
    const int uses_2pass = c->n_fc > 1;
3610
27.5k
    const int cols = f->frame_hdr->tiling.cols;
3611
27.5k
    const int rows = f->frame_hdr->tiling.rows;
3612
27.5k
    atomic_store(&f->task_thread.task_counter,
3613
27.5k
                 (cols * rows + f->sbh) << uses_2pass);
3614
3615
    // ref_mvs
3616
27.5k
    if (IS_INTER_OR_SWITCH(f->frame_hdr) || f->frame_hdr->allow_intrabc) {
3617
13.7k
        f->mvs_ref = dav1d_ref_create_using_pool(c->refmvs_pool,
3618
13.7k
            sizeof(*f->mvs) * f->sb128h * 16 * (f->b4_stride >> 1));
3619
13.7k
        if (!f->mvs_ref) {
3620
0
            res = DAV1D_ERR(ENOMEM);
3621
0
            goto error;
3622
0
        }
3623
13.7k
        f->mvs = f->mvs_ref->data;
3624
13.7k
        if (!f->frame_hdr->allow_intrabc) {
3625
81.2k
            for (int i = 0; i < 7; i++)
3626
71.1k
                f->refpoc[i] = f->refp[i].p.frame_hdr->frame_offset;
3627
10.1k
        } else {
3628
3.61k
            memset(f->refpoc, 0, sizeof(f->refpoc));
3629
3.61k
        }
3630
13.7k
        if (f->frame_hdr->use_ref_frame_mvs) {
3631
13.1k
            for (int i = 0; i < 7; i++) {
3632
11.4k
                const int refidx = f->frame_hdr->refidx[i];
3633
11.4k
                const int ref_w = ((ref_coded_width[i] + 7) >> 3) << 1;
3634
11.4k
                const int ref_h = ((f->refp[i].p.p.h + 7) >> 3) << 1;
3635
11.4k
                if (c->refs[refidx].refmvs != NULL &&
3636
3.87k
                    ref_w == f->bw && ref_h == f->bh)
3637
3.65k
                {
3638
3.65k
                    f->ref_mvs_ref[i] = c->refs[refidx].refmvs;
3639
3.65k
                    dav1d_ref_inc(f->ref_mvs_ref[i]);
3640
3.65k
                    f->ref_mvs[i] = c->refs[refidx].refmvs->data;
3641
7.81k
                } else {
3642
7.81k
                    f->ref_mvs[i] = NULL;
3643
7.81k
                    f->ref_mvs_ref[i] = NULL;
3644
7.81k
                }
3645
11.4k
                memcpy(f->refrefpoc[i], c->refs[refidx].refpoc,
3646
11.4k
                       sizeof(*f->refrefpoc));
3647
11.4k
            }
3648
12.1k
        } else {
3649
12.1k
            memset(f->ref_mvs_ref, 0, sizeof(f->ref_mvs_ref));
3650
12.1k
        }
3651
13.7k
    } else {
3652
13.7k
        f->mvs_ref = NULL;
3653
13.7k
        memset(f->ref_mvs_ref, 0, sizeof(f->ref_mvs_ref));
3654
13.7k
    }
3655
3656
    // segmap
3657
27.5k
    if (f->frame_hdr->segmentation.enabled) {
3658
        // By default, the previous segmentation map is not initialised.
3659
10.5k
        f->prev_segmap_ref = NULL;
3660
10.5k
        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
10.5k
        if (f->frame_hdr->segmentation.temporal || !f->frame_hdr->segmentation.update_map) {
3665
3.49k
            const int pri_ref = f->frame_hdr->primary_ref_frame;
3666
3.49k
            assert(pri_ref != DAV1D_PRIMARY_REF_NONE);
3667
3.49k
            const int ref_w = ((ref_coded_width[pri_ref] + 7) >> 3) << 1;
3668
3.49k
            const int ref_h = ((f->refp[pri_ref].p.p.h + 7) >> 3) << 1;
3669
3.49k
            if (ref_w == f->bw && ref_h == f->bh) {
3670
3.22k
                f->prev_segmap_ref = c->refs[f->frame_hdr->refidx[pri_ref]].segmap;
3671
3.22k
                if (f->prev_segmap_ref) {
3672
2.11k
                    dav1d_ref_inc(f->prev_segmap_ref);
3673
2.11k
                    f->prev_segmap = f->prev_segmap_ref->data;
3674
2.11k
                }
3675
3.22k
            }
3676
3.49k
        }
3677
3678
10.5k
        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.61k
            f->cur_segmap_ref = dav1d_ref_create_using_pool(c->segmap_pool,
3683
7.61k
                sizeof(*f->cur_segmap) * f->b4_stride * 32 * f->sb128h);
3684
7.61k
            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.61k
            f->cur_segmap = f->cur_segmap_ref->data;
3690
7.61k
        } else if (f->prev_segmap_ref) {
3691
            // We're not updating an existing map, and we have a valid
3692
            // reference. Use that.
3693
1.95k
            f->cur_segmap_ref = f->prev_segmap_ref;
3694
1.95k
            dav1d_ref_inc(f->cur_segmap_ref);
3695
1.95k
            f->cur_segmap = f->prev_segmap_ref->data;
3696
1.95k
        } else {
3697
            // We need to make a new map. Allocate one here and zero it out.
3698
971
            const size_t segmap_size = sizeof(*f->cur_segmap) * f->b4_stride * 32 * f->sb128h;
3699
971
            f->cur_segmap_ref = dav1d_ref_create_using_pool(c->segmap_pool, segmap_size);
3700
971
            if (!f->cur_segmap_ref) {
3701
0
                res = DAV1D_ERR(ENOMEM);
3702
0
                goto error;
3703
0
            }
3704
971
            f->cur_segmap = f->cur_segmap_ref->data;
3705
971
            memset(f->cur_segmap, 0, segmap_size);
3706
971
        }
3707
16.9k
    } else {
3708
16.9k
        f->cur_segmap = NULL;
3709
16.9k
        f->cur_segmap_ref = NULL;
3710
16.9k
        f->prev_segmap_ref = NULL;
3711
16.9k
    }
3712
3713
    // update references etc.
3714
27.5k
    const unsigned refresh_frame_flags = f->frame_hdr->refresh_frame_flags;
3715
247k
    for (int i = 0; i < 8; i++) {
3716
220k
        if (refresh_frame_flags & (1 << i)) {
3717
171k
            if (c->refs[i].p.p.frame_hdr)
3718
45.1k
                dav1d_thread_picture_unref(&c->refs[i].p);
3719
171k
            dav1d_thread_picture_ref(&c->refs[i].p, &f->sr_cur);
3720
3721
171k
            dav1d_cdf_thread_unref(&c->cdf[i]);
3722
171k
            if (f->frame_hdr->refresh_context) {
3723
50.2k
                dav1d_cdf_thread_ref(&c->cdf[i], &f->out_cdf);
3724
120k
            } else {
3725
120k
                dav1d_cdf_thread_ref(&c->cdf[i], &f->in_cdf);
3726
120k
            }
3727
3728
171k
            dav1d_ref_dec(&c->refs[i].segmap);
3729
171k
            c->refs[i].segmap = f->cur_segmap_ref;
3730
171k
            if (f->cur_segmap_ref)
3731
62.8k
                dav1d_ref_inc(f->cur_segmap_ref);
3732
171k
            dav1d_ref_dec(&c->refs[i].refmvs);
3733
171k
            if (!f->frame_hdr->allow_intrabc) {
3734
142k
                c->refs[i].refmvs = f->mvs_ref;
3735
142k
                if (f->mvs_ref)
3736
34.0k
                    dav1d_ref_inc(f->mvs_ref);
3737
142k
            }
3738
171k
            memcpy(c->refs[i].refpoc, f->refpoc, sizeof(f->refpoc));
3739
171k
        }
3740
220k
    }
3741
3742
27.5k
    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
27.5k
    } else {
3757
27.5k
        dav1d_task_frame_init(f);
3758
27.5k
        pthread_mutex_unlock(&c->task_thread.lock);
3759
27.5k
    }
3760
3761
27.5k
    return 0;
3762
127
error:
3763
127
    atomic_init(&f->task_thread.error, 1);
3764
127
    dav1d_cdf_thread_unref(&f->in_cdf);
3765
127
    if (f->frame_hdr->refresh_context)
3766
63
        dav1d_cdf_thread_unref(&f->out_cdf);
3767
1.01k
    for (int i = 0; i < 7; i++) {
3768
889
        if (f->refp[i].p.frame_hdr)
3769
0
            dav1d_thread_picture_unref(&f->refp[i]);
3770
889
        dav1d_ref_dec(&f->ref_mvs_ref[i]);
3771
889
    }
3772
127
    if (c->n_fc == 1)
3773
0
        dav1d_thread_picture_unref(&c->out);
3774
127
    else
3775
127
        dav1d_thread_picture_unref(out_delayed);
3776
127
    dav1d_picture_unref_internal(&f->cur);
3777
127
    dav1d_thread_picture_unref(&f->sr_cur);
3778
127
    dav1d_ref_dec(&f->mvs_ref);
3779
127
    dav1d_ref_dec(&f->seq_hdr_ref);
3780
127
    dav1d_ref_dec(&f->frame_hdr_ref);
3781
127
    dav1d_data_props_copy(&c->cached_error_props, &c->in.m);
3782
3783
127
    for (int i = 0; i < f->n_tile_data; i++)
3784
0
        dav1d_data_unref_internal(&f->tile[i].data);
3785
127
    f->n_tile_data = 0;
3786
3787
127
    if (c->n_fc > 1)
3788
127
        pthread_mutex_unlock(&c->task_thread.lock);
3789
3790
127
    return res;
3791
27.5k
}