decode.c 143 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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
    const int sign = msac_decode_bool_adapt(&ts->msac, mv_comp->sign);
    const int cl = msac_decode_symbol_adapt(&ts->msac, mv_comp->classes, 11);
    int up, fp, hp;

    if (!cl) {
        up = msac_decode_bool_adapt(&ts->msac, mv_comp->class0);
        if (have_fp) {
            fp = msac_decode_symbol_adapt(&ts->msac, mv_comp->class0_fp[up], 4);
            hp = have_hp ? msac_decode_bool_adapt(&ts->msac, mv_comp->class0_hp) : 1;
        } else {
            fp = 3;
            hp = 1;
        }
    } else {
        up = 1 << cl;
        for (int n = 0; n < cl; n++)
            up |= msac_decode_bool_adapt(&ts->msac, mv_comp->classN[n]) << n;
        if (have_fp) {
            fp = msac_decode_symbol_adapt(&ts->msac, mv_comp->classN_fp, 4);
            hp = have_hp ? msac_decode_bool_adapt(&ts->msac, mv_comp->classN_hp) : 1;
        } 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)
{
    switch (msac_decode_symbol_adapt(&t->ts->msac, t->ts->cdf.mv.joint, N_MV_JOINTS)) {
    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;
139
    const TxfmInfo *const t_dim = &dav1d_txfm_dimensions[from];
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
    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;

        is_split = msac_decode_bool_adapt(&t->ts->msac, t->ts->cdf.m.txpart[cat][a + l]);
        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;
157
        const TxfmInfo *const sub_t_dim = &dav1d_txfm_dimensions[sub];
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
        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
176
177
178
179
180
181
182
183
#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
184
185
186
    }
}

187
static int neg_deinterleave(int diff, int ref, int max) {
188
189
190
191
192
193
194
195
196
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
    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);

225
#define bs(rp) dav1d_block_dimensions[sbtype_to_bs[(rp)->sb_type]]
226
227
228
229
230
231
232
233
234
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
#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,
287
                          Dav1dWarpedMotionParams *const wmp)
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
{
    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]);
    } else for (unsigned off = 0, xmask = masks[0]; np < 8 && xmask;) { // top
307
        const int tz = ctz(xmask);
308
        off += tz;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
309
        xmask >>= tz;
310
        add_sample(off, 0, 1, -1, &r[off - b4_stride]);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
311
        xmask &= ~1;
312
313
314
315
316
    }
    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]);
    } else for (unsigned off = 0, ymask = masks[1]; np < 8 && ymask;) { // left
317
        const int tz = ctz(ymask);
318
        off += tz;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
319
        ymask >>= tz;
320
        add_sample(0, off, -1, 1, &r[off * b4_stride - 1]);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
321
        ymask &= ~1;
322
323
324
325
326
327
328
329
330
331
332
333
    }
    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++) {
334
335
        mvd[i] = abs(pts[i][1][0] - pts[i][0][0] - mv.x) +
                 abs(pts[i][1][1] - pts[i][0][1] - mv.y);
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
        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));
    }

353
354
    if (!dav1d_find_affine_int(pts, ret, bw4, bh4, mv, wmp, t->bx, t->by) &&
        !dav1d_get_shear_params(wmp))
355
    {
356
        wmp->type = DAV1D_WM_TYPE_AFFINE;
357
    } else
358
        wmp->type = DAV1D_WM_TYPE_IDENTITY;
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
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
}

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;
    const int pal_sz = b->pal_sz[pl] = 2 + msac_decode_symbol_adapt(&ts->msac,
                                                 ts->cdf.m.pal_sz[pl][sz_ctx], 7);
    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++)
417
        if (msac_decode_bool_equi(&ts->msac))
418
419
420
421
422
423
424
425
            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) +
                            ((t->bx >> 1) + (t->by & 1))][pl] : t->pal[pl];
    if (i < pal_sz) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
426
        int prev = pal[i++] = msac_decode_bools(&ts->msac, f->cur.p.bpc);
427
428

        if (i < pal_sz) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
