decode.c 144 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
 * Copyright © 2018, VideoLAN and dav1d authors
 * Copyright © 2018, Two Orioles, LLC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>

#include "dav1d/data.h"

#include "common/intops.h"
#include "common/mem.h"

Ronald S. Bultje's avatar
Ronald S. Bultje committed
41
#include "src/ctx.h"
42
43
44
#include "src/decode.h"
#include "src/dequant_tables.h"
#include "src/env.h"
45
#include "src/log.h"
46
47
48
49
50
51
52
#include "src/qm.h"
#include "src/recon.h"
#include "src/ref.h"
#include "src/tables.h"
#include "src/thread_task.h"
#include "src/warpmv.h"

53
54
static void init_quant_tables(const Dav1dSequenceHeader *const seq_hdr,
                              const Dav1dFrameHeader *const frame_hdr,
55
56
57
58
59
60
61
62
63
64
65
                              const int qidx, uint16_t (*dq)[3][2])
{
    for (int i = 0; i < (frame_hdr->segmentation.enabled ? 8 : 1); i++) {
        const int yac = frame_hdr->segmentation.enabled ?
            iclip_u8(qidx + frame_hdr->segmentation.seg_data.d[i].delta_q) : qidx;
        const int ydc = iclip_u8(yac + frame_hdr->quant.ydc_delta);
        const int uac = iclip_u8(yac + frame_hdr->quant.uac_delta);
        const int udc = iclip_u8(yac + frame_hdr->quant.udc_delta);
        const int vac = iclip_u8(yac + frame_hdr->quant.vac_delta);
        const int vdc = iclip_u8(yac + frame_hdr->quant.vdc_delta);

66
67
68
69
70
71
        dq[i][0][0] = dav1d_dq_tbl[seq_hdr->hbd][ydc][0];
        dq[i][0][1] = dav1d_dq_tbl[seq_hdr->hbd][yac][1];
        dq[i][1][0] = dav1d_dq_tbl[seq_hdr->hbd][udc][0];
        dq[i][1][1] = dav1d_dq_tbl[seq_hdr->hbd][uac][1];
        dq[i][2][0] = dav1d_dq_tbl[seq_hdr->hbd][vdc][0];
        dq[i][2][1] = dav1d_dq_tbl[seq_hdr->hbd][vac][1];
72
73
74
75
76
77
78
79
80
    }
}

static int read_mv_component_diff(Dav1dTileContext *const t,
                                  CdfMvComponent *const mv_comp,
                                  const int have_fp)
{
    Dav1dTileState *const ts = t->ts;
    const Dav1dFrameContext *const f = t->f;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
81
    const int have_hp = f->frame_hdr->hp;
82
    const int sign = dav1d_msac_decode_bool_adapt(&ts->msac, mv_comp->sign);
83
84
    const int cl = dav1d_msac_decode_symbol_adapt16(&ts->msac,
                                                    mv_comp->classes, 11);
85
86
87
    int up, fp, hp;

    if (!cl) {
88
        up = dav1d_msac_decode_bool_adapt(&ts->msac, mv_comp->class0);
89
        if (have_fp) {
90
91
            fp = dav1d_msac_decode_symbol_adapt4(&ts->msac,
                                                 mv_comp->class0_fp[up], 4);
92
93
            hp = have_hp ? dav1d_msac_decode_bool_adapt(&ts->msac,
                                                        mv_comp->class0_hp) : 1;
94
95
96
97
98
99
100
        } else {
            fp = 3;
            hp = 1;
        }
    } else {
        up = 1 << cl;
        for (int n = 0; n < cl; n++)
101
102
            up |= dav1d_msac_decode_bool_adapt(&ts->msac,
                                               mv_comp->classN[n]) << n;
103
        if (have_fp) {
104
105
            fp = dav1d_msac_decode_symbol_adapt4(&ts->msac,
                                                 mv_comp->classN_fp, 4);
106
107
            hp = have_hp ? dav1d_msac_decode_bool_adapt(&ts->msac,
                                                        mv_comp->classN_hp) : 1;
108
109
110
111
112
113
114
115
116
117
118
119
120
121
        } else {
            fp = 3;
            hp = 1;
        }
    }

    const int diff = ((up << 3) | (fp << 1) | hp) + 1;

    return sign ? -diff : diff;
}

static void read_mv_residual(Dav1dTileContext *const t, mv *const ref_mv,
                             CdfMvContext *const mv_cdf, const int have_fp)
{
122
123
    switch (dav1d_msac_decode_symbol_adapt4(&t->ts->msac, t->ts->cdf.mv.joint,
                                            N_MV_JOINTS))
124
    {
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    case MV_JOINT_HV:
        ref_mv->y += read_mv_component_diff(t, &mv_cdf->comp[0], have_fp);
        ref_mv->x += read_mv_component_diff(t, &mv_cdf->comp[1], have_fp);
        break;
    case MV_JOINT_H:
        ref_mv->x += read_mv_component_diff(t, &mv_cdf->comp[1], have_fp);
        break;
    case MV_JOINT_V:
        ref_mv->y += read_mv_component_diff(t, &mv_cdf->comp[0], have_fp);
        break;
    default:
        break;
    }
}

static void read_tx_tree(Dav1dTileContext *const t,
                         const enum RectTxfmSize from,
                         const int depth, uint16_t *const masks,
                         const int x_off, const int y_off)
{
    const Dav1dFrameContext *const f = t->f;
    const int bx4 = t->bx & 31, by4 = t->by & 31;
147
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];
148
149
150
151
152
153
154
155
    const int txw = t_dim->lw, txh = t_dim->lh;
    int is_split;

    if (depth < 2 && from > (int) TX_4X4) {
        const int cat = 2 * (TX_64X64 - t_dim->max) - depth;
        const int a = t->a->tx[bx4] < txw;
        const int l = t->l.tx[by4] < txh;

156
157
        is_split = dav1d_msac_decode_bool_adapt(&t->ts->msac,
                       t->ts->cdf.m.txpart[cat][a + l]);
158
159
160
161
162
163
164
165
        if (is_split)
            masks[depth] |= 1 << (y_off * 4 + x_off);
    } else {
        is_split = 0;
    }

    if (is_split && t_dim->max > TX_8X8) {
        const enum RectTxfmSize sub = t_dim->sub;
166
        const TxfmInfo *const sub_t_dim = &dav1d_txfm_dimensions[sub];
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
        const int txsw = sub_t_dim->w, txsh = sub_t_dim->h;

        read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 0);
        t->bx += txsw;
        if (txw >= txh && t->bx < f->bw)
            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 1, y_off * 2 + 0);
        t->bx -= txsw;
        t->by += txsh;
        if (txh >= txw && t->by < f->bh) {
            read_tx_tree(t, sub, depth + 1, masks, x_off * 2 + 0, y_off * 2 + 1);
            t->bx += txsw;
            if (txw >= txh && t->bx < f->bw)
                read_tx_tree(t, sub, depth + 1, masks,
                             x_off * 2 + 1, y_off * 2 + 1);
            t->bx -= txsw;
        }
        t->by -= txsh;
    } else {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
185
186
187
188
189
190
191
192
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
        rep_macro(type, t->dir tx, off, is_split ? TX_4X4 : mul * txh)
        case_set_upto16(t_dim->h, l., 1, by4);
#undef set_ctx
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
        rep_macro(type, t->dir tx, off, is_split ? TX_4X4 : mul * txw)
        case_set_upto16(t_dim->w, a->, 0, bx4);
#undef set_ctx
193
194
195
    }
}

