imagescript 3.2.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -10
- package/THIRD_PARTY_NOTICES.md +298 -2
- package/dist/animation.d.ts +25 -8
- package/dist/animation.js +44 -13
- package/dist/codecs/av1/cdef.js +197 -0
- package/dist/codecs/av1/data.js +141 -0
- package/dist/codecs/av1/decode.js +1769 -0
- package/dist/codecs/av1/filmgrain.js +219 -0
- package/dist/codecs/av1/frame.js +114 -0
- package/dist/codecs/av1/ipred.js +491 -0
- package/dist/codecs/av1/itx.js +950 -0
- package/dist/codecs/av1/loopfilter.js +149 -0
- package/dist/codecs/av1/msac.js +161 -0
- package/dist/codecs/av1/obu.js +516 -0
- package/dist/codecs/av1/postfilter.js +28 -0
- package/dist/codecs/av1/restoration.js +193 -0
- package/dist/codecs/av1/tables.js +160 -0
- package/dist/codecs/avif.js +581 -0
- package/dist/codecs/bmp.js +317 -0
- package/dist/codecs/crc.js +5 -0
- package/dist/codecs/gif.js +10 -35
- package/dist/codecs/hdr.d.ts +25 -0
- package/dist/codecs/hdr.js +201 -0
- package/dist/codecs/ico.js +48 -0
- package/dist/codecs/jpeg.js +11 -28
- package/dist/codecs/jxl/bits.js +126 -0
- package/dist/codecs/jxl/blend.js +117 -0
- package/dist/codecs/jxl/color.js +116 -0
- package/dist/codecs/jxl/dct.js +404 -0
- package/dist/codecs/jxl/entropy.js +556 -0
- package/dist/codecs/jxl/features.js +325 -0
- package/dist/codecs/jxl/filters.js +119 -0
- package/dist/codecs/jxl/frame-header.js +195 -0
- package/dist/codecs/jxl/frame.js +319 -0
- package/dist/codecs/jxl/headers.js +249 -0
- package/dist/codecs/jxl/idct.js +484 -0
- package/dist/codecs/jxl/modular.js +688 -0
- package/dist/codecs/jxl/quant.js +219 -0
- package/dist/codecs/jxl/upsample.js +52 -0
- package/dist/codecs/jxl/vardct.js +472 -0
- package/dist/codecs/jxl.js +89 -0
- package/dist/codecs/netpbm.js +239 -0
- package/dist/codecs/png.js +22 -10
- package/dist/codecs/qoi.js +150 -0
- package/dist/codecs/tga.js +3 -1
- package/dist/codecs/tiff.js +7 -2
- package/dist/codecs/vp8-enc-dsp.js +932 -0
- package/dist/codecs/vp8-enc-tables.js +78 -0
- package/dist/codecs/vp8-enc.js +1930 -0
- package/dist/codecs/vp8.js +3 -1
- package/dist/codecs/vp8l.js +126 -58
- package/dist/codecs/webp.js +47 -11
- package/dist/codecs/zlib.js +81 -69
- package/dist/frame.d.ts +1 -0
- package/dist/frame.js +4 -2
- package/dist/gif.d.ts +1 -0
- package/dist/gif.js +2 -2
- package/dist/image-type.d.ts +15 -1
- package/dist/image-type.js +45 -2
- package/dist/image.d.ts +89 -13
- package/dist/image.js +266 -113
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -4
- package/dist/render/bidi.js +350 -0
- package/dist/render/buffer.js +362 -0
- package/dist/render/color.js +164 -0
- package/dist/render/colr.js +523 -0
- package/dist/render/font.js +173 -241
- package/dist/render/hinting.js +38 -22
- package/dist/render/layout.js +1553 -0
- package/dist/render/linebreak.js +210 -0
- package/dist/render/segment.js +106 -0
- package/dist/render/shape.js +984 -0
- package/dist/render/shapers/arabic.js +284 -0
- package/dist/render/shapers/hangul.js +142 -0
- package/dist/render/shapers/hebrew.js +49 -0
- package/dist/render/shapers/index.js +52 -0
- package/dist/render/shapers/indic.js +579 -0
- package/dist/render/shapers/khmer.js +104 -0
- package/dist/render/shapers/machine.js +129 -0
- package/dist/render/shapers/myanmar.js +121 -0
- package/dist/render/shapers/syllabic.js +100 -0
- package/dist/render/shapers/thai.js +125 -0
- package/dist/render/shapers/use.js +235 -0
- package/dist/render/svg.js +102 -23
- package/dist/render/text.js +373 -103
- package/dist/render/unicode-data.js +63 -0
- package/dist/render/unicode.js +50 -0
- package/dist/text-layout.d.ts +4 -1
- package/dist/text-layout.js +2 -2
- package/dist/util/alpha.js +43 -0
- package/dist/util/blur.js +20 -33
- package/dist/util/bytes.js +40 -0
- package/dist/util/limits.js +34 -0
- package/dist/util/options.js +7 -0
- package/dist/util/resample.js +126 -7
- package/dist/util/rotate.js +43 -0
- package/dist/version.js +1 -1
- package/licenses/HarfBuzz.txt +42 -0
- package/licenses/Unicode-3.0.txt +39 -0
- package/package.json +25 -2
|
@@ -0,0 +1,1769 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Decodes the tiles of AV1 intra frames: partitions, modes, palettes, transform sizes, coefficients and the intra
|
|
3
|
+
* reconstruction, ported from dav1d (src/decode.c, src/recon_tmpl.c, src/lf_mask.c). Copyright (c) 2018-2021,
|
|
4
|
+
* VideoLAN and dav1d authors, Copyright (c) 2018, Two Orioles, LLC, BSD-2-Clause License (see THIRD_PARTY_NOTICES.md)
|
|
5
|
+
*/
|
|
6
|
+
import { SymbolDecoder } from "./msac.js";
|
|
7
|
+
import { RESTORATION_NONE, RESTORATION_SWITCHABLE, RESTORATION_WIENER, RESTORATION_SGRPROJ } from "./obu.js";
|
|
8
|
+
import { CDF, BLOCK_DIMENSIONS, TXFM_DIMENSIONS, MAX_TXFM_SIZE_FOR_BS, AL_PART_CTX, BLOCK_SIZES, PARTITION_TYPE_COUNT, INTRA_MODE_CONTEXT, TXTP_FROM_UVMODE, TX_TYPES_PER_SET, FILTER_MODE_TO_Y_MODE, LO_CTX_OFFSETS, SKIP_CTX, TX_TYPE_CLASS, SGR_PARAMS, CFL_ALLOWED_MASK, BL_128X128, BL_8X8, BS_128x128, BS_64x64, BS_4x4, PARTITION_NONE, PARTITION_H, PARTITION_V, PARTITION_SPLIT, PARTITION_T_TOP_SPLIT, PARTITION_T_BOTTOM_SPLIT, PARTITION_T_LEFT_SPLIT, PARTITION_T_RIGHT_SPLIT, PARTITION_H4, PARTITION_V4, DC_PRED, VERT_PRED, VERT_LEFT_PRED, SMOOTH_PRED, SMOOTH_V_PRED, SMOOTH_H_PRED, CFL_PRED, FILTER_PRED, TX_4X4, TX_64X64, TX_16X16, TX_32X32, RTX_4X8, DCT_DCT, IDTX, WHT_WHT, TX_CLASS_2D, TX_CLASS_H, EDGE_ALL_TR_AND_BL, EDGE_ALL_TOP_HAS_RIGHT, EDGE_ALL_LEFT_HAS_BOTTOM, EDGE_I444_TOP_HAS_RIGHT, EDGE_I444_LEFT_HAS_BOTTOM, EDGE_I420_TOP_HAS_RIGHT, EDGE_I420_LEFT_HAS_BOTTOM, edgeTree, defaultCdfs, scan, dequant, quantizerMatrix } from "./tables.js";
|
|
9
|
+
import { prepareEdges, predict, preparedAngle, cflAc, cflPredict, ANGLE_USE_EDGE_FILTER, ANGLE_SMOOTH_EDGE } from "./ipred.js";
|
|
10
|
+
import { inverseTransformAdd } from "./itx.js";
|
|
11
|
+
const bdim = (bs, i) => BLOCK_DIMENSIONS[bs * 4 + i];
|
|
12
|
+
const tdim = (tx, i) => TXFM_DIMENSIONS[tx * 8 + i];
|
|
13
|
+
const W = 0, H = 1, LW = 2, LH = 3, MIN = 4, MAX = 5, SUB = 6, CTX = 7;
|
|
14
|
+
export class Frame {
|
|
15
|
+
seq;
|
|
16
|
+
hdr;
|
|
17
|
+
width;
|
|
18
|
+
height;
|
|
19
|
+
bitdepth;
|
|
20
|
+
bitdepthMax;
|
|
21
|
+
layout;
|
|
22
|
+
ssx;
|
|
23
|
+
ssy;
|
|
24
|
+
planes = [];
|
|
25
|
+
strides = [];
|
|
26
|
+
bw;
|
|
27
|
+
bh;
|
|
28
|
+
b4Stride;
|
|
29
|
+
lfLevels;
|
|
30
|
+
txW;
|
|
31
|
+
txH;
|
|
32
|
+
uvTxW;
|
|
33
|
+
uvTxH;
|
|
34
|
+
skip;
|
|
35
|
+
cdefIdx;
|
|
36
|
+
segMap;
|
|
37
|
+
lr = [[], [], []];
|
|
38
|
+
lrUnitsW = [0, 0, 0];
|
|
39
|
+
lrUnitsH = [0, 0, 0];
|
|
40
|
+
incomplete = false;
|
|
41
|
+
constructor(seq, hdr) {
|
|
42
|
+
this.seq = seq;
|
|
43
|
+
this.hdr = hdr;
|
|
44
|
+
this.width = hdr.width;
|
|
45
|
+
this.height = hdr.height;
|
|
46
|
+
this.bitdepth = seq.bitDepth;
|
|
47
|
+
this.bitdepthMax = (1 << seq.bitDepth) - 1;
|
|
48
|
+
this.layout = seq.monochrome ? 0 : seq.ssx ? seq.ssy ? 1 : 2 : 3;
|
|
49
|
+
this.ssx = seq.ssx;
|
|
50
|
+
this.ssy = seq.ssy;
|
|
51
|
+
this.bw = (hdr.width + 7 >> 3) << 1;
|
|
52
|
+
this.bh = (hdr.height + 7 >> 3) << 1;
|
|
53
|
+
this.b4Stride = this.bw + 31 & ~31;
|
|
54
|
+
const b4Rows = this.bh + 31 & ~31;
|
|
55
|
+
const lumaStride = this.b4Stride * 4, lumaRows = b4Rows * 4;
|
|
56
|
+
for (let p = 0; p < (seq.monochrome ? 1 : 3); p++) {
|
|
57
|
+
const sx = p ? this.ssx : 0, sy = p ? this.ssy : 0;
|
|
58
|
+
this.strides.push(lumaStride >> sx);
|
|
59
|
+
this.planes.push(new Uint16Array((lumaStride >> sx) * (lumaRows >> sy)));
|
|
60
|
+
}
|
|
61
|
+
const n = this.b4Stride * b4Rows;
|
|
62
|
+
this.lfLevels = new Uint8Array(n * 4);
|
|
63
|
+
this.txW = new Uint8Array(n);
|
|
64
|
+
this.txH = new Uint8Array(n);
|
|
65
|
+
this.uvTxW = new Uint8Array(n);
|
|
66
|
+
this.uvTxH = new Uint8Array(n);
|
|
67
|
+
this.skip = new Uint8Array(n);
|
|
68
|
+
this.segMap = new Uint8Array(n);
|
|
69
|
+
this.cdefIdx = new Int8Array((this.b4Stride >> 4) * (b4Rows >> 4)).fill(-1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function calcLfLevels(hdr, delta) {
|
|
73
|
+
const lf = hdr.loopFilter;
|
|
74
|
+
const out = [];
|
|
75
|
+
const value = (base, lfDelta, segDelta) => {
|
|
76
|
+
const b = Math.min(63, Math.max(0, Math.min(63, Math.max(0, base + lfDelta)) + segDelta));
|
|
77
|
+
if (!lf.modeRefDeltaEnabled)
|
|
78
|
+
return b;
|
|
79
|
+
return Math.min(63, Math.max(0, b + lf.refDeltas[0] * (1 << (b >= 32 ? 1 : 0))));
|
|
80
|
+
};
|
|
81
|
+
for (let s = 0; s < (hdr.segmentation.enabled ? 8 : 1); s++) {
|
|
82
|
+
if (!lf.levelY[0] && !lf.levelY[1]) {
|
|
83
|
+
out.push([0, 0, 0, 0]);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const seg = hdr.segmentation.enabled ? hdr.segmentation.data[s].deltaLf : [0, 0, 0, 0];
|
|
87
|
+
const multi = hdr.deltaLf.multi;
|
|
88
|
+
out.push([
|
|
89
|
+
value(lf.levelY[0], delta[0], seg[0]),
|
|
90
|
+
value(lf.levelY[1], delta[multi ? 1 : 0], seg[1]),
|
|
91
|
+
lf.levelU ? value(lf.levelU, delta[multi ? 2 : 0], seg[2]) : 0,
|
|
92
|
+
lf.levelV ? value(lf.levelV, delta[multi ? 3 : 0], seg[3]) : 0
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
function quantTables(seq, hdr, qidx) {
|
|
98
|
+
const q = hdr.quant, hbd = seq.bitDepth === 8 ? 0 : seq.bitDepth === 10 ? 1 : 2;
|
|
99
|
+
const clip = (v) => Math.min(255, Math.max(0, v));
|
|
100
|
+
const out = [];
|
|
101
|
+
for (let i = 0; i < (hdr.segmentation.enabled ? 8 : 1); i++) {
|
|
102
|
+
const yac = hdr.segmentation.enabled ? clip(qidx + hdr.segmentation.data[i].deltaQ) : qidx;
|
|
103
|
+
out.push([
|
|
104
|
+
[dequant(hbd, clip(yac + q.ydcDelta), 0), dequant(hbd, yac, 1)],
|
|
105
|
+
[dequant(hbd, clip(yac + q.udcDelta), 0), dequant(hbd, clip(yac + q.uacDelta), 1)],
|
|
106
|
+
[dequant(hbd, clip(yac + q.vdcDelta), 0), dequant(hbd, clip(yac + q.vacDelta), 1)]
|
|
107
|
+
]);
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
const neg_deinterleave = (diff, ref, max) => {
|
|
112
|
+
if (!ref)
|
|
113
|
+
return diff;
|
|
114
|
+
if (ref >= max - 1)
|
|
115
|
+
return max - diff - 1;
|
|
116
|
+
if (2 * ref < max) {
|
|
117
|
+
if (diff <= 2 * ref)
|
|
118
|
+
return diff & 1 ? ref + (diff + 1 >> 1) : ref - (diff >> 1);
|
|
119
|
+
return diff;
|
|
120
|
+
}
|
|
121
|
+
if (diff <= 2 * (max - ref - 1))
|
|
122
|
+
return diff & 1 ? ref + (diff + 1 >> 1) : ref - (diff >> 1);
|
|
123
|
+
return max - (diff + 1);
|
|
124
|
+
};
|
|
125
|
+
export function decodeTileGroup(decoder, data, start, end, first, last) {
|
|
126
|
+
const hdr = decoder.frame.hdr;
|
|
127
|
+
let o = start;
|
|
128
|
+
for (let j = first; j <= last; j++) {
|
|
129
|
+
let size;
|
|
130
|
+
if (j === last)
|
|
131
|
+
size = end - o;
|
|
132
|
+
else {
|
|
133
|
+
size = 0;
|
|
134
|
+
for (let k = 0; k < hdr.tiles.sizeBytes; k++)
|
|
135
|
+
size += data[o++] * 2 ** (k * 8);
|
|
136
|
+
size++;
|
|
137
|
+
if (o + size > end)
|
|
138
|
+
throw new Error('AV1: invalid tile size');
|
|
139
|
+
}
|
|
140
|
+
decoder.decodeTile(data, o, o + size, Math.floor(j / hdr.tiles.cols), j % hdr.tiles.cols);
|
|
141
|
+
o += size;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export class TileDecoder {
|
|
145
|
+
frame;
|
|
146
|
+
seq;
|
|
147
|
+
hdr;
|
|
148
|
+
msac;
|
|
149
|
+
cdf;
|
|
150
|
+
bx = 0;
|
|
151
|
+
by = 0;
|
|
152
|
+
colStart = 0;
|
|
153
|
+
colEnd = 0;
|
|
154
|
+
rowStart = 0;
|
|
155
|
+
rowEnd = 0;
|
|
156
|
+
lastQidx = 0;
|
|
157
|
+
lastDeltaLf = [0, 0, 0, 0];
|
|
158
|
+
dq;
|
|
159
|
+
frameDq;
|
|
160
|
+
lfLvl;
|
|
161
|
+
frameLfLvl;
|
|
162
|
+
lrRef = [];
|
|
163
|
+
cdefSb = 0;
|
|
164
|
+
aMode;
|
|
165
|
+
lMode = new Uint8Array(32);
|
|
166
|
+
aLcoef;
|
|
167
|
+
lLcoef = new Uint8Array(32);
|
|
168
|
+
aCcoef;
|
|
169
|
+
lCcoef = [new Uint8Array(32), new Uint8Array(32)];
|
|
170
|
+
aSegPred;
|
|
171
|
+
lSegPred = new Uint8Array(32);
|
|
172
|
+
aSkip;
|
|
173
|
+
lSkip = new Uint8Array(32);
|
|
174
|
+
aIntra;
|
|
175
|
+
lIntra = new Uint8Array(32);
|
|
176
|
+
aTxIntra;
|
|
177
|
+
lTxIntra = new Int8Array(32);
|
|
178
|
+
aTx;
|
|
179
|
+
lTx = new Int8Array(32);
|
|
180
|
+
aUvmode;
|
|
181
|
+
lUvmode = new Uint8Array(32);
|
|
182
|
+
aPalSz;
|
|
183
|
+
lPalSz = new Uint8Array(32);
|
|
184
|
+
aPalSzUv;
|
|
185
|
+
lPalSzUv = new Uint8Array(32);
|
|
186
|
+
aPartition;
|
|
187
|
+
lPartition = new Uint8Array(16);
|
|
188
|
+
aPal;
|
|
189
|
+
lPal = new Uint16Array(32 * 24);
|
|
190
|
+
pal = new Uint16Array(24);
|
|
191
|
+
palIdxY = new Uint8Array(64 * 64);
|
|
192
|
+
palIdxUv = new Uint8Array(64 * 64);
|
|
193
|
+
palTmp = new Uint8Array(64 * 64);
|
|
194
|
+
cf = new Int32Array(32 * 32);
|
|
195
|
+
levels = new Uint8Array(36 * 36);
|
|
196
|
+
ac = new Int16Array(32 * 32);
|
|
197
|
+
qm = [];
|
|
198
|
+
constructor(frame) {
|
|
199
|
+
this.frame = frame;
|
|
200
|
+
this.seq = frame.seq;
|
|
201
|
+
this.hdr = frame.hdr;
|
|
202
|
+
const n = frame.b4Stride + 32;
|
|
203
|
+
this.aMode = new Uint8Array(n);
|
|
204
|
+
this.aLcoef = new Uint8Array(n);
|
|
205
|
+
this.aCcoef = [new Uint8Array(n), new Uint8Array(n)];
|
|
206
|
+
this.aSegPred = new Uint8Array(n);
|
|
207
|
+
this.aSkip = new Uint8Array(n);
|
|
208
|
+
this.aIntra = new Uint8Array(n);
|
|
209
|
+
this.aTxIntra = new Int8Array(n);
|
|
210
|
+
this.aTx = new Int8Array(n);
|
|
211
|
+
this.aUvmode = new Uint8Array(n);
|
|
212
|
+
this.aPalSz = new Uint8Array(n);
|
|
213
|
+
this.aPalSzUv = new Uint8Array(n);
|
|
214
|
+
this.aPartition = new Uint8Array(n >> 1);
|
|
215
|
+
this.aPal = new Uint16Array(n * 24);
|
|
216
|
+
this.frameDq = this.dq = quantTables(this.seq, this.hdr, this.hdr.quant.yac);
|
|
217
|
+
this.frameLfLvl = this.lfLvl = calcLfLevels(this.hdr, [0, 0, 0, 0]);
|
|
218
|
+
for (let tx = 0; tx < 19; tx++) {
|
|
219
|
+
const q = this.hdr.quant;
|
|
220
|
+
this.qm.push(q.qm ? [q.qmY, q.qmU, q.qmV].map((level, p) => level < 15 ? quantizerMatrix(level, p ? 1 : 0, tx) : null) : [null, null, null]);
|
|
221
|
+
}
|
|
222
|
+
this.resetAbove(0, n);
|
|
223
|
+
if (this.hdr.allowIntrabc) {
|
|
224
|
+
const size = frame.b4Stride * ((frame.bh + 31 & ~31) + 32);
|
|
225
|
+
this.mvY = new Int16Array(size);
|
|
226
|
+
this.mvX = new Int16Array(size);
|
|
227
|
+
this.mvValid = new Uint8Array(size);
|
|
228
|
+
this.mvBs = new Uint8Array(size);
|
|
229
|
+
}
|
|
230
|
+
for (let p = 0; p < frame.planes.length; p++) {
|
|
231
|
+
const type = this.hdr.restoration.types[p];
|
|
232
|
+
if (type === RESTORATION_NONE)
|
|
233
|
+
continue;
|
|
234
|
+
const sx = p ? frame.ssx : 0, sy = p ? frame.ssy : 0;
|
|
235
|
+
const size = 1 << this.hdr.restoration.unitSizeLog2[p ? 1 : 0];
|
|
236
|
+
const w = this.hdr.upscaledWidth + sx >> sx, h = frame.height + sy >> sy;
|
|
237
|
+
const cols = Math.max(1, Math.floor((w + (size >> 1)) / size)), rows = Math.max(1, Math.floor((h + (size >> 1)) / size));
|
|
238
|
+
frame.lrUnitsW[p] = cols;
|
|
239
|
+
frame.lrUnitsH[p] = rows;
|
|
240
|
+
for (let i = 0; i < cols * rows; i++)
|
|
241
|
+
frame.lr[p].push({ type: RESTORATION_NONE, filterV: [3, -7, 15], filterH: [3, -7, 15], sgrWeights: [-32, 31] });
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
resetAbove(from, to) {
|
|
245
|
+
this.aIntra.fill(1, from, to);
|
|
246
|
+
this.aUvmode.fill(DC_PRED, from, to);
|
|
247
|
+
this.aMode.fill(DC_PRED, from, to);
|
|
248
|
+
this.aPartition.fill(0, from >> 1, to + 1 >> 1);
|
|
249
|
+
this.aSkip.fill(0, from, to);
|
|
250
|
+
this.aTxIntra.fill(-1, from, to);
|
|
251
|
+
this.aTx.fill(TX_64X64, from, to);
|
|
252
|
+
this.aLcoef.fill(0x40, from, to);
|
|
253
|
+
this.aCcoef[0].fill(0x40, from, to);
|
|
254
|
+
this.aCcoef[1].fill(0x40, from, to);
|
|
255
|
+
this.aSegPred.fill(0, from, to);
|
|
256
|
+
this.aPalSz.fill(0, from, to);
|
|
257
|
+
this.aPalSzUv.fill(0, from, to);
|
|
258
|
+
}
|
|
259
|
+
resetLeft() {
|
|
260
|
+
this.lIntra.fill(1);
|
|
261
|
+
this.lUvmode.fill(DC_PRED);
|
|
262
|
+
this.lMode.fill(DC_PRED);
|
|
263
|
+
this.lPartition.fill(0);
|
|
264
|
+
this.lSkip.fill(0);
|
|
265
|
+
this.lTxIntra.fill(-1);
|
|
266
|
+
this.lTx.fill(TX_64X64);
|
|
267
|
+
this.lLcoef.fill(0x40);
|
|
268
|
+
this.lCcoef[0].fill(0x40);
|
|
269
|
+
this.lCcoef[1].fill(0x40);
|
|
270
|
+
this.lSegPred.fill(0);
|
|
271
|
+
this.lPalSz.fill(0);
|
|
272
|
+
this.lPalSzUv.fill(0);
|
|
273
|
+
}
|
|
274
|
+
tileRow = -1;
|
|
275
|
+
decodeTile(data, start, end, tileRow, tileCol) {
|
|
276
|
+
const f = this.frame, hdr = this.hdr, seq = this.seq;
|
|
277
|
+
if (tileRow !== this.tileRow) {
|
|
278
|
+
this.tileRow = tileRow;
|
|
279
|
+
this.resetAbove(0, this.aMode.length);
|
|
280
|
+
}
|
|
281
|
+
const sbShift = seq.sb128 ? 5 : 4, sbStep = 1 << sbShift;
|
|
282
|
+
this.colStart = hdr.tiles.colStarts[tileCol] << sbShift;
|
|
283
|
+
this.colEnd = Math.min(hdr.tiles.colStarts[tileCol + 1] << sbShift, f.bw);
|
|
284
|
+
this.rowStart = hdr.tiles.rowStarts[tileRow] << sbShift;
|
|
285
|
+
this.rowEnd = Math.min(hdr.tiles.rowStarts[tileRow + 1] << sbShift, f.bh);
|
|
286
|
+
this.cdf = defaultCdfs(hdr.quant.yac);
|
|
287
|
+
this.msac = new SymbolDecoder(data, start, end, !hdr.disableCdfUpdate);
|
|
288
|
+
this.lastQidx = hdr.quant.yac;
|
|
289
|
+
this.lastDeltaLf = [0, 0, 0, 0];
|
|
290
|
+
this.dq = this.frameDq;
|
|
291
|
+
this.lfLvl = this.frameLfLvl;
|
|
292
|
+
for (let p = 0; p < 3; p++)
|
|
293
|
+
this.lrRef[p] = { type: RESTORATION_NONE, filterV: [3, -7, 15], filterH: [3, -7, 15], sgrWeights: [-32, 31] };
|
|
294
|
+
const root = edgeTree(seq.sb128);
|
|
295
|
+
for (this.by = this.rowStart; this.by < this.rowEnd; this.by += sbStep) {
|
|
296
|
+
this.resetLeft();
|
|
297
|
+
for (this.bx = this.colStart; this.bx < this.colEnd; this.bx += sbStep) {
|
|
298
|
+
this.cdefSb = (this.by >> 4) * (f.b4Stride >> 4) + (this.bx >> 4);
|
|
299
|
+
this.readRestorationUnits();
|
|
300
|
+
this.decodeSb(seq.sb128 ? BL_128X128 : 1, root);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (this.msac.overread)
|
|
304
|
+
throw new Error('AV1: truncated tile data');
|
|
305
|
+
}
|
|
306
|
+
readRestorationUnits() {
|
|
307
|
+
const f = this.frame, hdr = this.hdr;
|
|
308
|
+
if (hdr.superresDenominator !== 8 && hdr.restoration.types.some(t => t)) {
|
|
309
|
+
this.readRestorationUnitsSuperres();
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
for (let p = 0; p < f.planes.length; p++) {
|
|
313
|
+
const type = hdr.restoration.types[p];
|
|
314
|
+
if (type === RESTORATION_NONE)
|
|
315
|
+
continue;
|
|
316
|
+
const sx = p ? f.ssx : 0, sy = p ? f.ssy : 0;
|
|
317
|
+
const sizeLog2 = hdr.restoration.unitSizeLog2[p ? 1 : 0], size = 1 << sizeLog2, mask = size - 1;
|
|
318
|
+
const y = this.by * 4 >> sy, h = f.height + sy >> sy;
|
|
319
|
+
if (y & mask)
|
|
320
|
+
continue;
|
|
321
|
+
if (y && y + (size >> 1) > h)
|
|
322
|
+
continue;
|
|
323
|
+
const x = this.bx * 4 >> sx, w = f.width + sx >> sx;
|
|
324
|
+
if (x & mask)
|
|
325
|
+
continue;
|
|
326
|
+
if (x && x + (size >> 1) > w)
|
|
327
|
+
continue;
|
|
328
|
+
const unit = f.lr[p][(y >> sizeLog2) * f.lrUnitsW[p] + (x >> sizeLog2)];
|
|
329
|
+
this.readRestorationInfo(unit, p, type);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
readRestorationUnitsSuperres() {
|
|
333
|
+
const f = this.frame, hdr = this.hdr;
|
|
334
|
+
const sbStep = this.seq.sb128 ? 32 : 16;
|
|
335
|
+
for (let p = 0; p < f.planes.length; p++) {
|
|
336
|
+
const type = hdr.restoration.types[p];
|
|
337
|
+
if (type === RESTORATION_NONE)
|
|
338
|
+
continue;
|
|
339
|
+
const sx = p ? f.ssx : 0, sy = p ? f.ssy : 0;
|
|
340
|
+
const sizeLog2 = hdr.restoration.unitSizeLog2[p ? 1 : 0], size = 1 << sizeLog2;
|
|
341
|
+
const y = this.by * 4 >> sy, h = f.height + sy >> sy;
|
|
342
|
+
if (y & size - 1)
|
|
343
|
+
continue;
|
|
344
|
+
if (y && y + (size >> 1) > h)
|
|
345
|
+
continue;
|
|
346
|
+
const d = hdr.superresDenominator;
|
|
347
|
+
const rnd = size * 8 - 1, shift = sizeLog2 + 3;
|
|
348
|
+
const x0 = (4 * this.bx * d >> sx) + rnd >> shift;
|
|
349
|
+
const x1 = (4 * (this.bx + sbStep) * d >> sx) + rnd >> shift;
|
|
350
|
+
for (let x = x0; x < Math.min(x1, f.lrUnitsW[p]); x++) {
|
|
351
|
+
const unit = f.lr[p][(y >> sizeLog2) * f.lrUnitsW[p] + x];
|
|
352
|
+
this.readRestorationInfo(unit, p, type);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
readRestorationInfo(lr, p, frameType) {
|
|
357
|
+
const m = this.msac, cdf = this.cdf;
|
|
358
|
+
if (frameType === RESTORATION_SWITCHABLE) {
|
|
359
|
+
const filter = m.symbol(cdf, CDF.restoreSwitchable, 2);
|
|
360
|
+
lr.type = filter ? filter + 1 : RESTORATION_NONE;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
const type = m.boolAdapt(cdf, frameType === RESTORATION_WIENER ? CDF.restoreWiener : CDF.restoreSgrproj);
|
|
364
|
+
lr.type = type ? frameType : RESTORATION_NONE;
|
|
365
|
+
}
|
|
366
|
+
const ref = this.lrRef[p];
|
|
367
|
+
if (lr.type === RESTORATION_WIENER) {
|
|
368
|
+
lr.filterV = [
|
|
369
|
+
p ? 0 : m.subexp(ref.filterV[0] + 5, 16, 1) - 5,
|
|
370
|
+
m.subexp(ref.filterV[1] + 23, 32, 2) - 23,
|
|
371
|
+
m.subexp(ref.filterV[2] + 17, 64, 3) - 17
|
|
372
|
+
];
|
|
373
|
+
lr.filterH = [
|
|
374
|
+
p ? 0 : m.subexp(ref.filterH[0] + 5, 16, 1) - 5,
|
|
375
|
+
m.subexp(ref.filterH[1] + 23, 32, 2) - 23,
|
|
376
|
+
m.subexp(ref.filterH[2] + 17, 64, 3) - 17
|
|
377
|
+
];
|
|
378
|
+
lr.sgrWeights = ref.sgrWeights.slice();
|
|
379
|
+
this.lrRef[p] = lr;
|
|
380
|
+
}
|
|
381
|
+
else if (lr.type === RESTORATION_SGRPROJ) {
|
|
382
|
+
const idx = m.bools(4);
|
|
383
|
+
lr.type += idx;
|
|
384
|
+
lr.sgrWeights = [
|
|
385
|
+
SGR_PARAMS[idx * 2] ? m.subexp(ref.sgrWeights[0] + 96, 128, 4) - 96 : 0,
|
|
386
|
+
SGR_PARAMS[idx * 2 + 1] ? m.subexp(ref.sgrWeights[1] + 32, 128, 4) - 32 : 95
|
|
387
|
+
];
|
|
388
|
+
lr.filterV = ref.filterV.slice();
|
|
389
|
+
lr.filterH = ref.filterH.slice();
|
|
390
|
+
this.lrRef[p] = lr;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
decodeSb(bl, node) {
|
|
394
|
+
const f = this.frame;
|
|
395
|
+
const hsz = 16 >> bl;
|
|
396
|
+
const haveH = f.bw > this.bx + hsz, haveV = f.bh > this.by + hsz;
|
|
397
|
+
if (!haveH && !haveV)
|
|
398
|
+
return this.decodeSb(bl + 1, node.split[0]);
|
|
399
|
+
const bx8 = this.bx >> 1, by8 = (this.by & 31) >> 1;
|
|
400
|
+
const ctx = (this.aPartition[bx8] >> (4 - bl) & 1) + ((this.lPartition[by8] >> (4 - bl) & 1) << 1);
|
|
401
|
+
const pc = CDF.partition + (bl * 4 + ctx) * 16;
|
|
402
|
+
const cdf = this.cdf;
|
|
403
|
+
let bp;
|
|
404
|
+
if (haveH && haveV) {
|
|
405
|
+
bp = this.msac.symbol(cdf, pc, PARTITION_TYPE_COUNT[bl]);
|
|
406
|
+
if (f.layout === 2 && (bp === PARTITION_V || bp === PARTITION_V4 || bp === PARTITION_T_LEFT_SPLIT || bp === PARTITION_T_RIGHT_SPLIT))
|
|
407
|
+
throw new Error('AV1: invalid partition');
|
|
408
|
+
const b = (i) => BLOCK_SIZES[(bl * 10 + bp) * 2 + i];
|
|
409
|
+
switch (bp) {
|
|
410
|
+
case PARTITION_NONE:
|
|
411
|
+
this.decodeB(b(0), node.o);
|
|
412
|
+
break;
|
|
413
|
+
case PARTITION_H:
|
|
414
|
+
this.decodeB(b(0), node.h[0]);
|
|
415
|
+
this.by += hsz;
|
|
416
|
+
this.decodeB(b(0), node.h[1]);
|
|
417
|
+
this.by -= hsz;
|
|
418
|
+
break;
|
|
419
|
+
case PARTITION_V:
|
|
420
|
+
this.decodeB(b(0), node.v[0]);
|
|
421
|
+
this.bx += hsz;
|
|
422
|
+
this.decodeB(b(0), node.v[1]);
|
|
423
|
+
this.bx -= hsz;
|
|
424
|
+
break;
|
|
425
|
+
case PARTITION_SPLIT:
|
|
426
|
+
if (bl === BL_8X8) {
|
|
427
|
+
this.decodeB(BS_4x4, EDGE_ALL_TR_AND_BL);
|
|
428
|
+
this.bx++;
|
|
429
|
+
this.decodeB(BS_4x4, node.tip[0]);
|
|
430
|
+
this.bx--;
|
|
431
|
+
this.by++;
|
|
432
|
+
this.decodeB(BS_4x4, node.tip[1]);
|
|
433
|
+
this.bx++;
|
|
434
|
+
this.decodeB(BS_4x4, node.tip[2]);
|
|
435
|
+
this.bx--;
|
|
436
|
+
this.by--;
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
this.decodeSb(bl + 1, node.split[0]);
|
|
440
|
+
this.bx += hsz;
|
|
441
|
+
this.decodeSb(bl + 1, node.split[1]);
|
|
442
|
+
this.bx -= hsz;
|
|
443
|
+
this.by += hsz;
|
|
444
|
+
this.decodeSb(bl + 1, node.split[2]);
|
|
445
|
+
this.bx += hsz;
|
|
446
|
+
this.decodeSb(bl + 1, node.split[3]);
|
|
447
|
+
this.bx -= hsz;
|
|
448
|
+
this.by -= hsz;
|
|
449
|
+
}
|
|
450
|
+
break;
|
|
451
|
+
case PARTITION_T_TOP_SPLIT:
|
|
452
|
+
this.decodeB(b(0), EDGE_ALL_TR_AND_BL);
|
|
453
|
+
this.bx += hsz;
|
|
454
|
+
this.decodeB(b(0), node.v[1]);
|
|
455
|
+
this.bx -= hsz;
|
|
456
|
+
this.by += hsz;
|
|
457
|
+
this.decodeB(b(1), node.h[1]);
|
|
458
|
+
this.by -= hsz;
|
|
459
|
+
break;
|
|
460
|
+
case PARTITION_T_BOTTOM_SPLIT:
|
|
461
|
+
this.decodeB(b(0), node.h[0]);
|
|
462
|
+
this.by += hsz;
|
|
463
|
+
this.decodeB(b(1), node.v[0]);
|
|
464
|
+
this.bx += hsz;
|
|
465
|
+
this.decodeB(b(1), 0);
|
|
466
|
+
this.bx -= hsz;
|
|
467
|
+
this.by -= hsz;
|
|
468
|
+
break;
|
|
469
|
+
case PARTITION_T_LEFT_SPLIT:
|
|
470
|
+
this.decodeB(b(0), EDGE_ALL_TR_AND_BL);
|
|
471
|
+
this.by += hsz;
|
|
472
|
+
this.decodeB(b(0), node.h[1]);
|
|
473
|
+
this.by -= hsz;
|
|
474
|
+
this.bx += hsz;
|
|
475
|
+
this.decodeB(b(1), node.v[1]);
|
|
476
|
+
this.bx -= hsz;
|
|
477
|
+
break;
|
|
478
|
+
case PARTITION_T_RIGHT_SPLIT:
|
|
479
|
+
this.decodeB(b(0), node.v[0]);
|
|
480
|
+
this.bx += hsz;
|
|
481
|
+
this.decodeB(b(1), node.h[0]);
|
|
482
|
+
this.by += hsz;
|
|
483
|
+
this.decodeB(b(1), 0);
|
|
484
|
+
this.by -= hsz;
|
|
485
|
+
this.bx -= hsz;
|
|
486
|
+
break;
|
|
487
|
+
case PARTITION_H4:
|
|
488
|
+
this.decodeB(b(0), node.h[0]);
|
|
489
|
+
this.by += hsz >> 1;
|
|
490
|
+
this.decodeB(b(0), node.h4);
|
|
491
|
+
this.by += hsz >> 1;
|
|
492
|
+
this.decodeB(b(0), EDGE_ALL_LEFT_HAS_BOTTOM);
|
|
493
|
+
this.by += hsz >> 1;
|
|
494
|
+
if (this.by < f.bh)
|
|
495
|
+
this.decodeB(b(0), node.h[1]);
|
|
496
|
+
this.by -= hsz * 3 >> 1;
|
|
497
|
+
break;
|
|
498
|
+
case PARTITION_V4:
|
|
499
|
+
this.decodeB(b(0), node.v[0]);
|
|
500
|
+
this.bx += hsz >> 1;
|
|
501
|
+
this.decodeB(b(0), node.v4);
|
|
502
|
+
this.bx += hsz >> 1;
|
|
503
|
+
this.decodeB(b(0), EDGE_ALL_TOP_HAS_RIGHT);
|
|
504
|
+
this.bx += hsz >> 1;
|
|
505
|
+
if (this.bx < f.bw)
|
|
506
|
+
this.decodeB(b(0), node.v[1]);
|
|
507
|
+
this.bx -= hsz * 3 >> 1;
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
else if (haveH) {
|
|
512
|
+
let prob = cdf[pc + PARTITION_V - 1] - cdf[pc + PARTITION_T_TOP_SPLIT];
|
|
513
|
+
prob += cdf[pc + PARTITION_T_LEFT_SPLIT - 1];
|
|
514
|
+
if (bl !== BL_128X128)
|
|
515
|
+
prob += cdf[pc + PARTITION_V4 - 1] - cdf[pc + PARTITION_T_RIGHT_SPLIT];
|
|
516
|
+
const split = this.msac.boolProb(prob);
|
|
517
|
+
if (split) {
|
|
518
|
+
bp = PARTITION_SPLIT;
|
|
519
|
+
this.decodeSb(bl + 1, node.split[0]);
|
|
520
|
+
this.bx += hsz;
|
|
521
|
+
this.decodeSb(bl + 1, node.split[1]);
|
|
522
|
+
this.bx -= hsz;
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
bp = PARTITION_H;
|
|
526
|
+
this.decodeB(BLOCK_SIZES[(bl * 10 + PARTITION_H) * 2], node.h[0]);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
let prob = cdf[pc + PARTITION_H - 1] - cdf[pc + PARTITION_H];
|
|
531
|
+
prob += cdf[pc + PARTITION_SPLIT - 1] - cdf[pc + PARTITION_T_LEFT_SPLIT];
|
|
532
|
+
if (bl !== BL_128X128)
|
|
533
|
+
prob += cdf[pc + PARTITION_H4 - 1] - cdf[pc + PARTITION_H4];
|
|
534
|
+
const split = this.msac.boolProb(prob);
|
|
535
|
+
if (f.layout === 2 && !split)
|
|
536
|
+
throw new Error('AV1: invalid partition');
|
|
537
|
+
if (split) {
|
|
538
|
+
bp = PARTITION_SPLIT;
|
|
539
|
+
this.decodeSb(bl + 1, node.split[0]);
|
|
540
|
+
this.by += hsz;
|
|
541
|
+
this.decodeSb(bl + 1, node.split[2]);
|
|
542
|
+
this.by -= hsz;
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
bp = PARTITION_V;
|
|
546
|
+
this.decodeB(BLOCK_SIZES[(bl * 10 + PARTITION_V) * 2], node.v[0]);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
if (bp !== PARTITION_SPLIT || bl === BL_8X8) {
|
|
550
|
+
this.aPartition.fill(AL_PART_CTX[bl * 10 + bp], bx8, bx8 + hsz);
|
|
551
|
+
this.lPartition.fill(AL_PART_CTX[50 + bl * 10 + bp], by8, by8 + hsz);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
decodeB(bs, edgeFlags) {
|
|
555
|
+
const f = this.frame, hdr = this.hdr, seq = this.seq, m = this.msac, cdf = this.cdf;
|
|
556
|
+
const bx = this.bx, by = this.by, bx4 = bx, by4 = by & 31;
|
|
557
|
+
const ssx = f.ssx, ssy = f.ssy;
|
|
558
|
+
const cbx4 = bx4 >> ssx, cby4 = by4 >> ssy;
|
|
559
|
+
const bw4 = bdim(bs, 0), bh4 = bdim(bs, 1), lw4 = bdim(bs, 2), lh4 = bdim(bs, 3);
|
|
560
|
+
const w4 = Math.min(bw4, f.bw - bx), h4 = Math.min(bh4, f.bh - by);
|
|
561
|
+
const cbw4 = bw4 + ssx >> ssx, cbh4 = bh4 + ssy >> ssy;
|
|
562
|
+
const haveLeft = bx > this.colStart, haveTop = by > this.rowStart;
|
|
563
|
+
const hasChroma = f.layout !== 0 && (bw4 > ssx || !!(bx & 1)) && (bh4 > ssy || !!(by & 1));
|
|
564
|
+
const b = { segId: 0, skip: 0, yMode: 0, yAngle: 0, uvMode: 0, uvAngle: 0, cflAlpha: [0, 0], palSz: [0, 0], tx: 0, uvtx: 0 };
|
|
565
|
+
const segmentation = hdr.segmentation;
|
|
566
|
+
let seg = null;
|
|
567
|
+
const readSegId = () => {
|
|
568
|
+
const map = f.segMap, s = f.b4Stride, o = by * s + bx;
|
|
569
|
+
let segCtx, pred;
|
|
570
|
+
if (haveLeft && haveTop) {
|
|
571
|
+
const l = map[o - 1], a = map[o - s], al = map[o - s - 1];
|
|
572
|
+
segCtx = l === a && al === l ? 2 : l === a || al === l || a === al ? 1 : 0;
|
|
573
|
+
pred = a === al ? a : l;
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
segCtx = 0;
|
|
577
|
+
pred = haveLeft ? map[o - 1] : haveTop ? map[o - s] : 0;
|
|
578
|
+
}
|
|
579
|
+
if (b.skip && !segmentation.preskip)
|
|
580
|
+
b.segId = pred;
|
|
581
|
+
else {
|
|
582
|
+
const diff = m.symbol(cdf, CDF.segId + segCtx * 8, 7);
|
|
583
|
+
b.segId = neg_deinterleave(diff, pred, segmentation.lastActiveSegId + 1);
|
|
584
|
+
if (b.segId > segmentation.lastActiveSegId)
|
|
585
|
+
b.segId = 0;
|
|
586
|
+
}
|
|
587
|
+
if (b.segId >= 8)
|
|
588
|
+
b.segId = 0;
|
|
589
|
+
};
|
|
590
|
+
if (segmentation.enabled && segmentation.preskip) {
|
|
591
|
+
readSegId();
|
|
592
|
+
seg = segmentation.data[b.segId];
|
|
593
|
+
}
|
|
594
|
+
if (seg?.skip)
|
|
595
|
+
b.skip = 1;
|
|
596
|
+
else {
|
|
597
|
+
b.skip = m.boolAdapt(cdf, CDF.skip + (this.aSkip[bx4] + this.lSkip[by4]) * 2);
|
|
598
|
+
}
|
|
599
|
+
if (segmentation.enabled && !segmentation.preskip)
|
|
600
|
+
readSegId();
|
|
601
|
+
if (!b.skip) {
|
|
602
|
+
const idx = seq.sb128 ? this.cdefSb + (bx >> 4 & 1) + (by >> 4 & 1) * (f.b4Stride >> 4) : this.cdefSb;
|
|
603
|
+
if (f.cdefIdx[idx] === -1) {
|
|
604
|
+
const v = m.bools(hdr.cdef.bits);
|
|
605
|
+
f.cdefIdx[idx] = v;
|
|
606
|
+
const stride = f.b4Stride >> 4;
|
|
607
|
+
if (bw4 > 16)
|
|
608
|
+
f.cdefIdx[idx + 1] = v;
|
|
609
|
+
if (bh4 > 16)
|
|
610
|
+
f.cdefIdx[idx + stride] = v;
|
|
611
|
+
if (bw4 === 32 && bh4 === 32)
|
|
612
|
+
f.cdefIdx[idx + stride + 1] = v;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
const sbMask = seq.sb128 ? 31 : 15;
|
|
616
|
+
if (!(bx & sbMask) && !(by & sbMask)) {
|
|
617
|
+
const prevQidx = this.lastQidx;
|
|
618
|
+
const prevDeltaLf = this.lastDeltaLf.join();
|
|
619
|
+
if (hdr.deltaQ.present && (bs !== (seq.sb128 ? BS_128x128 : BS_64x64) || !b.skip)) {
|
|
620
|
+
const readDelta = (o) => {
|
|
621
|
+
let d = m.symbol(cdf, o, 3);
|
|
622
|
+
if (d === 3) {
|
|
623
|
+
const n = 1 + m.bools(3);
|
|
624
|
+
d = m.bools(n) + 1 + (1 << n);
|
|
625
|
+
}
|
|
626
|
+
return d;
|
|
627
|
+
};
|
|
628
|
+
let deltaQ = readDelta(CDF.deltaQ);
|
|
629
|
+
if (deltaQ) {
|
|
630
|
+
if (m.bool())
|
|
631
|
+
deltaQ = -deltaQ;
|
|
632
|
+
deltaQ *= 1 << hdr.deltaQ.resLog2;
|
|
633
|
+
}
|
|
634
|
+
this.lastQidx = Math.min(255, Math.max(1, this.lastQidx + deltaQ));
|
|
635
|
+
if (hdr.deltaLf.present) {
|
|
636
|
+
const n = hdr.deltaLf.multi ? f.layout ? 4 : 2 : 1;
|
|
637
|
+
for (let i = 0; i < n; i++) {
|
|
638
|
+
let d = readDelta(CDF.deltaLf + (i + (hdr.deltaLf.multi ? 1 : 0)) * 4);
|
|
639
|
+
if (d) {
|
|
640
|
+
if (m.bool())
|
|
641
|
+
d = -d;
|
|
642
|
+
d *= 1 << hdr.deltaLf.resLog2;
|
|
643
|
+
}
|
|
644
|
+
this.lastDeltaLf[i] = Math.min(63, Math.max(-63, this.lastDeltaLf[i] + d));
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
if (this.lastQidx === hdr.quant.yac)
|
|
649
|
+
this.dq = this.frameDq;
|
|
650
|
+
else if (this.lastQidx !== prevQidx)
|
|
651
|
+
this.dq = quantTables(seq, hdr, this.lastQidx);
|
|
652
|
+
if (this.lastDeltaLf.every(v => !v))
|
|
653
|
+
this.lfLvl = this.frameLfLvl;
|
|
654
|
+
else if (this.lastDeltaLf.join() !== prevDeltaLf)
|
|
655
|
+
this.lfLvl = calcLfLevels(hdr, this.lastDeltaLf);
|
|
656
|
+
}
|
|
657
|
+
if (hdr.allowIntrabc && m.boolAdapt(cdf, CDF.intrabc)) {
|
|
658
|
+
this.intrabcBlock(bs, edgeFlags, b, hasChroma);
|
|
659
|
+
this.storeBlock(bs, b, hasChroma);
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
b.yMode = m.symbol(cdf, CDF.kfYMode + (INTRA_MODE_CONTEXT[this.aMode[bx4]] * 5 + INTRA_MODE_CONTEXT[this.lMode[by4]]) * 16, 12);
|
|
663
|
+
if (lw4 + lh4 >= 2 && b.yMode >= VERT_PRED && b.yMode <= VERT_LEFT_PRED)
|
|
664
|
+
b.yAngle = m.symbol(cdf, CDF.angleDelta + (b.yMode - VERT_PRED) * 8, 6) - 3;
|
|
665
|
+
const lossless = hdr.segmentation.lossless[b.segId];
|
|
666
|
+
if (hasChroma) {
|
|
667
|
+
const cflAllowed = lossless ? cbw4 === 1 && cbh4 === 1 : !!(CFL_ALLOWED_MASK & 1 << bs);
|
|
668
|
+
b.uvMode = m.symbol(cdf, CDF.uvMode + ((cflAllowed ? 1 : 0) * 13 + b.yMode) * 16, cflAllowed ? 13 : 12);
|
|
669
|
+
if (b.uvMode === CFL_PRED) {
|
|
670
|
+
const sign = m.symbol(cdf, CDF.cflSign, 7) + 1;
|
|
671
|
+
const signU = sign * 0x56 >> 8, signV = sign - signU * 3;
|
|
672
|
+
if (signU) {
|
|
673
|
+
const ctx = (signU === 2 ? 3 : 0) + signV;
|
|
674
|
+
b.cflAlpha[0] = m.symbol(cdf, CDF.cflAlpha + ctx * 16, 15) + 1;
|
|
675
|
+
if (signU === 1)
|
|
676
|
+
b.cflAlpha[0] = -b.cflAlpha[0];
|
|
677
|
+
}
|
|
678
|
+
if (signV) {
|
|
679
|
+
const ctx = (signV === 2 ? 3 : 0) + signU;
|
|
680
|
+
b.cflAlpha[1] = m.symbol(cdf, CDF.cflAlpha + ctx * 16, 15) + 1;
|
|
681
|
+
if (signV === 1)
|
|
682
|
+
b.cflAlpha[1] = -b.cflAlpha[1];
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
else if (lw4 + lh4 >= 2 && b.uvMode >= VERT_PRED && b.uvMode <= VERT_LEFT_PRED) {
|
|
686
|
+
b.uvAngle = m.symbol(cdf, CDF.angleDelta + (b.uvMode - VERT_PRED) * 8, 6) - 3;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
if (hdr.allowScreenContentTools && Math.max(bw4, bh4) <= 16 && bw4 + bh4 >= 4) {
|
|
690
|
+
const szCtx = lw4 + lh4 - 2;
|
|
691
|
+
if (b.yMode === DC_PRED) {
|
|
692
|
+
const palCtx = (this.aPalSz[bx4] > 0 ? 1 : 0) + (this.lPalSz[by4] > 0 ? 1 : 0);
|
|
693
|
+
if (m.boolAdapt(cdf, CDF.palY + (szCtx * 3 + palCtx) * 2))
|
|
694
|
+
this.readPalPlane(b, 0, szCtx, bx4, by4);
|
|
695
|
+
}
|
|
696
|
+
if (hasChroma && b.uvMode === DC_PRED) {
|
|
697
|
+
if (m.boolAdapt(cdf, CDF.palUv + (b.palSz[0] > 0 ? 2 : 0)))
|
|
698
|
+
this.readPalUv(b, szCtx, bx4, by4);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
if (b.yMode === DC_PRED && !b.palSz[0] && Math.max(lw4, lh4) <= 3 && seq.filterIntra) {
|
|
702
|
+
if (m.boolAdapt(cdf, CDF.useFilterIntra + bs * 2)) {
|
|
703
|
+
b.yMode = FILTER_PRED;
|
|
704
|
+
b.yAngle = m.symbol(cdf, CDF.filterIntra, 4);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
if (b.palSz[0])
|
|
708
|
+
this.readPalIndices(this.palIdxY, b.palSz[0], 0, w4, h4, bw4, bh4);
|
|
709
|
+
if (hasChroma && b.palSz[1]) {
|
|
710
|
+
const cw4 = w4 + ssx >> ssx, ch4 = h4 + ssy >> ssy;
|
|
711
|
+
this.readPalIndices(this.palIdxUv, b.palSz[1], 1, cw4, ch4, cbw4, cbh4);
|
|
712
|
+
}
|
|
713
|
+
let tx;
|
|
714
|
+
if (lossless) {
|
|
715
|
+
tx = b.uvtx = TX_4X4;
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
tx = MAX_TXFM_SIZE_FOR_BS[bs * 4];
|
|
719
|
+
b.uvtx = MAX_TXFM_SIZE_FOR_BS[bs * 4 + f.layout];
|
|
720
|
+
if (hdr.txMode === 2 && tdim(tx, MAX) > TX_4X4) {
|
|
721
|
+
const tctx = (this.lTxIntra[by4] >= tdim(tx, LH) ? 1 : 0) + (this.aTxIntra[bx4] >= tdim(tx, LW) ? 1 : 0);
|
|
722
|
+
let depth = m.symbol(cdf, CDF.txSize + ((tdim(tx, MAX) - 1) * 3 + tctx) * 4, Math.min(tdim(tx, MAX), 2));
|
|
723
|
+
while (depth--)
|
|
724
|
+
tx = tdim(tx, SUB);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
b.tx = tx;
|
|
728
|
+
this.reconIntra(bs, edgeFlags, b, hasChroma);
|
|
729
|
+
this.storeBlock(bs, b, hasChroma);
|
|
730
|
+
const yModeNofilt = b.yMode === FILTER_PRED ? DC_PRED : b.yMode;
|
|
731
|
+
const aw = 1 << lw4, lh = 1 << lh4;
|
|
732
|
+
this.aTxIntra.fill(tdim(tx, LW), bx4, bx4 + aw);
|
|
733
|
+
this.lTxIntra.fill(tdim(tx, LH), by4, by4 + lh);
|
|
734
|
+
this.aTx.fill(tdim(tx, LW), bx4, bx4 + aw);
|
|
735
|
+
this.lTx.fill(tdim(tx, LH), by4, by4 + lh);
|
|
736
|
+
this.aMode.fill(yModeNofilt, bx4, bx4 + aw);
|
|
737
|
+
this.lMode.fill(yModeNofilt, by4, by4 + lh);
|
|
738
|
+
this.aPalSz.fill(b.palSz[0], bx4, bx4 + aw);
|
|
739
|
+
this.lPalSz.fill(b.palSz[0], by4, by4 + lh);
|
|
740
|
+
this.aSegPred.fill(0, bx4, bx4 + aw);
|
|
741
|
+
this.lSegPred.fill(0, by4, by4 + lh);
|
|
742
|
+
this.aIntra.fill(1, bx4, bx4 + aw);
|
|
743
|
+
this.lIntra.fill(1, by4, by4 + lh);
|
|
744
|
+
this.aSkip.fill(b.skip, bx4, bx4 + aw);
|
|
745
|
+
this.lSkip.fill(b.skip, by4, by4 + lh);
|
|
746
|
+
this.aPalSzUv.fill(hasChroma ? b.palSz[1] : 0, bx4, bx4 + aw);
|
|
747
|
+
this.lPalSzUv.fill(hasChroma ? b.palSz[1] : 0, by4, by4 + lh);
|
|
748
|
+
if (b.palSz[0]) {
|
|
749
|
+
for (let x = 0; x < bw4; x++)
|
|
750
|
+
this.aPal.set(this.pal.subarray(0, 8), (bx4 + x) * 24);
|
|
751
|
+
for (let y = 0; y < bh4; y++)
|
|
752
|
+
this.lPal.set(this.pal.subarray(0, 8), (by4 + y) * 24);
|
|
753
|
+
}
|
|
754
|
+
if (hasChroma) {
|
|
755
|
+
this.aUvmode.fill(b.uvMode, cbx4, cbx4 + cbw4);
|
|
756
|
+
this.lUvmode.fill(b.uvMode, cby4, cby4 + cbh4);
|
|
757
|
+
if (b.palSz[1]) {
|
|
758
|
+
for (let pl = 1; pl <= 2; pl++) {
|
|
759
|
+
for (let x = 0; x < bw4; x++)
|
|
760
|
+
this.aPal.set(this.pal.subarray(pl * 8, pl * 8 + 8), (bx4 + x) * 24 + pl * 8);
|
|
761
|
+
for (let y = 0; y < bh4; y++)
|
|
762
|
+
this.lPal.set(this.pal.subarray(pl * 8, pl * 8 + 8), (by4 + y) * 24 + pl * 8);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
if (hdr.allowIntrabc)
|
|
767
|
+
this.splatMv(bs, -1, 0, 0);
|
|
768
|
+
}
|
|
769
|
+
storeBlock(bs, b, hasChroma) {
|
|
770
|
+
const f = this.frame, bx = this.bx, by = this.by, ssx = f.ssx, ssy = f.ssy;
|
|
771
|
+
const bw4 = bdim(bs, 0), bh4 = bdim(bs, 1);
|
|
772
|
+
const w4 = Math.min(bw4, f.bw - bx), h4 = Math.min(bh4, f.bh - by);
|
|
773
|
+
const tx = b.tx;
|
|
774
|
+
const lvl = this.lfLvl[b.segId];
|
|
775
|
+
const s4 = f.b4Stride;
|
|
776
|
+
for (let y = 0; y < h4; y++) {
|
|
777
|
+
for (let x = 0; x < w4; x++) {
|
|
778
|
+
const o = (by + y) * s4 + bx + x;
|
|
779
|
+
f.lfLevels.set(lvl, o * 4);
|
|
780
|
+
f.txW[o] = tdim(tx, LW);
|
|
781
|
+
f.txH[o] = tdim(tx, LH);
|
|
782
|
+
f.skip[o] = b.skip;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
if (hasChroma) {
|
|
786
|
+
const cx = bx >> ssx, cy = by >> ssy, cw4 = w4 + ssx >> ssx, ch4 = h4 + ssy >> ssy;
|
|
787
|
+
for (let y = 0; y < ch4; y++) {
|
|
788
|
+
for (let x = 0; x < cw4; x++) {
|
|
789
|
+
const o = (cy + y) * s4 + cx + x;
|
|
790
|
+
f.uvTxW[o] = tdim(b.uvtx, LW);
|
|
791
|
+
f.uvTxH[o] = tdim(b.uvtx, LH);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
if (this.hdr.segmentation.enabled) {
|
|
796
|
+
for (let y = 0; y < bh4 && by + y < f.bh; y++)
|
|
797
|
+
f.segMap.fill(b.segId, (by + y) * s4 + bx, (by + y) * s4 + bx + bw4);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
mvY = null;
|
|
801
|
+
mvX = null;
|
|
802
|
+
mvValid = null;
|
|
803
|
+
mvBs = null;
|
|
804
|
+
txSplit = [0, 0];
|
|
805
|
+
maxYtx = 0;
|
|
806
|
+
txtpMap = new Uint8Array(32 * 32);
|
|
807
|
+
splatMv(bs, valid, y, x) {
|
|
808
|
+
const f = this.frame, s4 = f.b4Stride;
|
|
809
|
+
const bw4 = bdim(bs, 0), bh4 = bdim(bs, 1);
|
|
810
|
+
for (let r = 0; r < bh4; r++) {
|
|
811
|
+
const o = (this.by + r) * s4 + this.bx;
|
|
812
|
+
this.mvY.fill(y, o, o + bw4);
|
|
813
|
+
this.mvX.fill(x, o, o + bw4);
|
|
814
|
+
this.mvValid.fill(valid > 0 ? 1 : 0, o, o + bw4);
|
|
815
|
+
this.mvBs.fill(bs, o, o + bw4);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
findMvs(bs, edgeFlags) {
|
|
819
|
+
const f = this.frame, s4 = f.b4Stride;
|
|
820
|
+
const by4 = this.by, bx4 = this.bx;
|
|
821
|
+
const iw4 = f.width + 3 >> 2, ih4 = f.height + 3 >> 2;
|
|
822
|
+
const colStart = this.colStart, colEnd = Math.min(this.colEnd, iw4), rowStart = this.rowStart, rowEnd = Math.min(this.rowEnd, ih4);
|
|
823
|
+
const bw4 = bdim(bs, 0), w4 = Math.min(Math.min(bw4, 16), colEnd - bx4);
|
|
824
|
+
const bh4 = bdim(bs, 1), h4 = Math.min(Math.min(bh4, 16), rowEnd - by4);
|
|
825
|
+
const valid = this.mvValid, mvY = this.mvY, mvX = this.mvX, mvBs = this.mvBs;
|
|
826
|
+
const stack = [];
|
|
827
|
+
const add = (o, weight) => {
|
|
828
|
+
if (!valid[o])
|
|
829
|
+
return;
|
|
830
|
+
const y = mvY[o], x = mvX[o];
|
|
831
|
+
for (const c of stack) {
|
|
832
|
+
if (c.y === y && c.x === x) {
|
|
833
|
+
c.weight += weight;
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
if (stack.length < 8)
|
|
838
|
+
stack.push({ y, x, weight });
|
|
839
|
+
};
|
|
840
|
+
const scanRow = (row, col, maxRows, step) => {
|
|
841
|
+
const o = row * s4 + col;
|
|
842
|
+
const firstBw4 = bdim(mvBs[o], 0);
|
|
843
|
+
let len = Math.max(step, Math.min(bw4, firstBw4));
|
|
844
|
+
if (bw4 <= firstBw4) {
|
|
845
|
+
const weight = bw4 === 1 ? 2 : Math.max(2, Math.min(2 * maxRows, bdim(mvBs[o], 1)));
|
|
846
|
+
add(o, len * weight);
|
|
847
|
+
return weight >> 1;
|
|
848
|
+
}
|
|
849
|
+
for (let x = 0;;) {
|
|
850
|
+
add(o + x, len * 2);
|
|
851
|
+
x += len;
|
|
852
|
+
if (x >= w4)
|
|
853
|
+
return 1;
|
|
854
|
+
len = Math.max(step, bdim(mvBs[o + x], 0));
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
const scanCol = (row, col, maxCols, step) => {
|
|
858
|
+
const o = row * s4 + col;
|
|
859
|
+
const firstBh4 = bdim(mvBs[o], 1);
|
|
860
|
+
let len = Math.max(step, Math.min(bh4, firstBh4));
|
|
861
|
+
if (bh4 <= firstBh4) {
|
|
862
|
+
const weight = bh4 === 1 ? 2 : Math.max(2, Math.min(2 * maxCols, bdim(mvBs[o], 0)));
|
|
863
|
+
add(o, len * weight);
|
|
864
|
+
return weight >> 1;
|
|
865
|
+
}
|
|
866
|
+
for (let y = 0;;) {
|
|
867
|
+
add(o + y * s4, len * 2);
|
|
868
|
+
y += len;
|
|
869
|
+
if (y >= h4)
|
|
870
|
+
return 1;
|
|
871
|
+
len = Math.max(step, bdim(mvBs[o + y * s4], 1));
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
const NONE = 0xffffffff;
|
|
875
|
+
let maxRows = 0, nRows = NONE;
|
|
876
|
+
if (by4 > rowStart) {
|
|
877
|
+
maxRows = Math.min((by4 - rowStart + 1) >> 1, 2 + (bh4 > 1 ? 1 : 0));
|
|
878
|
+
nRows = scanRow(by4 - 1, bx4, maxRows, bw4 >= 16 ? 4 : 1);
|
|
879
|
+
}
|
|
880
|
+
let maxCols = 0, nCols = NONE;
|
|
881
|
+
if (bx4 > colStart) {
|
|
882
|
+
maxCols = Math.min((bx4 - colStart + 1) >> 1, 2 + (bw4 > 1 ? 1 : 0));
|
|
883
|
+
nCols = scanCol(by4, bx4 - 1, maxCols, bh4 >= 16 ? 4 : 1);
|
|
884
|
+
}
|
|
885
|
+
if (nRows !== NONE && edgeFlags & EDGE_I444_TOP_HAS_RIGHT && Math.max(bw4, bh4) <= 16 && bw4 + bx4 < colEnd)
|
|
886
|
+
add((by4 - 1) * s4 + bx4 + bw4, 4);
|
|
887
|
+
const nearest = stack.length;
|
|
888
|
+
for (const c of stack)
|
|
889
|
+
c.weight += 640;
|
|
890
|
+
if (nRows !== NONE && nCols !== NONE)
|
|
891
|
+
add((by4 - 1) * s4 + bx4 - 1, 4);
|
|
892
|
+
for (let n = 2; n <= 3; n++) {
|
|
893
|
+
if (nRows !== NONE && n > nRows && n <= maxRows) {
|
|
894
|
+
nRows += scanRow(((by4 - 2 * n + 1) | 1), bx4 | 1, 1 + maxRows - n, bw4 >= 16 ? 4 : 2);
|
|
895
|
+
}
|
|
896
|
+
if (nCols !== NONE && n > nCols && n <= maxCols) {
|
|
897
|
+
nCols += scanCol(by4 | 1, (bx4 - n * 2 + 1) | 1, 1 + maxCols - n, bh4 >= 16 ? 4 : 2);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
const sort = (from, to) => {
|
|
901
|
+
let len = to;
|
|
902
|
+
while (len > from) {
|
|
903
|
+
let last = from;
|
|
904
|
+
for (let n = from + 1; n < len; n++) {
|
|
905
|
+
if (stack[n - 1].weight < stack[n].weight) {
|
|
906
|
+
[stack[n - 1], stack[n]] = [stack[n], stack[n - 1]];
|
|
907
|
+
last = n;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
len = last;
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
sort(0, nearest);
|
|
914
|
+
sort(nearest, stack.length);
|
|
915
|
+
const left = -(bx4 + bw4 + 4) * 32, right = (iw4 - bx4 + 4) * 32;
|
|
916
|
+
const top = -(by4 + bh4 + 4) * 32, bottom = (ih4 - by4 + 4) * 32;
|
|
917
|
+
const out = stack.map(c => [Math.min(bottom, Math.max(top, c.y)), Math.min(right, Math.max(left, c.x))]);
|
|
918
|
+
while (out.length < 2)
|
|
919
|
+
out.push([0, 0]);
|
|
920
|
+
return out;
|
|
921
|
+
}
|
|
922
|
+
readMvComponent(comp) {
|
|
923
|
+
const m = this.msac, cdf = this.cdf;
|
|
924
|
+
const sign = m.boolAdapt(cdf, comp ? CDF.mvSign1 : CDF.mvSign0);
|
|
925
|
+
const cl = m.symbol(cdf, comp ? CDF.mvClasses1 : CDF.mvClasses0, 10);
|
|
926
|
+
let up;
|
|
927
|
+
if (!cl)
|
|
928
|
+
up = m.boolAdapt(cdf, comp ? CDF.mvClass01 : CDF.mvClass00);
|
|
929
|
+
else {
|
|
930
|
+
up = 1 << cl;
|
|
931
|
+
for (let n = 0; n < cl; n++)
|
|
932
|
+
up |= m.boolAdapt(cdf, (comp ? CDF.mvClassN1 : CDF.mvClassN0) + n * 2) << n;
|
|
933
|
+
}
|
|
934
|
+
const diff = (up << 3 | 7) + 1;
|
|
935
|
+
return sign ? -diff : diff;
|
|
936
|
+
}
|
|
937
|
+
intrabcBlock(bs, edgeFlags, b, hasChroma) {
|
|
938
|
+
const f = this.frame, seq = this.seq, m = this.msac, cdf = this.cdf;
|
|
939
|
+
const bx = this.bx, by = this.by, bx4 = bx, by4 = by & 31;
|
|
940
|
+
const ssx = f.ssx, ssy = f.ssy;
|
|
941
|
+
const bw4 = bdim(bs, 0), bh4 = bdim(bs, 1);
|
|
942
|
+
const sb128 = seq.sb128 ? 1 : 0;
|
|
943
|
+
const stack = this.findMvs(bs, edgeFlags);
|
|
944
|
+
let [mvy, mvx] = stack[0][0] || stack[0][1] ? stack[0] : stack[1][0] || stack[1][1] ? stack[1] : [0, 0];
|
|
945
|
+
if (!mvy && !mvx) {
|
|
946
|
+
if (by - (16 << sb128) < this.rowStart) {
|
|
947
|
+
mvy = 0;
|
|
948
|
+
mvx = -(512 << sb128) - 2048;
|
|
949
|
+
}
|
|
950
|
+
else {
|
|
951
|
+
mvy = -(512 << sb128);
|
|
952
|
+
mvx = 0;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
const joint = m.symbol(cdf, CDF.mvJoint, 3);
|
|
956
|
+
if (joint & 2)
|
|
957
|
+
mvy += this.readMvComponent(0);
|
|
958
|
+
if (joint & 1)
|
|
959
|
+
mvx += this.readMvComponent(1);
|
|
960
|
+
let borderLeft = this.colStart * 4, borderTop = this.rowStart * 4;
|
|
961
|
+
if (hasChroma) {
|
|
962
|
+
if (bw4 < 2 && ssx)
|
|
963
|
+
borderLeft += 4;
|
|
964
|
+
if (bh4 < 2 && ssy)
|
|
965
|
+
borderTop += 4;
|
|
966
|
+
}
|
|
967
|
+
let srcLeft = bx * 4 + (mvx >> 3), srcTop = by * 4 + (mvy >> 3);
|
|
968
|
+
let srcRight = srcLeft + bw4 * 4, srcBottom = srcTop + bh4 * 4;
|
|
969
|
+
const borderRight = ((this.colEnd + (bw4 - 1)) & ~(bw4 - 1)) * 4;
|
|
970
|
+
if (srcLeft < borderLeft) {
|
|
971
|
+
srcRight += borderLeft - srcLeft;
|
|
972
|
+
srcLeft = borderLeft;
|
|
973
|
+
}
|
|
974
|
+
else if (srcRight > borderRight) {
|
|
975
|
+
srcLeft -= srcRight - borderRight;
|
|
976
|
+
srcRight = borderRight;
|
|
977
|
+
}
|
|
978
|
+
if (srcTop < borderTop) {
|
|
979
|
+
srcBottom += borderTop - srcTop;
|
|
980
|
+
srcTop = borderTop;
|
|
981
|
+
}
|
|
982
|
+
const sbx = (bx >> (4 + sb128)) << (6 + sb128), sby = (by >> (4 + sb128)) << (6 + sb128), sbSize = 1 << (6 + sb128);
|
|
983
|
+
if (srcBottom > sby && srcRight > sbx) {
|
|
984
|
+
if (srcTop - borderTop >= srcBottom - sby) {
|
|
985
|
+
srcTop -= srcBottom - sby;
|
|
986
|
+
srcBottom = sby;
|
|
987
|
+
}
|
|
988
|
+
else if (srcLeft - borderLeft >= srcRight - sbx) {
|
|
989
|
+
srcLeft -= srcRight - sbx;
|
|
990
|
+
srcRight = sbx;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
if (srcBottom > sby + sbSize) {
|
|
994
|
+
srcTop -= srcBottom - (sby + sbSize);
|
|
995
|
+
srcBottom = sby + sbSize;
|
|
996
|
+
}
|
|
997
|
+
if (srcBottom > sby && srcRight > sbx)
|
|
998
|
+
throw new Error('AV1: invalid intra block copy vector');
|
|
999
|
+
mvx = (srcLeft - bx * 4) * 8;
|
|
1000
|
+
mvy = (srcTop - by * 4) * 8;
|
|
1001
|
+
this.readVartxTree(b, bs);
|
|
1002
|
+
b.tx = this.maxYtx;
|
|
1003
|
+
this.reconInter(bs, b, hasChroma, mvy, mvx);
|
|
1004
|
+
this.splatMv(bs, 1, mvy, mvx);
|
|
1005
|
+
const aw = 1 << bdim(bs, 2), lh = 1 << bdim(bs, 3);
|
|
1006
|
+
this.aTxIntra.fill(bdim(bs, 2), bx4, bx4 + aw);
|
|
1007
|
+
this.lTxIntra.fill(bdim(bs, 3), by4, by4 + lh);
|
|
1008
|
+
this.aMode.fill(DC_PRED, bx4, bx4 + aw);
|
|
1009
|
+
this.lMode.fill(DC_PRED, by4, by4 + lh);
|
|
1010
|
+
this.aPalSz.fill(0, bx4, bx4 + aw);
|
|
1011
|
+
this.lPalSz.fill(0, by4, by4 + lh);
|
|
1012
|
+
this.aPalSzUv.fill(0, bx4, bx4 + aw);
|
|
1013
|
+
this.lPalSzUv.fill(0, by4, by4 + lh);
|
|
1014
|
+
this.aSegPred.fill(0, bx4, bx4 + aw);
|
|
1015
|
+
this.lSegPred.fill(0, by4, by4 + lh);
|
|
1016
|
+
this.aIntra.fill(0, bx4, bx4 + aw);
|
|
1017
|
+
this.lIntra.fill(0, by4, by4 + lh);
|
|
1018
|
+
this.aSkip.fill(b.skip, bx4, bx4 + aw);
|
|
1019
|
+
this.lSkip.fill(b.skip, by4, by4 + lh);
|
|
1020
|
+
if (hasChroma) {
|
|
1021
|
+
const cbx4 = bx4 >> ssx, cby4 = by4 >> ssy, cbw4 = bw4 + ssx >> ssx, cbh4 = bh4 + ssy >> ssy;
|
|
1022
|
+
this.aUvmode.fill(DC_PRED, cbx4, cbx4 + cbw4);
|
|
1023
|
+
this.lUvmode.fill(DC_PRED, cby4, cby4 + cbh4);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
readVartxTree(b, bs) {
|
|
1027
|
+
const f = this.frame, hdr = this.hdr;
|
|
1028
|
+
const bw4 = bdim(bs, 0), bh4 = bdim(bs, 1), lw = bdim(bs, 2), lh = bdim(bs, 3);
|
|
1029
|
+
const bx4 = this.bx, by4 = this.by & 31;
|
|
1030
|
+
this.txSplit = [0, 0];
|
|
1031
|
+
this.maxYtx = MAX_TXFM_SIZE_FOR_BS[bs * 4];
|
|
1032
|
+
if (!b.skip && (hdr.segmentation.lossless[b.segId] || this.maxYtx === TX_4X4)) {
|
|
1033
|
+
this.maxYtx = b.uvtx = TX_4X4;
|
|
1034
|
+
if (hdr.txMode === 2) {
|
|
1035
|
+
this.aTx.fill(TX_4X4, bx4, bx4 + (1 << lw));
|
|
1036
|
+
this.lTx.fill(TX_4X4, by4, by4 + (1 << lh));
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
else if (hdr.txMode !== 2 || b.skip) {
|
|
1040
|
+
if (hdr.txMode === 2) {
|
|
1041
|
+
this.aTx.fill(lw, bx4, bx4 + (1 << lw));
|
|
1042
|
+
this.lTx.fill(lh, by4, by4 + (1 << lh));
|
|
1043
|
+
}
|
|
1044
|
+
b.uvtx = MAX_TXFM_SIZE_FOR_BS[bs * 4 + f.layout];
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
const ytx = this.maxYtx, tw = tdim(ytx, W), th = tdim(ytx, H);
|
|
1048
|
+
for (let y = 0, yOff = 0; y < bh4; y += th, yOff++) {
|
|
1049
|
+
for (let x = 0, xOff = 0; x < bw4; x += tw, xOff++) {
|
|
1050
|
+
this.readTxTree(ytx, 0, xOff, yOff);
|
|
1051
|
+
this.bx += tw;
|
|
1052
|
+
}
|
|
1053
|
+
this.bx -= bw4 + tw - 1 & ~(tw - 1);
|
|
1054
|
+
this.by += th;
|
|
1055
|
+
}
|
|
1056
|
+
this.by -= bh4 + th - 1 & ~(th - 1);
|
|
1057
|
+
b.uvtx = MAX_TXFM_SIZE_FOR_BS[bs * 4 + f.layout];
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
readTxTree(from, depth, xOff, yOff) {
|
|
1061
|
+
const f = this.frame, m = this.msac;
|
|
1062
|
+
const bx4 = this.bx, by4 = this.by & 31;
|
|
1063
|
+
const txw = tdim(from, LW), txh = tdim(from, LH);
|
|
1064
|
+
let split = 0;
|
|
1065
|
+
if (depth < 2 && from > TX_4X4) {
|
|
1066
|
+
const cat = 2 * (TX_64X64 - tdim(from, MAX)) - depth;
|
|
1067
|
+
const a = this.aTx[bx4] < txw ? 1 : 0, l = this.lTx[by4] < txh ? 1 : 0;
|
|
1068
|
+
split = m.boolAdapt(this.cdf, CDF.txPart + (cat * 3 + a + l) * 2);
|
|
1069
|
+
if (split)
|
|
1070
|
+
this.txSplit[depth] |= 1 << (yOff * 4 + xOff);
|
|
1071
|
+
}
|
|
1072
|
+
if (split && tdim(from, MAX) > 1) {
|
|
1073
|
+
const sub = tdim(from, SUB), sw = tdim(sub, W), sh = tdim(sub, H);
|
|
1074
|
+
this.readTxTree(sub, depth + 1, xOff * 2, yOff * 2);
|
|
1075
|
+
this.bx += sw;
|
|
1076
|
+
if (tdim(from, W) >= tdim(from, H) && this.bx < f.bw)
|
|
1077
|
+
this.readTxTree(sub, depth + 1, xOff * 2 + 1, yOff * 2);
|
|
1078
|
+
this.bx -= sw;
|
|
1079
|
+
this.by += sh;
|
|
1080
|
+
if (tdim(from, H) >= tdim(from, W) && this.by < f.bh) {
|
|
1081
|
+
this.readTxTree(sub, depth + 1, xOff * 2, yOff * 2 + 1);
|
|
1082
|
+
this.bx += sw;
|
|
1083
|
+
if (tdim(from, W) >= tdim(from, H) && this.bx < f.bw)
|
|
1084
|
+
this.readTxTree(sub, depth + 1, xOff * 2 + 1, yOff * 2 + 1);
|
|
1085
|
+
this.bx -= sw;
|
|
1086
|
+
}
|
|
1087
|
+
this.by -= sh;
|
|
1088
|
+
}
|
|
1089
|
+
else {
|
|
1090
|
+
this.aTx.fill(split ? TX_4X4 : txw, bx4, bx4 + (1 << tdim(from, LW)));
|
|
1091
|
+
this.lTx.fill(split ? TX_4X4 : txh, by4, by4 + (1 << tdim(from, LH)));
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
mc(plane, w4, h4, bx, by, mvy, mvx) {
|
|
1095
|
+
const f = this.frame, ssx = plane ? f.ssx : 0, ssy = plane ? f.ssy : 0;
|
|
1096
|
+
const hMul = 4 >> ssx, vMul = 4 >> ssy;
|
|
1097
|
+
const mx = mvx & (15 >> (ssx ? 0 : 1)), my = mvy & (15 >> (ssy ? 0 : 1));
|
|
1098
|
+
const dx = bx * hMul + (mvx >> (3 + ssx)), dy = by * vMul + (mvy >> (3 + ssy));
|
|
1099
|
+
const w = (f.bw * 4) >> ssx, h = (f.bh * 4) >> ssy;
|
|
1100
|
+
const pic = f.planes[plane], stride = f.strides[plane];
|
|
1101
|
+
const bw = w4 * hMul, bh = h4 * vMul;
|
|
1102
|
+
const fx = mx << (ssx ? 0 : 1), fy = my << (ssy ? 0 : 1);
|
|
1103
|
+
const at = (x, y) => pic[Math.min(h - 1, Math.max(0, y)) * stride + Math.min(w - 1, Math.max(0, x))];
|
|
1104
|
+
const ib = f.bitdepth === 12 ? 2 : 4, rnd = (1 << ib) >> 1, max = f.bitdepthMax;
|
|
1105
|
+
const clip = (v) => v < 0 ? 0 : v > max ? max : v;
|
|
1106
|
+
const out = new Uint16Array(bw * bh);
|
|
1107
|
+
for (let y = 0; y < bh; y++) {
|
|
1108
|
+
for (let x = 0; x < bw; x++) {
|
|
1109
|
+
const sx = dx + x, sy = dy + y;
|
|
1110
|
+
let v;
|
|
1111
|
+
if (fx && fy) {
|
|
1112
|
+
const h0 = 16 * at(sx, sy) + fx * (at(sx + 1, sy) - at(sx, sy)) + ((1 << (4 - ib)) >> 1) >> (4 - ib);
|
|
1113
|
+
const h1 = 16 * at(sx, sy + 1) + fx * (at(sx + 1, sy + 1) - at(sx, sy + 1)) + ((1 << (4 - ib)) >> 1) >> (4 - ib);
|
|
1114
|
+
v = clip((16 * h0 + fy * (h1 - h0) + ((1 << (4 + ib)) >> 1)) >> (4 + ib));
|
|
1115
|
+
}
|
|
1116
|
+
else if (fx) {
|
|
1117
|
+
const p = 16 * at(sx, sy) + fx * (at(sx + 1, sy) - at(sx, sy)) + ((1 << (4 - ib)) >> 1) >> (4 - ib);
|
|
1118
|
+
v = clip((p + rnd) >> ib);
|
|
1119
|
+
}
|
|
1120
|
+
else if (fy) {
|
|
1121
|
+
v = clip((16 * at(sx, sy) + fy * (at(sx, sy + 1) - at(sx, sy)) + 8) >> 4);
|
|
1122
|
+
}
|
|
1123
|
+
else
|
|
1124
|
+
v = at(sx, sy);
|
|
1125
|
+
out[y * bw + x] = v;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
for (let y = 0; y < bh; y++)
|
|
1129
|
+
pic.set(out.subarray(y * bw, (y + 1) * bw), (by * vMul + y) * stride + bx * hMul);
|
|
1130
|
+
}
|
|
1131
|
+
reconInter(bs, b, hasChroma, mvy, mvx) {
|
|
1132
|
+
const f = this.frame, ssx = f.ssx, ssy = f.ssy;
|
|
1133
|
+
const bx = this.bx, by = this.by, bx4 = bx, by4 = by & 31;
|
|
1134
|
+
const cbx4 = bx4 >> ssx, cby4 = by4 >> ssy;
|
|
1135
|
+
const bw4 = bdim(bs, 0), bh4 = bdim(bs, 1);
|
|
1136
|
+
const w4 = Math.min(bw4, f.bw - bx), h4 = Math.min(bh4, f.bh - by);
|
|
1137
|
+
const cbw4 = bw4 + ssx >> ssx, cbh4 = bh4 + ssy >> ssy;
|
|
1138
|
+
this.mc(0, bw4, bh4, bx, by, mvy, mvx);
|
|
1139
|
+
if (hasChroma) {
|
|
1140
|
+
for (let pl = 1; pl < 3; pl++) {
|
|
1141
|
+
this.mc(pl, bw4 << (bw4 === ssx ? 1 : 0), bh4 << (bh4 === ssy ? 1 : 0), bx & ~ssx, by & ~ssy, mvy, mvx);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
if (b.skip) {
|
|
1145
|
+
this.aLcoef.fill(0x40, bx4, bx4 + (1 << bdim(bs, 2)));
|
|
1146
|
+
this.lLcoef.fill(0x40, by4, by4 + (1 << bdim(bs, 3)));
|
|
1147
|
+
if (hasChroma) {
|
|
1148
|
+
const cw = 1 << (31 - Math.clz32(cbw4)), ch = 1 << (31 - Math.clz32(cbh4));
|
|
1149
|
+
for (let pl = 0; pl < 2; pl++) {
|
|
1150
|
+
this.aCcoef[pl].fill(0x40, cbx4, cbx4 + cw);
|
|
1151
|
+
this.lCcoef[pl].fill(0x40, cby4, cby4 + ch);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
const ytx = this.maxYtx, ytw = tdim(ytx, W), yth = tdim(ytx, H);
|
|
1157
|
+
const uvtx = b.uvtx, uvtw = tdim(uvtx, W), uvth = tdim(uvtx, H);
|
|
1158
|
+
const cw4 = w4 + ssx >> ssx, ch4 = h4 + ssy >> ssy;
|
|
1159
|
+
const stride = f.strides[0], cstride = f.strides[1];
|
|
1160
|
+
for (let initY = 0; initY < bh4; initY += 16) {
|
|
1161
|
+
for (let initX = 0; initX < bw4; initX += 16) {
|
|
1162
|
+
let yOff = initY ? 1 : 0;
|
|
1163
|
+
for (let y = initY; y < Math.min(h4, initY + 16); y += yth, yOff++) {
|
|
1164
|
+
let xOff = initX ? 1 : 0;
|
|
1165
|
+
for (let x = initX; x < Math.min(w4, initX + 16); x += ytw, xOff++) {
|
|
1166
|
+
this.bx = bx + x;
|
|
1167
|
+
this.by = by + y;
|
|
1168
|
+
this.readCoefTree(bs, b, ytx, 0, xOff, yOff, 4 * ((by + y) * stride + bx + x));
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
this.bx = bx;
|
|
1172
|
+
this.by = by;
|
|
1173
|
+
if (!hasChroma)
|
|
1174
|
+
continue;
|
|
1175
|
+
for (let pl = 0; pl < 2; pl++) {
|
|
1176
|
+
const plane = f.planes[1 + pl];
|
|
1177
|
+
for (let y = initY >> ssy; y < Math.min(ch4, (initY + 16) >> ssy); y += uvth) {
|
|
1178
|
+
for (let x = initX >> ssx; x < Math.min(cw4, (initX + 16) >> ssx); x += uvtw) {
|
|
1179
|
+
const tbx = bx + (x << ssx), tby = by + (y << ssy);
|
|
1180
|
+
this.txtp = this.txtpMap[((by4 + (y << ssy)) & 31) * 32 + ((bx4 + (x << ssx)) & 31)];
|
|
1181
|
+
const eob = this.decodeCoefs(this.aCcoef[pl], cbx4 + x, this.lCcoef[pl], cby4 + y, uvtx, bs, b, 1 + pl, false);
|
|
1182
|
+
const ctw = Math.min(uvtw, (f.bw - tbx + ssx) >> ssx), cth = Math.min(uvth, (f.bh - tby + ssy) >> ssy);
|
|
1183
|
+
this.aCcoef[pl].fill(this.resCtx, cbx4 + x, cbx4 + x + ctw);
|
|
1184
|
+
this.lCcoef[pl].fill(this.resCtx, cby4 + y, cby4 + y + cth);
|
|
1185
|
+
if (eob >= 0)
|
|
1186
|
+
inverseTransformAdd(plane, 4 * (((by >> ssy) + y) * cstride + (bx >> ssx) + x), cstride, this.cf, eob, uvtx, this.txtp, f.bitdepthMax);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
readCoefTree(bs, b, ytx, depth, xOff, yOff, dst) {
|
|
1194
|
+
const f = this.frame;
|
|
1195
|
+
const tw = tdim(ytx, W), th = tdim(ytx, H);
|
|
1196
|
+
if (depth < 2 && this.txSplit[depth] && this.txSplit[depth] & 1 << (yOff * 4 + xOff)) {
|
|
1197
|
+
const sub = tdim(ytx, SUB), sw = tdim(sub, W), sh = tdim(sub, H);
|
|
1198
|
+
const stride = f.strides[0];
|
|
1199
|
+
this.readCoefTree(bs, b, sub, depth + 1, xOff * 2, yOff * 2, dst);
|
|
1200
|
+
this.bx += sw;
|
|
1201
|
+
if (tw >= th && this.bx < f.bw)
|
|
1202
|
+
this.readCoefTree(bs, b, sub, depth + 1, xOff * 2 + 1, yOff * 2, dst + 4 * sw);
|
|
1203
|
+
this.bx -= sw;
|
|
1204
|
+
this.by += sh;
|
|
1205
|
+
if (th >= tw && this.by < f.bh) {
|
|
1206
|
+
const d2 = dst + 4 * sh * stride;
|
|
1207
|
+
this.readCoefTree(bs, b, sub, depth + 1, xOff * 2, yOff * 2 + 1, d2);
|
|
1208
|
+
this.bx += sw;
|
|
1209
|
+
if (tw >= th && this.bx < f.bw)
|
|
1210
|
+
this.readCoefTree(bs, b, sub, depth + 1, xOff * 2 + 1, yOff * 2 + 1, d2 + 4 * sw);
|
|
1211
|
+
this.bx -= sw;
|
|
1212
|
+
}
|
|
1213
|
+
this.by -= sh;
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
const bx4 = this.bx, by4 = this.by & 31;
|
|
1217
|
+
const eob = this.decodeCoefs(this.aLcoef, bx4, this.lLcoef, by4, ytx, bs, b, 0, false);
|
|
1218
|
+
this.aLcoef.fill(this.resCtx, bx4, bx4 + Math.min(tw, f.bw - this.bx));
|
|
1219
|
+
this.lLcoef.fill(this.resCtx, by4, by4 + Math.min(th, f.bh - this.by));
|
|
1220
|
+
for (let y = 0; y < th; y++)
|
|
1221
|
+
this.txtpMap.fill(this.txtp, ((by4 + y) & 31) * 32 + (bx4 & 31), ((by4 + y) & 31) * 32 + (bx4 & 31) + Math.min(1 << tdim(ytx, LW), 16));
|
|
1222
|
+
if (eob >= 0)
|
|
1223
|
+
inverseTransformAdd(f.planes[0], dst, f.strides[0], this.cf, eob, ytx, this.txtp, f.bitdepthMax);
|
|
1224
|
+
}
|
|
1225
|
+
readPalPlane(b, pl, szCtx, bx4, by4) {
|
|
1226
|
+
const m = this.msac, f = this.frame;
|
|
1227
|
+
const palSz = b.palSz[pl] = m.symbol(this.cdf, CDF.palSize + (pl * 7 + szCtx) * 8, 6) + 2;
|
|
1228
|
+
const cache = [], used = [];
|
|
1229
|
+
let lCache = pl ? this.lPalSzUv[by4] : this.lPalSz[by4];
|
|
1230
|
+
let aCache = by4 & 15 ? pl ? this.aPalSzUv[bx4] : this.aPalSz[bx4] : 0;
|
|
1231
|
+
let l = by4 * 24 + pl * 8, a = bx4 * 24 + pl * 8;
|
|
1232
|
+
const L = this.lPal, A = this.aPal;
|
|
1233
|
+
const push = (v) => {
|
|
1234
|
+
if (!cache.length || cache[cache.length - 1] !== v)
|
|
1235
|
+
cache.push(v);
|
|
1236
|
+
};
|
|
1237
|
+
while (lCache && aCache) {
|
|
1238
|
+
if (L[l] < A[a]) {
|
|
1239
|
+
push(L[l++]);
|
|
1240
|
+
lCache--;
|
|
1241
|
+
}
|
|
1242
|
+
else {
|
|
1243
|
+
if (A[a] === L[l]) {
|
|
1244
|
+
l++;
|
|
1245
|
+
lCache--;
|
|
1246
|
+
}
|
|
1247
|
+
push(A[a++]);
|
|
1248
|
+
aCache--;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
while (lCache-- > 0)
|
|
1252
|
+
push(L[l++]);
|
|
1253
|
+
while (aCache-- > 0)
|
|
1254
|
+
push(A[a++]);
|
|
1255
|
+
for (let n = 0; n < cache.length && used.length < palSz; n++)
|
|
1256
|
+
if (m.bool())
|
|
1257
|
+
used.push(cache[n]);
|
|
1258
|
+
const pal = this.pal, o = pl * 8;
|
|
1259
|
+
let i = used.length;
|
|
1260
|
+
if (i < palSz) {
|
|
1261
|
+
const bpc = f.bitdepth;
|
|
1262
|
+
let prev = pal[o + i++] = m.bools(bpc);
|
|
1263
|
+
if (i < palSz) {
|
|
1264
|
+
let bits = bpc - 3 + m.bools(2);
|
|
1265
|
+
const max = (1 << bpc) - 1, minus = pl ? 0 : 1;
|
|
1266
|
+
do {
|
|
1267
|
+
const delta = m.bools(bits);
|
|
1268
|
+
prev = pal[o + i++] = Math.min(prev + delta + minus, max);
|
|
1269
|
+
if (prev + minus >= max) {
|
|
1270
|
+
for (; i < palSz; i++)
|
|
1271
|
+
pal[o + i] = max;
|
|
1272
|
+
break;
|
|
1273
|
+
}
|
|
1274
|
+
bits = Math.min(bits, 1 + (31 - Math.clz32(max - prev - minus)));
|
|
1275
|
+
} while (i < palSz);
|
|
1276
|
+
}
|
|
1277
|
+
const merged = [];
|
|
1278
|
+
let n = 0, k = used.length;
|
|
1279
|
+
for (i = 0; i < palSz; i++) {
|
|
1280
|
+
if (n < used.length && (k >= palSz || used[n] <= pal[o + k]))
|
|
1281
|
+
merged.push(used[n++]);
|
|
1282
|
+
else
|
|
1283
|
+
merged.push(pal[o + k++]);
|
|
1284
|
+
}
|
|
1285
|
+
pal.set(merged, o);
|
|
1286
|
+
}
|
|
1287
|
+
else
|
|
1288
|
+
pal.set(used, o);
|
|
1289
|
+
}
|
|
1290
|
+
readPalUv(b, szCtx, bx4, by4) {
|
|
1291
|
+
this.readPalPlane(b, 1, szCtx, bx4, by4);
|
|
1292
|
+
const m = this.msac, pal = this.pal, bpc = this.frame.bitdepth;
|
|
1293
|
+
if (m.bool()) {
|
|
1294
|
+
const bits = bpc - 4 + m.bools(2);
|
|
1295
|
+
let prev = pal[16] = m.bools(bpc);
|
|
1296
|
+
const max = (1 << bpc) - 1;
|
|
1297
|
+
for (let i = 1; i < b.palSz[1]; i++) {
|
|
1298
|
+
let delta = m.bools(bits);
|
|
1299
|
+
if (delta && m.bool())
|
|
1300
|
+
delta = -delta;
|
|
1301
|
+
prev = pal[16 + i] = prev + delta & max;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
for (let i = 0; i < b.palSz[1]; i++)
|
|
1306
|
+
pal[16 + i] = m.bools(bpc);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
readPalIndices(out, palSz, pl, w4, h4, bw4, bh4) {
|
|
1310
|
+
const m = this.msac, cdf = this.cdf, stride = bw4 * 4, t = this.palTmp;
|
|
1311
|
+
t[0] = m.uniform(palSz);
|
|
1312
|
+
const order = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
1313
|
+
for (let i = 1; i < 4 * (w4 + h4) - 1; i++) {
|
|
1314
|
+
const first = Math.min(i, w4 * 4 - 1), last = Math.max(0, i - h4 * 4 + 1);
|
|
1315
|
+
for (let j = first; j >= last; j--) {
|
|
1316
|
+
const p = (i - j) * stride + j;
|
|
1317
|
+
const haveTop = i - j > 0, haveLeft = j > 0;
|
|
1318
|
+
let ctx, n = 0, mask = 0;
|
|
1319
|
+
const add = (v) => { order[n++] = v; mask |= 1 << v; };
|
|
1320
|
+
if (!haveLeft) {
|
|
1321
|
+
ctx = 0;
|
|
1322
|
+
add(t[p - stride]);
|
|
1323
|
+
}
|
|
1324
|
+
else if (!haveTop) {
|
|
1325
|
+
ctx = 0;
|
|
1326
|
+
add(t[p - 1]);
|
|
1327
|
+
}
|
|
1328
|
+
else {
|
|
1329
|
+
const l = t[p - 1], tp = t[p - stride], tl = t[p - stride - 1];
|
|
1330
|
+
const sameTL = tp === l, sameTTl = tp === tl, sameLTl = l === tl;
|
|
1331
|
+
if (sameTL && sameTTl && sameLTl) {
|
|
1332
|
+
ctx = 4;
|
|
1333
|
+
add(tp);
|
|
1334
|
+
}
|
|
1335
|
+
else if (sameTL) {
|
|
1336
|
+
ctx = 3;
|
|
1337
|
+
add(tp);
|
|
1338
|
+
add(tl);
|
|
1339
|
+
}
|
|
1340
|
+
else if (sameTTl || sameLTl) {
|
|
1341
|
+
ctx = 2;
|
|
1342
|
+
add(tl);
|
|
1343
|
+
add(sameTTl ? l : tp);
|
|
1344
|
+
}
|
|
1345
|
+
else {
|
|
1346
|
+
ctx = 1;
|
|
1347
|
+
add(Math.min(tp, l));
|
|
1348
|
+
add(Math.max(tp, l));
|
|
1349
|
+
add(tl);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
for (let bit = 0; bit < 8; bit++)
|
|
1353
|
+
if (!(mask & 1 << bit))
|
|
1354
|
+
order[n++] = bit;
|
|
1355
|
+
const idx = m.symbol(cdf, CDF.colorMap + ((pl * 7 + palSz - 2) * 5 + ctx) * 8, palSz - 1);
|
|
1356
|
+
t[p] = order[idx];
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
const w = w4 * 4, h = h4 * 4, bw = bw4 * 4, bh = bh4 * 4;
|
|
1360
|
+
for (let y = 0; y < h; y++) {
|
|
1361
|
+
for (let x = 0; x < w; x++)
|
|
1362
|
+
out[y * bw + x] = t[y * stride + x];
|
|
1363
|
+
out.fill(t[y * stride + w - 1], y * bw + w, y * bw + bw);
|
|
1364
|
+
}
|
|
1365
|
+
for (let y = h; y < bh; y++)
|
|
1366
|
+
out.copyWithin(y * bw, (h - 1) * bw, h * bw);
|
|
1367
|
+
}
|
|
1368
|
+
txtp = 0;
|
|
1369
|
+
resCtx = 0;
|
|
1370
|
+
decodeCoefs(aArr, a, lArr, l, tx, bs, b, plane, intra = true) {
|
|
1371
|
+
const m = this.msac, cdf = this.cdf, f = this.frame, hdr = this.hdr;
|
|
1372
|
+
const chroma = plane ? 1 : 0;
|
|
1373
|
+
const lossless = hdr.segmentation.lossless[b.segId];
|
|
1374
|
+
const tlw = tdim(tx, LW), tlh = tdim(tx, LH), tctx = tdim(tx, CTX), tmin = tdim(tx, MIN), tmax = tdim(tx, MAX);
|
|
1375
|
+
let sctx;
|
|
1376
|
+
const aw = 1 << tlw, lh = 1 << tlh;
|
|
1377
|
+
if (chroma) {
|
|
1378
|
+
const bl2 = bdim(bs, 2), bl3 = bdim(bs, 3);
|
|
1379
|
+
const notOneBlk = bl2 - (bl2 && f.ssx ? 1 : 0) > tlw || bl3 - (bl3 && f.ssy ? 1 : 0) > tlh;
|
|
1380
|
+
let ca = 0, cl = 0;
|
|
1381
|
+
for (let i = 0; i < aw; i++)
|
|
1382
|
+
if (aArr[a + i] !== 0x40) {
|
|
1383
|
+
ca = 1;
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
for (let i = 0; i < lh; i++)
|
|
1387
|
+
if (lArr[l + i] !== 0x40) {
|
|
1388
|
+
cl = 1;
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
sctx = 7 + (notOneBlk ? 3 : 0) + ca + cl;
|
|
1392
|
+
}
|
|
1393
|
+
else if (bdim(bs, 2) === tlw && bdim(bs, 3) === tlh) {
|
|
1394
|
+
sctx = 0;
|
|
1395
|
+
}
|
|
1396
|
+
else {
|
|
1397
|
+
let la = 0, ll = 0;
|
|
1398
|
+
for (let i = 0; i < aw; i++)
|
|
1399
|
+
la |= aArr[a + i];
|
|
1400
|
+
for (let i = 0; i < lh; i++)
|
|
1401
|
+
ll |= lArr[l + i];
|
|
1402
|
+
sctx = SKIP_CTX[Math.min(la & 0x3f, 4) * 5 + Math.min(ll & 0x3f, 4)];
|
|
1403
|
+
}
|
|
1404
|
+
if (m.boolAdapt(cdf, CDF.coefSkip + (tctx * 13 + sctx) * 2)) {
|
|
1405
|
+
this.resCtx = 0x40;
|
|
1406
|
+
this.txtp = lossless ? WHT_WHT : DCT_DCT;
|
|
1407
|
+
return -1;
|
|
1408
|
+
}
|
|
1409
|
+
let txtp;
|
|
1410
|
+
if (lossless)
|
|
1411
|
+
txtp = WHT_WHT;
|
|
1412
|
+
else if (tmax + (intra ? 1 : 0) >= TX_64X64)
|
|
1413
|
+
txtp = DCT_DCT;
|
|
1414
|
+
else if (chroma) {
|
|
1415
|
+
if (intra)
|
|
1416
|
+
txtp = TXTP_FROM_UVMODE[b.uvMode];
|
|
1417
|
+
else {
|
|
1418
|
+
const y = this.txtp;
|
|
1419
|
+
if (tmax === TX_32X32)
|
|
1420
|
+
txtp = y === IDTX ? IDTX : DCT_DCT;
|
|
1421
|
+
else if (tmin === TX_16X16 && (1 << y & (1 << 15 | 1 << 14 | 1 << 13 | 1 << 12)))
|
|
1422
|
+
txtp = DCT_DCT;
|
|
1423
|
+
else
|
|
1424
|
+
txtp = y;
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
else if (!hdr.segmentation.qidx[b.segId])
|
|
1428
|
+
txtp = DCT_DCT;
|
|
1429
|
+
else if (!intra) {
|
|
1430
|
+
if (hdr.reducedTxSet || tmax === TX_32X32)
|
|
1431
|
+
txtp = m.boolAdapt(cdf, CDF.txtpInter3 + tmin * 2) ? DCT_DCT : IDTX;
|
|
1432
|
+
else if (tmin === TX_16X16)
|
|
1433
|
+
txtp = TX_TYPES_PER_SET[m.symbol(cdf, CDF.txtpInter2, 11) + 12];
|
|
1434
|
+
else
|
|
1435
|
+
txtp = TX_TYPES_PER_SET[m.symbol(cdf, CDF.txtpInter1 + tmin * 16, 15) + 24];
|
|
1436
|
+
}
|
|
1437
|
+
else {
|
|
1438
|
+
const yModeNofilt = b.yMode === FILTER_PRED ? FILTER_MODE_TO_Y_MODE[b.yAngle] : b.yMode;
|
|
1439
|
+
if (hdr.reducedTxSet || tmin === TX_16X16)
|
|
1440
|
+
txtp = TX_TYPES_PER_SET[m.symbol(cdf, CDF.txtpIntra2 + (tmin * 13 + yModeNofilt) * 8, 4)];
|
|
1441
|
+
else
|
|
1442
|
+
txtp = TX_TYPES_PER_SET[m.symbol(cdf, CDF.txtpIntra1 + (tmin * 13 + yModeNofilt) * 8, 6) + 5];
|
|
1443
|
+
}
|
|
1444
|
+
this.txtp = txtp;
|
|
1445
|
+
const slw = Math.min(tlw, 3), slh = Math.min(tlh, 3);
|
|
1446
|
+
const tx2d = slw + slh;
|
|
1447
|
+
const txClass = TX_TYPE_CLASS[txtp];
|
|
1448
|
+
const is1d = txClass !== TX_CLASS_2D ? 1 : 0;
|
|
1449
|
+
let eobBin;
|
|
1450
|
+
switch (tx2d) {
|
|
1451
|
+
case 0:
|
|
1452
|
+
eobBin = m.symbol(cdf, CDF.eobBin16 + (chroma * 2 + is1d) * 8, 4);
|
|
1453
|
+
break;
|
|
1454
|
+
case 1:
|
|
1455
|
+
eobBin = m.symbol(cdf, CDF.eobBin32 + (chroma * 2 + is1d) * 8, 5);
|
|
1456
|
+
break;
|
|
1457
|
+
case 2:
|
|
1458
|
+
eobBin = m.symbol(cdf, CDF.eobBin64 + (chroma * 2 + is1d) * 8, 6);
|
|
1459
|
+
break;
|
|
1460
|
+
case 3:
|
|
1461
|
+
eobBin = m.symbol(cdf, CDF.eobBin128 + (chroma * 2 + is1d) * 8, 7);
|
|
1462
|
+
break;
|
|
1463
|
+
case 4:
|
|
1464
|
+
eobBin = m.symbol(cdf, CDF.eobBin256 + (chroma * 2 + is1d) * 16, 8);
|
|
1465
|
+
break;
|
|
1466
|
+
case 5:
|
|
1467
|
+
eobBin = m.symbol(cdf, CDF.eobBin512 + chroma * 16, 9);
|
|
1468
|
+
break;
|
|
1469
|
+
default:
|
|
1470
|
+
eobBin = m.symbol(cdf, CDF.eobBin1024 + chroma * 16, 10);
|
|
1471
|
+
break;
|
|
1472
|
+
}
|
|
1473
|
+
let eob;
|
|
1474
|
+
if (eobBin > 1) {
|
|
1475
|
+
const hi = m.boolAdapt(cdf, CDF.eobHiBit + ((tctx * 2 + chroma) * 11 + eobBin) * 2);
|
|
1476
|
+
eob = (hi | 2) << (eobBin - 2) | m.bools(eobBin - 2);
|
|
1477
|
+
}
|
|
1478
|
+
else
|
|
1479
|
+
eob = eobBin;
|
|
1480
|
+
const cf = this.cf, levels = this.levels;
|
|
1481
|
+
const eobCdf = CDF.eobBaseTok + (tctx * 2 + chroma) * 16;
|
|
1482
|
+
const hiCdf = CDF.brTok + (Math.min(tctx, 3) * 2 + chroma) * 84;
|
|
1483
|
+
let rc, dcTok;
|
|
1484
|
+
if (eob) {
|
|
1485
|
+
const loCdf = CDF.baseTok + (tctx * 2 + chroma) * 164;
|
|
1486
|
+
let ctx = 1 + (eob > 2 << tx2d ? 1 : 0) + (eob > 4 << tx2d ? 1 : 0);
|
|
1487
|
+
const eobTok = m.symbol(cdf, eobCdf + ctx * 4, 2);
|
|
1488
|
+
let tok = eobTok + 1;
|
|
1489
|
+
let levelTok = tok * 0x41;
|
|
1490
|
+
let mag = 0;
|
|
1491
|
+
let scanTable = null, stride, shift, shift2, mask, offsets = 0;
|
|
1492
|
+
if (txClass === TX_CLASS_2D) {
|
|
1493
|
+
const nonsquare = tx >= RTX_4X8 ? 1 : 0;
|
|
1494
|
+
offsets = (nonsquare + (tx & nonsquare)) * 25;
|
|
1495
|
+
scanTable = scan(tx);
|
|
1496
|
+
stride = 4 << slh;
|
|
1497
|
+
shift = slh + 2;
|
|
1498
|
+
shift2 = 0;
|
|
1499
|
+
mask = (4 << slh) - 1;
|
|
1500
|
+
levels.fill(0, 0, stride * ((4 << slw) + 2));
|
|
1501
|
+
}
|
|
1502
|
+
else if (txClass === TX_CLASS_H) {
|
|
1503
|
+
stride = 16;
|
|
1504
|
+
shift = slh + 2;
|
|
1505
|
+
shift2 = 0;
|
|
1506
|
+
mask = (4 << slh) - 1;
|
|
1507
|
+
levels.fill(0, 0, stride * ((4 << slh) + 2));
|
|
1508
|
+
}
|
|
1509
|
+
else {
|
|
1510
|
+
stride = 16;
|
|
1511
|
+
shift = slw + 2;
|
|
1512
|
+
shift2 = slh + 2;
|
|
1513
|
+
mask = (4 << slw) - 1;
|
|
1514
|
+
levels.fill(0, 0, stride * ((4 << slw) + 2));
|
|
1515
|
+
}
|
|
1516
|
+
let hiMag = 0;
|
|
1517
|
+
const loCtx = (lv, x, y) => {
|
|
1518
|
+
let mg = levels[lv + 1] + levels[lv + stride];
|
|
1519
|
+
let off;
|
|
1520
|
+
if (txClass === TX_CLASS_2D) {
|
|
1521
|
+
mg += levels[lv + stride + 1];
|
|
1522
|
+
hiMag = mg;
|
|
1523
|
+
mg += levels[lv + 2] + levels[lv + 2 * stride];
|
|
1524
|
+
off = LO_CTX_OFFSETS[offsets + Math.min(y, 4) * 5 + Math.min(x, 4)];
|
|
1525
|
+
}
|
|
1526
|
+
else {
|
|
1527
|
+
mg += levels[lv + 2];
|
|
1528
|
+
hiMag = mg;
|
|
1529
|
+
mg += levels[lv + 3] + levels[lv + 4];
|
|
1530
|
+
off = 26 + (y > 1 ? 10 : y * 5);
|
|
1531
|
+
}
|
|
1532
|
+
return off + (mg > 512 ? 4 : mg + 64 >> 7);
|
|
1533
|
+
};
|
|
1534
|
+
const position = (i) => {
|
|
1535
|
+
if (txClass === TX_CLASS_2D) {
|
|
1536
|
+
const r = scanTable[i];
|
|
1537
|
+
return [r, r >> shift, r & mask];
|
|
1538
|
+
}
|
|
1539
|
+
const x = i & mask, y = i >> shift;
|
|
1540
|
+
return [txClass === TX_CLASS_H ? i : x << shift2 | y, x, y];
|
|
1541
|
+
};
|
|
1542
|
+
const [r, x, y] = position(eob);
|
|
1543
|
+
rc = r;
|
|
1544
|
+
if (eobTok === 2) {
|
|
1545
|
+
ctx = (txClass === TX_CLASS_2D ? (x | y) > 1 : y !== 0) ? 14 : 7;
|
|
1546
|
+
tok = m.hiTok(cdf, hiCdf + ctx * 4);
|
|
1547
|
+
levelTok = tok + (3 << 6);
|
|
1548
|
+
}
|
|
1549
|
+
cf[rc] = tok << 11;
|
|
1550
|
+
levels[x * stride + y] = levelTok;
|
|
1551
|
+
for (let i = eob - 1; i > 0; i--) {
|
|
1552
|
+
const [rcI, xi, yi0] = position(i);
|
|
1553
|
+
const lv = xi * stride + yi0;
|
|
1554
|
+
ctx = loCtx(lv, xi, yi0);
|
|
1555
|
+
const yi = txClass === TX_CLASS_2D ? yi0 | xi : yi0;
|
|
1556
|
+
tok = m.symbol(cdf, loCdf + ctx * 4, 3);
|
|
1557
|
+
if (tok === 3) {
|
|
1558
|
+
mag = hiMag & 63;
|
|
1559
|
+
ctx = (yi > (txClass === TX_CLASS_2D ? 1 : 0) ? 14 : 7) + (mag > 12 ? 6 : mag + 1 >> 1);
|
|
1560
|
+
tok = m.hiTok(cdf, hiCdf + ctx * 4);
|
|
1561
|
+
levels[lv] = tok + (3 << 6);
|
|
1562
|
+
cf[rcI] = tok << 11 | rc;
|
|
1563
|
+
rc = rcI;
|
|
1564
|
+
}
|
|
1565
|
+
else {
|
|
1566
|
+
levels[lv] = tok * 0x41;
|
|
1567
|
+
if (tok) {
|
|
1568
|
+
cf[rcI] = tok << 11 | rc;
|
|
1569
|
+
rc = rcI;
|
|
1570
|
+
}
|
|
1571
|
+
else
|
|
1572
|
+
cf[rcI] = 0;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
ctx = txClass === TX_CLASS_2D ? 0 : loCtx(0, 0, 0);
|
|
1576
|
+
dcTok = m.symbol(cdf, loCdf + ctx * 4, 3);
|
|
1577
|
+
if (dcTok === 3) {
|
|
1578
|
+
if (txClass === TX_CLASS_2D)
|
|
1579
|
+
hiMag = levels[1] + levels[stride] + levels[stride + 1];
|
|
1580
|
+
mag = hiMag & 63;
|
|
1581
|
+
ctx = mag > 12 ? 6 : mag + 1 >> 1;
|
|
1582
|
+
dcTok = m.hiTok(cdf, hiCdf + ctx * 4);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
else {
|
|
1586
|
+
const tokBr = m.symbol(cdf, eobCdf, 2);
|
|
1587
|
+
dcTok = 1 + tokBr;
|
|
1588
|
+
if (tokBr === 2)
|
|
1589
|
+
dcTok = m.hiTok(cdf, hiCdf);
|
|
1590
|
+
rc = 0;
|
|
1591
|
+
}
|
|
1592
|
+
const dq = this.dq[b.segId][plane];
|
|
1593
|
+
const qm = txtp < IDTX ? this.qm[tx][plane] : null;
|
|
1594
|
+
const dqShift = Math.max(0, tctx - 2);
|
|
1595
|
+
const cfMax = (128 << (f.bitdepth === 8 ? 8 : f.bitdepth)) - 1;
|
|
1596
|
+
let culLevel, dcSignLevel;
|
|
1597
|
+
if (!dcTok) {
|
|
1598
|
+
culLevel = 0;
|
|
1599
|
+
dcSignLevel = 1 << 6;
|
|
1600
|
+
}
|
|
1601
|
+
else {
|
|
1602
|
+
let sctx2 = 0;
|
|
1603
|
+
for (let i = 0; i < aw; i++)
|
|
1604
|
+
sctx2 += aArr[a + i] >> 6;
|
|
1605
|
+
for (let i = 0; i < lh; i++)
|
|
1606
|
+
sctx2 += lArr[l + i] >> 6;
|
|
1607
|
+
sctx2 -= aw + lh;
|
|
1608
|
+
const dcSignCtx = (sctx2 !== 0 ? 1 : 0) + (sctx2 > 0 ? 1 : 0);
|
|
1609
|
+
const dcSign = m.boolAdapt(cdf, CDF.dcSign + (chroma * 3 + dcSignCtx) * 2);
|
|
1610
|
+
let dcDq = dq[0];
|
|
1611
|
+
dcSignLevel = (dcSign - 1) & (2 << 6);
|
|
1612
|
+
if (qm)
|
|
1613
|
+
dcDq = (dcDq * qm[0] + 16) >> 5;
|
|
1614
|
+
if (dcTok === 15) {
|
|
1615
|
+
dcTok = m.golomb() + 15 & 0xfffff;
|
|
1616
|
+
dcDq = (dcDq * dcTok & 0xffffff) >> dqShift;
|
|
1617
|
+
dcDq = Math.min(dcDq, cfMax + dcSign);
|
|
1618
|
+
}
|
|
1619
|
+
else {
|
|
1620
|
+
dcDq = (dcDq * dcTok) >> dqShift;
|
|
1621
|
+
if (qm)
|
|
1622
|
+
dcDq = Math.min(dcDq, cfMax + dcSign);
|
|
1623
|
+
}
|
|
1624
|
+
culLevel = dcTok;
|
|
1625
|
+
cf[0] = dcSign ? -dcDq : dcDq;
|
|
1626
|
+
}
|
|
1627
|
+
if (rc) {
|
|
1628
|
+
const acDq = dq[1];
|
|
1629
|
+
do {
|
|
1630
|
+
const sign = m.bool();
|
|
1631
|
+
const rcTok = cf[rc];
|
|
1632
|
+
let tok, d = qm ? (acDq * qm[rc] + 16) >> 5 : acDq;
|
|
1633
|
+
if (rcTok >= 15 << 11) {
|
|
1634
|
+
tok = m.golomb() + 15 & 0xfffff;
|
|
1635
|
+
d = (d * tok & 0xffffff) >> dqShift;
|
|
1636
|
+
d = Math.min(d, cfMax + sign);
|
|
1637
|
+
}
|
|
1638
|
+
else {
|
|
1639
|
+
tok = rcTok >> 11;
|
|
1640
|
+
d = (d * tok) >> dqShift;
|
|
1641
|
+
if (qm)
|
|
1642
|
+
d = Math.min(d, cfMax + sign);
|
|
1643
|
+
}
|
|
1644
|
+
culLevel += tok;
|
|
1645
|
+
cf[rc] = sign ? -d : d;
|
|
1646
|
+
rc = rcTok & 0x3ff;
|
|
1647
|
+
} while (rc);
|
|
1648
|
+
}
|
|
1649
|
+
this.resCtx = Math.min(culLevel, 63) | dcSignLevel;
|
|
1650
|
+
return eob;
|
|
1651
|
+
}
|
|
1652
|
+
reconIntra(bs, edgeFlags, b, hasChroma) {
|
|
1653
|
+
const f = this.frame, seq = this.seq;
|
|
1654
|
+
const bx = this.bx, by = this.by, bx4 = bx, by4 = by & 31;
|
|
1655
|
+
const ssx = f.ssx, ssy = f.ssy;
|
|
1656
|
+
const cbx4 = bx4 >> ssx, cby4 = by4 >> ssy;
|
|
1657
|
+
const bw4 = bdim(bs, 0), bh4 = bdim(bs, 1);
|
|
1658
|
+
const w4 = Math.min(bw4, f.bw - bx), h4 = Math.min(bh4, f.bh - by);
|
|
1659
|
+
const cw4 = w4 + ssx >> ssx, ch4 = h4 + ssy >> ssy;
|
|
1660
|
+
const cbw4 = bw4 + ssx >> ssx, cbh4 = bh4 + ssy >> ssy;
|
|
1661
|
+
const tx = b.tx, uvtx = b.uvtx;
|
|
1662
|
+
const tw = tdim(tx, W), th = tdim(tx, H), uvtw = tdim(uvtx, W), uvth = tdim(uvtx, H);
|
|
1663
|
+
const filterFlag = seq.intraEdgeFilter ? ANGLE_USE_EDGE_FILTER : 0;
|
|
1664
|
+
const bdMax = f.bitdepthMax;
|
|
1665
|
+
const pic = f.planes[0], stride = f.strides[0];
|
|
1666
|
+
const smFlag = (mode) => mode === SMOOTH_PRED || mode === SMOOTH_H_PRED || mode === SMOOTH_V_PRED ? ANGLE_SMOOTH_EDGE : 0;
|
|
1667
|
+
for (let initY = 0; initY < h4; initY += 16) {
|
|
1668
|
+
const subH4 = Math.min(h4, 16 + initY);
|
|
1669
|
+
const subCh4 = Math.min(ch4, initY + 16 >> ssy);
|
|
1670
|
+
for (let initX = 0; initX < w4; initX += 16) {
|
|
1671
|
+
if (b.palSz[0]) {
|
|
1672
|
+
const d = 4 * (by * stride + bx), bw = bw4 * 4;
|
|
1673
|
+
for (let y = 0; y < bh4 * 4; y++)
|
|
1674
|
+
for (let x = 0; x < bw; x++)
|
|
1675
|
+
pic[d + y * stride + x] = this.pal[this.palIdxY[y * bw + x]];
|
|
1676
|
+
}
|
|
1677
|
+
const intraFlags = (this.aIntra[bx4] ? smFlag(this.aMode[bx4]) : 0) | (this.lIntra[by4] ? smFlag(this.lMode[by4]) : 0) | filterFlag;
|
|
1678
|
+
const sbHasTr = initX + 16 < w4 ? 1 : initY ? 0 : edgeFlags & EDGE_I444_TOP_HAS_RIGHT;
|
|
1679
|
+
const sbHasBl = initX ? 0 : initY + 16 < h4 ? 1 : edgeFlags & EDGE_I444_LEFT_HAS_BOTTOM;
|
|
1680
|
+
const subW4 = Math.min(w4, initX + 16);
|
|
1681
|
+
for (let y = initY; y < subH4; y += th) {
|
|
1682
|
+
const ty = by + y;
|
|
1683
|
+
let d = 4 * (ty * stride + bx + initX);
|
|
1684
|
+
for (let x = initX; x < subW4; x += tw, d += 4 * tw) {
|
|
1685
|
+
const tx4 = bx + x;
|
|
1686
|
+
if (!b.palSz[0]) {
|
|
1687
|
+
const flags = (((y > initY || !sbHasTr) && x + tw >= subW4) ? 0 : EDGE_I444_TOP_HAS_RIGHT) |
|
|
1688
|
+
((x > initX || (!sbHasBl && y + th >= subH4)) ? 0 : EDGE_I444_LEFT_HAS_BOTTOM);
|
|
1689
|
+
const mode = prepareEdges(tx4, tx4 > this.colStart, ty, ty > this.rowStart, this.colEnd, this.rowEnd, flags, pic, d, stride, b.yMode, b.yAngle, tw, th, seq.intraEdgeFilter, f.bitdepth);
|
|
1690
|
+
predict(mode, pic, d, stride, tw * 4, th * 4, preparedAngle | intraFlags, 4 * f.bw - 4 * tx4, 4 * f.bh - 4 * ty, bdMax);
|
|
1691
|
+
}
|
|
1692
|
+
if (!b.skip) {
|
|
1693
|
+
const eob = this.decodeCoefs(this.aLcoef, bx4 + x, this.lLcoef, by4 + y, tx, bs, b, 0);
|
|
1694
|
+
this.aLcoef.fill(this.resCtx, bx4 + x, bx4 + x + Math.min(tw, f.bw - tx4));
|
|
1695
|
+
this.lLcoef.fill(this.resCtx, by4 + y, by4 + y + Math.min(th, f.bh - ty));
|
|
1696
|
+
if (eob >= 0)
|
|
1697
|
+
inverseTransformAdd(pic, d, stride, this.cf, eob, tx, this.txtp, bdMax);
|
|
1698
|
+
}
|
|
1699
|
+
else {
|
|
1700
|
+
this.aLcoef.fill(0x40, bx4 + x, bx4 + x + tw);
|
|
1701
|
+
this.lLcoef.fill(0x40, by4 + y, by4 + y + th);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
if (!hasChroma)
|
|
1706
|
+
continue;
|
|
1707
|
+
const cstride = f.strides[1];
|
|
1708
|
+
if (b.uvMode === CFL_PRED) {
|
|
1709
|
+
const yo = 4 * (bx & ~ssx) + 4 * (by & ~ssy) * stride;
|
|
1710
|
+
const furthestR = ((cw4 << ssx) + tw - 1) & ~(tw - 1);
|
|
1711
|
+
const furthestB = ((ch4 << ssy) + th - 1) & ~(th - 1);
|
|
1712
|
+
cflAc(this.ac, pic, yo, stride, cbw4 - (furthestR >> ssx), cbh4 - (furthestB >> ssy), cbw4 * 4, cbh4 * 4, ssx, ssy);
|
|
1713
|
+
const uvOff = 4 * ((bx >> ssx) + (by >> ssy) * cstride);
|
|
1714
|
+
for (let pl = 0; pl < 2; pl++) {
|
|
1715
|
+
if (!b.cflAlpha[pl])
|
|
1716
|
+
continue;
|
|
1717
|
+
const xpos = bx >> ssx, ypos = by >> ssy;
|
|
1718
|
+
const mode = prepareEdges(xpos, xpos > this.colStart >> ssx, ypos, ypos > this.rowStart >> ssy, this.colEnd >> ssx, this.rowEnd >> ssy, 0, f.planes[1 + pl], uvOff, cstride, DC_PRED, 0, uvtw, uvth, false, f.bitdepth);
|
|
1719
|
+
cflPredict(mode, f.planes[1 + pl], uvOff, cstride, uvtw * 4, uvth * 4, this.ac, b.cflAlpha[pl], bdMax);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
else if (b.palSz[1]) {
|
|
1723
|
+
const uvOff = 4 * ((bx >> ssx) + (by >> ssy) * cstride), bw = cbw4 * 4;
|
|
1724
|
+
for (let pl = 1; pl <= 2; pl++) {
|
|
1725
|
+
const plane = f.planes[pl];
|
|
1726
|
+
for (let y = 0; y < cbh4 * 4; y++)
|
|
1727
|
+
for (let x = 0; x < bw; x++)
|
|
1728
|
+
plane[uvOff + y * cstride + x] = this.pal[pl * 8 + this.palIdxUv[y * bw + x]];
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
const smUv = smFlag(this.aUvmode[cbx4]) | smFlag(this.lUvmode[cby4]);
|
|
1732
|
+
const edge = f.layout === 1 ? [EDGE_I420_TOP_HAS_RIGHT, EDGE_I420_LEFT_HAS_BOTTOM] : f.layout === 2 ? [2, 16] : [1, 8];
|
|
1733
|
+
const uvSbHasTr = (initX + 16 >> ssx) < cw4 ? 1 : initY ? 0 : edgeFlags & edge[0];
|
|
1734
|
+
const uvSbHasBl = initX ? 0 : (initY + 16 >> ssy) < ch4 ? 1 : edgeFlags & edge[1];
|
|
1735
|
+
const subCw4 = Math.min(cw4, initX + 16 >> ssx);
|
|
1736
|
+
for (let pl = 0; pl < 2; pl++) {
|
|
1737
|
+
const plane = f.planes[1 + pl];
|
|
1738
|
+
const aC = this.aCcoef[pl], lC = this.lCcoef[pl];
|
|
1739
|
+
for (let y = initY >> ssy, tyl = by + initY; y < subCh4; y += uvth, tyl += uvth << ssy) {
|
|
1740
|
+
let d = 4 * ((tyl >> ssy) * cstride + (bx + initX >> ssx));
|
|
1741
|
+
for (let x = initX >> ssx, txl = bx + initX; x < subCw4; x += uvtw, txl += uvtw << ssx, d += uvtw * 4) {
|
|
1742
|
+
if (!(b.uvMode === CFL_PRED && b.cflAlpha[pl]) && !b.palSz[1]) {
|
|
1743
|
+
const flags = (((y > (initY >> ssy) || !uvSbHasTr) && x + uvtw >= subCw4) ? 0 : EDGE_I444_TOP_HAS_RIGHT) |
|
|
1744
|
+
((x > (initX >> ssx) || (!uvSbHasBl && y + uvth >= subCh4)) ? 0 : EDGE_I444_LEFT_HAS_BOTTOM);
|
|
1745
|
+
const uvMode = b.uvMode === CFL_PRED ? DC_PRED : b.uvMode;
|
|
1746
|
+
const xpos = txl >> ssx, ypos = tyl >> ssy;
|
|
1747
|
+
const mode = prepareEdges(xpos, xpos > this.colStart >> ssx, ypos, ypos > this.rowStart >> ssy, this.colEnd >> ssx, this.rowEnd >> ssy, flags, plane, d, cstride, uvMode, b.uvAngle, uvtw, uvth, seq.intraEdgeFilter, f.bitdepth);
|
|
1748
|
+
predict(mode, plane, d, cstride, uvtw * 4, uvth * 4, preparedAngle | filterFlag | smUv, (4 * f.bw + ssx - 4 * (txl & ~ssx)) >> ssx, (4 * f.bh + ssy - 4 * (tyl & ~ssy)) >> ssy, bdMax);
|
|
1749
|
+
}
|
|
1750
|
+
if (!b.skip) {
|
|
1751
|
+
const eob = this.decodeCoefs(aC, cbx4 + x, lC, cby4 + y, uvtx, bs, b, 1 + pl);
|
|
1752
|
+
const ctw = Math.min(uvtw, (f.bw - txl + ssx) >> ssx);
|
|
1753
|
+
const cth = Math.min(uvth, (f.bh - tyl + ssy) >> ssy);
|
|
1754
|
+
aC.fill(this.resCtx, cbx4 + x, cbx4 + x + ctw);
|
|
1755
|
+
lC.fill(this.resCtx, cby4 + y, cby4 + y + cth);
|
|
1756
|
+
if (eob >= 0)
|
|
1757
|
+
inverseTransformAdd(plane, d, cstride, this.cf, eob, uvtx, this.txtp, bdMax);
|
|
1758
|
+
}
|
|
1759
|
+
else {
|
|
1760
|
+
aC.fill(0x40, cbx4 + x, cbx4 + x + uvtw);
|
|
1761
|
+
lC.fill(0x40, cby4 + y, cby4 + y + uvth);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|