429
430
            int bits = f->cur.p.bpc - 3 + msac_decode_bools(&ts->msac, 2);
            const int max = (1 << f->cur.p.bpc) - 1;
431
432
433
434
435
436

            do {
                const int delta = msac_decode_bools(&ts->msac, bits);
                prev = pal[i++] = imin(prev + delta + !pl, max);
                if (prev + !pl >= max) {
                    for (; i < pal_sz; i++)
437
                        pal[i] = max;
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
                    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=",
460
               pl, pal_sz, n_cache, n_used_cache, ts->msac.rng);
461
462
463
        for (int n = 0; n < n_cache; n++)
            printf("%c%02x", n ? ' ' : '[', cache[n]);
        printf("%s, pal=", n_cache ? "]" : "[]");
464
        for (int n = 0; n < pal_sz; n++)
465
466
467
468
469
470
            printf("%c%02x", n ? ' ' : '[', pal[n]);
        printf("]\n");
    }
}

static void read_pal_uv(Dav1dTileContext *const t, Av1Block *const b,
471
                        const int sz_ctx, const int bx4, const int by4)
472
{
473
    read_pal_plane(t, b, 1, sz_ctx, bx4, by4);
474
475
476
477
478
479
480

    // 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) +
                            ((t->bx >> 1) + (t->by & 1))][2] : t->pal[2];
481
    if (msac_decode_bool_equi(&ts->msac)) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
482
483
484
        const int bits = f->cur.p.bpc - 4 + msac_decode_bools(&ts->msac, 2);
        int prev = pal[0] = msac_decode_bools(&ts->msac, f->cur.p.bpc);
        const int max = (1 << f->cur.p.bpc) - 1;
485
486
        for (int i = 1; i < b->pal_sz[1]; i++) {
            int delta = msac_decode_bools(&ts->msac, bits);
487
            if (delta && msac_decode_bool_equi(&ts->msac)) delta = -delta;
488
489
490
491
            prev = pal[i] = (prev + delta) & max;
        }
    } else {
        for (int i = 0; i < b->pal_sz[1]; i++)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
492
            pal[i] = msac_decode_bools(&ts->msac, f->cur.p.bpc);
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
    }
    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; \
524
        assert((unsigned)v < 8U); \
525
526
527
528
529
530
531
532
533
534
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
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
        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;
    pal_idx[0] = msac_decode_uniform(&ts->msac, b->pal_sz[pl]);
    uint16_t (*const color_map_cdf)[8 + 1] =
        ts->cdf.m.color_map[pl][b->pal_sz[pl] - 2];
    for (int i = 1; i < 4 * (w4 + h4) - 1; i++) {
        // top/left-to-bottom/right diagonals ("wave-front")
        uint8_t order[64][8], ctx[64];
        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++) {
            const int color_idx =
                msac_decode_symbol_adapt(&ts->msac, color_map_cdf[ctx[m]],
                                         b->pal_sz[pl]);
            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;
611
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
612
613
614
615
    const int bw4 = b_dim[0], bh4 = b_dim[1];

    // var-tx tree coding
    b->tx_split[0] = b->tx_split[1] = 0;
616
    b->max_ytx = dav1d_max_txfm_size_for_bs[bs][0];
Ronald S. Bultje's avatar
Ronald S. Bultje committed
617
    if (f->frame_hdr->segmentation.lossless[b->seg_id] ||
618
619
620
        b->max_ytx == TX_4X4)
    {
        b->max_ytx = b->uvtx = TX_4X4;
621
        if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
622
623
624
625
626
#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
627
        }
628
629
    } 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
630
631
632
633
634
#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
635
        } else {
636
            assert(f->frame_hdr->txfm_mode == DAV1D_TX_LARGEST);
637
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
638
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
639
640
641
    } else {
        assert(imin(bw4, bh4) <= 16 || b->max_ytx == TX_64X64);
        int y, x, y_off, x_off;
642
        const TxfmInfo *const ytx = &dav1d_txfm_dimensions[b->max_ytx];
643
644
645
646
647
648
649
650
651
652
653
654
655
        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
656
        b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
657
658
659
660
661
662
663
664
665
666
667
    }
}

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;