196
static int neg_deinterleave(int diff, int ref, int max) {
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    if (!ref) return diff;
    if (ref >= (max - 1)) return max - diff - 1;
    if (2 * ref < max) {
        if (diff <= 2 * ref) {
            if (diff & 1)
                return ref + ((diff + 1) >> 1);
            else
                return ref - (diff >> 1);
        }
        return diff;
    } else {
        if (diff <= 2 * (max - ref - 1)) {
            if (diff & 1)
                return ref + ((diff + 1) >> 1);
            else
                return ref - (diff >> 1);
        }
        return max - (diff + 1);
    }
}

static void find_matching_ref(const Dav1dTileContext *const t,
                              const enum EdgeFlags intra_edge_flags,
                              const int bw4, const int bh4,
                              const int w4, const int h4,
                              const int have_left, const int have_top,
                              const int ref, uint64_t masks[2])
{
    const Dav1dFrameContext *const f = t->f;
    const ptrdiff_t b4_stride = f->b4_stride;
    const refmvs *const r = &f->mvs[t->by * b4_stride + t->bx];
    int count = 0;
    int have_topleft = have_top && have_left;
    int have_topright = imax(bw4, bh4) < 32 &&
                        have_top && t->bx + bw4 < t->ts->tiling.col_end &&
                        (intra_edge_flags & EDGE_I444_TOP_HAS_RIGHT);

234
#define bs(rp) dav1d_block_dimensions[dav1d_sbtype_to_bs[(rp)->sb_type]]
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#define matches(rp) ((rp)->ref[0] == ref + 1 && (rp)->ref[1] == -1)

    if (have_top) {
        const refmvs *r2 = &r[-b4_stride];
        if (matches(r2)) {
            masks[0] |= 1;
            count = 1;
        }
        int aw4 = bs(r2)[0];
        if (aw4 >= bw4) {
            const int off = t->bx & (aw4 - 1);
            if (off) have_topleft = 0;
            if (aw4 - off > bw4) have_topright = 0;
        } else {
            unsigned mask = 1 << aw4;
            for (int x = aw4; x < w4; x += aw4) {
                r2 += aw4;
                if (matches(r2)) {
                    masks[0] |= mask;
                    if (++count >= 8) return;
                }
                aw4 = bs(r2)[0];
                mask <<= aw4;
            }
        }
    }
    if (have_left) {
        const refmvs *r2 = &r[-1];
        if (matches(r2)) {
            masks[1] |= 1;
            if (++count >= 8) return;
        }
        int lh4 = bs(r2)[1];
        if (lh4 >= bh4) {
            if (t->by & (lh4 - 1)) have_topleft = 0;
        } else {
            unsigned mask = 1 << lh4;
            for (int y = lh4; y < h4; y += lh4) {
                r2 += lh4 * b4_stride;
                if (matches(r2)) {
                    masks[1] |= mask;
                    if (++count >= 8) return;
                }
                lh4 = bs(r2)[1];
                mask <<= lh4;
            }
        }
    }
    if (have_topleft && matches(&r[-(1 + b4_stride)])) {
        masks[1] |= 1ULL << 32;
        if (++count >= 8) return;
    }
    if (have_topright && matches(&r[bw4 - b4_stride])) {
        masks[0] |= 1ULL << 32;
    }
#undef matches
}

static void derive_warpmv(const Dav1dTileContext *const t,
                          const int bw4, const int bh4,
                          const uint64_t masks[2], const struct mv mv,
296
                          Dav1dWarpedMotionParams *const wmp)
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
{
    int pts[8][2 /* in, out */][2 /* x, y */], np = 0;
    const Dav1dFrameContext *const f = t->f;
    const ptrdiff_t b4_stride = f->b4_stride;
    const refmvs *const r = &f->mvs[t->by * b4_stride + t->bx];

#define add_sample(dx, dy, sx, sy, rp) do { \
    pts[np][0][0] = 16 * (2 * dx + sx * bs(rp)[0]) - 8; \
    pts[np][0][1] = 16 * (2 * dy + sy * bs(rp)[1]) - 8; \
    pts[np][1][0] = pts[np][0][0] + (rp)->mv[0].x; \
    pts[np][1][1] = pts[np][0][1] + (rp)->mv[0].y; \
    np++; \
} while (0)

    // use masks[] to find the projectable motion vectors in the edges
    if ((unsigned) masks[0] == 1 && !(masks[1] >> 32)) {
        const int off = t->bx & (bs(&r[-b4_stride])[0] - 1);
        add_sample(-off, 0, 1, -1, &r[-b4_stride]);
315
    } else for (unsigned off = 0, xmask = (uint32_t) masks[0]; np < 8 && xmask;) { // top
316
        const int tz = ctz(xmask);
317
        off += tz;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
318
        xmask >>= tz;
319
        add_sample(off, 0, 1, -1, &r[off - b4_stride]);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
320
        xmask &= ~1;
321
322
323
324
    }
    if (np < 8 && masks[1] == 1) {
        const int off = t->by & (bs(&r[-1])[1] - 1);
        add_sample(0, -off, -1, 1, &r[-1 - off * b4_stride]);
325
    } else for (unsigned off = 0, ymask = (uint32_t) masks[1]; np < 8 && ymask;) { // left
326
        const int tz = ctz(ymask);
327
        off += tz;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
328
        ymask >>= tz;
329
        add_sample(0, off, -1, 1, &r[off * b4_stride - 1]);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
330
        ymask &= ~1;
331
332
333
334
335
336
337
338
339
340
341
342
    }
    if (np < 8 && masks[1] >> 32) // top/left
        add_sample(0, 0, -1, -1, &r[-(1 + b4_stride)]);
    if (np < 8 && masks[0] >> 32) // top/right
        add_sample(bw4, 0, 1, -1, &r[bw4 - b4_stride]);
    assert(np > 0 && np <= 8);
#undef bs

    // select according to motion vector difference against a threshold
    int mvd[8], ret = 0;
    const int thresh = 4 * iclip(imax(bw4, bh4), 4, 28);
    for (int i = 0; i < np; i++) {
343
344
        mvd[i] = abs(pts[i][1][0] - pts[i][0][0] - mv.x) +
                 abs(pts[i][1][1] - pts[i][0][1] - mv.y);
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
        if (mvd[i] > thresh)
            mvd[i] = -1;
        else
            ret++;
    }
    if (!ret) {
        ret = 1;
    } else for (int i = 0, j = np - 1, k = 0; k < np - ret; k++, i++, j--) {
        while (mvd[i] != -1) i++;
        while (mvd[j] == -1) j--;
        assert(i != j);
        if (i > j) break;
        // replace the discarded samples;
        mvd[i] = mvd[j];
        memcpy(pts[i], pts[j], sizeof(*pts));
    }

362
363
    if (!dav1d_find_affine_int(pts, ret, bw4, bh4, mv, wmp, t->bx, t->by) &&
        !dav1d_get_shear_params(wmp))
364
    {
365
        wmp->type = DAV1D_WM_TYPE_AFFINE;
366
    } else
367
        wmp->type = DAV1D_WM_TYPE_IDENTITY;
368
369
370
371
372
373
374
375
376
377
378
379
380
381
}

static inline int findoddzero(const uint8_t *buf, int len) {
    for (int n = 0; n < len; n++)
        if (!buf[n * 2]) return 1;
    return 0;
}