668
    assert(f->frame_hdr->primary_ref_frame != DAV1D_PRIMARY_REF_NONE);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
669
    if (dav1d_thread_picture_wait(&f->refp[f->frame_hdr->primary_ref_frame],
670
671
672
673
                                  (by + h4) * 4, PLANE_TYPE_BLOCK))
    {
        return 8;
    }
674
675
676
677
678
679
680
681
682
683
684
685

    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;
}

686
687
688
689
690
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)
691
692
693
694
695
{
    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;
696
    const uint8_t *const b_dim = dav1d_block_dimensions[bs];
697
    const int bx4 = t->bx & 31, by4 = t->by & 31;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
698
699
    const int ss_ver = f->cur.p.layout == DAV1D_PIXEL_LAYOUT_I420;
    const int ss_hor = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I444;
700
701
702
703
704
705
    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;
706
    const int has_chroma = f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 &&
707
708
709
710
711
712
713
714
715
                           (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
716
717
718
719
720
721
722
723
724
725
726
727
728
729
#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
            }
730
        } else {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
731
            if (f->frame_hdr->frame_type & 1 /* not intrabc */ &&
732
733
                b->comp_type == COMP_INTER_NONE && b->motion_mode == MM_WARP)
            {
734
735
736
737
738
                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);
            }
739
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
740

741
            const uint8_t *const filter = dav1d_filter_dir[b->filter2d];
Ronald S. Bultje's avatar
Ronald S. Bultje committed
742
743
744
745
746
747
748
749
#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

750
            if (has_chroma) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
751
752
753
754
755
#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
756
757
            }
        }
758
        return 0;
759
760
761
762
763
764
765
766
    }

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

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

767
    const Dav1dSegmentationData *seg = NULL;
768
769
770

    // segment_id (if seg_feature for skip/ref/gmv is enabled)
    int seg_pred = 0;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
771
772
    if (f->frame_hdr->segmentation.enabled) {
        if (!f->frame_hdr->segmentation.update_map) {
773
774
775
776
777
778
779
780
781
            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
782
783
784
            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 &&
785
786
787
788
789
                (seg_pred = msac_decode_bool_adapt(&ts->msac,
                                       ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
                                                          t->l.seg_pred[by4]])))
            {
                // temporal predicted seg_id
790
791
792
793
794
795
796
797
798
799
                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;
                }
800
801
802
803
804
805
806
            } 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);
                const unsigned diff = msac_decode_symbol_adapt(&ts->msac,
                                                   ts->cdf.m.seg_id[seg_ctx],
807
                                                   DAV1D_MAX_SEGMENTS);
808
                const unsigned last_active_seg_id =
Ronald S. Bultje's avatar
Ronald S. Bultje committed
809
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
810
811
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
                                             last_active_seg_id + 1);
812
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
813
                if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
814
815
816
817
818
            }

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

Ronald S. Bultje's avatar
Ronald S. Bultje committed
820
            seg = &f->frame_hdr->segmentation.seg_data.d[b->seg_id];
821
822
823
824
825
        }
    } else {
        b->seg_id = 0;
    }

826
827
    // skip_mode
    if ((!seg || (!seg->globalmv && seg->ref == -1 && !seg->skip)) &&
Ronald S. Bultje's avatar
Ronald S. Bultje committed
828
        f->frame_hdr->skip_mode_enabled && imin(bw4, bh4) > 1)
829
830
831
832
833
834
835
836
837
838
    {
        const int smctx = t->a->skip_mode[bx4] + t->l.skip_mode[by4];
        b->skip_mode = msac_decode_bool_adapt(&ts->msac,
                                              ts->cdf.m.skip_mode[smctx]);
        if (DEBUG_BLOCK_INFO)
            printf("Post-skipmode[%d]: r=%d\n", b->skip_mode, ts->msac.rng);
    } else {
        b->skip_mode = 0;
    }

839
    // skip