static void read_pal_plane(Dav1dTileContext *const t, Av1Block *const b,
                           const int pl, const int sz_ctx,
                           const int bx4, const int by4)
{
    Dav1dTileState *const ts = t->ts;
    const Dav1dFrameContext *const f = t->f;
382
    const int pal_sz = b->pal_sz[pl] = dav1d_msac_decode_symbol_adapt8(&ts->msac,
383
                                           ts->cdf.m.pal_sz[pl][sz_ctx], 7) + 2;
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
    uint16_t cache[16], used_cache[8];
    int l_cache = pl ? t->pal_sz_uv[1][by4] : t->l.pal_sz[by4];
    int n_cache = 0;
    // don't reuse above palette outside SB64 boundaries
    int a_cache = by4 & 15 ? pl ? t->pal_sz_uv[0][bx4] : t->a->pal_sz[bx4] : 0;
    const uint16_t *l = t->al_pal[1][by4][pl], *a = t->al_pal[0][bx4][pl];

    // fill/sort cache
    while (l_cache && a_cache) {
        if (*l < *a) {
            if (!n_cache || cache[n_cache - 1] != *l)
                cache[n_cache++] = *l;
            l++;
            l_cache--;
        } else {
            if (*a == *l) {
                l++;
                l_cache--;
            }
            if (!n_cache || cache[n_cache - 1] != *a)
                cache[n_cache++] = *a;
            a++;
            a_cache--;
        }
    }
    if (l_cache) {
        do {
            if (!n_cache || cache[n_cache - 1] != *l)
                cache[n_cache++] = *l;
            l++;
        } while (--l_cache > 0);
    } else if (a_cache) {
        do {
            if (!n_cache || cache[n_cache - 1] != *a)
                cache[n_cache++] = *a;
            a++;
        } while (--a_cache > 0);
    }

    // find reused cache entries
    int i = 0;
    for (int n = 0; n < n_cache && i < pal_sz; n++)
426
        if (dav1d_msac_decode_bool_equi(&ts->msac))
427
428
429
430
431
432
            used_cache[i++] = cache[n];
    const int n_used_cache = i;

    // parse new entries
    uint16_t *const pal = f->frame_thread.pass ?
        f->frame_thread.pal[((t->by >> 1) + (t->bx & 1)) * (f->b4_stride >> 1) +
Henrik Gramner's avatar
Henrik Gramner committed
433
                            ((t->bx >> 1) + (t->by & 1))][pl] : t->scratch.pal[pl];
434
    if (i < pal_sz) {
435
        int prev = pal[i++] = dav1d_msac_decode_bools(&ts->msac, f->cur.p.bpc);
436
437

        if (i < pal_sz) {
438
            int bits = f->cur.p.bpc - 3 + dav1d_msac_decode_bools(&ts->msac, 2);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
439
            const int max = (1 << f->cur.p.bpc) - 1;
440
441

            do {
442
                const int delta = dav1d_msac_decode_bools(&ts->msac, bits);
443
444
445
                prev = pal[i++] = imin(prev + delta + !pl, max);
                if (prev + !pl >= max) {
                    for (; i < pal_sz; i++)
446
                        pal[i] = max;
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
                    break;
                }
                bits = imin(bits, 1 + ulog2(max - prev - !pl));
            } while (i < pal_sz);
        }

        // merge cache+new entries
        int n = 0, m = n_used_cache;
        for (i = 0; i < pal_sz; i++) {
            if (n < n_used_cache && (m >= pal_sz || used_cache[n] <= pal[m])) {
                pal[i] = used_cache[n++];
            } else {
                assert(m < pal_sz);
                pal[i] = pal[m++];
            }
        }
    } else {
        memcpy(pal, used_cache, n_used_cache * sizeof(*used_cache));
    }

    if (DEBUG_BLOCK_INFO) {
        printf("Post-pal[pl=%d,sz=%d,cache_size=%d,used_cache=%d]: r=%d, cache=",
469
               pl, pal_sz, n_cache, n_used_cache, ts->msac.rng);
470
471
472
        for (int n = 0; n < n_cache; n++)
            printf("%c%02x", n ? ' ' : '[', cache[n]);
        printf("%s, pal=", n_cache ? "]" : "[]");
473
        for (int n = 0; n < pal_sz; n++)
474
475
476
477
478
479
            printf("%c%02x", n ? ' ' : '[', pal[n]);
        printf("]\n");
    }
}

static void read_pal_uv(Dav1dTileContext *const t, Av1Block *const b,
480
                        const int sz_ctx, const int bx4, const int by4)
481
{
482
    read_pal_plane(t, b, 1, sz_ctx, bx4, by4);
483
484
485
486
487
488

    // V pal coding
    Dav1dTileState *const ts = t->ts;
    const Dav1dFrameContext *const f = t->f;
    uint16_t *const pal = f->frame_thread.pass ?
        f->frame_thread.pal[((t->by >> 1) + (t->bx & 1)) * (f->b4_stride >> 1) +
Henrik Gramner's avatar
Henrik Gramner committed
489
                            ((t->bx >> 1) + (t->by & 1))][2] : t->scratch.pal[2];
490
491
492
493
    if (dav1d_msac_decode_bool_equi(&ts->msac)) {
        const int bits = f->cur.p.bpc - 4 +
                         dav1d_msac_decode_bools(&ts->msac, 2);
        int prev = pal[0] = dav1d_msac_decode_bools(&ts->msac, f->cur.p.bpc);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
494
        const int max = (1 << f->cur.p.bpc) - 1;
495
        for (int i = 1; i < b->pal_sz[1]; i++) {
496
497
            int delta = dav1d_msac_decode_bools(&ts->msac, bits);
            if (delta && dav1d_msac_decode_bool_equi(&ts->msac)) delta = -delta;
498
499
500
501
            prev = pal[i] = (prev + delta) & max;
        }
    } else {
        for (int i = 0; i < b->pal_sz[1]; i++)
502
            pal[i] = dav1d_msac_decode_bools(&ts->msac, f->cur.p.bpc);
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
    }
    if (DEBUG_BLOCK_INFO) {
        printf("Post-pal[pl=2]: r=%d ", ts->msac.rng);
        for (int n = 0; n < b->pal_sz[1]; n++)
            printf("%c%02x", n ? ' ' : '[', pal[n]);
        printf("]\n");
    }
}

// meant to be SIMD'able, so that theoretical complexity of this function
// times block size goes from w4*h4 to w4+h4-1
// a and b are previous two lines containing (a) top/left entries or (b)
// top/left entries, with a[0] being either the first top or first left entry,
// depending on top_offset being 1 or 0, and b being the first top/left entry
// for whichever has one. left_offset indicates whether the (len-1)th entry
// has a left neighbour.
// output is order[] and ctx for each member of this diagonal.
static void order_palette(const uint8_t *pal_idx, const ptrdiff_t stride,
                          const int i, const int first, const int last,
                          uint8_t (*const order)[8], uint8_t *const ctx)
{
    int have_top = i > first;

    pal_idx += first + (i - first) * stride;
    for (int j = first, n = 0; j >= last; have_top = 1, j--, n++, pal_idx += stride - 1) {
        const int have_left = j > 0;

        assert(have_left || have_top);

#define add(v_in) do { \
        const int v = v_in; \
534
        assert((unsigned)v < 8U); \
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
        order[n][o_idx++] = v; \
        mask |= 1 << v; \
    } while (0)

        unsigned mask = 0;
        int o_idx = 0;
        if (!have_left) {
            ctx[n] = 0;
            add(pal_idx[-stride]);
        } else if (!have_top) {
            ctx[n] = 0;
            add(pal_idx[-1]);
        } else {
            const int l = pal_idx[-1], t = pal_idx[-stride], tl = pal_idx[-(stride + 1)];
            const int same_t_l = t == l;
            const int same_t_tl = t == tl;
            const int same_l_tl = l == tl;
            const int same_all = same_t_l & same_t_tl & same_l_tl;

            if (same_all) {
                ctx[n] = 4;
                add(t);
            } else if (same_t_l) {
                ctx[n] = 3;
                add(t);
                add(tl);
            } else if (same_t_tl | same_l_tl) {
                ctx[n] = 2;
                add(tl);
                add(same_t_tl ? l : t);
            } else {
                ctx[n] = 1;
                add(imin(t, l));
                add(imax(t, l));
                add(tl);
            }
        }
        for (unsigned m = 1, bit = 0; m < 0x100; m <<= 1, bit++)
            if (!(mask & m))
                order[n][o_idx++] = bit;
        assert(o_idx == 8);
#undef add
    }
}

static void read_pal_indices(Dav1dTileContext *const t,
                             uint8_t *const pal_idx,
                             const Av1Block *const b, const int pl,
                             const int w4, const int h4,
                             const int bw4, const int bh4)
{
    Dav1dTileState *const ts = t->ts;
    const ptrdiff_t stride = bw4 * 4;
588
    pal_idx[0] = dav1d_msac_decode_uniform(&ts->msac, b->pal_sz[pl]);
589
590
    uint16_t (*const color_map_cdf)[8 + 1] =
        ts->cdf.m.color_map[pl][b->pal_sz[pl] - 2];
Henrik Gramner's avatar
Henrik Gramner committed
591
592
    uint8_t (*const order)[8] = t->scratch.pal_order;
    uint8_t *const ctx = t->scratch.pal_ctx;
593
594
595
596
597
598
    for (int i = 1; i < 4 * (w4 + h4) - 1; i++) {
        // top/left-to-bottom/right diagonals ("wave-front")
        const int first = imin(i, w4 * 4 - 1);
        const int last = imax(0, i - h4 * 4 + 1);
        order_palette(pal_idx, stride, i, first, last, order, ctx);
        for (int j = first, m = 0; j >= last; j--, m++) {
599
            const int color_idx = dav1d_msac_decode_symbol_adapt8(&ts->msac,
600
                                      color_map_cdf[ctx[m]], b->pal_sz[pl]);
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
            pal_idx[(i - j) * stride + j] = order[m][color_idx];
        }
    }
    // fill invisible edges
    if (bw4 > w4)
        for (int y = 0; y < 4 * h4; y++)
            memset(&pal_idx[y * stride + 4 * w4],
                   pal_idx[y * stride + 4 * w4 - 1], 4 * (bw4 - w4));
    if (h4 < bh4) {
        const uint8_t *const src = &pal_idx[stride * (4 * h4 - 1)];
        for (int y = h4 * 4; y < bh4 * 4; y++)
            memcpy(&pal_idx[y * stride], src, bw4 * 4);
    }
}

static void read_vartx_tree(Dav1dTileContext *const t,
                            Av1Block *const b, const enum BlockSize bs,
                            const int bx4, const int by4)
{
    const Dav1dFrameContext *const f = t->f;
621
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
622
623
624
625
    const int bw4 = b_dim[0], bh4 = b_dim[1];

    // var-tx tree coding
    b->tx_split[0] = b->tx_split[1] = 0;
626
    b->max_ytx = dav1d_max_txfm_size_for_bs[bs][0];
Ronald S. Bultje's avatar
Ronald S. Bultje committed
627
    if (f->frame_hdr->segmentation.lossless[b->seg_id] ||
628
629
630
        b->max_ytx == TX_4X4)
    {
        b->max_ytx = b->uvtx = TX_4X4;
631
        if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
632
633
634
635
636
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
            rep_macro(type, t->dir tx, off, TX_4X4)
            case_set(bh4, l., 1, by4);
            case_set(bw4, a->, 0, bx4);
#undef set_ctx
637
        }
638
639
    } else if (f->frame_hdr->txfm_mode != DAV1D_TX_SWITCHABLE || b->skip) {
        if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
640
641
642
643
644
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
            rep_macro(type, t->dir tx, off, mul * b_dim[2 + diridx])
            case_set(bh4, l., 1, by4);
            case_set(bw4, a->, 0, bx4);
#undef set_ctx
645
        } else {
646
            assert(f->frame_hdr->txfm_mode == DAV1D_TX_LARGEST);
647
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
648
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
649
650
651
    } else {
        assert(imin(bw4, bh4) <= 16 || b->max_ytx == TX_64X64);
        int y, x, y_off, x_off;
652
        const TxfmInfo *const ytx = &dav1d_txfm_dimensions[b->max_ytx];
653
654
655
656
657
658
659
660
661
662
663
664
665
        for (y = 0, y_off = 0; y < bh4; y += ytx->h, y_off++) {
            for (x = 0, x_off = 0; x < bw4; x += ytx->w, x_off++) {
                read_tx_tree(t, b->max_ytx, 0, b->tx_split, x_off, y_off);
                // contexts are updated inside read_tx_tree()
                t->bx += ytx->w;
            }
            t->bx -= x;
            t->by += ytx->h;
        }
        t->by -= y;
        if (DEBUG_BLOCK_INFO)
            printf("Post-vartxtree[%x/%x]: r=%d\n",
                   b->tx_split[0], b->tx_split[1], t->ts->msac.rng);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
666
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
667
668
669
670
671
672
673
674
675
676
677
    }
}

static inline unsigned get_prev_frame_segid(const Dav1dFrameContext *const f,
                                            const int by, const int bx,
                                            const int w4, int h4,
                                            const uint8_t *ref_seg_map,
                                            const ptrdiff_t stride)
{
    unsigned seg_id = 8;

678
    assert(f->frame_hdr->primary_ref_frame != DAV1D_PRIMARY_REF_NONE);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
679
    if (dav1d_thread_picture_wait(&f->refp[f->frame_hdr->primary_ref_frame],
680
681
682
683
                                  (by + h4) * 4, PLANE_TYPE_BLOCK))
    {
        return 8;
    }
684
685
686
687
688
689
690
691
692
693
694
695

    ref_seg_map += by * stride + bx;
    do {
        for (int x = 0; x < w4; x++)
            seg_id = imin(seg_id, ref_seg_map[x]);
        ref_seg_map += stride;
    } while (--h4 > 0);
    assert(seg_id < 8);

    return seg_id;
}

696
697
698
699
700
static int decode_b(Dav1dTileContext *const t,
                    const enum BlockLevel bl,
                    const enum BlockSize bs,
                    const enum BlockPartition bp,
                    const enum EdgeFlags intra_edge_flags)