840
841
842
843
844
845
846
847
    if (b->skip_mode || (seg && seg->skip)) {
        b->skip = 1;
    } else {
        const int sctx = t->a->skip[bx4] + t->l.skip[by4];
        b->skip = msac_decode_bool_adapt(&ts->msac, ts->cdf.m.skip[sctx]);
        if (DEBUG_BLOCK_INFO)
            printf("Post-skip[%d]: r=%d\n", b->skip, ts->msac.rng);
    }
848
849

    // segment_id
Ronald S. Bultje's avatar
Ronald S. Bultje committed
850
851
852
    if (f->frame_hdr->segmentation.enabled &&
        f->frame_hdr->segmentation.update_map &&
        !f->frame_hdr->segmentation.seg_data.preskip)
853
    {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
854
        if (!b->skip && f->frame_hdr->segmentation.temporal &&
855
856
857
858
859
            (seg_pred = msac_decode_bool_adapt(&ts->msac,
                                   ts->cdf.m.seg_pred[t->a->seg_pred[bx4] +
                                                      t->l.seg_pred[by4]])))
        {
            // temporal predicted seg_id
860
861
862
863
864
865
866
867
868
            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;
            }
869
870
871
872
873
874
875
876
877
878
        } 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 {
                const unsigned diff = msac_decode_symbol_adapt(&ts->msac,
                                                   ts->cdf.m.seg_id[seg_ctx],
879
                                                   DAV1D_MAX_SEGMENTS);
880
                const unsigned last_active_seg_id =
Ronald S. Bultje's avatar
Ronald S. Bultje committed
881
                    f->frame_hdr->segmentation.seg_data.last_active_segid;
882
883
                b->seg_id = neg_deinterleave(diff, pred_seg_id,
                                             last_active_seg_id + 1);
884
885
                if (b->seg_id > last_active_seg_id) b->seg_id = 0; // error?
            }
886
            if (b->seg_id >= DAV1D_MAX_SEGMENTS) b->seg_id = 0; // error?
887
888
        }

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

891
892
893
894
895
896
897
        if (DEBUG_BLOCK_INFO)
            printf("Post-segid[postskip;%d]: r=%d\n",
                   b->seg_id, ts->msac.rng);
    }

    // cdef index
    if (!b->skip) {
898
        const int idx = f->seq_hdr->sb128 ? ((t->bx & 16) >> 4) +
899
900
                                           ((t->by & 16) >> 3) : 0;
        if (t->cur_sb_cdef_idx_ptr[idx] == -1) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
901
            const int v = msac_decode_bools(&ts->msac, f->frame_hdr->cdef.n_bits);
902
903
904
905
906
907
908
909
910
911
912
913
            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
914
915
    if (!(t->bx & (31 >> !f->seq_hdr->sb128)) &&
        !(t->by & (31 >> !f->seq_hdr->sb128)))
916
917
    {
        const int prev_qidx = ts->last_qidx;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
918
        const int have_delta_q = f->frame_hdr->delta.q.present &&
919
            (bs != (f->seq_hdr->sb128 ? BS_128x128 : BS_64x64) || !b->skip);
920
921
922
923

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

924
925
926
927
928
929
930
        if (have_delta_q) {
            int delta_q = msac_decode_symbol_adapt(&ts->msac, ts->cdf.m.delta_q, 4);
            if (delta_q == 3) {
                const int n_bits = 1 + msac_decode_bools(&ts->msac, 3);
                delta_q = msac_decode_bools(&ts->msac, n_bits) + 1 + (1 << n_bits);
            }
            if (delta_q) {
931
                if (msac_decode_bool_equi(&ts->msac)) delta_q = -delta_q;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
932
                delta_q *= 1 << f->frame_hdr->delta.q.res_log2;
933
934
935
936
937
            }
            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);
938

Ronald S. Bultje's avatar
Ronald S. Bultje committed
939
940
            if (f->frame_hdr->delta.lf.present) {
                const int n_lfs = f->frame_hdr->delta.lf.multi ?
941
                    f->cur.p.layout != DAV1D_PIXEL_LAYOUT_I400 ? 4 : 2 : 1;
942
943
944
945

                for (int i = 0; i < n_lfs; i++) {
                    int delta_lf =
                        msac_decode_symbol_adapt(&ts->msac,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
946
                        ts->cdf.m.delta_lf[i + f->frame_hdr->delta.lf.multi], 4);
947
948
949
950
951
952
                    if (delta_lf == 3) {
                        const int n_bits = 1 + msac_decode_bools(&ts->msac, 3);
                        delta_lf = msac_decode_bools(&ts->msac, n_bits) +
                                   1 + (1 << n_bits);
                    }
                    if (delta_lf) {
953
                        if (msac_decode_bool_equi(&ts->msac))
954
                            delta_lf = -delta_lf;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
955
                        delta_lf *= 1 << f->frame_hdr->delta.lf.res_log2;
956
957
958
959
960
961
962
963
                    }
                    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);
                }
            }
964
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
965
        if (ts->last_qidx == f->frame_hdr->quant.yac) {
966
967
968
969
            // 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
970
            init_quant_tables(f->seq_hdr, f->frame_hdr, ts->last_qidx, ts->dqmem);
971
972
973
974
975
976
977
            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
978
            dav1d_calc_lf_values(ts->lflvlmem, f->frame_hdr, ts->last_delta_lf);
979
980
981
982
983
984
            ts->lflvl = ts->lflvlmem;
        }
    }

    if (b->skip_mode) {
        b->intra = 0;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
985
    } else if (f->frame_hdr->frame_type & 1) {
986
987
988
989
990
991
992
993
994
        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);
            b->intra = !msac_decode_bool_adapt(&ts->msac, ts->cdf.m.intra[ictx]);
            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