701
702
703
704
705
{
    Dav1dTileState *const ts = t->ts;
    const Dav1dFrameContext *const f = t->f;
    Av1Block b_mem, *const b = f->frame_thread.pass ?
        &f->frame_thread.b[t->by * f->b4_stride + t->bx] : &b_mem;
706
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
707
    const int bx4 = t->bx & 31, by4 = t->by & 31;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
708
709
    const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
    const int ss_hor = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
710
711
712
713
714
715
    const int cbx4 = bx4 >> ss_hor, cby4 = by4 >> ss_ver;
    const int bw4 = b_dim[0], bh4 = b_dim[1];
    const int w4 = imin(bw4, f->bw - t->bx), h4 = imin(bh4, f->bh - t->by);
    const int cbw4 = (bw4 + ss_hor) >> ss_hor, cbh4 = (bh4 + ss_ver) >> ss_ver;
    const int have_left = t->bx > ts->tiling.col_start;
    const int have_top = t->by > ts->tiling.row_start;
716
    const int has_chroma = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 &&
717
718
719
720
721
722
723
724
725
                           (bw4 > ss_hor || t->bx & 1) &&
                           (bh4 > ss_ver || t->by & 1);

    if (f->frame_thread.pass == 2) {
        if (b->intra) {
            f->bd_fn.recon_b_intra(t, bs, intra_edge_flags, b);

            const enum IntraPredMode y_mode_nofilt =
                b->y_mode == FILTER_PRED ? DC_PRED : b->y_mode;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
726
727
728
729
730
731
732
733
734
735
736
737
738
739
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
            rep_macro(type, t->dir mode, off, mul * y_mode_nofilt); \
            rep_macro(type, t->dir intra, off, mul)
            case_set(bh4, l., 1, by4);
            case_set(bw4, a->, 0, bx4);
#undef set_ctx

            if (has_chroma) {
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
                rep_macro(type, t->dir uvmode, off, mul * b->uv_mode)
                case_set(cbh4, l., 1, cby4);
                case_set(cbw4, a->, 0, cbx4);
#undef set_ctx
            }
740
        } else {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
741
            if (f->frame_hdr->frame_type & 1 /* not intrabc */ &&
742
743
                b->comp_type == COMP_INTER_NONE && b->motion_mode == MM_WARP)
            {
744
745
746
747
748
                uint64_t mask[2] = { 0, 0 };
                find_matching_ref(t, intra_edge_flags, bw4, bh4, w4, h4,
                                  have_left, have_top, b->ref[0], mask);
                derive_warpmv(t, bw4, bh4, mask, b->mv[0], &t->warpmv);
            }
749
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
750

751
            const uint8_t *const filter = dav1d_filter_dir[b->filter2d];
Ronald S. Bultje's avatar
Ronald S. Bultje committed
752
753
754
755
756
757
758
759
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
            rep_macro(type, t->dir filter[0], off, mul * filter[0]); \
            rep_macro(type, t->dir filter[1], off, mul * filter[1]); \
            rep_macro(type, t->dir intra, off, 0)
            case_set(bh4, l., 1, by4);
            case_set(bw4, a->, 0, bx4);
#undef set_ctx

760
            if (has_chroma) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
761
762
763
764
765
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
                rep_macro(type, t->dir uvmode, off, mul * DC_PRED)
                case_set(cbh4, l., 1, cby4);
                case_set(cbw4, a->, 0, cbx4);
#undef set_ctx
766
767
            }
        }
768
        return 0;
769
770
771
772
773
774
775
776
    }

    const int cw4 = (w4 + ss_hor) >> ss_hor, ch4 = (h4 + ss_ver) >> ss_ver;

    b->bl = bl;
    b->bp = bp;
    b->bs = bs;

777
    const Dav1dSegmentationData *seg = NULL;
778
779
780

    // segment_id (if seg_feature for skip/ref/gmv is enabled)
    int seg_pred = 0;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
781
782
    if (f->frame_hdr->segmentation.enabled) {
        if (!f->frame_hdr->segmentation.update_map) {
783
784
785
786
787
788
789
790
791
            if (f->prev_segmap) {
                unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
                                                       f->prev_segmap,
                                                       f->b4_stride);
                if (seg_id >= 8) return -1;
                b->seg_id = seg_id;
            } else {
                b->seg_id = 0;
            }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
792
793
794
            seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
        } else if (f->frame_hdr->segmentation.seg_data.preskip) {
            if (f->frame_hdr->segmentation.temporal &&
795
796
797
                (seg_pred = dav1d_msac_decode_bool_adapt(&ts->msac,
                                ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
                                t->l.seg_pred[by4]])))
798
799
            {
                // temporal predicted seg_id
800
801
802
803
804
805
806
807
808
809
                if (f->prev_segmap) {
                    unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx,
                                                           w4, h4,
                                                           f->prev_segmap,
                                                           f->b4_stride);
                    if (seg_id >= 8) return -1;
                    b->seg_id = seg_id;
                } else {
                    b->seg_id = 0;
                }
810
811
812
813
814
            } else {
                int seg_ctx;
                const unsigned pred_seg_id =
                    get_cur_frame_segid(t->by, t->bx, have_top, have_left,
                                        &seg_ctx, f->cur_segmap, f->b4_stride);
815
                const unsigned diff = dav1d_msac_decode_symbol_adapt8(&ts->msac,
816
817
                                          ts->cdf.m.seg_id[seg_ctx],
                                          DAV1D_MAX_SEGMENTS);
818
                const unsigned last_active_seg_id =
Ronald S. Bultje's avatar
Ronald S. Bultje committed
819
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
820
821
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
                                             last_active_seg_id + 1);
822
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
823
                if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
824
825
826
827
828
            }

            if (DEBUG_BLOCK_INFO)
                printf("Post-segid[preskip;%d]: r=%d\n",
                       b->seg_id, ts->msac.rng);
829

Ronald S. Bultje's avatar
Ronald S. Bultje committed
830
            seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
831
832
833
834
835
        }
    } else {
        b->seg_id = 0;
    }

836
837
    // skip_mode
    if ((!seg || (!seg->globalmv && seg->ref == -1 && !seg->skip)) &&
Ronald S. Bultje's avatar
Ronald S. Bultje committed
838
        f->frame_hdr->skip_mode_enabled && imin(bw4, bh4) > 1)
839
840
    {
        const int smctx = t->a->skip_mode[bx4] + t->l.skip_mode[by4];
841
842
        b->skip_mode = dav1d_msac_decode_bool_adapt(&ts->msac,
                           ts->cdf.m.skip_mode[smctx]);
843
844
845
846
847
848
        if (DEBUG_BLOCK_INFO)
            printf("Post-skipmode[%d]: r=%d\n", b->skip_mode, ts->msac.rng);
    } else {
        b->skip_mode = 0;
    }

849
    // skip
850
851
852
853
    if (b->skip_mode || (seg && seg->skip)) {
        b->skip = 1;
    } else {
        const int sctx = t->a->skip[bx4] + t->l.skip[by4];
854
        b->skip = dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.skip[sctx]);
855
856
857
        if (DEBUG_BLOCK_INFO)
            printf("Post-skip[%d]: r=%d\n", b->skip, ts->msac.rng);
    }
858
859

    // segment_id
Ronald S. Bultje's avatar
Ronald S. Bultje committed
860
861
862
    if (f->frame_hdr->segmentation.enabled &&
        f->frame_hdr->segmentation.update_map &&
        !f->frame_hdr->segmentation.seg_data.preskip)
863
    {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
864
        if (!b->skip && f->frame_hdr->segmentation.temporal &&
865
866
867
            (seg_pred = dav1d_msac_decode_bool_adapt(&ts->msac,
                            ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
                            t->l.seg_pred[by4]])))
868
869
        {
            // temporal predicted seg_id
870
871
872
873
874
875
876
877
878
            if (f->prev_segmap) {
                unsigned seg_id = get_prev_frame_segid(f, t->by, t->bx, w4, h4,
                                                       f->prev_segmap,
                                                       f->b4_stride);
                if (seg_id >= 8) return -1;
                b->seg_id = seg_id;
            } else {
                b->seg_id = 0;
            }
879
880
881
882
883
884
885
886
        } else {
            int seg_ctx;
            const unsigned pred_seg_id =
                get_cur_frame_segid(t->by, t->bx, have_top, have_left,
                                    &seg_ctx, f->cur_segmap, f->b4_stride);
            if (b->skip) {
                b->seg_id = pred_seg_id;
            } else {
887
                const unsigned diff = dav1d_msac_decode_symbol_adapt8(&ts->msac,
888
889
                                          ts->cdf.m.seg_id[seg_ctx],
                                          DAV1D_MAX_SEGMENTS);
890
                const unsigned last_active_seg_id =
Ronald S. Bultje's avatar
Ronald S. Bultje committed
891
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
892
893
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
                                             last_active_seg_id + 1);
894
895
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
            }
896
            if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
897
898
        }

Ronald S. Bultje's avatar
Ronald S. Bultje committed
899
        seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
900

901
902
903
904
905
906
907
        if (DEBUG_BLOCK_INFO)
            printf("Post-segid[postskip;%d]: r=%d\n",
                   b->seg_id, ts->msac.rng);
    }

    // cdef index
    if (!b->skip) {
908
        const int idx = f->seq_hdr->sb128 ? ((t->bx & 16) >> 4) +
909
910
                                           ((t->by & 16) >> 3) : 0;
        if (t->cur_sb_cdef_idx_ptr[idx] == -1) {
911
912
            const int v = dav1d_msac_decode_bools(&ts->msac,
                              f->frame_hdr->cdef.n_bits);
913
914
915
916
917
918
919
920
921
922
923
924
            t->cur_sb_cdef_idx_ptr[idx] = v;
            if (bw4 > 16) t->cur_sb_cdef_idx_ptr[idx + 1] = v;
            if (bh4 > 16) t->cur_sb_cdef_idx_ptr[idx + 2] = v;
            if (bw4 == 32 && bh4 == 32) t->cur_sb_cdef_idx_ptr[idx + 3] = v;

            if (DEBUG_BLOCK_INFO)
                printf("Post-cdef_idx[%d]: r=%d\n",
                        *t->cur_sb_cdef_idx_ptr, ts->msac.rng);
        }
    }

    // delta-q/lf
925
926
    if (!(t->bx & (31 >> !f->seq_hdr->sb128)) &&
        !(t->by & (31 >> !f->seq_hdr->sb128)))