995
    } else if (f->frame_hdr->allow_intrabc) {
996
997
998
999
1000
1001
1002
1003
1004
        b->intra = !msac_decode_bool_adapt(&ts->msac, ts->cdf.m.intrabc);
        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
1005
        uint16_t *const ymode_cdf = f->frame_hdr->frame_type & 1 ?
1006
1007
1008
            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]]];
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
        b->y_mode = msac_decode_symbol_adapt(&ts->msac, ymode_cdf,
                                              N_INTRA_PRED_MODES);
        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];
            const int angle = msac_decode_symbol_adapt(&ts->msac, acdf, 7);
            b->y_angle = angle - 3;
        } else {
            b->y_angle = 0;
        }

        if (has_chroma) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1026
            const int cfl_allowed = f->frame_hdr->segmentation.lossless[b->seg_id] ?
1027
                cbw4 == 1 && cbh4 == 1 : !!(cfl_allowed_mask & (1 << bs));
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
            uint16_t *const uvmode_cdf = ts->cdf.m.uv_mode[cfl_allowed][b->y_mode];
            b->uv_mode = msac_decode_symbol_adapt(&ts->msac, uvmode_cdf,
                                         N_UV_INTRA_PRED_MODES - !cfl_allowed);
            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))
                const int sign =
                    msac_decode_symbol_adapt(&ts->msac, ts->cdf.m.cfl_sign, 8) + 1;
                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;
                    b->cfl_alpha[0] = msac_decode_symbol_adapt(&ts->msac,
                                            ts->cdf.m.cfl_alpha[ctx], 16) + 1;
                    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;
                    b->cfl_alpha[1] = msac_decode_symbol_adapt(&ts->msac,
                                            ts->cdf.m.cfl_alpha[ctx], 16) + 1;
                    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];
                const int angle = msac_decode_symbol_adapt(&ts->msac, acdf, 7);
                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
1072
        if (f->frame_hdr->allow_screen_content_tools &&
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
            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);
                const int use_y_pal =
                    msac_decode_bool_adapt(&ts->msac, ts->cdf.m.pal_y[sz_ctx][pal_ctx]);
                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;
                const int use_uv_pal =
                    msac_decode_bool_adapt(&ts->msac, ts->cdf.m.pal_uv[pal_ctx]);
                if (DEBUG_BLOCK_INFO)
                    printf("Post-uv_pal[%d]: r=%d\n", use_uv_pal, ts->msac.rng);