927
928
    {
        const int prev_qidx = ts->last_qidx;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
929
        const int have_delta_q = f->frame_hdr->delta.q.present &&
930
            (bs != (f->seq_hdr->sb128 ? BS_128x128 : BS_64x64) || !b->skip);
931
932
933
934

        int8_t prev_delta_lf[4];
        memcpy(prev_delta_lf, ts->last_delta_lf, 4);

935
        if (have_delta_q) {
936
937
            int delta_q = dav1d_msac_decode_symbol_adapt4(&ts->msac,
                                                          ts->cdf.m.delta_q, 4);
938
            if (delta_q == 3) {
939
940
941
                const int n_bits = 1 + dav1d_msac_decode_bools(&ts->msac, 3);
                delta_q = dav1d_msac_decode_bools(&ts->msac, n_bits) +
                          1 + (1 << n_bits);
942
943
            }
            if (delta_q) {
944
                if (dav1d_msac_decode_bool_equi(&ts->msac)) delta_q = -delta_q;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
945
                delta_q *= 1 << f->frame_hdr->delta.q.res_log2;
946
947
948
949
950
            }
            ts->last_qidx = iclip(ts->last_qidx + delta_q, 1, 255);
            if (have_delta_q && DEBUG_BLOCK_INFO)
                printf("Post-delta_q[%d->%d]: r=%d\n",
                       delta_q, ts->last_qidx, ts->msac.rng);
951

Ronald S. Bultje's avatar
Ronald S. Bultje committed
952
953
            if (f->frame_hdr->delta.lf.present) {
                const int n_lfs = f->frame_hdr->delta.lf.multi ?
954
                    f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 ? 4 : 2 : 1;
955
956

                for (int i = 0; i < n_lfs; i++) {
957
                    int delta_lf = dav1d_msac_decode_symbol_adapt4(&ts->msac,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
958
                        ts->cdf.m.delta_lf[i + f->frame_hdr->delta.lf.multi], 4);
959
                    if (delta_lf == 3) {
960
961
                        const int n_bits = 1 + dav1d_msac_decode_bools(&ts->msac, 3);
                        delta_lf = dav1d_msac_decode_bools(&ts->msac, n_bits) +
962
963
964
                                   1 + (1 << n_bits);
                    }
                    if (delta_lf) {
965
                        if (dav1d_msac_decode_bool_equi(&ts->msac))
966
                            delta_lf = -delta_lf;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
967
                        delta_lf *= 1 << f->frame_hdr->delta.lf.res_log2;
968
969
970
971
972
973
974
975
                    }
                    ts->last_delta_lf[i] =
                        iclip(ts->last_delta_lf[i] + delta_lf, -63, 63);
                    if (have_delta_q && DEBUG_BLOCK_INFO)
                        printf("Post-delta_lf[%d:%d]: r=%d\n", i, delta_lf,
                               ts->msac.rng);
                }
            }
976
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
977
        if (ts->last_qidx == f->frame_hdr->quant.yac) {
978
979
980
981
            // assign frame-wide q values to this sb
            ts->dq = f->dq;
        } else if (ts->last_qidx != prev_qidx) {
            // find sb-specific quant parameters
Ronald S. Bultje's avatar
Ronald S. Bultje committed
982
            init_quant_tables(f->seq_hdr, f->frame_hdr, ts->last_qidx, ts->dqmem);
983
984
985
986
987
988
989
            ts->dq = ts->dqmem;
        }
        if (!memcmp(ts->last_delta_lf, (int8_t[4]) { 0, 0, 0, 0 }, 4)) {
            // assign frame-wide lf values to this sb
            ts->lflvl = f->lf.lvl;
        } else if (memcmp(ts->last_delta_lf, prev_delta_lf, 4)) {
            // find sb-specific lf lvl parameters
Ronald S. Bultje's avatar
Ronald S. Bultje committed
990
            dav1d_calc_lf_values(ts->lflvlmem, f->frame_hdr, ts->last_delta_lf);
991
992
993
994
995
996
            ts->lflvl = ts->lflvlmem;
        }
    }

    if (b->skip_mode) {
        b->intra = 0;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
997
    } else if (f->frame_hdr->frame_type & 1) {
998
999
1000
1001
1002
        if (seg && (seg->ref >= 0 || seg->globalmv)) {
            b->intra = !seg->ref;
        } else {
            const int ictx = get_intra_ctx(t->a, &t->l, by4, bx4,
                                           have_top, have_left);
1003
1004
            b->intra = !dav1d_msac_decode_bool_adapt(&ts->msac,
                            ts->cdf.m.intra[ictx]);
1005
1006
1007
            if (DEBUG_BLOCK_INFO)
                printf("Post-intra[%d]: r=%d\n", b->intra, ts->msac.rng);
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1008
    } else if (f->frame_hdr->allow_intrabc) {
1009
        b->intra = !dav1d_msac_decode_bool_adapt(&ts->msac, ts->cdf.m.intrabc);
1010
1011
1012
1013
1014
1015
1016
1017
        if (DEBUG_BLOCK_INFO)
            printf("Post-intrabcflag[%d]: r=%d\n", b->intra, ts->msac.rng);
    } else {
        b->intra = 1;
    }

    // intra/inter-specific stuff
    if (b->intra) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1018
        uint16_t *const ymode_cdf = f->frame_hdr->frame_type & 1 ?
1019
1020
1021
            ts->cdf.m.y_mode[dav1d_ymode_size_context[bs]] :
            ts->cdf.kfym[dav1d_intra_mode_context[t->a->mode[bx4]]]
                        [dav1d_intra_mode_context[t->l.mode[by4]]];
1022
1023
        b->y_mode = dav1d_msac_decode_symbol_adapt16(&ts->msac, ymode_cdf,
                                                     N_INTRA_PRED_MODES);
1024
1025
1026
1027
1028
1029
1030
1031
        if (DEBUG_BLOCK_INFO)
            printf("Post-ymode[%d]: r=%d\n", b->y_mode, ts->msac.rng);

        // angle delta
        if (b_dim[2] + b_dim[3] >= 2 && b->y_mode >= VERT_PRED &&
            b->y_mode <= VERT_LEFT_PRED)
        {
            uint16_t *const acdf = ts->cdf.m.angle_delta[b->y_mode - VERT_PRED];
1032
            const int angle = dav1d_msac_decode_symbol_adapt8(&ts->msac, acdf, 7);
1033
1034
1035
1036
1037
1038
            b->y_angle = angle - 3;
        } else {
            b->y_angle = 0;
        }

        if (has_chroma) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1039
            const int cfl_allowed = f->frame_hdr->segmentation.lossless[b->seg_id] ?
1040
                cbw4 == 1 && cbh4 == 1 : !!(cfl_allowed_mask & (1 << bs));
1041
            uint16_t *const uvmode_cdf = ts->cdf.m.uv_mode[cfl_allowed][b->y_mode];
1042
            b->uv_mode = dav1d_msac_decode_symbol_adapt16(&ts->msac, uvmode_cdf,
1043
                             N_UV_INTRA_PRED_MODES - !cfl_allowed);
1044
1045
1046
1047
1048
            if (DEBUG_BLOCK_INFO)
                printf("Post-uvmode[%d]: r=%d\n", b->uv_mode, ts->msac.rng);

            if (b->uv_mode == CFL_PRED) {
#define SIGN(a) (!!(a) + ((a) > 0))
1049
                const int sign = dav1d_msac_decode_symbol_adapt8(&ts->msac,
1050
                                     ts->cdf.m.cfl_sign, 8) + 1;
1051
1052
1053
1054
                const int sign_u = sign * 0x56 >> 8, sign_v = sign - sign_u * 3;
                assert(sign_u == sign / 3);
                if (sign_u) {
                    const int ctx = (sign_u == 2) * 3 + sign_v;
1055
                    b->cfl_alpha[0] = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1056
                                          ts->cdf.m.cfl_alpha[ctx], 16) + 1;
1057
1058
1059
1060
1061
1062
                    if (sign_u == 1) b->cfl_alpha[0] = -b->cfl_alpha[0];
                } else {
                    b->cfl_alpha[0] = 0;
                }
                if (sign_v) {
                    const int ctx = (sign_v == 2) * 3 + sign_u;
1063
                    b->cfl_alpha[1] = dav1d_msac_decode_symbol_adapt16(&ts->msac,
1064
                                          ts->cdf.m.cfl_alpha[ctx], 16) + 1;
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
                    if (sign_v == 1) b->cfl_alpha[1] = -b->cfl_alpha[1];
                } else {
                    b->cfl_alpha[1] = 0;
                }
#undef SIGN
                if (DEBUG_BLOCK_INFO)
                    printf("Post-uvalphas[%d/%d]: r=%d\n",
                           b->cfl_alpha[0], b->cfl_alpha[1], ts->msac.rng);
            } else if (b_dim[2] + b_dim[3] >= 2 && b->uv_mode >= VERT_PRED &&
                       b->uv_mode <= VERT_LEFT_PRED)
            {
                uint16_t *const acdf = ts->cdf.m.angle_delta[b->uv_mode - VERT_PRED];
1077
                const int angle = dav1d_msac_decode_symbol_adapt8(&ts->msac, acdf, 7);
1078
1079
1080
1081
1082
1083
1084
                b->uv_angle = angle - 3;
            } else {
                b->uv_angle = 0;
            }
        }

        b->pal_sz[0] = b->pal_sz[1] = 0;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1085
        if (f->frame_hdr->allow_screen_content_tools &&
1086
1087
1088
1089
1090
            imax(bw4, bh4) <= 16 && bw4 + bh4 >= 4)
        {
            const int sz_ctx = b_dim[2] + b_dim[3] - 2;
            if (b->y_mode == DC_PRED) {
                const int pal_ctx = (t->a->pal_sz[bx4] > 0) + (t->l.pal_sz[by4] > 0);
1091
1092
                const int use_y_pal = dav1d_msac_decode_bool_adapt(&ts->msac,
                                          ts->cdf.m.pal_y[sz_ctx][pal_ctx]);
1093
1094
1095
1096
1097
1098
1099
1100
                if (DEBUG_BLOCK_INFO)
                    printf("Post-y_pal[%d]: r=%d\n", use_y_pal, ts->msac.rng);
                if (use_y_pal)
                    read_pal_plane(t, b, 0, sz_ctx, bx4, by4);
            }

            if (has_chroma && b->uv_mode == DC_PRED) {
                const int pal_ctx = b->pal_sz[0] > 0;
1101
1102
                const int use_uv_pal = dav1d_msac_decode_bool_adapt(&ts->msac,
                                           ts->cdf.m.pal_uv[pal_ctx]);
1103
1104
                if (DEBUG_BLOCK_INFO)
                    printf("Post-uv_pal[%d]: r=%d\n", use_uv_pal, ts->msac.rng);
1105
1106
                if (use_uv_pal) // see aomedia bug 2183 for why we use luma coordinates
                    read_pal_uv(t, b, sz_ctx, bx4, by4);
1107
1108
1109
1110
            }
        }

        if (b->y_mode == DC_PRED && !b->pal_sz[0] &&
1111
            imax(b_dim[2], b_dim[3]) <= 3 && f->seq_hdr->filter_intra)