1092
1093
                if (use_uv_pal) // see aomedia bug 2183 for why we use luma coordinates
                    read_pal_uv(t, b, sz_ctx, bx4, by4);
1094
1095
1096
1097
            }
        }

        if (b->y_mode == DC_PRED && !b->pal_sz[0] &&
1098
            imax(b_dim[2], b_dim[3]) <= 3 && f->seq_hdr->filter_intra)
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
        {
            const int is_filter = msac_decode_bool_adapt(&ts->msac,
                                            ts->cdf.m.use_filter_intra[bs]);
            if (is_filter) {
                b->y_mode = FILTER_PRED;
                b->y_angle = msac_decode_symbol_adapt(&ts->msac,
                                                  ts->cdf.m.filter_intra, 5);
            }
            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
1137
        if (f->frame_hdr->segmentation.lossless[b->seg_id]) {
1138
            b->tx = b->uvtx = (int) TX_4X4;
1139
            t_dim = &dav1d_txfm_dimensions[TX_4X4];
1140
        } else {
1141
            b->tx = dav1d_max_txfm_size_for_bs[bs][0];
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1142
            b->uvtx = dav1d_max_txfm_size_for_bs[bs][f->cur.p.layout];
1143
            t_dim = &dav1d_txfm_dimensions[b->tx];
1144
            if (f->frame_hdr->txfm_mode == DAV1D_TX_SWITCHABLE && t_dim->max > TX_4X4) {
1145
                const int tctx = get_tx_ctx(t->a, &t->l, t_dim, by4, bx4);
1146
1147
1148
1149
1150
1151
                uint16_t *const tx_cdf = ts->cdf.m.txsz[t_dim->max - 1][tctx];
                int depth = msac_decode_symbol_adapt(&ts->msac, tx_cdf,
                                                     imin(t_dim->max + 1, 3));

                while (depth--) {
                    b->tx = t_dim->sub;
1152
                    t_dim = &dav1d_txfm_dimensions[b->tx];
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
                }
            }
            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
1167
                                   f->frame_hdr, (const uint8_t (*)[8][2])
1168
                                   &ts->lflvl[b->seg_id][0][0][0],
1169
                                   t->bx, t->by, f->w4, f->h4, bs,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1170
                                   b->tx, b->uvtx, f->cur.p.layout,
1171
1172
1173
1174
1175
                                   &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
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
#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
1187
        if (f->frame_hdr->frame_type & 1) { \
1188
            rep_macro(type, t->dir comp_type, off, mul * COMP_INTER_NONE); \
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1189
1190
            rep_macro(type, t->dir ref[0], off, mul * ((uint8_t) -1)); \
            rep_macro(type, t->dir ref[1], off, mul * ((uint8_t) -1)); \
1191
1192
            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
1193
        }
1194
1195
        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
1196
1197
1198
        case_set(bh4, l., 1, by4);
        case_set(bw4, a->, 0, bx4);
#undef set_ctx
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
        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) +
                                    ((t->bx >> 1) + (t->by & 1))][0] : t->pal[0];
            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