1112
        {
1113
1114
            const int is_filter = dav1d_msac_decode_bool_adapt(&ts->msac,
                                      ts->cdf.m.use_filter_intra[bs]);
1115
1116
            if (is_filter) {
                b->y_mode = FILTER_PRED;
1117
                b->y_angle = dav1d_msac_decode_symbol_adapt4(&ts->msac,
1118
                                 ts->cdf.m.filter_intra, 5);
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
            }
            if (DEBUG_BLOCK_INFO)
                printf("Post-filterintramode[%d/%d]: r=%d\n",
                       b->y_mode, b->y_angle, ts->msac.rng);
        }

        if (b->pal_sz[0]) {
            uint8_t *pal_idx;
            if (f->frame_thread.pass) {
                pal_idx = ts->frame_thread.pal_idx;
                ts->frame_thread.pal_idx += bw4 * bh4 * 16;
            } else
                pal_idx = t->scratch.pal_idx;
            read_pal_indices(t, pal_idx, b, 0, w4, h4, bw4, bh4);
            if (DEBUG_BLOCK_INFO)
                printf("Post-y-pal-indices: r=%d\n", ts->msac.rng);
        }

        if (has_chroma && b->pal_sz[1]) {
            uint8_t *pal_idx;
            if (f->frame_thread.pass) {
                pal_idx = ts->frame_thread.pal_idx;
                ts->frame_thread.pal_idx += cbw4 * cbh4 * 16;
            } else
                pal_idx = &t->scratch.pal_idx[bw4 * bh4 * 16];
            read_pal_indices(t, pal_idx, b, 1, cw4, ch4, cbw4, cbh4);
            if (DEBUG_BLOCK_INFO)
                printf("Post-uv-pal-indices: r=%d\n", ts->msac.rng);
        }

        const TxfmInfo *t_dim;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1150
        if (f->frame_hdr->segmentation.lossless[b->seg_id]) {
1151
            b->tx = b->uvtx = (int) TX_4X4;
1152
            t_dim = &dav1d_txfm_dimensions[TX_4X4];
1153
        } else {
1154
            b->tx = dav1d_max_txfm_size_for_bs[bs][0];
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1155
            b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
1156
            t_dim = &dav1d_txfm_dimensions[b->tx];
1157
            if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE && t_dim->max > TX_4X4) {
1158
                const int tctx = get_tx_ctx(t->a, &t->l, t_dim, by4, bx4);
1159
                uint16_t *const tx_cdf = ts->cdf.m.txsz[t_dim->max - 1][tctx];
1160
                int depth = dav1d_msac_decode_symbol_adapt4(&ts->msac, tx_cdf,
1161
                                imin(t_dim->max + 1, 3));
1162
1163
1164

                while (depth--) {
                    b->tx = t_dim->sub;
1165
                    t_dim = &dav1d_txfm_dimensions[b->tx];
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
                }
            }
            if (DEBUG_BLOCK_INFO)
                printf("Post-tx[%d]: r=%d\n", b->tx, ts->msac.rng);
        }

        // reconstruction
        if (f->frame_thread.pass == 1) {
            f->bd_fn.read_coef_blocks(t, bs, b);
        } else {
            f->bd_fn.recon_b_intra(t, bs, intra_edge_flags, b);
        }

        dav1d_create_lf_mask_intra(t->lf_mask, f->lf.level, f->b4_stride,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1180
                                   f->frame_hdr, (const uint8_t (*)[8][2])
1181
                                   &ts->lflvl[b->seg_id][0][0][0],
1182
                                   t->bx, t->by, f->w4, f->h4, bs,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1183
                                   b->tx, b->uvtx, f->cur.p.layout,
1184
1185
1186
1187
1188
                                   &t->a->tx_lpf_y[bx4], &t->l.tx_lpf_y[by4],
                                   has_chroma ? &t->a->tx_lpf_uv[cbx4] : NULL,
                                   has_chroma ? &t->l.tx_lpf_uv[cby4] : NULL);

        // update contexts
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
        rep_macro(type, t->dir tx_intra, off, mul * (((uint8_t *) &t_dim->lw)[diridx])); \
        rep_macro(type, t->dir tx, off, mul * (((uint8_t *) &t_dim->lw)[diridx])); \
        rep_macro(type, t->dir mode, off, mul * y_mode_nofilt); \
        rep_macro(type, t->dir pal_sz, off, mul * b->pal_sz[0]); \
        rep_macro(type, t->dir seg_pred, off, mul * seg_pred); \
        rep_macro(type, t->dir skip_mode, off, 0); \
        rep_macro(type, t->dir intra, off, mul); \
        rep_macro(type, t->dir skip, off, mul * b->skip); \
        /* see aomedia bug 2183 for why we use luma coordinates here */ \
        rep_macro(type, t->pal_sz_uv[diridx], off, mul * (has_chroma ? b->pal_sz[1] : 0)); \
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1200
        if (f->frame_hdr->frame_type & 1) { \
1201
            rep_macro(type, t->dir comp_type, off, mul * COMP_INTER_NONE); \
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1202
1203
            rep_macro(type, t->dir ref[0], off, mul * ((uint8_t) -1)); \
            rep_macro(type, t->dir ref[1], off, mul * ((uint8_t) -1)); \
1204
1205
            rep_macro(type, t->dir filter[0], off, mul * DAV1D_N_SWITCHABLE_FILTERS); \
            rep_macro(type, t->dir filter[1], off, mul * DAV1D_N_SWITCHABLE_FILTERS); \
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1206
        }
1207
1208
        const enum IntraPredMode y_mode_nofilt =
            b->y_mode == FILTER_PRED ? DC_PRED : b->y_mode;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1209
1210
1211
        case_set(bh4, l., 1, by4);
        case_set(bw4, a->, 0, bx4);
#undef set_ctx
1212
1213
1214
        if (b->pal_sz[0]) {
            uint16_t *const pal = f->frame_thread.pass ?
                f->frame_thread.pal[((t->by >> 1) + (t->bx & 1)) * (f->b4_stride >> 1) +
Henrik Gramner's avatar
Henrik Gramner committed
1215
                                    ((t->bx >> 1) + (t->by & 1))][0] : t->scratch.pal[0];
1216
1217
1218
1219
1220
1221
            for (int x = 0; x < bw4; x++)
                memcpy(t->al_pal[0][bx4 + x][0], pal, 16);
            for (int y = 0; y < bh4; y++)
                memcpy(t->al_pal[1][by4 + y][0], pal, 16);
        }
        if (has_chroma) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1222
1223
1224
1225
1226
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
                rep_macro(type, t->dir uvmode, off, mul * b->uv_mode)
                case_set(cbh4, l., 1, cby4);
                case_set(cbw4, a->, 0, cbx4);
#undef set_ctx
Henrik Gramner's avatar
Henrik Gramner committed
1227
1228
1229
1230
1231
            if (b->pal_sz[1]) {
                const uint16_t (*const pal)[8] = f->frame_thread.pass ?
                    f->frame_thread.pal[((t->by >> 1) + (t->bx & 1)) *
                    (f->b4_stride >> 1) + ((t->bx >> 1) + (t->by & 1))] :
                    t->scratch.pal;
1232
                // see aomedia bug 2183 for why we use luma coordinates here
Henrik Gramner's avatar
Henrik Gramner committed
1233
1234
1235
1236
1237
1238
                for (int pl = 1; pl <= 2; pl++) {
                    for (int x = 0; x < bw4; x++)
                        memcpy(t->al_pal[0][bx4 + x][pl], pal[pl], 16);
                    for (int y = 0; y < bh4; y++)
                        memcpy(t->al_pal[1][by4 + y][pl], pal[pl], 16);
                }
1239
1240
            }
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1241
        if ((f->frame_hdr->frame_type & 1) || f->frame_hdr->allow_intrabc) {
1242
1243
1244
            splat_intraref(f->mvs, f->b4_stride, t->by, t->bx, bs,
                           y_mode_nofilt);
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1245
    } else if (!(f->frame_hdr->frame_type & 1)) {
1246
1247
1248
1249
        // intra block copy
        candidate_mv mvstack[8];
        int n_mvs;
        mv mvlist[2][2];
1250
1251
1252
1253
1254
        dav1d_find_ref_mvs(mvstack, <