1209
1210
1211
1212
1213
#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
1214
1215
1216
1217
            if (b->pal_sz[1]) for (int pl = 1; pl < 3; pl++) {
                uint16_t *const pal = f->frame_thread.pass ?
                    f->frame_thread.pal[((t->by >> 1) + (t->bx & 1)) * (f->b4_stride >> 1) +
                                        ((t->bx >> 1) + (t->by & 1))][pl] : t->pal[pl];
1218
1219
1220
1221
1222
                // see aomedia bug 2183 for why we use luma coordinates here
                for (int x = 0; x < bw4; x++)
                    memcpy(t->al_pal[0][bx4 + x][pl], pal, 16);
                for (int y = 0; y < bh4; y++)
                    memcpy(t->al_pal[1][by4 + y][pl], pal, 16);
1223
1224
            }
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1225
        if ((f->frame_hdr->frame_type & 1) || f->frame_hdr->allow_intrabc) {
1226
1227
1228
            splat_intraref(f->mvs, f->b4_stride, t->by, t->bx, bs,
                           y_mode_nofilt);
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1229
    } else if (!(f->frame_hdr->frame_type & 1)) {
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
        // intra block copy
        candidate_mv mvstack[8];
        int n_mvs;
        mv mvlist[2][2];
        av1_find_ref_mvs(mvstack, &n_mvs, mvlist, NULL,
                         (int[2]) { -1, -1 }, f->bw, f->bh,
                         bs, bp, t->by, t->bx, ts->tiling.col_start,
                         ts->tiling.col_end, ts->tiling.row_start,
                         ts->tiling.row_end, f->libaom_cm);

        if (mvlist[0][0].y | mvlist[0][0].x)
            b->mv[0] = mvlist[0][0];
        else if (mvlist[0][1].y | mvlist[0][1].x)
            b->mv[0] = mvlist[0][1];
        else {
1245
            if (t->by - (16 << f->seq_hdr->sb128) < ts->tiling.row_start) {
1246
                b->mv[0].y = 0;
1247
                b->mv[0].x = -(512 << f->seq_hdr->sb128) - 2048;
1248
            } else {
1249
                b->mv[0].y = -(512 << f->seq_hdr->sb128);
1250
1251
1252
1253
1254
1255
                b->mv[0].x = 0;
            }
        }

        const struct mv ref = b->mv[0];
        read_mv_residual(t, &b->mv[0], &ts->cdf.dmv, 0);
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267

        // clip intrabc motion vector to decoded parts of current tile
        int border_left = ts->tiling.col_start * 4;
        int border_top  = ts->tiling.row_start * 4;
        if (has_chroma) {
            if (bw4 < 2 &&  ss_hor)
                border_left += 4;
            if (bh4 < 2 &&  ss_ver)
                border_top  += 4;
        }
        int src_left   = t->bx * 4 + (b->mv[0].x >> 3);
        int src_top    = t->by * 4 + (b->mv[0].y >> 3);
1268
1269
1270
        int src_right  = src_left + bw4 * 4;
        int src_bottom = src_top  + bh4 * 4;
        const int border_right = ((ts->tiling.col_end + (bw4 - 1)) & ~(bw4 - 1)) * 4;
1271
1272
1273
1274
1275

        // check against left or right tile boundary and adjust if necessary
        if (src_left < border_left) {
            src_right += border_left - src_left;
            src_left  += border_left - src_left;
1276
1277
1278
        } else if (src_right > border_right) {
            src_left  -= src_right - border_right;
            src_right -= src_right - border_right;
1279
1280
1281
1282
1283
1284
1285
        }
        // check against top tile boundary and adjust if necessary
        if (src_top < border_top) {
            src_bottom += border_top - src_top;
            src_top    += border_top - src_top;
        }

1286
1287
1288
        const int sbx = (t->bx >> (4 + f->seq_hdr->sb128)) << (6 + f->seq_hdr->sb128);
        const int sby = (t->by >> (4 + f->seq_hdr->sb128)) << (6 + f->seq_hdr->sb128);
        const int sb_size = 1 << (6 + f->seq_hdr->sb128);
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
        // check for overlap with current superblock
        if (src_bottom > sby && src_right > sbx) {
            if (src_top - border_top >= src_bottom - sby) {
                // if possible move src up into the previous suberblock row
                src_top    -= src_bottom - sby;
                src_bottom -= src_bottom - sby;
            } else if (src_left - border_left >= src_right - sbx) {
                // if possible move src left into the previous suberblock
                src_left  -= src_right - sbx;
                src_right -= src_right - sbx;
            }
        }
        // move src up if it is below current superblock row
        if (src_bottom > sby + sb_size) {
            src_top    -= src_bottom - (sby + sb_size);
            src_bottom -= src_bottom - (sby + sb_size);
        }
        // error out if mv still overlaps with the current superblock
        if (src_bottom > sby && src_right > sbx)
            return -1;

        b->mv[0].x = (src_left - t->bx * 4) * 8;
        b->mv[0].y = (src_top  - t->by * 4) * 8;

1313
1314
1315
1316
1317
1318
1319
1320
1321
        if (DEBUG_BLOCK_INFO)
            printf("Post-dmv[%d/%d,ref=%d/%d|%d/%d]: r=%d\n",
                   b->mv[0].y, b->mv[0].x, ref.y, ref.x,
                   mvlist[0][0].y, mvlist[0][0].x, ts->msac.rng);
        read_vartx_tree(t, b, bs, bx4, by4);

        // reconstruction
        if (f->frame_thread.pass == 1) {
            f->bd_fn.read_coef_blocks(t, bs, b);
1322
            b->filter2d = FILTER_2D_BILINEAR;
1323
        } else {
1324
            if (f->bd_fn.recon_b_inter(t, bs, b)) return -1;
1325
1326
1327
1328
        }

        splat_intrabc_mv(f->mvs, f->b4_stride, t->by, t->bx, bs, b->mv[0]);

Ronald S. Bultje's avatar
Ronald S. Bultje committed
1329
1330
1331
1332
1333
1334
#define set_ctx(type, dir, diridx, off, mul, rep_macro) \
        rep_macro(type, t->dir tx_intra, off, mul * b_dim[2 + diridx]); \
        rep_macro(type, t->dir mode, off, mul * DC_PRED); \
        rep_macro(type, t->dir pal_sz, off, 0); \
        /* see aomedia bug 2183 for why this is outside if (has_chroma) */ \
        rep_macro(type, t->pal_sz_uv[diridx], off, 0); \
1335
        rep_macro(type, t->dir seg_pred, off, mul * seg_pred); \
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1336
1337
        rep_macro(type, t->dir skip_mode, off, 0); \
        rep_macro(type, t->dir intra, off, 0); \
1338
        rep_macro(type, t->dir skip, off, mul * b->skip)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1339
1340
1341
        case_set(bh4, l., 1, by4);
        case_set(bw4, a->, 0, bx4);
#undef set_ctx
1342
        if (has_chroma) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1343
1344
1345
1346
1347
#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
1348
1349
1350
1351
1352
1353
1354
        }
    } else {
        // inter-specific mode/mv coding
        int is_comp, has_subpel_filter;

        if (b->skip_mode) {
            is_comp = 1;
1355
        } else if ((!seg || (seg->ref == -1 && !seg->globalmv && !seg->skip)) &&
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1356
                   f->frame_hdr->switchable_comp_refs && imin(bw4, bh4) > 1)
1357
        {
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
            const int ctx = get_comp_ctx(t->a, &t->l, by4, bx4,
                                         have_top, have_left);
            is_comp = msac_decode_bool_adapt(&ts->msac, ts->cdf.m.comp[ctx]);
            if (DEBUG_BLOCK_INFO)
                printf("Post-compflag[%d]: r=%d\n", is_comp, ts->msac.rng);
        } else {
            is_comp = 0;
        }

        if (b->skip_mode) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1368
1369
            b->ref[0] = f->frame_hdr->skip_mode_refs[0];
            b->ref[1] = f->frame_hdr->skip_mode_refs[1];
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
            b->comp_type = COMP_INTER_AVG;
            b->inter_mode = NEARESTMV_NEARESTMV;
            b->drl_idx = 0;
            has_subpel_filter = 0;

            candidate_mv mvstack[8];
            int n_mvs, ctx;
            mv mvlist[2][2];
            av1_find_ref_mvs(mvstack, &n_mvs, mvlist, &ctx,
                             (int[2]) { b->ref[0], b->ref[1] }, f->bw, f->bh,
                             bs, bp, t->by, t->bx, ts->tiling.col_start,
                             ts->tiling.col_end, ts->tiling.row_start,
                             ts->tiling.row_end, f->libaom_cm);

            b->mv[0] = mvstack[0].this_mv;
            b->mv[1] = mvstack[0].comp_mv;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1386
1387
            fix_mv_precision(f->frame_hdr, &b->mv[0]);
            fix_mv_precision(f->frame_hdr, &b->mv[1]);
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458