@fxi/zartigl 0.14.2 → 0.15.1
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/dist/{backdrop-Dceb4d8E.js → backdrop-BMwRyFI5.js} +6 -6
- package/dist/catalog.js +1 -1
- package/dist/engine.d.ts +54 -8
- package/dist/engine.js +55 -52
- package/dist/geovideo-index-D-BHqpO6.js +2991 -0
- package/dist/{index-B1lj-XR_.js → index-DxMsDfgL.js} +15 -14
- package/dist/zartigl.js +1018 -1622
- package/package.json +2 -2
- package/dist/engine-C8ZNzILO.js +0 -2302
package/dist/engine-C8ZNzILO.js
DELETED
|
@@ -1,2302 +0,0 @@
|
|
|
1
|
-
import "./backdrop-Dceb4d8E.js";
|
|
2
|
-
const ye = { label: "Thermal", tags: ["sequential", "temperature"], colors: ["#042333", "#2c3395", "#744796", "#b15f82", "#eb7958", "#fbb43d", "#e8fa5b"] }, _e = { label: "Haline", tags: ["sequential", "salinity"], colors: ["#2a186c", "#17568b", "#1a7e8f", "#22a785", "#55c666", "#aadc32", "#fde333"] }, xe = { label: "Solar", tags: ["sequential", "irradiance"], colors: ["#330f0b", "#6b2313", "#a83c12", "#d6621a", "#f3951e", "#f7c741", "#f9f871"] }, Re = { label: "Ice", tags: ["sequential"], colors: ["#040d1a", "#123365", "#1c5f9e", "#2b8ece", "#62bde3", "#aaddf2", "#f2faff"] }, ve = { label: "Deep", tags: ["sequential", "depth"], colors: ["#fdfecc", "#c8e59b", "#74c8a3", "#3194b0", "#2a5b8e", "#281a5e", "#0c0820"] }, ke = { label: "RdYlBu", tags: ["diverging"], colors: ["#3288bd", "#66c2a5", "#abdda4", "#e6f598", "#fee08b", "#fdae61", "#f46d43", "#d53e4f"] }, Ae = { label: "Dense", tags: ["sequential"], colors: ["#e6f1f1", "#92c4ca", "#44929a", "#20627a", "#1a3c6a", "#211a50", "#0d0621"] }, Fe = { label: "Algae", tags: ["sequential", "biology", "log"], colors: ["#d7f9d0", "#a2d595", "#64b463", "#129450", "#126e45", "#1a482f", "#122414"] }, Se = { label: "Oxygen", tags: ["sequential", "biology", "hypoxia"], colors: ["#09060f", "#5b1028", "#d43d2f", "#f39b3d", "#f3e7b3", "#79cbd1", "#176b9c"] }, Ue = { label: "Matter", tags: ["sequential", "biology"], colors: ["#fdfecc", "#f2c98a", "#e07c4e", "#bc3754", "#8d1a6d", "#51156b", "#1c0c3f"] }, Me = { label: "Viridis", tags: ["sequential", "perceptual"], colors: ["#440154", "#443983", "#31688e", "#21918c", "#35b779", "#90d743", "#fde725"] }, De = { label: "Plasma", tags: ["sequential", "perceptual"], colors: ["#0d0887", "#5e01a6", "#9c179e", "#cc4778", "#ed7953", "#fdb42f", "#f0f921"] }, Pe = { label: "Cyclic", tags: ["cyclic", "direction"], colors: ["#2e22ea", "#b541fb", "#fc93c0", "#f1ee35", "#77c80d", "#458776", "#2c24e9"] }, Ge = { label: "Tempo", tags: ["sequential"], colors: ["#fff6f4", "#c2d1b9", "#7db390", "#2a937f", "#156d73", "#1c455b", "#151d44"] }, Ne = { label: "Turbid", tags: ["sequential", "biology", "log"], colors: ["#e9f5a0", "#c8c86e", "#a09845", "#786031", "#533324", "#341423", "#150d17"] }, Ie = { label: "Speed", tags: ["sequential", "velocity"], colors: ["#fcfea4", "#d5e429", "#94c63e", "#52a657", "#2d8169", "#1d5b6d", "#0d3361"] }, Le = { label: "Amp", tags: ["sequential"], colors: ["#f2f2f2", "#c0b8db", "#9180b6", "#6c4e9e", "#4e2e83", "#32185d", "#110a35"] }, Ce = { label: "Heat", tags: ["sequential"], colors: ["#fde725", "#fde725", "#f8961e", "#e63946", "#9d0208", "#3a0007"] }, Ve = { label: "Balance", tags: ["diverging"], colors: ["#181c43", "#3066af", "#9bbcdd", "#f2f2f2", "#e07d53", "#b13626", "#2c0b0e"] }, Oe = { label: "Delta", tags: ["diverging"], colors: ["#0e3f31", "#20877b", "#99d4c1", "#f2f2f2", "#a1b0d4", "#3c5b9e", "#0d1938"] }, Be = { label: "Curl", tags: ["diverging"], colors: ["#152237", "#2471b3", "#8dbac4", "#f2f2f2", "#c79f84", "#a63827", "#270b17"] }, Xe = { label: "Gray", tags: ["sequential"], colors: ["#000000", "#252525", "#4d4d4d", "#7a7a7a", "#a8a8a8", "#d4d4d4", "#ffffff"] }, ue = {
|
|
3
|
-
thermal: ye,
|
|
4
|
-
"thermal-alt": { label: "Thermal Alt", tags: ["sequential", "temperature"], colors: ["#176b9c", "#79cbd1", "#f3e7b3", "#f39b3d", "#d43d2f", "#5b1028", "#09060f"] },
|
|
5
|
-
haline: _e,
|
|
6
|
-
solar: xe,
|
|
7
|
-
ice: Re,
|
|
8
|
-
deep: ve,
|
|
9
|
-
rdylbu: ke,
|
|
10
|
-
dense: Ae,
|
|
11
|
-
algae: Fe,
|
|
12
|
-
oxygen: Se,
|
|
13
|
-
matter: Ue,
|
|
14
|
-
viridis: Me,
|
|
15
|
-
plasma: De,
|
|
16
|
-
cyclic: Pe,
|
|
17
|
-
tempo: Ge,
|
|
18
|
-
turbid: Ne,
|
|
19
|
-
speed: Ie,
|
|
20
|
-
amp: Le,
|
|
21
|
-
heat: Ce,
|
|
22
|
-
"heat-alert": { label: "Heat Alert", tags: ["sequential", "alpha", "deprecated"], colors: ["#fde72500", "#fde725cc", "#f8961e", "#e63946", "#9d0208", "#3a0007"] },
|
|
23
|
-
balance: Ve,
|
|
24
|
-
delta: Oe,
|
|
25
|
-
curl: Be,
|
|
26
|
-
"mono-black": { label: "Black", tags: ["monochrome", "particles"], colors: ["#000000", "#000000"] },
|
|
27
|
-
"mono-white": { label: "White", tags: ["monochrome", "particles"], colors: ["#ffffff", "#ffffff"] },
|
|
28
|
-
"mono-pink": { label: "Pink", tags: ["monochrome", "particles"], colors: ["#ff2aa1", "#ff2aa1"] },
|
|
29
|
-
gray: Xe
|
|
30
|
-
}, ne = 64, $e = {
|
|
31
|
-
linear: (t) => t,
|
|
32
|
-
// Rises fast: values just inside the zone already show.
|
|
33
|
-
log: (t) => Math.log10(1 + 9 * t),
|
|
34
|
-
// Stays faint longer: codec noise at the end of the range stays hidden.
|
|
35
|
-
exp: (t) => (10 ** t - 1) / 9
|
|
36
|
-
};
|
|
37
|
-
function qe(t, e) {
|
|
38
|
-
const i = $e[e.curve ?? "linear"], r = e.low ?? 0, n = e.high ?? 0;
|
|
39
|
-
let s = 1;
|
|
40
|
-
return r > 0 && t < r && (s = Math.min(s, i(Math.max(t, 0) / r))), n > 0 && t > 1 - n && (s = Math.min(s, i(Math.max(1 - t, 0) / n))), s;
|
|
41
|
-
}
|
|
42
|
-
function We(t) {
|
|
43
|
-
let e = t.replace("#", "");
|
|
44
|
-
(e.length === 3 || e.length === 4) && (e = [...e].map((r) => r + r).join(""));
|
|
45
|
-
const i = (r) => parseInt(e.slice(r, r + 2), 16);
|
|
46
|
-
return [
|
|
47
|
-
i(0),
|
|
48
|
-
i(2),
|
|
49
|
-
i(4),
|
|
50
|
-
e.length === 8 ? i(6) : 255
|
|
51
|
-
];
|
|
52
|
-
}
|
|
53
|
-
function He([t, e, i, r]) {
|
|
54
|
-
return `#${[t, e, i, r].map(
|
|
55
|
-
(n) => Math.round(Math.min(255, Math.max(0, n))).toString(16).padStart(2, "0")
|
|
56
|
-
).join("")}`;
|
|
57
|
-
}
|
|
58
|
-
function ze(t, e) {
|
|
59
|
-
if (e <= t[0][0])
|
|
60
|
-
return t[0][1];
|
|
61
|
-
for (let i = 1; i < t.length; i++) {
|
|
62
|
-
const [r, n] = t[i];
|
|
63
|
-
if (e <= r) {
|
|
64
|
-
const [s, o] = t[i - 1], a = r === s ? 1 : (e - s) / (r - s);
|
|
65
|
-
return o.map((c, l) => c + (n[l] - c) * a);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return t[t.length - 1][1];
|
|
69
|
-
}
|
|
70
|
-
function Ye(t, e) {
|
|
71
|
-
const i = Object.entries(t).map(
|
|
72
|
-
([n, s]) => [Number(n), We(s)]
|
|
73
|
-
).sort((n, s) => n[0] - s[0]), r = {};
|
|
74
|
-
for (let n = 0; n <= ne; n++) {
|
|
75
|
-
const s = n / ne, [o, a, c, l] = ze(i, s);
|
|
76
|
-
r[s] = He([o, a, c, l * qe(s, e)]);
|
|
77
|
-
}
|
|
78
|
-
return r;
|
|
79
|
-
}
|
|
80
|
-
const je = (t) => !!t && ((t.low ?? 0) > 0 || (t.high ?? 0) > 0);
|
|
81
|
-
function se(t) {
|
|
82
|
-
const e = {}, i = t.length - 1;
|
|
83
|
-
return t.forEach((r, n) => {
|
|
84
|
-
e[i === 0 ? 0 : n / i] = r;
|
|
85
|
-
}), e;
|
|
86
|
-
}
|
|
87
|
-
function Ke(t, e) {
|
|
88
|
-
const i = Qe(t, e?.reverse ?? !1);
|
|
89
|
-
return je(e?.alphaFade) ? Ye(i, e.alphaFade) : i;
|
|
90
|
-
}
|
|
91
|
-
function Qe(t, e) {
|
|
92
|
-
const i = ue;
|
|
93
|
-
if (typeof t == "string") {
|
|
94
|
-
const r = i[t];
|
|
95
|
-
if (!r)
|
|
96
|
-
throw new Error(
|
|
97
|
-
`Palette "${t}" not found. Available palettes: ${Object.keys(
|
|
98
|
-
i
|
|
99
|
-
).join(", ")}`
|
|
100
|
-
);
|
|
101
|
-
const n = e ? [...r.colors].reverse() : r.colors;
|
|
102
|
-
return se(n);
|
|
103
|
-
}
|
|
104
|
-
if (Array.isArray(t)) {
|
|
105
|
-
const r = e ? [...t].reverse() : t;
|
|
106
|
-
return se(r);
|
|
107
|
-
}
|
|
108
|
-
return e ? Object.fromEntries(
|
|
109
|
-
Object.entries(t).map(([r, n]) => [1 - Number(r), n])
|
|
110
|
-
) : t;
|
|
111
|
-
}
|
|
112
|
-
function Jt(t = {}) {
|
|
113
|
-
return Object.entries(ue).map(([i, r]) => ({ id: i, ...r })).filter(
|
|
114
|
-
(i) => t.includeDeprecated || !i.tags.includes("deprecated")
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
function ae(t, e, i) {
|
|
118
|
-
const r = t.createShader(e);
|
|
119
|
-
if (!r)
|
|
120
|
-
throw new Error("Failed to create shader");
|
|
121
|
-
if (t.shaderSource(r, i), t.compileShader(r), !t.getShaderParameter(r, t.COMPILE_STATUS)) {
|
|
122
|
-
const n = t.getShaderInfoLog(r);
|
|
123
|
-
throw t.deleteShader(r), new Error(`Shader compile error: ${n}`);
|
|
124
|
-
}
|
|
125
|
-
return r;
|
|
126
|
-
}
|
|
127
|
-
function ei(t, e, i) {
|
|
128
|
-
const r = t.createProgram();
|
|
129
|
-
if (!r)
|
|
130
|
-
throw new Error("Failed to create program");
|
|
131
|
-
const n = ae(t, t.VERTEX_SHADER, e), s = ae(t, t.FRAGMENT_SHADER, i);
|
|
132
|
-
if (t.attachShader(r, n), t.attachShader(r, s), t.linkProgram(r), !t.getProgramParameter(r, t.LINK_STATUS)) {
|
|
133
|
-
const o = t.getProgramInfoLog(r);
|
|
134
|
-
throw t.deleteProgram(r), new Error(`Program link error: ${o}`);
|
|
135
|
-
}
|
|
136
|
-
return t.deleteShader(n), t.deleteShader(s), r;
|
|
137
|
-
}
|
|
138
|
-
function ti(t, e, i, r, n) {
|
|
139
|
-
const s = t.createTexture();
|
|
140
|
-
if (!s)
|
|
141
|
-
throw new Error("Failed to create texture");
|
|
142
|
-
return t.bindTexture(t.TEXTURE_2D, s), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, e), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, e), t.texImage2D(
|
|
143
|
-
t.TEXTURE_2D,
|
|
144
|
-
0,
|
|
145
|
-
t.RGBA,
|
|
146
|
-
r,
|
|
147
|
-
n,
|
|
148
|
-
0,
|
|
149
|
-
t.RGBA,
|
|
150
|
-
t.UNSIGNED_BYTE,
|
|
151
|
-
i
|
|
152
|
-
), t.bindTexture(t.TEXTURE_2D, null), s;
|
|
153
|
-
}
|
|
154
|
-
function Ze(t, e, i) {
|
|
155
|
-
const r = t.getParameter(
|
|
156
|
-
t.TEXTURE_BINDING_2D
|
|
157
|
-
), n = t.getParameter(
|
|
158
|
-
t.FRAMEBUFFER_BINDING
|
|
159
|
-
), s = t.createTexture(), o = t.createFramebuffer();
|
|
160
|
-
if (!s || !o)
|
|
161
|
-
return s && t.deleteTexture(s), o && t.deleteFramebuffer(o), t.bindTexture(t.TEXTURE_2D, r), t.bindFramebuffer(t.FRAMEBUFFER, n), !1;
|
|
162
|
-
let a = !1;
|
|
163
|
-
try {
|
|
164
|
-
t.bindTexture(t.TEXTURE_2D, s), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.NEAREST), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.NEAREST), t.texImage2D(
|
|
165
|
-
t.TEXTURE_2D,
|
|
166
|
-
0,
|
|
167
|
-
e,
|
|
168
|
-
1,
|
|
169
|
-
1,
|
|
170
|
-
0,
|
|
171
|
-
t.RGBA,
|
|
172
|
-
i,
|
|
173
|
-
null
|
|
174
|
-
), t.bindFramebuffer(t.FRAMEBUFFER, o), t.framebufferTexture2D(
|
|
175
|
-
t.FRAMEBUFFER,
|
|
176
|
-
t.COLOR_ATTACHMENT0,
|
|
177
|
-
t.TEXTURE_2D,
|
|
178
|
-
s,
|
|
179
|
-
0
|
|
180
|
-
), a = t.checkFramebufferStatus(t.FRAMEBUFFER) === t.FRAMEBUFFER_COMPLETE;
|
|
181
|
-
} finally {
|
|
182
|
-
t.bindFramebuffer(t.FRAMEBUFFER, n), t.bindTexture(t.TEXTURE_2D, r), t.deleteFramebuffer(o), t.deleteTexture(s);
|
|
183
|
-
}
|
|
184
|
-
return a;
|
|
185
|
-
}
|
|
186
|
-
function Je(t) {
|
|
187
|
-
return {
|
|
188
|
-
kind: "rgba8-packed",
|
|
189
|
-
internalFormat: t.RGBA,
|
|
190
|
-
type: t.UNSIGNED_BYTE
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
function ii(t) {
|
|
194
|
-
if (typeof WebGL2RenderingContext > "u" || !(t instanceof WebGL2RenderingContext))
|
|
195
|
-
throw new Error("zartigl requires WebGL2");
|
|
196
|
-
return t;
|
|
197
|
-
}
|
|
198
|
-
function ri(t) {
|
|
199
|
-
const e = [];
|
|
200
|
-
t.getExtension("EXT_color_buffer_float") ? e.push(
|
|
201
|
-
{ kind: "float32", internalFormat: t.RGBA32F, type: t.FLOAT },
|
|
202
|
-
{ kind: "float16", internalFormat: t.RGBA16F, type: t.HALF_FLOAT }
|
|
203
|
-
) : t.getExtension("EXT_color_buffer_half_float") && e.push({
|
|
204
|
-
kind: "float16",
|
|
205
|
-
internalFormat: t.RGBA16F,
|
|
206
|
-
type: t.HALF_FLOAT
|
|
207
|
-
});
|
|
208
|
-
for (const i of e)
|
|
209
|
-
if (Ze(
|
|
210
|
-
t,
|
|
211
|
-
i.internalFormat,
|
|
212
|
-
i.type
|
|
213
|
-
))
|
|
214
|
-
return i;
|
|
215
|
-
return Je(t);
|
|
216
|
-
}
|
|
217
|
-
function ni(t, e, i, r, n, s, o) {
|
|
218
|
-
const a = t.createTexture();
|
|
219
|
-
if (!a)
|
|
220
|
-
throw new Error("Failed to create texture");
|
|
221
|
-
return t.bindTexture(t.TEXTURE_2D, a), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, e), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, e), t.texImage2D(
|
|
222
|
-
t.TEXTURE_2D,
|
|
223
|
-
0,
|
|
224
|
-
s,
|
|
225
|
-
r,
|
|
226
|
-
n,
|
|
227
|
-
0,
|
|
228
|
-
t.RGBA,
|
|
229
|
-
o,
|
|
230
|
-
i
|
|
231
|
-
), t.bindTexture(t.TEXTURE_2D, null), a;
|
|
232
|
-
}
|
|
233
|
-
function si(t, e, i) {
|
|
234
|
-
t.activeTexture(t.TEXTURE0 + i), t.bindTexture(t.TEXTURE_2D, e);
|
|
235
|
-
}
|
|
236
|
-
function ai(t, e) {
|
|
237
|
-
const i = t.createFramebuffer();
|
|
238
|
-
if (!i)
|
|
239
|
-
throw new Error("Failed to create framebuffer");
|
|
240
|
-
return t.bindFramebuffer(t.FRAMEBUFFER, i), t.framebufferTexture2D(
|
|
241
|
-
t.FRAMEBUFFER,
|
|
242
|
-
t.COLOR_ATTACHMENT0,
|
|
243
|
-
t.TEXTURE_2D,
|
|
244
|
-
e,
|
|
245
|
-
0
|
|
246
|
-
), t.bindFramebuffer(t.FRAMEBUFFER, null), i;
|
|
247
|
-
}
|
|
248
|
-
function oi(t) {
|
|
249
|
-
const e = t.createBuffer();
|
|
250
|
-
if (!e)
|
|
251
|
-
throw new Error("Failed to create buffer");
|
|
252
|
-
return t.bindBuffer(t.ARRAY_BUFFER, e), t.bufferData(
|
|
253
|
-
t.ARRAY_BUFFER,
|
|
254
|
-
new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
|
|
255
|
-
t.STATIC_DRAW
|
|
256
|
-
), e;
|
|
257
|
-
}
|
|
258
|
-
const et = {
|
|
259
|
-
0: "#3288bd",
|
|
260
|
-
0.1: "#66c2a5",
|
|
261
|
-
0.2: "#abdda4",
|
|
262
|
-
0.3: "#e6f598",
|
|
263
|
-
0.4: "#fee08b",
|
|
264
|
-
0.5: "#fdae61",
|
|
265
|
-
0.6: "#f46d43",
|
|
266
|
-
1: "#d53e4f"
|
|
267
|
-
};
|
|
268
|
-
function ci(t, e, i) {
|
|
269
|
-
const r = Ke(e ?? et, i), n = document.createElement("canvas");
|
|
270
|
-
n.width = 256, n.height = 1;
|
|
271
|
-
const s = n.getContext("2d"), o = s.createLinearGradient(0, 0, 256, 0);
|
|
272
|
-
for (const [c, l] of Object.entries(r))
|
|
273
|
-
o.addColorStop(Number(c), l);
|
|
274
|
-
s.fillStyle = o, s.fillRect(0, 0, 256, 1);
|
|
275
|
-
const a = t.createTexture();
|
|
276
|
-
if (!a)
|
|
277
|
-
throw new Error("Failed to create color ramp texture");
|
|
278
|
-
return t.bindTexture(t.TEXTURE_2D, a), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.LINEAR), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, n), t.bindTexture(t.TEXTURE_2D, null), a;
|
|
279
|
-
}
|
|
280
|
-
function li(t) {
|
|
281
|
-
const e = t.getExtension("WEBGL_debug_renderer_info");
|
|
282
|
-
return {
|
|
283
|
-
vendor: String(t.getParameter(t.VENDOR) ?? ""),
|
|
284
|
-
renderer: String(t.getParameter(t.RENDERER) ?? ""),
|
|
285
|
-
unmaskedVendor: e ? String(t.getParameter(e.UNMASKED_VENDOR_WEBGL) ?? "") : void 0,
|
|
286
|
-
unmaskedRenderer: e ? String(t.getParameter(e.UNMASKED_RENDERER_WEBGL) ?? "") : void 0,
|
|
287
|
-
version: String(t.getParameter(t.VERSION) ?? "")
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
function di(t) {
|
|
291
|
-
return {
|
|
292
|
-
program: t.getParameter(t.CURRENT_PROGRAM),
|
|
293
|
-
activeTexture: t.getParameter(t.ACTIVE_TEXTURE),
|
|
294
|
-
arrayBuffer: t.getParameter(t.ARRAY_BUFFER_BINDING),
|
|
295
|
-
elementBuffer: t.getParameter(t.ELEMENT_ARRAY_BUFFER_BINDING),
|
|
296
|
-
framebuffer: t.getParameter(t.FRAMEBUFFER_BINDING),
|
|
297
|
-
blend: t.isEnabled(t.BLEND),
|
|
298
|
-
depthTest: t.isEnabled(t.DEPTH_TEST),
|
|
299
|
-
stencilTest: t.isEnabled(t.STENCIL_TEST),
|
|
300
|
-
viewport: t.getParameter(t.VIEWPORT),
|
|
301
|
-
blendFunc: [
|
|
302
|
-
t.getParameter(t.BLEND_SRC_RGB),
|
|
303
|
-
t.getParameter(t.BLEND_DST_RGB)
|
|
304
|
-
]
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
function hi(t, e) {
|
|
308
|
-
t.useProgram(e.program), t.activeTexture(e.activeTexture), t.bindBuffer(t.ARRAY_BUFFER, e.arrayBuffer), t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, e.elementBuffer), t.bindFramebuffer(t.FRAMEBUFFER, e.framebuffer), e.blend ? t.enable(t.BLEND) : t.disable(t.BLEND), e.depthTest ? t.enable(t.DEPTH_TEST) : t.disable(t.DEPTH_TEST), e.stencilTest ? t.enable(t.STENCIL_TEST) : t.disable(t.STENCIL_TEST), t.viewport(e.viewport[0], e.viewport[1], e.viewport[2], e.viewport[3]), t.blendFunc(e.blendFunc[0], e.blendFunc[1]);
|
|
309
|
-
}
|
|
310
|
-
const fe = new Float32Array([
|
|
311
|
-
1,
|
|
312
|
-
0,
|
|
313
|
-
0,
|
|
314
|
-
0,
|
|
315
|
-
0,
|
|
316
|
-
1,
|
|
317
|
-
0,
|
|
318
|
-
0,
|
|
319
|
-
0,
|
|
320
|
-
0,
|
|
321
|
-
1,
|
|
322
|
-
0,
|
|
323
|
-
0,
|
|
324
|
-
0,
|
|
325
|
-
0,
|
|
326
|
-
1
|
|
327
|
-
]), ui = {
|
|
328
|
-
projectionTransition: 1,
|
|
329
|
-
fallbackMatrix: fe
|
|
330
|
-
};
|
|
331
|
-
function fi(t, e, i) {
|
|
332
|
-
t.uniform1f(
|
|
333
|
-
e.u_projection_transition,
|
|
334
|
-
i.projectionTransition ?? 1
|
|
335
|
-
), t.uniformMatrix4fv(
|
|
336
|
-
e.u_fallback_matrix,
|
|
337
|
-
!1,
|
|
338
|
-
i.fallbackMatrix ? i.fallbackMatrix instanceof Float32Array ? i.fallbackMatrix : new Float32Array(Array.from(i.fallbackMatrix)) : fe
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
const tt = {
|
|
342
|
-
degrees_c: "°C",
|
|
343
|
-
degc: "°C",
|
|
344
|
-
degrees_celsius: "°C",
|
|
345
|
-
degree_celsius: "°C",
|
|
346
|
-
celsius: "°C",
|
|
347
|
-
// Degree heating weeks accumulate °C over weeks: a product, not a rate.
|
|
348
|
-
degree_celsius_weeks: "°C-weeks",
|
|
349
|
-
degree: "°",
|
|
350
|
-
degrees: "°",
|
|
351
|
-
kelvin: "K",
|
|
352
|
-
1: "",
|
|
353
|
-
"1e-3": "PSU",
|
|
354
|
-
"0.001": "PSU",
|
|
355
|
-
psu: "PSU",
|
|
356
|
-
stress_level: ""
|
|
357
|
-
}, it = {
|
|
358
|
-
meter: "m",
|
|
359
|
-
meters: "m",
|
|
360
|
-
metre: "m",
|
|
361
|
-
metres: "m",
|
|
362
|
-
second: "s",
|
|
363
|
-
seconds: "s",
|
|
364
|
-
day: "d",
|
|
365
|
-
days: "d",
|
|
366
|
-
hour: "h",
|
|
367
|
-
hours: "h",
|
|
368
|
-
gram: "g",
|
|
369
|
-
grams: "g",
|
|
370
|
-
milligram: "mg",
|
|
371
|
-
milligrams: "mg",
|
|
372
|
-
kilogram: "kg",
|
|
373
|
-
kilograms: "kg",
|
|
374
|
-
mole: "mol",
|
|
375
|
-
millimole: "mmol",
|
|
376
|
-
watt: "W",
|
|
377
|
-
newton: "N",
|
|
378
|
-
pascal: "Pa",
|
|
379
|
-
kelvin: "K"
|
|
380
|
-
}, rt = "⁰¹²³⁴⁵⁶⁷⁸⁹";
|
|
381
|
-
function oe(t) {
|
|
382
|
-
return t === 1 ? "" : [...String(t)].map((e) => rt[Number(e)]).join("");
|
|
383
|
-
}
|
|
384
|
-
function mi(t) {
|
|
385
|
-
const e = t?.trim() ?? "", i = tt[e.toLowerCase()];
|
|
386
|
-
if (i != null)
|
|
387
|
-
return i;
|
|
388
|
-
if (e.includes("/"))
|
|
389
|
-
return e;
|
|
390
|
-
const r = [], n = [];
|
|
391
|
-
for (const s of e.split(/\s+/)) {
|
|
392
|
-
const o = /^([A-Za-z]+)\^?(-?\d+)?$/.exec(s);
|
|
393
|
-
if (!o)
|
|
394
|
-
return e.replace(/_/g, " ");
|
|
395
|
-
const a = it[o[1]] ?? o[1], c = Number(o[2] ?? 1);
|
|
396
|
-
c < 0 ? n.push(a + oe(-c)) : r.push(a + oe(c));
|
|
397
|
-
}
|
|
398
|
-
return [r.join(" ") || "1", ...n].join("/");
|
|
399
|
-
}
|
|
400
|
-
const ce = 20, nt = 600;
|
|
401
|
-
function st(t) {
|
|
402
|
-
const e = Math.max(0, Math.min(1, t));
|
|
403
|
-
return ce * Math.pow(nt / ce, e);
|
|
404
|
-
}
|
|
405
|
-
function pi(t) {
|
|
406
|
-
return Math.exp(-1 / st(t));
|
|
407
|
-
}
|
|
408
|
-
const at = 0.8, ot = 120, ct = 300;
|
|
409
|
-
class Ei {
|
|
410
|
-
constructor(e) {
|
|
411
|
-
this.base = e, this.moving = !1, this.start = 0, this.duration = 0, this.from = e, this.to = e;
|
|
412
|
-
}
|
|
413
|
-
/** Configured opacity, applied at once unless the camera moves. */
|
|
414
|
-
setBase(e) {
|
|
415
|
-
this.base = e, this.moving || (this.from = e, this.to = e, this.duration = 0);
|
|
416
|
-
}
|
|
417
|
-
setMoving(e, i) {
|
|
418
|
-
e !== this.moving && (this.from = this.value(i), this.moving = e, this.to = e ? at : this.base, this.start = i, this.duration = e ? ot : ct);
|
|
419
|
-
}
|
|
420
|
-
value(e) {
|
|
421
|
-
if (this.duration === 0)
|
|
422
|
-
return this.to;
|
|
423
|
-
const i = Math.min(1, Math.max(0, (e - this.start) / this.duration));
|
|
424
|
-
return i === 1 ? (this.duration = 0, this.from = this.to, this.to) : this.from + (this.to - this.from) * i * i * (3 - 2 * i);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
var lt = `vec3 velocityValue(vec4 texel, vec2 minimum, vec2 maximum, float physical) {
|
|
428
|
-
if (physical > 0.5) return texel.xyz;
|
|
429
|
-
return vec3(mix(minimum, maximum, texel.rg), texel.a);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
vec3 blendVelocity(vec3 a, vec3 b, float fraction) {
|
|
433
|
-
if (fraction <= 0.0) return a;
|
|
434
|
-
return mix(a, b, fraction);
|
|
435
|
-
}`, dt = `vec3 applyVibrance(vec3 c, float v) {
|
|
436
|
-
float mx = max(c.r, max(c.g, c.b));
|
|
437
|
-
float mn = min(c.r, min(c.g, c.b));
|
|
438
|
-
float boost = v * (1.0 - (mx - mn));
|
|
439
|
-
float luma = dot(c, vec3(0.299, 0.587, 0.114));
|
|
440
|
-
return mix(vec3(luma), c, 1.0 + boost);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
vec3 gradeColor(vec3 c, vec4 g) {
|
|
444
|
-
float m = max(c.r, max(c.g, c.b));
|
|
445
|
-
if (m > 0.0) {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
float e = g.x > 1e-3 ? (1.0 - exp(-g.x * m)) / (1.0 - exp(-g.x)) : m;
|
|
449
|
-
|
|
450
|
-
e += g.w * smoothstep(0.5, 1.0, e) * (1.0 - e);
|
|
451
|
-
c *= e / m;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
c = mix(c, c * c * (3.0 - 2.0 * c), g.y);
|
|
455
|
-
return clamp(applyVibrance(c, g.z), 0.0, 1.0);
|
|
456
|
-
}`, ht = `uniform vec2 u_code_range;
|
|
457
|
-
uniform vec2 u_value_range;
|
|
458
|
-
uniform float u_scalar_transfer;
|
|
459
|
-
|
|
460
|
-
float geoVideoScalarCode(float r) {
|
|
461
|
-
return clamp((r - u_code_range.x) / (u_code_range.y - u_code_range.x), 0.0, 1.0);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
float geoVideoScalarValue(float r) {
|
|
465
|
-
float code = geoVideoScalarCode(r);
|
|
466
|
-
float t = mix(code, (pow(10.0, code) - 1.0) / 9.0, u_scalar_transfer);
|
|
467
|
-
return mix(u_value_range.x, u_value_range.y, t);
|
|
468
|
-
}`, ut = `uint pcg(uint v) {
|
|
469
|
-
uint state = v * 747796405u + 2891336453u;
|
|
470
|
-
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
|
471
|
-
return (word >> 22u) ^ word;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
float random(uvec3 v) {
|
|
475
|
-
return float(pcg(v.x ^ pcg(v.y ^ pcg(v.z))) >> 8u) * (1.0 / 16777216.0);
|
|
476
|
-
}`, ft = `vec3 applyVibrance(vec3 c, float v) {
|
|
477
|
-
float mx = max(c.r, max(c.g, c.b));
|
|
478
|
-
float mn = min(c.r, min(c.g, c.b));
|
|
479
|
-
float boost = v * (1.0 - (mx - mn));
|
|
480
|
-
float luma = dot(c, vec3(0.299, 0.587, 0.114));
|
|
481
|
-
return mix(vec3(luma), c, 1.0 + boost);
|
|
482
|
-
}`, mt = `#define GLOW_SCALE 4
|
|
483
|
-
|
|
484
|
-
vec4 glowGather(sampler2D trails, ivec2 texel) {
|
|
485
|
-
ivec2 last = textureSize(trails, 0) - 1;
|
|
486
|
-
ivec2 origin = texel * GLOW_SCALE;
|
|
487
|
-
vec4 sum = vec4(0.0);
|
|
488
|
-
for (int y = 0; y < GLOW_SCALE; y++) {
|
|
489
|
-
for (int x = 0; x < GLOW_SCALE; x++) {
|
|
490
|
-
vec4 c = texelFetch(trails, min(origin + ivec2(x, y), last), 0);
|
|
491
|
-
sum += vec4(c.rgb * c.a, c.a);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
return sum / float(GLOW_SCALE * GLOW_SCALE);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
vec4 addGlow(vec4 trail, sampler2D glowTex, vec2 uv, float gain) {
|
|
498
|
-
vec2 d = 1.0 / vec2(textureSize(glowTex, 0));
|
|
499
|
-
vec4 glow = 0.25 * (
|
|
500
|
-
texture(glowTex, uv + vec2(-d.x, -d.y)) +
|
|
501
|
-
texture(glowTex, uv + vec2(d.x, -d.y)) +
|
|
502
|
-
texture(glowTex, uv + vec2(-d.x, d.y)) +
|
|
503
|
-
texture(glowTex, uv + vec2(d.x, d.y)));
|
|
504
|
-
glow = min(glow * gain, vec4(1.0));
|
|
505
|
-
float under = 1.0 - trail.a;
|
|
506
|
-
float alpha = trail.a + glow.a * under;
|
|
507
|
-
vec3 rgb = (trail.rgb * trail.a + glow.rgb * under) / max(alpha, 1e-4);
|
|
508
|
-
return vec4(rgb, alpha);
|
|
509
|
-
}`;
|
|
510
|
-
const gi = ft, Ti = dt, bi = ut, wi = ht, yi = lt, _i = mt, xi = 4, Ri = 1.2;
|
|
511
|
-
function vi(t) {
|
|
512
|
-
if (t == null)
|
|
513
|
-
return null;
|
|
514
|
-
if (!Number.isFinite(t[0]) || !Number.isFinite(t[1]) || t[0] >= t[1])
|
|
515
|
-
throw new RangeError(
|
|
516
|
-
"colorDomain must contain two finite, increasing values"
|
|
517
|
-
);
|
|
518
|
-
return [t[0], t[1]];
|
|
519
|
-
}
|
|
520
|
-
function R(t, e) {
|
|
521
|
-
if (typeof t != "number" || !Number.isFinite(t))
|
|
522
|
-
throw new Error(`Invalid GeoVideo manifest ${e}`);
|
|
523
|
-
return t;
|
|
524
|
-
}
|
|
525
|
-
function B(t, e) {
|
|
526
|
-
if (typeof t != "string")
|
|
527
|
-
throw new Error(`Invalid GeoVideo manifest ${e}`);
|
|
528
|
-
const i = new Date(t).getTime();
|
|
529
|
-
if (!Number.isFinite(i))
|
|
530
|
-
throw new Error(`Invalid GeoVideo manifest ${e}`);
|
|
531
|
-
return i;
|
|
532
|
-
}
|
|
533
|
-
function K(t) {
|
|
534
|
-
return typeof t == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(
|
|
535
|
-
t
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
function le(t) {
|
|
539
|
-
if (!t || typeof t != "object")
|
|
540
|
-
throw new Error("Invalid GeoVideo manifest");
|
|
541
|
-
const e = t;
|
|
542
|
-
if (e.schemaVersion !== 3 || e.type !== "geovideo")
|
|
543
|
-
throw new Error("Unsupported GeoVideo manifest version or type");
|
|
544
|
-
if (e.projection !== "equirectangular")
|
|
545
|
-
throw new Error(
|
|
546
|
-
`Unsupported GeoVideo projection: ${String(e.projection)}`
|
|
547
|
-
);
|
|
548
|
-
if (!Array.isArray(e.bounds) || e.bounds.length !== 4)
|
|
549
|
-
throw new Error("Invalid GeoVideo manifest bounds");
|
|
550
|
-
const [i, r, n, s] = e.bounds.map(
|
|
551
|
-
(m, E) => R(m, `bounds[${E}]`)
|
|
552
|
-
);
|
|
553
|
-
if (r < -90 || s > 90 || r >= s || i === n)
|
|
554
|
-
throw new Error("Invalid GeoVideo geographic bounds");
|
|
555
|
-
const o = e.media;
|
|
556
|
-
if (!o || typeof o.url != "string" || !o.url)
|
|
557
|
-
throw new Error("Invalid GeoVideo media");
|
|
558
|
-
for (const m of ["width", "height", "fps", "durationSeconds"])
|
|
559
|
-
if (R(o[m], `media.${m}`) <= 0)
|
|
560
|
-
throw new Error(`Invalid GeoVideo media.${m}`);
|
|
561
|
-
const a = e.encoding;
|
|
562
|
-
if (!a || a.bits !== 8 || a.colorSpace !== "bt709" || a.colorRange !== "limited" && a.colorRange !== "full")
|
|
563
|
-
throw new Error("Invalid GeoVideo encoding");
|
|
564
|
-
const c = R(a.codeMin, "encoding.codeMin"), l = R(a.codeMax, "encoding.codeMax");
|
|
565
|
-
if (c < 0 || l > 255 || c >= l)
|
|
566
|
-
throw new Error("Invalid GeoVideo code range");
|
|
567
|
-
let d = o.height;
|
|
568
|
-
if (a.kind === "scalar-luma") {
|
|
569
|
-
if (a.transfer !== "linear" && a.transfer !== "log10-1p9" || R(a.valueMin, "encoding.valueMin") >= R(a.valueMax, "encoding.valueMax"))
|
|
570
|
-
throw new Error("Invalid GeoVideo scalar-luma encoding");
|
|
571
|
-
} else if (a.kind === "vector-luma") {
|
|
572
|
-
if (a.transfer !== "linear" && a.transfer !== "sqrt" || a.layout !== "stacked-uv" || R(a.valueDomain, "encoding.valueDomain") <= 0 || o.height % 2 !== 0)
|
|
573
|
-
throw new Error("Invalid GeoVideo vector-luma encoding");
|
|
574
|
-
d = o.height / 2;
|
|
575
|
-
} else
|
|
576
|
-
throw new Error("Unsupported GeoVideo encoding");
|
|
577
|
-
const h = e.mask;
|
|
578
|
-
if (!h || h.kind !== "static-validity" || typeof h.url != "string" || !h.url || R(h.width, "mask.width") !== o.width || R(h.height, "mask.height") !== d || R(h.threshold, "mask.threshold") < 0 || h.threshold > 1)
|
|
579
|
-
throw new Error("Invalid GeoVideo static mask");
|
|
580
|
-
if (e.timeline?.kind === "range") {
|
|
581
|
-
const m = B(e.timeline.dateStart, "timeline.dateStart");
|
|
582
|
-
if (B(e.timeline.dateEnd, "timeline.dateEnd") <= m)
|
|
583
|
-
throw new Error("GeoVideo timeline end must follow start");
|
|
584
|
-
if (e.timeline.interpolation !== "linear" && e.timeline.interpolation !== "nearest")
|
|
585
|
-
throw new Error("Invalid GeoVideo interpolation");
|
|
586
|
-
} else if (e.timeline?.kind === "snapshot-loop")
|
|
587
|
-
B(e.timeline.date, "timeline.date");
|
|
588
|
-
else if (e.timeline?.kind === "sample-sequence") {
|
|
589
|
-
if (!Array.isArray(e.timeline.values) || e.timeline.values.length === 0)
|
|
590
|
-
throw new Error("GeoVideo sample sequence must contain values");
|
|
591
|
-
const m = e.timeline.values.map(
|
|
592
|
-
(E, w) => B(E, `timeline.values[${w}]`)
|
|
593
|
-
);
|
|
594
|
-
if (m.some((E, w) => w > 0 && E <= m[w - 1]))
|
|
595
|
-
throw new Error(
|
|
596
|
-
"GeoVideo sample sequence values must be strictly increasing"
|
|
597
|
-
);
|
|
598
|
-
} else
|
|
599
|
-
throw new Error("Invalid GeoVideo timeline");
|
|
600
|
-
const p = e.style?.colorDomain;
|
|
601
|
-
if (!Array.isArray(p) || p.length !== 2 || !p.every(Number.isFinite) || p[0] >= p[1])
|
|
602
|
-
throw new Error("Invalid GeoVideo color domain");
|
|
603
|
-
if (!K(e.id) || !e.provenance || !K(e.provenance.catalogEntryId) || !K(e.provenance.inputSourceId) || !Array.isArray(e.provenance.variables) || e.provenance.variables.length === 0)
|
|
604
|
-
throw new Error("Invalid GeoVideo provenance");
|
|
605
|
-
return { ...e, bounds: [i, r, n, s] };
|
|
606
|
-
}
|
|
607
|
-
async function pt(t, e) {
|
|
608
|
-
if (typeof t != "string")
|
|
609
|
-
return le(t);
|
|
610
|
-
const i = await fetch(t, { signal: e });
|
|
611
|
-
if (!i.ok)
|
|
612
|
-
throw new Error(
|
|
613
|
-
`GeoVideo manifest request failed (${i.status}): ${t}`
|
|
614
|
-
);
|
|
615
|
-
const r = await i.json(), n = le(r), s = typeof document < "u" ? new URL(t, document.baseURI).href : t;
|
|
616
|
-
return {
|
|
617
|
-
...n,
|
|
618
|
-
media: { ...n.media, url: new URL(n.media.url, s).href },
|
|
619
|
-
mask: { ...n.mask, url: new URL(n.mask.url, s).href }
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
function M(t) {
|
|
623
|
-
if (t.timeline.kind === "snapshot-loop")
|
|
624
|
-
return [new Date(t.timeline.date).getTime()];
|
|
625
|
-
if (t.timeline.kind === "sample-sequence")
|
|
626
|
-
return t.timeline.values.map((n) => new Date(n).getTime());
|
|
627
|
-
const e = new Date(t.timeline.dateStart).getTime(), i = new Date(t.timeline.dateEnd).getTime(), r = Math.max(
|
|
628
|
-
2,
|
|
629
|
-
Math.round(t.media.durationSeconds * t.media.fps)
|
|
630
|
-
);
|
|
631
|
-
return Array.from(
|
|
632
|
-
{ length: r },
|
|
633
|
-
(n, s) => e + (i - e) * s / (r - 1)
|
|
634
|
-
);
|
|
635
|
-
}
|
|
636
|
-
function me(t) {
|
|
637
|
-
return t.timeline.kind === "sample-sequence" ? t.timeline.values.length / t.media.durationSeconds : t.media.fps;
|
|
638
|
-
}
|
|
639
|
-
function ki(t, e) {
|
|
640
|
-
return e / me(t);
|
|
641
|
-
}
|
|
642
|
-
function Et(t, e) {
|
|
643
|
-
if (t.timeline.kind === "snapshot-loop")
|
|
644
|
-
return 0;
|
|
645
|
-
if (t.timeline.kind === "sample-sequence") {
|
|
646
|
-
const s = M(t);
|
|
647
|
-
let o = 0;
|
|
648
|
-
for (let c = 1; c < s.length; c += 1)
|
|
649
|
-
Math.abs(s[c] - e) < Math.abs(s[o] - e) && (o = c);
|
|
650
|
-
const a = t.media.durationSeconds / s.length;
|
|
651
|
-
return o * a + Math.min(a / 2, 0.5 / t.media.fps);
|
|
652
|
-
}
|
|
653
|
-
const i = new Date(t.timeline.dateStart).getTime(), r = new Date(t.timeline.dateEnd).getTime();
|
|
654
|
-
return Math.max(0, Math.min(1, (e - i) / (r - i))) * pe(t);
|
|
655
|
-
}
|
|
656
|
-
function Ai(t, e) {
|
|
657
|
-
if (t.timeline.kind === "snapshot-loop")
|
|
658
|
-
return new Date(t.timeline.date).getTime();
|
|
659
|
-
if (t.timeline.kind === "sample-sequence") {
|
|
660
|
-
const o = M(t), a = t.media.durationSeconds / o.length, c = Math.floor((e + 0.25 / t.media.fps) / a);
|
|
661
|
-
return o[Math.max(0, Math.min(o.length - 1, c))];
|
|
662
|
-
}
|
|
663
|
-
const i = new Date(t.timeline.dateStart).getTime(), r = new Date(t.timeline.dateEnd).getTime(), n = pe(t), s = n > 0 ? Math.max(0, Math.min(1, e / n)) : 0;
|
|
664
|
-
return i + (r - i) * s;
|
|
665
|
-
}
|
|
666
|
-
function pe(t) {
|
|
667
|
-
return Math.max(0, t.media.durationSeconds - 1 / t.media.fps);
|
|
668
|
-
}
|
|
669
|
-
function gt(t, e) {
|
|
670
|
-
const i = new Uint8Array(t.length / 4);
|
|
671
|
-
for (let r = 0; r < i.length; r++) {
|
|
672
|
-
const n = t[r * 4];
|
|
673
|
-
i[r] = e === "limited" ? Math.round(n * 219 / 255 + 16) : n;
|
|
674
|
-
}
|
|
675
|
-
return i;
|
|
676
|
-
}
|
|
677
|
-
class Tt {
|
|
678
|
-
constructor() {
|
|
679
|
-
this.gl = null, this.texture = null, this.framebuffer = null;
|
|
680
|
-
}
|
|
681
|
-
read(e, i, r) {
|
|
682
|
-
const n = this.context();
|
|
683
|
-
n.bindTexture(n.TEXTURE_2D, this.texture), n.pixelStorei(n.UNPACK_FLIP_Y_WEBGL, !1), n.pixelStorei(n.UNPACK_PREMULTIPLY_ALPHA_WEBGL, !1), n.pixelStorei(n.UNPACK_COLORSPACE_CONVERSION_WEBGL, n.NONE), n.texParameteri(n.TEXTURE_2D, n.TEXTURE_MIN_FILTER, n.NEAREST), n.texParameteri(n.TEXTURE_2D, n.TEXTURE_MAG_FILTER, n.NEAREST), n.texParameteri(n.TEXTURE_2D, n.TEXTURE_WRAP_S, n.CLAMP_TO_EDGE), n.texParameteri(n.TEXTURE_2D, n.TEXTURE_WRAP_T, n.CLAMP_TO_EDGE), n.texImage2D(n.TEXTURE_2D, 0, n.RGBA, n.RGBA, n.UNSIGNED_BYTE, e), n.bindFramebuffer(n.FRAMEBUFFER, this.framebuffer), n.framebufferTexture2D(
|
|
684
|
-
n.FRAMEBUFFER,
|
|
685
|
-
n.COLOR_ATTACHMENT0,
|
|
686
|
-
n.TEXTURE_2D,
|
|
687
|
-
this.texture,
|
|
688
|
-
0
|
|
689
|
-
);
|
|
690
|
-
const s = new Uint8Array(i * r * 4);
|
|
691
|
-
return n.readPixels(0, 0, i, r, n.RGBA, n.UNSIGNED_BYTE, s), n.bindFramebuffer(n.FRAMEBUFFER, null), s;
|
|
692
|
-
}
|
|
693
|
-
release() {
|
|
694
|
-
this.gl?.getExtension("WEBGL_lose_context")?.loseContext(), this.gl = null, this.texture = null, this.framebuffer = null;
|
|
695
|
-
}
|
|
696
|
-
context() {
|
|
697
|
-
if (this.gl)
|
|
698
|
-
return this.gl;
|
|
699
|
-
const e = document.createElement("canvas"), i = {
|
|
700
|
-
premultipliedAlpha: !1,
|
|
701
|
-
antialias: !1
|
|
702
|
-
}, r = e.getContext("webgl2", i);
|
|
703
|
-
if (!r)
|
|
704
|
-
throw new Error("WebGL2 is required to decode GeoVideo frames");
|
|
705
|
-
return this.gl = r, this.texture = r.createTexture(), this.framebuffer = r.createFramebuffer(), r;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
function de(t) {
|
|
709
|
-
const e = Math.max(4, Math.floor(t.length / 4 / 997) * 4);
|
|
710
|
-
for (let i = 3; i < t.length; i += e)
|
|
711
|
-
if (t[i] !== 0)
|
|
712
|
-
return !1;
|
|
713
|
-
return !0;
|
|
714
|
-
}
|
|
715
|
-
function g() {
|
|
716
|
-
return new DOMException("GeoVideo frame request was cancelled", "AbortError");
|
|
717
|
-
}
|
|
718
|
-
function G(t, e, i) {
|
|
719
|
-
return e ? e.aborted ? (t.catch(() => {
|
|
720
|
-
}), i?.(), Promise.reject(g())) : new Promise((r, n) => {
|
|
721
|
-
const s = () => {
|
|
722
|
-
i?.(), n(g());
|
|
723
|
-
};
|
|
724
|
-
e.addEventListener("abort", s, { once: !0 }), t.then(r, n).finally(() => {
|
|
725
|
-
e.removeEventListener("abort", s);
|
|
726
|
-
});
|
|
727
|
-
}) : t;
|
|
728
|
-
}
|
|
729
|
-
function Q(t, e) {
|
|
730
|
-
return new Promise(
|
|
731
|
-
(i) => t.addEventListener(e, () => i(), { once: !0 })
|
|
732
|
-
);
|
|
733
|
-
}
|
|
734
|
-
const bt = 250;
|
|
735
|
-
function wt(t) {
|
|
736
|
-
return "requestVideoFrameCallback" in t ? Promise.race([
|
|
737
|
-
new Promise(
|
|
738
|
-
(e) => t.requestVideoFrameCallback(() => e())
|
|
739
|
-
),
|
|
740
|
-
new Promise((e) => setTimeout(e, bt))
|
|
741
|
-
]) : Promise.resolve();
|
|
742
|
-
}
|
|
743
|
-
class Ee {
|
|
744
|
-
constructor(e, i, r = {}) {
|
|
745
|
-
this.reader = new Tt(), this.video = null, this.maskCodes = null, this.initPromise = null, this.presented = !1, this.primed = !1, this.queue = Promise.resolve(), this.frames = /* @__PURE__ */ new Map(), this.pending = /* @__PURE__ */ new Set(), this.manifest = e, this.planes = i, this.cacheSize = Math.max(1, r.cacheSize ?? 3), this.width = e.media.width, this.height = e.media.height / i, this.times = Float64Array.from(M(e));
|
|
746
|
-
}
|
|
747
|
-
/** Static validity, one 8-bit value per grid cell; null before init(). */
|
|
748
|
-
get mask() {
|
|
749
|
-
return this.maskCodes;
|
|
750
|
-
}
|
|
751
|
-
/** Luma codes of the presented frame, or null when it is blank. */
|
|
752
|
-
readCodes(e, i) {
|
|
753
|
-
const r = this.reader.read(e, this.width, i);
|
|
754
|
-
return de(r) ? null : gt(r, this.manifest.encoding.colorRange);
|
|
755
|
-
}
|
|
756
|
-
/** True when the decoder exposed no pixels; reads back one row only. */
|
|
757
|
-
isBlank(e) {
|
|
758
|
-
return de(this.reader.read(e, this.width, 1));
|
|
759
|
-
}
|
|
760
|
-
init() {
|
|
761
|
-
return this.initPromise ??= this.load().catch((e) => {
|
|
762
|
-
throw this.initPromise = null, e;
|
|
763
|
-
}), this.initPromise;
|
|
764
|
-
}
|
|
765
|
-
/** Abort every pending frame decode; frames already decoded stay cached. */
|
|
766
|
-
cancelAll() {
|
|
767
|
-
for (const e of [...this.pending])
|
|
768
|
-
this.drop(e);
|
|
769
|
-
}
|
|
770
|
-
/** Release the video element and GL context; a later init() reloads them. */
|
|
771
|
-
release() {
|
|
772
|
-
this.cancelAll(), this.frames.clear(), this.video && (this.video.removeAttribute("src"), this.video.load()), this.video = null, this.maskCodes = null, this.presented = !1, this.primed = !1, this.initPromise = null, this.reader.release();
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* One decode per time step, cached and shared by concurrent requests.
|
|
776
|
-
* Aborting `request.signal` rejects this request with an AbortError; the
|
|
777
|
-
* decode goes on while another request waits for it.
|
|
778
|
-
*/
|
|
779
|
-
frame(e, i = {}) {
|
|
780
|
-
const { signal: r } = i;
|
|
781
|
-
if (r?.aborted)
|
|
782
|
-
return Promise.reject(g());
|
|
783
|
-
let n = this.frames.get(e);
|
|
784
|
-
if (n ? (this.frames.delete(e), this.frames.set(e, n)) : n = this.enqueue(e), n.settled)
|
|
785
|
-
return n.promise;
|
|
786
|
-
const s = n;
|
|
787
|
-
return s.waiters++, G(s.promise, r, () => this.leave(s));
|
|
788
|
-
}
|
|
789
|
-
enqueue(e) {
|
|
790
|
-
const i = new AbortController(), r = this.queue.then(
|
|
791
|
-
() => i.signal.aborted ? Promise.reject(g()) : this.decode(e, i.signal)
|
|
792
|
-
);
|
|
793
|
-
this.queue = r.catch(() => {
|
|
794
|
-
});
|
|
795
|
-
const n = {
|
|
796
|
-
index: e,
|
|
797
|
-
controller: i,
|
|
798
|
-
promise: G(r, i.signal),
|
|
799
|
-
waiters: 0,
|
|
800
|
-
settled: !1
|
|
801
|
-
};
|
|
802
|
-
for (this.pending.add(n), n.promise.then(
|
|
803
|
-
() => {
|
|
804
|
-
n.settled = !0, this.pending.delete(n);
|
|
805
|
-
},
|
|
806
|
-
() => {
|
|
807
|
-
n.settled = !0, this.pending.delete(n), this.frames.get(e) === n && this.frames.delete(e);
|
|
808
|
-
}
|
|
809
|
-
), this.frames.set(e, n); this.frames.size > this.cacheSize; )
|
|
810
|
-
this.frames.delete(this.frames.keys().next().value);
|
|
811
|
-
return n;
|
|
812
|
-
}
|
|
813
|
-
/** A request left; drop the decode when it was the last one waiting. */
|
|
814
|
-
leave(e) {
|
|
815
|
-
e.waiters--, e.waiters <= 0 && !e.settled && this.drop(e);
|
|
816
|
-
}
|
|
817
|
-
drop(e) {
|
|
818
|
-
e.controller.abort(), this.pending.delete(e), this.frames.get(e.index) === e && this.frames.delete(e.index);
|
|
819
|
-
}
|
|
820
|
-
async load() {
|
|
821
|
-
const [e] = await Promise.all([this.loadMask(), this.loadMedia()]);
|
|
822
|
-
this.maskCodes = e;
|
|
823
|
-
}
|
|
824
|
-
async loadMask() {
|
|
825
|
-
const { url: e, width: i, height: r } = this.manifest.mask, n = new Image();
|
|
826
|
-
n.crossOrigin = "anonymous", n.src = e;
|
|
827
|
-
try {
|
|
828
|
-
await n.decode();
|
|
829
|
-
} catch {
|
|
830
|
-
throw new Error(`Failed to load GeoVideo mask: ${e}`);
|
|
831
|
-
}
|
|
832
|
-
if (n.naturalWidth !== i || n.naturalHeight !== r)
|
|
833
|
-
throw new Error(
|
|
834
|
-
`GeoVideo mask dimensions ${n.naturalWidth}x${n.naturalHeight} do not match manifest ${i}x${r}`
|
|
835
|
-
);
|
|
836
|
-
const s = this.reader.read(n, i, r), o = new Uint8Array(i * r);
|
|
837
|
-
for (let a = 0; a < o.length; a++)
|
|
838
|
-
o[a] = s[a * 4];
|
|
839
|
-
return o;
|
|
840
|
-
}
|
|
841
|
-
/** Open the media; the default reads frames by seeking a video element. */
|
|
842
|
-
async loadMedia() {
|
|
843
|
-
const e = document.createElement("video");
|
|
844
|
-
if (e.crossOrigin = "anonymous", e.muted = !0, e.playsInline = !0, e.preload = "metadata", e.src = this.manifest.media.url, this.video = e, await new Promise((i, r) => {
|
|
845
|
-
e.addEventListener("loadedmetadata", () => i(), {
|
|
846
|
-
once: !0
|
|
847
|
-
}), e.addEventListener(
|
|
848
|
-
"error",
|
|
849
|
-
() => r(
|
|
850
|
-
new Error(
|
|
851
|
-
`Failed to load GeoVideo media: ${this.manifest.media.url}`
|
|
852
|
-
)
|
|
853
|
-
),
|
|
854
|
-
{ once: !0 }
|
|
855
|
-
);
|
|
856
|
-
}), e.videoWidth !== this.manifest.media.width || e.videoHeight !== this.manifest.media.height)
|
|
857
|
-
throw new Error(
|
|
858
|
-
`GeoVideo media dimensions ${e.videoWidth}x${e.videoHeight} do not match manifest ${this.manifest.media.width}x${this.manifest.media.height}`
|
|
859
|
-
);
|
|
860
|
-
}
|
|
861
|
-
/** Seek to a frame and wait until it is presented. */
|
|
862
|
-
async presentFrame(e, i) {
|
|
863
|
-
if (this.presented && Math.abs(e.currentTime - i) <= 1e-3 && !e.seeking)
|
|
864
|
-
return;
|
|
865
|
-
const r = wt(e), n = Q(e, "seeked");
|
|
866
|
-
e.currentTime = i, await n, e.readyState < HTMLMediaElement.HAVE_CURRENT_DATA && await Promise.race([Q(e, "loadeddata"), Q(e, "canplay")]), await r, this.presented = !0;
|
|
867
|
-
}
|
|
868
|
-
/**
|
|
869
|
-
* Some mobile browsers expose no decoded pixels to WebGL until playback
|
|
870
|
-
* started once. A muted play/pause primes the decoder, only when needed:
|
|
871
|
-
* playback would otherwise buffer far beyond the requested frame.
|
|
872
|
-
*/
|
|
873
|
-
async primeDecoder(e) {
|
|
874
|
-
this.primed = !0;
|
|
875
|
-
try {
|
|
876
|
-
await e.play();
|
|
877
|
-
} catch {
|
|
878
|
-
}
|
|
879
|
-
e.pause(), this.presented = !1;
|
|
880
|
-
}
|
|
881
|
-
/** Media time inside the video frame showing step `index`. */
|
|
882
|
-
stepSeconds(e) {
|
|
883
|
-
return this.manifest.timeline.kind === "snapshot-loop" ? e / this.manifest.media.fps : Et(this.manifest, this.times[e]);
|
|
884
|
-
}
|
|
885
|
-
/**
|
|
886
|
-
* Seek and capture one step. `signal` aborts it between steps; a seek
|
|
887
|
-
* already started completes first, keeping the queue serial.
|
|
888
|
-
*/
|
|
889
|
-
async decode(e, i) {
|
|
890
|
-
if (i.aborted)
|
|
891
|
-
throw g();
|
|
892
|
-
await this.init();
|
|
893
|
-
const r = this.video, n = this.maskCodes;
|
|
894
|
-
if (i.aborted || !r || !n)
|
|
895
|
-
throw g();
|
|
896
|
-
const s = this.stepSeconds(e);
|
|
897
|
-
if (await this.presentFrame(r, s), i.aborted || r !== this.video)
|
|
898
|
-
throw g();
|
|
899
|
-
const o = this.height * this.planes;
|
|
900
|
-
let a = await this.capture(r, o, n);
|
|
901
|
-
if (a === null && !this.primed) {
|
|
902
|
-
if (await this.primeDecoder(r), await this.presentFrame(r, s), i.aborted || r !== this.video)
|
|
903
|
-
throw g();
|
|
904
|
-
a = await this.capture(r, o, n);
|
|
905
|
-
}
|
|
906
|
-
if (a === null)
|
|
907
|
-
throw new Error("GeoVideo frame could not be read back from the decoder");
|
|
908
|
-
return a;
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
function yt(t) {
|
|
912
|
-
return {
|
|
913
|
-
codeRange: [t.codeMin / 255, t.codeMax / 255],
|
|
914
|
-
valueRange: [t.valueMin, t.valueMax],
|
|
915
|
-
transfer: t.transfer === "log10-1p9" ? 1 : 0
|
|
916
|
-
};
|
|
917
|
-
}
|
|
918
|
-
class _t extends Ee {
|
|
919
|
-
constructor(e, i = {}) {
|
|
920
|
-
if (e.encoding.kind !== "scalar-luma")
|
|
921
|
-
throw new Error("GeoVideoScalarSource requires a scalar-luma manifest");
|
|
922
|
-
super(e, 1, i);
|
|
923
|
-
}
|
|
924
|
-
async capture(e) {
|
|
925
|
-
return this.isBlank(e) ? null : createImageBitmap(e, {
|
|
926
|
-
premultiplyAlpha: "none",
|
|
927
|
-
colorSpaceConversion: "none"
|
|
928
|
-
});
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
function v(t, e) {
|
|
932
|
-
if (e <= t[0])
|
|
933
|
-
return { index: 0, fraction: 0 };
|
|
934
|
-
const i = t.length - 1;
|
|
935
|
-
if (e >= t[i])
|
|
936
|
-
return { index: i, fraction: 0 };
|
|
937
|
-
let r = 0, n = i;
|
|
938
|
-
for (; n - r > 1; ) {
|
|
939
|
-
const s = r + n >> 1;
|
|
940
|
-
t[s] <= e ? r = s : n = s;
|
|
941
|
-
}
|
|
942
|
-
return { index: r, fraction: (e - t[r]) / (t[n] - t[r]) };
|
|
943
|
-
}
|
|
944
|
-
function Z(t, e) {
|
|
945
|
-
const { index: i, fraction: r } = v(t, e);
|
|
946
|
-
return i + r;
|
|
947
|
-
}
|
|
948
|
-
function xt(t, e) {
|
|
949
|
-
const i = Math.max(0, Math.min(t.length - 1, Math.floor(e))), r = Math.min(i + 1, t.length - 1);
|
|
950
|
-
return t[i] + (t[r] - t[i]) * Math.max(0, e - i);
|
|
951
|
-
}
|
|
952
|
-
function W(t, e, i) {
|
|
953
|
-
const r = [];
|
|
954
|
-
let n = e;
|
|
955
|
-
for (; n + 8 <= i; ) {
|
|
956
|
-
let s = t.getUint32(n);
|
|
957
|
-
const o = String.fromCharCode(
|
|
958
|
-
t.getUint8(n + 4),
|
|
959
|
-
t.getUint8(n + 5),
|
|
960
|
-
t.getUint8(n + 6),
|
|
961
|
-
t.getUint8(n + 7)
|
|
962
|
-
);
|
|
963
|
-
let a = 8;
|
|
964
|
-
if (s === 1 ? (s = Number(t.getBigUint64(n + 8)), a = 16) : s === 0 && (s = i - n), s < a || n + s > i)
|
|
965
|
-
throw new Error(`Malformed MP4 box ${o}`);
|
|
966
|
-
r.push({ type: o, start: n + a, end: n + s }), n += s;
|
|
967
|
-
}
|
|
968
|
-
return r;
|
|
969
|
-
}
|
|
970
|
-
function b(t, e, i) {
|
|
971
|
-
const r = W(t, e.start, e.end).find(
|
|
972
|
-
(n) => n.type === i
|
|
973
|
-
);
|
|
974
|
-
if (!r)
|
|
975
|
-
throw new Error(`MP4 box ${i} not found in ${e.type}`);
|
|
976
|
-
return r;
|
|
977
|
-
}
|
|
978
|
-
function V(t, e, i) {
|
|
979
|
-
return W(t, e.start, e.end).find((r) => r.type === i) ?? null;
|
|
980
|
-
}
|
|
981
|
-
function P(t, e) {
|
|
982
|
-
return { at: e.start + 8, count: t.getUint32(e.start + 4) };
|
|
983
|
-
}
|
|
984
|
-
function Rt(t, e, i) {
|
|
985
|
-
const r = V(t, e, "edts"), n = r && V(t, r, "elst");
|
|
986
|
-
if (!n)
|
|
987
|
-
return;
|
|
988
|
-
const { at: s, count: o } = P(t, n), a = t.getUint8(n.start) === 1 ? Number(t.getBigInt64(s + 8)) : t.getInt32(s + 4);
|
|
989
|
-
if (o !== 1 || a !== i)
|
|
990
|
-
throw new Error("Unsupported MP4 edit list");
|
|
991
|
-
}
|
|
992
|
-
function vt(t) {
|
|
993
|
-
const e = new DataView(t), i = { type: "file", start: 0, end: t.byteLength }, r = b(e, i, "moov"), n = W(e, r.start, r.end).find((f) => {
|
|
994
|
-
if (f.type !== "trak")
|
|
995
|
-
return !1;
|
|
996
|
-
const u = b(e, b(e, f, "mdia"), "hdlr");
|
|
997
|
-
return String.fromCharCode(...new Uint8Array(t, u.start + 8, 4)) === "vide";
|
|
998
|
-
});
|
|
999
|
-
if (!n)
|
|
1000
|
-
throw new Error("MP4 has no video track");
|
|
1001
|
-
const s = b(
|
|
1002
|
-
e,
|
|
1003
|
-
b(e, b(e, n, "mdia"), "minf"),
|
|
1004
|
-
"stbl"
|
|
1005
|
-
), o = b(e, s, "stsd"), [a] = W(e, o.start + 8, o.end);
|
|
1006
|
-
if (!a || a.type !== "avc1" && a.type !== "avc3")
|
|
1007
|
-
throw new Error(`Unsupported MP4 sample entry ${a?.type}`);
|
|
1008
|
-
const c = e.getUint16(a.start + 24), l = e.getUint16(a.start + 26), d = b(e, { ...a, start: a.start + 78 }, "avcC"), h = new Uint8Array(t.slice(d.start, d.end)), p = (f) => h[f].toString(16).padStart(2, "0"), m = `avc1.${p(1)}${p(2)}${p(3)}`, E = b(e, s, "stsz"), w = e.getUint32(E.start + 4), y = e.getUint32(E.start + 8), A = Array.from(
|
|
1009
|
-
{ length: y },
|
|
1010
|
-
(f, u) => w || e.getUint32(E.start + 12 + u * 4)
|
|
1011
|
-
), N = V(e, s, "co64"), O = N ?? b(e, s, "stco"), U = P(e, O), T = Array.from(
|
|
1012
|
-
{ length: U.count },
|
|
1013
|
-
(f, u) => N ? Number(e.getBigUint64(U.at + u * 8)) : e.getUint32(U.at + u * 4)
|
|
1014
|
-
), _ = P(e, b(e, s, "stsc")), F = [];
|
|
1015
|
-
for (let f = 0; f < _.count; f++) {
|
|
1016
|
-
const u = _.at + f * 12, I = e.getUint32(u) - 1, x = e.getUint32(u + 4), j = f + 1 < _.count ? e.getUint32(u + 12) - 1 : T.length;
|
|
1017
|
-
for (let L = I; L < j; L++) {
|
|
1018
|
-
let C = T[L];
|
|
1019
|
-
for (let re = 0; re < x && F.length < y; re++)
|
|
1020
|
-
F.push(C), C += A[F.length - 1];
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
const S = P(e, b(e, s, "stts")), k = [];
|
|
1024
|
-
let D = 0;
|
|
1025
|
-
for (let f = 0; f < S.count; f++) {
|
|
1026
|
-
const u = e.getUint32(S.at + f * 8), I = e.getUint32(S.at + f * 8 + 4);
|
|
1027
|
-
for (let x = 0; x < u; x++)
|
|
1028
|
-
k.push(D), D += I;
|
|
1029
|
-
}
|
|
1030
|
-
const z = V(e, s, "ctts");
|
|
1031
|
-
if (z) {
|
|
1032
|
-
const f = e.getUint8(z.start) === 1, u = P(e, z);
|
|
1033
|
-
let I = 0;
|
|
1034
|
-
for (let x = 0; x < u.count; x++) {
|
|
1035
|
-
const j = e.getUint32(u.at + x * 8), L = f ? e.getInt32(u.at + x * 8 + 4) : e.getUint32(u.at + x * 8 + 4);
|
|
1036
|
-
for (let C = 0; C < j; C++)
|
|
1037
|
-
k[I++] += L;
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
Rt(e, n, Math.min(...k.slice(0, y)));
|
|
1041
|
-
const we = k.slice(0, y).map((f, u) => [f, u]).sort((f, u) => f[0] - u[0]), te = new Array(y);
|
|
1042
|
-
we.forEach(([, f], u) => te[f] = u);
|
|
1043
|
-
const Y = V(e, s, "stss"), ie = /* @__PURE__ */ new Set();
|
|
1044
|
-
if (Y) {
|
|
1045
|
-
const f = P(e, Y);
|
|
1046
|
-
for (let u = 0; u < f.count; u++)
|
|
1047
|
-
ie.add(e.getUint32(f.at + u * 4) - 1);
|
|
1048
|
-
}
|
|
1049
|
-
if (F.length !== y || k.length < y)
|
|
1050
|
-
throw new Error("Inconsistent MP4 sample tables");
|
|
1051
|
-
return {
|
|
1052
|
-
codec: m,
|
|
1053
|
-
description: h,
|
|
1054
|
-
width: c,
|
|
1055
|
-
height: l,
|
|
1056
|
-
samples: A.map((f, u) => ({
|
|
1057
|
-
offset: F[u],
|
|
1058
|
-
size: f,
|
|
1059
|
-
frame: te[u],
|
|
1060
|
-
key: Y ? ie.has(u) : !0
|
|
1061
|
-
}))
|
|
1062
|
-
};
|
|
1063
|
-
}
|
|
1064
|
-
const kt = 50;
|
|
1065
|
-
class At extends _t {
|
|
1066
|
-
constructor() {
|
|
1067
|
-
super(...arguments), this.track = null, this.data = null, this.sampleOfFrame = [], this.decoder = null, this.fed = -1, this.taken = -1, this.outputs = /* @__PURE__ */ new Map(), this.progress = null, this.failure = null, this.loading = null;
|
|
1068
|
-
}
|
|
1069
|
-
/** True once the media decodes through WebCodecs. */
|
|
1070
|
-
get usesWebCodecs() {
|
|
1071
|
-
return this.track !== null;
|
|
1072
|
-
}
|
|
1073
|
-
async loadMedia() {
|
|
1074
|
-
if (typeof VideoDecoder > "u" || typeof fetch > "u")
|
|
1075
|
-
return super.loadMedia();
|
|
1076
|
-
const e = new AbortController();
|
|
1077
|
-
this.loading = e;
|
|
1078
|
-
const i = await fetch(this.manifest.media.url, {
|
|
1079
|
-
signal: e.signal
|
|
1080
|
-
});
|
|
1081
|
-
if (!i.ok)
|
|
1082
|
-
throw new Error(
|
|
1083
|
-
`Failed to load GeoVideo media: ${this.manifest.media.url}`
|
|
1084
|
-
);
|
|
1085
|
-
const r = await i.arrayBuffer();
|
|
1086
|
-
let n;
|
|
1087
|
-
try {
|
|
1088
|
-
n = vt(r);
|
|
1089
|
-
} catch {
|
|
1090
|
-
return this.loading === e ? super.loadMedia() : void 0;
|
|
1091
|
-
}
|
|
1092
|
-
if (n.width !== this.manifest.media.width || n.height !== this.manifest.media.height)
|
|
1093
|
-
throw new Error(
|
|
1094
|
-
`GeoVideo media dimensions ${n.width}x${n.height} do not match manifest ${this.manifest.media.width}x${this.manifest.media.height}`
|
|
1095
|
-
);
|
|
1096
|
-
const { supported: s } = await VideoDecoder.isConfigSupported(
|
|
1097
|
-
this.config(n)
|
|
1098
|
-
).catch(() => ({ supported: !1 }));
|
|
1099
|
-
if (this.loading !== e)
|
|
1100
|
-
throw g();
|
|
1101
|
-
if (this.loading = null, !s)
|
|
1102
|
-
return super.loadMedia();
|
|
1103
|
-
this.sampleOfFrame = [], n.samples.forEach(
|
|
1104
|
-
(o, a) => this.sampleOfFrame[o.frame] = a
|
|
1105
|
-
), this.data = r, this.track = n;
|
|
1106
|
-
}
|
|
1107
|
-
release() {
|
|
1108
|
-
this.loading?.abort(), this.loading = null, this.closeDecoder(), this.track = null, this.data = null, super.release();
|
|
1109
|
-
}
|
|
1110
|
-
async decode(e, i) {
|
|
1111
|
-
if (await this.init(), !this.track)
|
|
1112
|
-
return super.decode(e, i);
|
|
1113
|
-
if (i.aborted)
|
|
1114
|
-
throw g();
|
|
1115
|
-
const r = Math.min(
|
|
1116
|
-
this.track.samples.length - 1,
|
|
1117
|
-
Math.floor(this.stepSeconds(e) * this.manifest.media.fps + 1e-6)
|
|
1118
|
-
), n = await this.decodeFrame(r, i);
|
|
1119
|
-
try {
|
|
1120
|
-
return await createImageBitmap(n, {
|
|
1121
|
-
premultiplyAlpha: "none",
|
|
1122
|
-
colorSpaceConversion: "none"
|
|
1123
|
-
});
|
|
1124
|
-
} finally {
|
|
1125
|
-
n.close();
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
config(e) {
|
|
1129
|
-
return {
|
|
1130
|
-
codec: e.codec,
|
|
1131
|
-
description: e.description,
|
|
1132
|
-
codedWidth: e.width,
|
|
1133
|
-
codedHeight: e.height,
|
|
1134
|
-
optimizeForLatency: !0
|
|
1135
|
-
};
|
|
1136
|
-
}
|
|
1137
|
-
/** Video frame `frame`, owned by the caller. */
|
|
1138
|
-
async decodeFrame(e, i) {
|
|
1139
|
-
const r = this.track, n = this.sampleOfFrame[e], s = this.keySample(n);
|
|
1140
|
-
for ((this.fed < 0 || e <= this.taken || s > this.fed) && this.restart(s), this.taken = e - 1, this.dropOutputsBefore(e); !this.outputs.has(e); ) {
|
|
1141
|
-
if (this.failure)
|
|
1142
|
-
throw this.failure;
|
|
1143
|
-
if (i.aborted)
|
|
1144
|
-
throw g();
|
|
1145
|
-
const a = this.decoder;
|
|
1146
|
-
this.fed < r.samples.length && a.decodeQueueSize < 2 && (this.feed(this.fed++), this.fed === r.samples.length && a.flush().catch(() => {
|
|
1147
|
-
})), await this.waitProgress();
|
|
1148
|
-
}
|
|
1149
|
-
const o = this.outputs.get(e);
|
|
1150
|
-
return this.outputs.delete(e), this.taken = e, o;
|
|
1151
|
-
}
|
|
1152
|
-
dropOutputsBefore(e) {
|
|
1153
|
-
for (const [i, r] of this.outputs)
|
|
1154
|
-
i < e && (r.close(), this.outputs.delete(i));
|
|
1155
|
-
}
|
|
1156
|
-
keySample(e) {
|
|
1157
|
-
const { samples: i } = this.track;
|
|
1158
|
-
let r = e;
|
|
1159
|
-
for (; r > 0 && !i[r].key; )
|
|
1160
|
-
r--;
|
|
1161
|
-
return r;
|
|
1162
|
-
}
|
|
1163
|
-
restart(e) {
|
|
1164
|
-
this.closeDecoder(), this.failure = null;
|
|
1165
|
-
const i = new VideoDecoder({
|
|
1166
|
-
output: (r) => {
|
|
1167
|
-
this.decoder !== i || r.timestamp <= this.taken ? r.close() : this.outputs.set(r.timestamp, r), this.notify();
|
|
1168
|
-
},
|
|
1169
|
-
error: (r) => {
|
|
1170
|
-
this.decoder === i && (this.failure = r, this.fed = -1), this.notify();
|
|
1171
|
-
}
|
|
1172
|
-
});
|
|
1173
|
-
i.addEventListener("dequeue", () => this.notify()), i.configure(this.config(this.track)), this.decoder = i, this.fed = e, this.taken = this.track.samples[e].frame - 1;
|
|
1174
|
-
}
|
|
1175
|
-
feed(e) {
|
|
1176
|
-
const i = this.track.samples[e];
|
|
1177
|
-
this.decoder.decode(
|
|
1178
|
-
new EncodedVideoChunk({
|
|
1179
|
-
type: i.key ? "key" : "delta",
|
|
1180
|
-
// Video frame numbers: outputs carry them back in display order.
|
|
1181
|
-
timestamp: i.frame,
|
|
1182
|
-
data: new Uint8Array(this.data, i.offset, i.size)
|
|
1183
|
-
})
|
|
1184
|
-
);
|
|
1185
|
-
}
|
|
1186
|
-
/** Next output, dequeue or error; a timer for decoders without events. */
|
|
1187
|
-
waitProgress() {
|
|
1188
|
-
return new Promise((e) => {
|
|
1189
|
-
const i = setTimeout(r, kt);
|
|
1190
|
-
function r() {
|
|
1191
|
-
clearTimeout(i), e();
|
|
1192
|
-
}
|
|
1193
|
-
this.progress = r;
|
|
1194
|
-
});
|
|
1195
|
-
}
|
|
1196
|
-
notify() {
|
|
1197
|
-
const e = this.progress;
|
|
1198
|
-
this.progress = null, e?.();
|
|
1199
|
-
}
|
|
1200
|
-
closeDecoder() {
|
|
1201
|
-
this.decoder && this.decoder.state !== "closed" && this.decoder.close(), this.decoder = null, this.fed = -1;
|
|
1202
|
-
for (const e of this.outputs.values())
|
|
1203
|
-
e.close();
|
|
1204
|
-
this.outputs.clear();
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
function Ft(t, e) {
|
|
1208
|
-
let i = (t - e.codeMin) / (e.codeMax - e.codeMin) * 2 - 1;
|
|
1209
|
-
return i = Math.max(-1, Math.min(1, i)), e.transfer === "sqrt" && (i = Math.sign(i) * i * i), i * e.valueDomain;
|
|
1210
|
-
}
|
|
1211
|
-
function St(t, e, i, r) {
|
|
1212
|
-
const n = e.length;
|
|
1213
|
-
if (t.length !== 2 * n)
|
|
1214
|
-
throw new Error(
|
|
1215
|
-
`GeoVideo vector frame has ${t.length} codes, expected ${2 * n}`
|
|
1216
|
-
);
|
|
1217
|
-
const s = new Float32Array(256);
|
|
1218
|
-
for (let l = 0; l < 256; l++)
|
|
1219
|
-
s[l] = Ft(l, r);
|
|
1220
|
-
const o = i * 255, a = new Float32Array(n), c = new Float32Array(n);
|
|
1221
|
-
for (let l = 0; l < n; l++) {
|
|
1222
|
-
const d = e[l] >= o;
|
|
1223
|
-
a[l] = d ? s[t[l]] : NaN, c[l] = d ? s[t[n + l]] : NaN;
|
|
1224
|
-
}
|
|
1225
|
-
return { u: a, v: c };
|
|
1226
|
-
}
|
|
1227
|
-
class Ut extends Ee {
|
|
1228
|
-
constructor(e, i = {}) {
|
|
1229
|
-
if (e.encoding.kind !== "vector-luma")
|
|
1230
|
-
throw new Error("GeoVideoVectorSource requires a vector-luma manifest");
|
|
1231
|
-
super(e, 2, i), this.encoding = e.encoding;
|
|
1232
|
-
const [r, n, s, o] = e.bounds, a = (s - r) / this.width, c = (o - n) / this.height;
|
|
1233
|
-
this.coords = {
|
|
1234
|
-
time: this.times,
|
|
1235
|
-
vertical: new Float32Array([0]),
|
|
1236
|
-
latitude: Float32Array.from(
|
|
1237
|
-
{ length: this.height },
|
|
1238
|
-
(l, d) => o - (d + 0.5) * c
|
|
1239
|
-
),
|
|
1240
|
-
longitude: Float32Array.from(
|
|
1241
|
-
{ length: this.width },
|
|
1242
|
-
(l, d) => r + (d + 0.5) * a
|
|
1243
|
-
)
|
|
1244
|
-
};
|
|
1245
|
-
}
|
|
1246
|
-
getValueDomain() {
|
|
1247
|
-
return this.encoding.valueDomain;
|
|
1248
|
-
}
|
|
1249
|
-
getCoords() {
|
|
1250
|
-
return this.coords;
|
|
1251
|
-
}
|
|
1252
|
-
getDimensions() {
|
|
1253
|
-
return ["time", "latitude", "longitude"];
|
|
1254
|
-
}
|
|
1255
|
-
getChunkShape() {
|
|
1256
|
-
return [1, this.height, this.width];
|
|
1257
|
-
}
|
|
1258
|
-
findDepthIndex() {
|
|
1259
|
-
return 0;
|
|
1260
|
-
}
|
|
1261
|
-
findTimeIndex(e) {
|
|
1262
|
-
const i = typeof e == "number" ? e : new Date(e).getTime(), r = this.coords.time;
|
|
1263
|
-
let n = 0;
|
|
1264
|
-
for (let s = 1; s < r.length; s++)
|
|
1265
|
-
Math.abs(r[s] - i) < Math.abs(r[n] - i) && (n = s);
|
|
1266
|
-
return n;
|
|
1267
|
-
}
|
|
1268
|
-
getChunksForBounds(e, i, r) {
|
|
1269
|
-
const { latitude: n, longitude: s } = this.coords;
|
|
1270
|
-
return [
|
|
1271
|
-
{
|
|
1272
|
-
timeIdx: i,
|
|
1273
|
-
depthIdx: r,
|
|
1274
|
-
latIdx: 0,
|
|
1275
|
-
lonIdx: 0,
|
|
1276
|
-
latRange: [n[0], n[this.height - 1]],
|
|
1277
|
-
lonRange: [s[0], s[this.width - 1]],
|
|
1278
|
-
latSize: this.height,
|
|
1279
|
-
lonSize: this.width
|
|
1280
|
-
}
|
|
1281
|
-
];
|
|
1282
|
-
}
|
|
1283
|
-
async fetchSpatialChunkResult(e, i) {
|
|
1284
|
-
const r = await this.frame(i.timeIndex);
|
|
1285
|
-
return {
|
|
1286
|
-
data: e === "v" ? r.v : r.u,
|
|
1287
|
-
missing: !1,
|
|
1288
|
-
url: this.manifest.media.url
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
/** u/v codes are written into luma: read back, then decoded on the CPU. */
|
|
1292
|
-
async capture(e, i, r) {
|
|
1293
|
-
const n = this.readCodes(e, i);
|
|
1294
|
-
return n ? St(
|
|
1295
|
-
n,
|
|
1296
|
-
r,
|
|
1297
|
-
this.manifest.mask.threshold,
|
|
1298
|
-
this.encoding
|
|
1299
|
-
) : null;
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
function Mt(t, e, i = {}) {
|
|
1303
|
-
const [r, n] = i.range ?? [-1 / 0, 1 / 0], s = [...t].sort((a, c) => a.start - c.start), o = s.find(
|
|
1304
|
-
(a) => a.start > e && a.start <= n
|
|
1305
|
-
) ?? (i.loop ? s.find(
|
|
1306
|
-
(a) => a.end >= r && a.start <= n
|
|
1307
|
-
) : void 0);
|
|
1308
|
-
return o ? { chunk: o, time: Math.max(o.start, r) } : null;
|
|
1309
|
-
}
|
|
1310
|
-
function Dt(t, e) {
|
|
1311
|
-
let i = null, r = -1 / 0;
|
|
1312
|
-
for (const n of e) {
|
|
1313
|
-
const s = Math.min(t.end, n.end) - Math.max(t.start, n.start);
|
|
1314
|
-
Number.isFinite(s) && s >= 0 && s > r && (i = n, r = s);
|
|
1315
|
-
}
|
|
1316
|
-
return i;
|
|
1317
|
-
}
|
|
1318
|
-
function Pt(t) {
|
|
1319
|
-
return {
|
|
1320
|
-
width: t.mask.width,
|
|
1321
|
-
height: t.mask.height,
|
|
1322
|
-
bounds: t.bounds,
|
|
1323
|
-
rowOrder: "north-to-south"
|
|
1324
|
-
};
|
|
1325
|
-
}
|
|
1326
|
-
function ge(t, e = {}) {
|
|
1327
|
-
return t.encoding.kind === "vector-luma" ? new Ut(t, e) : new At(t, e);
|
|
1328
|
-
}
|
|
1329
|
-
const Gt = 3, Nt = 3, It = 0.6, Lt = 1.5;
|
|
1330
|
-
function Ct(t) {
|
|
1331
|
-
const e = new AbortController();
|
|
1332
|
-
if (!t)
|
|
1333
|
-
return { controller: e, unlink: () => {
|
|
1334
|
-
} };
|
|
1335
|
-
const i = () => e.abort();
|
|
1336
|
-
return t.aborted && i(), t.addEventListener("abort", i, { once: !0 }), {
|
|
1337
|
-
controller: e,
|
|
1338
|
-
unlink: () => t.removeEventListener("abort", i)
|
|
1339
|
-
};
|
|
1340
|
-
}
|
|
1341
|
-
class Fi {
|
|
1342
|
-
constructor(e) {
|
|
1343
|
-
this.manifests = /* @__PURE__ */ new Map(), this.open = /* @__PURE__ */ new Map(), this.id = e.id, this.chunks = e.chunks.filter(
|
|
1344
|
-
(i) => Number.isFinite(i.start) && Number.isFinite(i.end) && i.end >= i.start
|
|
1345
|
-
).sort((i, r) => i.start - r.start), this.maxOpenChunks = Math.max(2, e.maxOpenChunks ?? Gt), this.frameCacheSize = Math.max(
|
|
1346
|
-
1,
|
|
1347
|
-
e.frameCacheSize ?? Nt
|
|
1348
|
-
), this.prefetchAt = e.prefetchAt ?? It, this.maxGap = e.maxGap, this.loadManifest = e.loadManifest ?? pt, this.createFrameSource = e.createFrameSource ?? ((i, r) => ge(
|
|
1349
|
-
i,
|
|
1350
|
-
r
|
|
1351
|
-
));
|
|
1352
|
-
}
|
|
1353
|
-
/** First and last sample of the archive, or null without chunks. */
|
|
1354
|
-
get range() {
|
|
1355
|
-
const { chunks: e } = this;
|
|
1356
|
-
return e.length ? [e[0].start, Math.max(...e.map((i) => i.end))] : null;
|
|
1357
|
-
}
|
|
1358
|
-
/** The chunk whose sample range holds `time`, or null. */
|
|
1359
|
-
chunkAt(e) {
|
|
1360
|
-
const i = this.chunkIndexAt(e), r = i >= 0 ? this.chunks[i] : null;
|
|
1361
|
-
return r && e <= r.end ? r : null;
|
|
1362
|
-
}
|
|
1363
|
-
/** Every step time of the archive; loads all chunk manifests. */
|
|
1364
|
-
async steps(e = {}) {
|
|
1365
|
-
if (e.signal?.aborted)
|
|
1366
|
-
throw g();
|
|
1367
|
-
const i = await G(
|
|
1368
|
-
Promise.all(this.chunks.map((r) => this.manifest(r))),
|
|
1369
|
-
e.signal
|
|
1370
|
-
);
|
|
1371
|
-
return Float64Array.from(i.flatMap(M));
|
|
1372
|
-
}
|
|
1373
|
-
/**
|
|
1374
|
-
* The frames bracketing `time`, decoded; null out of coverage (before the
|
|
1375
|
-
* first step, after the last, or in a gap wider than `maxGap`).
|
|
1376
|
-
*/
|
|
1377
|
-
async sample(e, i = {}) {
|
|
1378
|
-
const { signal: r } = i, n = i.mode ?? "interpolate";
|
|
1379
|
-
if (r?.aborted)
|
|
1380
|
-
throw g();
|
|
1381
|
-
const s = this.chunkIndexAt(e);
|
|
1382
|
-
if (s < 0)
|
|
1383
|
-
return null;
|
|
1384
|
-
const o = [], { controller: a, unlink: c } = Ct(r);
|
|
1385
|
-
try {
|
|
1386
|
-
const l = this.acquire(this.chunks[s], o), d = await G(l.ready, a.signal), { times: h } = d;
|
|
1387
|
-
let p;
|
|
1388
|
-
if (e <= h[h.length - 1]) {
|
|
1389
|
-
const { index: T, fraction: _ } = v(h, e);
|
|
1390
|
-
p = n === "discrete" || _ === 0 ? [l, T, l, T, 0] : [l, T, l, T + 1, _];
|
|
1391
|
-
} else {
|
|
1392
|
-
const T = this.chunks[s + 1];
|
|
1393
|
-
if (!T)
|
|
1394
|
-
return null;
|
|
1395
|
-
const _ = this.acquire(T, o), F = await G(_.ready, a.signal), S = h.length - 1, k = h[S], D = F.times[0];
|
|
1396
|
-
if (D - k > this.gapLimit(h, F.times))
|
|
1397
|
-
return null;
|
|
1398
|
-
p = n === "discrete" ? [l, S, l, S, 0] : e >= D ? [_, 0, _, 0, 0] : [l, S, _, 0, (e - k) / (D - k)];
|
|
1399
|
-
}
|
|
1400
|
-
const [m, E, w, y, A] = p, N = m === w && E === y, O = [this.frame(m, E, a.signal)];
|
|
1401
|
-
N || O.push(this.frame(w, y, a.signal));
|
|
1402
|
-
let U;
|
|
1403
|
-
try {
|
|
1404
|
-
U = await Promise.all(O);
|
|
1405
|
-
} catch (T) {
|
|
1406
|
-
throw a.abort(), T;
|
|
1407
|
-
}
|
|
1408
|
-
return this.prefetchAfter(s, e), {
|
|
1409
|
-
time: e,
|
|
1410
|
-
a: U[0],
|
|
1411
|
-
b: U[N ? 0 : 1],
|
|
1412
|
-
mix: A
|
|
1413
|
-
};
|
|
1414
|
-
} finally {
|
|
1415
|
-
c();
|
|
1416
|
-
for (const l of o)
|
|
1417
|
-
l.users--;
|
|
1418
|
-
this.trim();
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
/** Open `chunk` and decode its first frame ahead of a request. */
|
|
1422
|
-
prefetch(e) {
|
|
1423
|
-
if (this.open.has(e.key))
|
|
1424
|
-
return;
|
|
1425
|
-
const i = this.touch(e), r = new AbortController();
|
|
1426
|
-
i.prefetch = r, i.ready.then(({ source: n }) => n.frame(0, { signal: r.signal })).catch(() => {
|
|
1427
|
-
}).finally(() => {
|
|
1428
|
-
i.prefetch === r && (i.prefetch = null);
|
|
1429
|
-
}), this.trim();
|
|
1430
|
-
}
|
|
1431
|
-
/** Release every open chunk source; later requests reopen them. */
|
|
1432
|
-
release() {
|
|
1433
|
-
for (const e of [...this.open.values()])
|
|
1434
|
-
this.close(e);
|
|
1435
|
-
}
|
|
1436
|
-
chunkIndexAt(e) {
|
|
1437
|
-
let i = 0, r = this.chunks.length - 1, n = -1;
|
|
1438
|
-
for (; i <= r; ) {
|
|
1439
|
-
const s = i + r >> 1;
|
|
1440
|
-
this.chunks[s].start <= e ? (n = s, i = s + 1) : r = s - 1;
|
|
1441
|
-
}
|
|
1442
|
-
return n;
|
|
1443
|
-
}
|
|
1444
|
-
gapLimit(e, i) {
|
|
1445
|
-
if (this.maxGap !== void 0)
|
|
1446
|
-
return this.maxGap;
|
|
1447
|
-
const r = [
|
|
1448
|
-
e.length > 1 ? e[e.length - 1] - e[e.length - 2] : 0,
|
|
1449
|
-
i.length > 1 ? i[1] - i[0] : 0
|
|
1450
|
-
], n = Math.max(...r);
|
|
1451
|
-
return n > 0 ? n * Lt : -1 / 0;
|
|
1452
|
-
}
|
|
1453
|
-
prefetchAfter(e, i) {
|
|
1454
|
-
const r = this.chunks[e], n = this.chunks[e + 1], s = r.end - r.start, o = s > 0 ? (i - r.start) / s : 1;
|
|
1455
|
-
n && o > this.prefetchAt && this.prefetch(n);
|
|
1456
|
-
}
|
|
1457
|
-
manifest(e) {
|
|
1458
|
-
let i = this.manifests.get(e.manifestUrl);
|
|
1459
|
-
return i || (i = this.loadManifest(e.manifestUrl), this.manifests.set(e.manifestUrl, i), i.catch(() => {
|
|
1460
|
-
this.manifests.get(e.manifestUrl) === i && this.manifests.delete(e.manifestUrl);
|
|
1461
|
-
})), i;
|
|
1462
|
-
}
|
|
1463
|
-
/** The open chunk, pinned for a running sample listed in `used`. */
|
|
1464
|
-
acquire(e, i) {
|
|
1465
|
-
const r = this.touch(e);
|
|
1466
|
-
return r.users++, i.push(r), r;
|
|
1467
|
-
}
|
|
1468
|
-
/** The open chunk, opened when needed, most recently used; not pinned. */
|
|
1469
|
-
touch(e) {
|
|
1470
|
-
let i = this.open.get(e.key);
|
|
1471
|
-
if (i)
|
|
1472
|
-
this.open.delete(e.key);
|
|
1473
|
-
else {
|
|
1474
|
-
const r = {
|
|
1475
|
-
chunk: e,
|
|
1476
|
-
ready: null,
|
|
1477
|
-
opened: null,
|
|
1478
|
-
users: 0,
|
|
1479
|
-
prefetch: null,
|
|
1480
|
-
released: !1
|
|
1481
|
-
};
|
|
1482
|
-
r.ready = this.manifest(e).then((n) => {
|
|
1483
|
-
if (r.released)
|
|
1484
|
-
throw g();
|
|
1485
|
-
return r.opened = {
|
|
1486
|
-
manifest: n,
|
|
1487
|
-
times: Float64Array.from(M(n)),
|
|
1488
|
-
grid: Pt(n),
|
|
1489
|
-
source: this.createFrameSource(n, {
|
|
1490
|
-
cacheSize: this.frameCacheSize
|
|
1491
|
-
})
|
|
1492
|
-
}, r.opened;
|
|
1493
|
-
}), r.ready.catch(() => {
|
|
1494
|
-
this.open.get(e.key) === r && this.open.delete(e.key);
|
|
1495
|
-
}), i = r;
|
|
1496
|
-
}
|
|
1497
|
-
return this.open.set(e.key, i), i;
|
|
1498
|
-
}
|
|
1499
|
-
async frame(e, i, r) {
|
|
1500
|
-
const { manifest: n, times: s, grid: o, source: a } = await G(
|
|
1501
|
-
e.ready,
|
|
1502
|
-
r
|
|
1503
|
-
);
|
|
1504
|
-
if (e.released)
|
|
1505
|
-
throw g();
|
|
1506
|
-
const c = await a.frame(i, { signal: r });
|
|
1507
|
-
return {
|
|
1508
|
-
key: `${this.id}/${e.chunk.key}/${i}`,
|
|
1509
|
-
chunk: e.chunk,
|
|
1510
|
-
step: i,
|
|
1511
|
-
time: s[i],
|
|
1512
|
-
data: c,
|
|
1513
|
-
grid: o,
|
|
1514
|
-
manifest: n
|
|
1515
|
-
};
|
|
1516
|
-
}
|
|
1517
|
-
/** Release least recently used chunks beyond the bound, unless in use. */
|
|
1518
|
-
trim() {
|
|
1519
|
-
let e = this.open.size - this.maxOpenChunks;
|
|
1520
|
-
for (const i of [...this.open.values()]) {
|
|
1521
|
-
if (e <= 0)
|
|
1522
|
-
return;
|
|
1523
|
-
i.users === 0 && (this.close(i), e--);
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
close(e) {
|
|
1527
|
-
e.released = !0, e.prefetch?.abort(), e.prefetch = null, e.opened?.source.release(), e.opened = null, this.open.get(e.chunk.key) === e && this.open.delete(e.chunk.key);
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
const Vt = {
|
|
1531
|
-
a: "u_vel0",
|
|
1532
|
-
b: "u_vel1",
|
|
1533
|
-
mix: "u_vel_mix",
|
|
1534
|
-
bounds: "u_bounds"
|
|
1535
|
-
}, Ot = {
|
|
1536
|
-
a: "u_tint0",
|
|
1537
|
-
b: "u_tint1",
|
|
1538
|
-
mix: "u_tint_mix",
|
|
1539
|
-
bounds: "u_tint_bounds"
|
|
1540
|
-
};
|
|
1541
|
-
function Bt(t) {
|
|
1542
|
-
const e = new Float32Array(t.u.length * 4);
|
|
1543
|
-
for (let i = 0; i < t.u.length; i++) {
|
|
1544
|
-
const r = t.u[i], n = t.v[i];
|
|
1545
|
-
Number.isNaN(r) || Number.isNaN(n) || (e[i * 4] = r, e[i * 4 + 1] = n, e[i * 4 + 2] = 1);
|
|
1546
|
-
}
|
|
1547
|
-
return e;
|
|
1548
|
-
}
|
|
1549
|
-
class Xt {
|
|
1550
|
-
constructor(e, i, r = {}) {
|
|
1551
|
-
this.gl = e, this.manifest = i, this.options = r, this.textures = /* @__PURE__ */ new Map(), this.pending = /* @__PURE__ */ new Map(), this.mask = null, this.pair = null, this.destroyed = !1, this.linearFilter = !0, this.uploadedFrames = 0, this.lastUploadDurationMs = 0, this.vector = i.encoding.kind === "vector-luma", this.source = ge(i, { cacheSize: 2 }), this.uniforms = this.vector ? Vt : Ot;
|
|
1552
|
-
const n = M(i);
|
|
1553
|
-
this.times = r.animateSnapshot && i.timeline.kind === "snapshot-loop" ? Array.from(
|
|
1554
|
-
{
|
|
1555
|
-
length: Math.max(
|
|
1556
|
-
1,
|
|
1557
|
-
Math.round(i.media.durationSeconds * i.media.fps)
|
|
1558
|
-
)
|
|
1559
|
-
},
|
|
1560
|
-
(s, o) => n[0] + o * 1e3 / i.media.fps
|
|
1561
|
-
) : n, this.bounds = i.bounds;
|
|
1562
|
-
}
|
|
1563
|
-
get currentPair() {
|
|
1564
|
-
return this.pair;
|
|
1565
|
-
}
|
|
1566
|
-
/** Fixed catalog color domain of a scalar field. */
|
|
1567
|
-
get domain() {
|
|
1568
|
-
return this.manifest.style.colorDomain;
|
|
1569
|
-
}
|
|
1570
|
-
/** Top of the color ramp and of the particle speed normalization. */
|
|
1571
|
-
get maxSpeed() {
|
|
1572
|
-
const { encoding: e, style: i } = this.manifest;
|
|
1573
|
-
return e.kind === "vector-luma" ? e.valueDomain : i.colorDomain[1];
|
|
1574
|
-
}
|
|
1575
|
-
/** Resolves once the step at `ms` is uploaded. */
|
|
1576
|
-
async prime(e) {
|
|
1577
|
-
const { index: i } = v(this.times, e);
|
|
1578
|
-
await this.request(i);
|
|
1579
|
-
}
|
|
1580
|
-
/** The uploaded texture of the step at `ms`, or null. */
|
|
1581
|
-
texture(e) {
|
|
1582
|
-
return this.textures.get(v(this.times, e).index) ?? null;
|
|
1583
|
-
}
|
|
1584
|
-
/** True once the frames interpolated at `ms` are uploaded. */
|
|
1585
|
-
ready(e) {
|
|
1586
|
-
const { index: i, fraction: r } = v(this.times, e);
|
|
1587
|
-
return this.textures.has(i) && (r === 0 || this.textures.has(i + 1));
|
|
1588
|
-
}
|
|
1589
|
-
/**
|
|
1590
|
-
* Latest wins while scrubbing: drop queued decodes outside the frames at
|
|
1591
|
-
* `ms`, then request those first.
|
|
1592
|
-
*/
|
|
1593
|
-
focus(e) {
|
|
1594
|
-
const { index: i } = v(this.times, e), r = Math.min(i + 1, this.times.length - 1);
|
|
1595
|
-
[...this.pending.keys()].some(
|
|
1596
|
-
(s) => s !== i && s !== r
|
|
1597
|
-
) && (this.source.cancelAll(), this.pending.clear());
|
|
1598
|
-
for (const s of [i, r])
|
|
1599
|
-
this.request(s).catch(() => {
|
|
1600
|
-
});
|
|
1601
|
-
}
|
|
1602
|
-
/**
|
|
1603
|
-
* Bracketing textures and their mix, retaining the last complete pair
|
|
1604
|
-
* while a requested frame decodes.
|
|
1605
|
-
*/
|
|
1606
|
-
sample(e, i = !0) {
|
|
1607
|
-
const { index: r, fraction: n } = v(this.times, e), s = Math.min(r + 1, this.times.length - 1);
|
|
1608
|
-
[...this.pending.keys()].some((l) => l < r || l > s + 1) && (this.source.cancelAll(), this.pending.clear());
|
|
1609
|
-
for (const l of [r, s, s + 1])
|
|
1610
|
-
l < this.times.length && this.request(l).catch(() => {
|
|
1611
|
-
});
|
|
1612
|
-
const o = this.textures.get(r), a = this.textures.get(s), c = i ? n : 0;
|
|
1613
|
-
return o && (c === 0 || a) && (this.pair = [o, c === 0 ? o : a, c]), this.evict(r), this.pair;
|
|
1614
|
-
}
|
|
1615
|
-
/** Switch spatial filtering without changing the decoded-step cache. */
|
|
1616
|
-
setFilter(e) {
|
|
1617
|
-
if (this.linearFilter === e)
|
|
1618
|
-
return;
|
|
1619
|
-
this.linearFilter = e;
|
|
1620
|
-
const i = this.gl, r = i.getParameter(
|
|
1621
|
-
i.TEXTURE_BINDING_2D
|
|
1622
|
-
);
|
|
1623
|
-
for (const n of this.textures.values())
|
|
1624
|
-
i.bindTexture(i.TEXTURE_2D, n), i.texParameteri(
|
|
1625
|
-
i.TEXTURE_2D,
|
|
1626
|
-
i.TEXTURE_MIN_FILTER,
|
|
1627
|
-
e ? i.LINEAR : i.NEAREST
|
|
1628
|
-
), i.texParameteri(
|
|
1629
|
-
i.TEXTURE_2D,
|
|
1630
|
-
i.TEXTURE_MAG_FILTER,
|
|
1631
|
-
e ? i.LINEAR : i.NEAREST
|
|
1632
|
-
);
|
|
1633
|
-
i.bindTexture(i.TEXTURE_2D, r);
|
|
1634
|
-
}
|
|
1635
|
-
get maskTexture() {
|
|
1636
|
-
return this.mask;
|
|
1637
|
-
}
|
|
1638
|
-
get cachedFrames() {
|
|
1639
|
-
return this.textures.size;
|
|
1640
|
-
}
|
|
1641
|
-
bind(e, i, r = 0) {
|
|
1642
|
-
if (!this.sample(i) || !this.pair)
|
|
1643
|
-
return !1;
|
|
1644
|
-
const n = this.uniforms;
|
|
1645
|
-
if (e.texture(n.a, r, this.pair[0]), e.texture(n.b, r + 1, this.pair[1]), e.float(n.mix, this.pair[2]), e.vec4(n.bounds, this.bounds), this.mask && this.manifest.encoding.kind === "scalar-luma") {
|
|
1646
|
-
const { codeRange: s, valueRange: o, transfer: a } = yt(
|
|
1647
|
-
this.manifest.encoding
|
|
1648
|
-
);
|
|
1649
|
-
e.texture("u_tint_mask", r + 2, this.mask), e.vec2("u_code_range", ...s), e.vec2("u_value_range", ...o), e.float("u_scalar_transfer", a);
|
|
1650
|
-
}
|
|
1651
|
-
return !0;
|
|
1652
|
-
}
|
|
1653
|
-
destroy() {
|
|
1654
|
-
this.destroyed = !0, this.source.cancelAll(), this.source.release();
|
|
1655
|
-
for (const e of this.textures.values())
|
|
1656
|
-
this.gl.deleteTexture(e);
|
|
1657
|
-
this.textures.clear(), this.gl.deleteTexture(this.mask), this.mask = null, this.pair = null;
|
|
1658
|
-
}
|
|
1659
|
-
request(e) {
|
|
1660
|
-
if (this.textures.has(e))
|
|
1661
|
-
return Promise.resolve();
|
|
1662
|
-
const i = this.pending.get(e);
|
|
1663
|
-
if (i)
|
|
1664
|
-
return i;
|
|
1665
|
-
const r = this.source.frame(e).then((n) => {
|
|
1666
|
-
if (!this.destroyed && this.pending.get(e) === r && !this.textures.has(e)) {
|
|
1667
|
-
const s = performance.now();
|
|
1668
|
-
this.textures.set(e, this.uploadPreservingState(n)), this.uploadedFrames++, this.lastUploadDurationMs = performance.now() - s, this.options.onReady?.();
|
|
1669
|
-
}
|
|
1670
|
-
}).catch((n) => {
|
|
1671
|
-
throw !this.destroyed && this.pending.get(e) === r && !(n instanceof Error && n.name === "AbortError") && this.options.onError?.(n), n;
|
|
1672
|
-
}).finally(() => {
|
|
1673
|
-
this.pending.get(e) === r && this.pending.delete(e);
|
|
1674
|
-
});
|
|
1675
|
-
return this.pending.set(e, r), r;
|
|
1676
|
-
}
|
|
1677
|
-
uploadPreservingState(e) {
|
|
1678
|
-
const i = this.gl, r = i.getParameter(
|
|
1679
|
-
i.TEXTURE_BINDING_2D
|
|
1680
|
-
), n = [
|
|
1681
|
-
i.UNPACK_FLIP_Y_WEBGL,
|
|
1682
|
-
i.UNPACK_PREMULTIPLY_ALPHA_WEBGL,
|
|
1683
|
-
i.UNPACK_COLORSPACE_CONVERSION_WEBGL,
|
|
1684
|
-
i.UNPACK_ALIGNMENT
|
|
1685
|
-
], s = n.map((o) => i.getParameter(o));
|
|
1686
|
-
try {
|
|
1687
|
-
return this.upload(e);
|
|
1688
|
-
} finally {
|
|
1689
|
-
i.bindTexture(i.TEXTURE_2D, r), n.forEach((o, a) => i.pixelStorei(o, s[a]));
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
upload(e) {
|
|
1693
|
-
const i = this.gl, { width: r, height: n } = this.source, s = this.gridTexture();
|
|
1694
|
-
return this.vector ? i.texImage2D(
|
|
1695
|
-
i.TEXTURE_2D,
|
|
1696
|
-
0,
|
|
1697
|
-
i.RGBA16F,
|
|
1698
|
-
r,
|
|
1699
|
-
n,
|
|
1700
|
-
0,
|
|
1701
|
-
i.RGBA,
|
|
1702
|
-
i.FLOAT,
|
|
1703
|
-
Bt(e)
|
|
1704
|
-
) : (i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL, !1), i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL, !1), i.pixelStorei(i.UNPACK_COLORSPACE_CONVERSION_WEBGL, i.NONE), i.texImage2D(
|
|
1705
|
-
i.TEXTURE_2D,
|
|
1706
|
-
0,
|
|
1707
|
-
i.RGBA8,
|
|
1708
|
-
i.RGBA,
|
|
1709
|
-
i.UNSIGNED_BYTE,
|
|
1710
|
-
e
|
|
1711
|
-
), this.mask ??= this.uploadMask()), i.bindTexture(i.TEXTURE_2D, null), s;
|
|
1712
|
-
}
|
|
1713
|
-
/** The source's mask, loaded with its first frame, as an R8 texture. */
|
|
1714
|
-
uploadMask() {
|
|
1715
|
-
const e = this.source.mask;
|
|
1716
|
-
if (!e)
|
|
1717
|
-
return null;
|
|
1718
|
-
const i = this.gl, r = this.gridTexture();
|
|
1719
|
-
return this.options.nearestMask && (i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MIN_FILTER, i.NEAREST), i.texParameteri(i.TEXTURE_2D, i.TEXTURE_MAG_FILTER, i.NEAREST)), i.pixelStorei(i.UNPACK_ALIGNMENT, 1), i.texImage2D(
|
|
1720
|
-
i.TEXTURE_2D,
|
|
1721
|
-
0,
|
|
1722
|
-
i.R8,
|
|
1723
|
-
this.source.width,
|
|
1724
|
-
this.source.height,
|
|
1725
|
-
0,
|
|
1726
|
-
i.RED,
|
|
1727
|
-
i.UNSIGNED_BYTE,
|
|
1728
|
-
e
|
|
1729
|
-
), i.pixelStorei(i.UNPACK_ALIGNMENT, 4), r;
|
|
1730
|
-
}
|
|
1731
|
-
/** A bound, linearly filtered texture over the field grid. */
|
|
1732
|
-
gridTexture() {
|
|
1733
|
-
const e = this.gl, i = e.createTexture();
|
|
1734
|
-
return e.bindTexture(e.TEXTURE_2D, i), e.texParameteri(
|
|
1735
|
-
e.TEXTURE_2D,
|
|
1736
|
-
e.TEXTURE_WRAP_S,
|
|
1737
|
-
this.options.repeatLongitude !== !1 && this.bounds[2] - this.bounds[0] >= 359 ? e.REPEAT : e.CLAMP_TO_EDGE
|
|
1738
|
-
), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(
|
|
1739
|
-
e.TEXTURE_2D,
|
|
1740
|
-
e.TEXTURE_MIN_FILTER,
|
|
1741
|
-
this.linearFilter ? e.LINEAR : e.NEAREST
|
|
1742
|
-
), e.texParameteri(
|
|
1743
|
-
e.TEXTURE_2D,
|
|
1744
|
-
e.TEXTURE_MAG_FILTER,
|
|
1745
|
-
this.linearFilter ? e.LINEAR : e.NEAREST
|
|
1746
|
-
), i;
|
|
1747
|
-
}
|
|
1748
|
-
/** Keep a small window around the playhead. */
|
|
1749
|
-
evict(e) {
|
|
1750
|
-
for (const [i, r] of this.textures) {
|
|
1751
|
-
const n = this.pair && (this.pair[0] === r || this.pair[1] === r);
|
|
1752
|
-
(i < e - 1 || i > e + 3) && !n && (this.gl.deleteTexture(r), this.textures.delete(i));
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
class $t {
|
|
1757
|
-
constructor(e, i) {
|
|
1758
|
-
this.onPlaying = i, this.time = 0, this.endFraction = 0, this.held = !1, this.playingValue = e;
|
|
1759
|
-
}
|
|
1760
|
-
/** Playhead, epoch ms. Assigning it also resets a terminal step's hold. */
|
|
1761
|
-
get ms() {
|
|
1762
|
-
return this.time;
|
|
1763
|
-
}
|
|
1764
|
-
set ms(e) {
|
|
1765
|
-
this.time = e, this.endFraction = 0;
|
|
1766
|
-
}
|
|
1767
|
-
/** Progress through the final sample's held step, 0 elsewhere. */
|
|
1768
|
-
get holdFraction() {
|
|
1769
|
-
return this.endFraction;
|
|
1770
|
-
}
|
|
1771
|
-
get playing() {
|
|
1772
|
-
return this.playingValue;
|
|
1773
|
-
}
|
|
1774
|
-
setPlaying(e) {
|
|
1775
|
-
this.playingValue !== e && (this.playingValue = e, this.onPlaying(e));
|
|
1776
|
-
}
|
|
1777
|
-
/** Playing and not held. */
|
|
1778
|
-
get advancing() {
|
|
1779
|
-
return this.playingValue && !this.held;
|
|
1780
|
-
}
|
|
1781
|
-
/**
|
|
1782
|
-
* Advance in step units, including irregular timelines. Returns true at a
|
|
1783
|
-
* non-looping end. holdLastStep gives the final sample a full step's duration.
|
|
1784
|
-
*/
|
|
1785
|
-
advance(e, i, r, n = [i[0], i[i.length - 1]], s = !1, o = !1) {
|
|
1786
|
-
if (!this.advancing || !i.length)
|
|
1787
|
-
return !1;
|
|
1788
|
-
const a = Z(i, n[0]), c = Z(i, n[1]), l = c + (o ? 1 : 0);
|
|
1789
|
-
let d = Math.max(a, Z(i, this.ms) + this.endFraction) + Math.max(0, e) * r;
|
|
1790
|
-
const h = o ? d >= l : d > l;
|
|
1791
|
-
return h && s && l > a ? d = a + (d - a) % (l - a) : d = Math.min(l, d), this.time = xt(i, Math.min(c, d)), this.endFraction = Math.max(0, d - c), h && !s;
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
function X(t) {
|
|
1795
|
-
const e = M(t);
|
|
1796
|
-
return [e[0], e[e.length - 1]];
|
|
1797
|
-
}
|
|
1798
|
-
function J(t, e) {
|
|
1799
|
-
return e ? [Math.max(t[0], e[0]), Math.min(t[1], e[1])] : t;
|
|
1800
|
-
}
|
|
1801
|
-
function $([t, e], i) {
|
|
1802
|
-
return Math.max(t, Math.min(e, i));
|
|
1803
|
-
}
|
|
1804
|
-
class Si {
|
|
1805
|
-
constructor(e, i, r) {
|
|
1806
|
-
this.repaint = i, this.emit = r, this.field = null, this.manifest = null, this.gl = null, this.pendingField = null, this.standby = null, this.awaitingNext = !1, this.timeRange = null, this.lastTick = null, this.lastStepTime = null, this.seekId = 0, this.seeking = !1, this.failed = !1, this.exactTime = 0, this.endEmitted = !1, this.destroyed = !1, this.resumePlayback = !1, this.playOnReady = e.autoplay ?? !0, this.loop = e.loop ?? !0, this.playbackRate = e.playbackRate ?? 1, this.stepsPerSecond = e.stepsPerSecond;
|
|
1807
|
-
const n = typeof e.time == "string" ? Date.parse(e.time) : e.time;
|
|
1808
|
-
this.requestedTime = n != null && Number.isFinite(n) ? n : null, this.requestedTimeRange = e.timeRange, this.clock = new $t(
|
|
1809
|
-
!1,
|
|
1810
|
-
(s) => this.emit("playbackChange", s)
|
|
1811
|
-
);
|
|
1812
|
-
}
|
|
1813
|
-
async load(e, i) {
|
|
1814
|
-
if (this.gl = e, this.manifest = i, this.timeRange = J(
|
|
1815
|
-
X(i),
|
|
1816
|
-
this.requestedTimeRange
|
|
1817
|
-
), this.timeRange[0] > this.timeRange[1])
|
|
1818
|
-
throw new Error(
|
|
1819
|
-
"GeoVideo time range does not overlap the manifest timeline"
|
|
1820
|
-
);
|
|
1821
|
-
this.pendingField = this.createField(i), await this.prepare(this.pendingField);
|
|
1822
|
-
}
|
|
1823
|
-
sample(e) {
|
|
1824
|
-
if (this.tick(e), !this.field)
|
|
1825
|
-
return null;
|
|
1826
|
-
const i = this.pendingField || this.seeking ? this.field.currentPair : this.field.sample(
|
|
1827
|
-
this.clock.advancing ? this.clock.ms : this.exactTime,
|
|
1828
|
-
this.clock.advancing && !this.awaitingNext
|
|
1829
|
-
);
|
|
1830
|
-
return this.handoff(i) ?? i;
|
|
1831
|
-
}
|
|
1832
|
-
/**
|
|
1833
|
-
* Through the final step of a chunk followed by a decoded one, the last
|
|
1834
|
-
* frame blends into the next chunk's first, as steps do within a chunk:
|
|
1835
|
-
* the chunk swap then lands on the frame already shown.
|
|
1836
|
-
*/
|
|
1837
|
-
handoff(e) {
|
|
1838
|
-
const i = this.clock.holdFraction, r = this.pendingField ?? this.standby?.field, n = this.pendingField ? this.requestedTime : this.standby?.time;
|
|
1839
|
-
if (!e || i <= 0 || !r || n == null)
|
|
1840
|
-
return null;
|
|
1841
|
-
const s = r.texture(n);
|
|
1842
|
-
return s ? [e[0], s, Math.min(1, i)] : null;
|
|
1843
|
-
}
|
|
1844
|
-
get time() {
|
|
1845
|
-
return this.clock.ms;
|
|
1846
|
-
}
|
|
1847
|
-
get preloadedMediaUrl() {
|
|
1848
|
-
return this.standby?.field.manifest.media.url;
|
|
1849
|
-
}
|
|
1850
|
-
setStepsPerSecond(e) {
|
|
1851
|
-
if (!Number.isFinite(e) || e <= 0)
|
|
1852
|
-
throw new Error("GeoVideo steps per second must be positive");
|
|
1853
|
-
this.stepsPerSecond = e;
|
|
1854
|
-
}
|
|
1855
|
-
suspend() {
|
|
1856
|
-
this.resumePlayback = this.isPlaying(), this.pause();
|
|
1857
|
-
}
|
|
1858
|
-
resume() {
|
|
1859
|
-
this.resumePlayback && this.play(), this.resumePlayback = !1;
|
|
1860
|
-
}
|
|
1861
|
-
destroy() {
|
|
1862
|
-
this.destroyed = !0, this.seekId++, this.pendingField?.destroy(), this.pendingField = null, this.discardStandby(), this.field?.destroy(), this.field = null, this.gl = null;
|
|
1863
|
-
}
|
|
1864
|
-
tick(e) {
|
|
1865
|
-
if (!this.field || this.pendingField || this.seeking || this.awaitingNext || !this.clock.advancing) {
|
|
1866
|
-
this.lastTick = null;
|
|
1867
|
-
return;
|
|
1868
|
-
}
|
|
1869
|
-
const i = this.lastTick === null ? 0 : (e - this.lastTick) / 1e3;
|
|
1870
|
-
this.lastTick = e;
|
|
1871
|
-
const r = this.clock.advance(
|
|
1872
|
-
i,
|
|
1873
|
-
this.field.times,
|
|
1874
|
-
this.stepsPerSecond ?? this.playbackRate * me(this.field.manifest),
|
|
1875
|
-
this.playbackRange(this.field),
|
|
1876
|
-
this.loop,
|
|
1877
|
-
!0
|
|
1878
|
-
), { index: n } = v(this.field.times, this.clock.ms), s = this.field.manifest.timeline.kind === "snapshot-loop" ? this.field.times[0] : $(this.timeRange, this.field.times[n]);
|
|
1879
|
-
s !== this.lastStepTime && (this.lastStepTime = s, this.emit("timeChange", s)), r ? this.reachEnd() : this.repaint();
|
|
1880
|
-
}
|
|
1881
|
-
setTime(e) {
|
|
1882
|
-
const i = typeof e == "number" ? e : Date.parse(e);
|
|
1883
|
-
if (!Number.isFinite(i))
|
|
1884
|
-
return;
|
|
1885
|
-
this.requestedTime = i, this.awaitingNext = !1;
|
|
1886
|
-
const r = this.pendingField ?? this.field;
|
|
1887
|
-
r && this.prepare(r).catch((n) => this.reportError(n));
|
|
1888
|
-
}
|
|
1889
|
-
/** Load the requested step first; stale seeks and swaps cannot replace it. */
|
|
1890
|
-
async prepare(e, i) {
|
|
1891
|
-
this.failed = !1;
|
|
1892
|
-
const r = ++this.seekId, n = this.timeRange ?? X(e.manifest), s = i ?? $(n, this.requestedTime ?? n[0]), o = v(e.times, s), a = Math.min(
|
|
1893
|
-
e.times.length - 1,
|
|
1894
|
-
o.index + (o.fraction > 0.5 ? 1 : 0)
|
|
1895
|
-
), c = e.times[a];
|
|
1896
|
-
this.seeking = !0, this.lastTick = null, e.focus(c);
|
|
1897
|
-
try {
|
|
1898
|
-
await e.prime(c);
|
|
1899
|
-
} catch (d) {
|
|
1900
|
-
if (r !== this.seekId)
|
|
1901
|
-
return;
|
|
1902
|
-
throw d;
|
|
1903
|
-
}
|
|
1904
|
-
if (r !== this.seekId || this.destroyed)
|
|
1905
|
-
return;
|
|
1906
|
-
const l = this.pendingField === e;
|
|
1907
|
-
if (l && (this.field?.destroy(), this.field = e, this.pendingField = null, this.lastStepTime = null), this.exactTime = c, this.clock.ms = $(this.playbackRange(e), c), e.sample(c, !1), this.seeking = !1, this.endEmitted = !1, this.repaint(), l) {
|
|
1908
|
-
const d = e.manifest;
|
|
1909
|
-
if (this.emit("loaded", {
|
|
1910
|
-
min: d.style.colorDomain[0],
|
|
1911
|
-
max: d.style.colorDomain[1],
|
|
1912
|
-
unit: d.style.unit ?? "",
|
|
1913
|
-
time: new Date(this.clock.ms).toISOString()
|
|
1914
|
-
}), this.emit("status", { phase: "ready", time: this.clock.ms }), this.playOnReady) {
|
|
1915
|
-
this.playOnReady = !1;
|
|
1916
|
-
const h = this.clock.playing;
|
|
1917
|
-
await this.play(), h && this.emit("playbackChange", !0);
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
/** Keep the outgoing pair until the incoming chunk's requested step is ready. */
|
|
1922
|
-
replaceManifest(e, i = {}) {
|
|
1923
|
-
const r = this.replacementTimeRange(e, i);
|
|
1924
|
-
if (!r || !this.gl)
|
|
1925
|
-
return !1;
|
|
1926
|
-
this.playOnReady ||= this.isPlaying(), this.pendingField?.destroy();
|
|
1927
|
-
const n = this.standby;
|
|
1928
|
-
return this.standby = null, n && n.field.manifest.media.url !== e.media.url && n.field.destroy(), this.pendingField = n?.field.manifest.media.url === e.media.url ? n.field : this.createField(e), this.awaitingNext = !1, this.manifest = e, this.requestedTimeRange = i.timeRange, this.timeRange = r, this.requestedTime = i.time ?? r[0], this.loop = i.loop ?? this.loop, this.playbackRate = i.playbackRate ?? this.playbackRate, this.stepsPerSecond = i.stepsPerSecond ?? this.stepsPerSecond, this.lastTick = null, this.prepare(this.pendingField).catch(
|
|
1929
|
-
(s) => this.reportError(s)
|
|
1930
|
-
), !0;
|
|
1931
|
-
}
|
|
1932
|
-
/** Decode the next chunk ahead of its swap, including its static mask. */
|
|
1933
|
-
preloadManifest(e, i = {}) {
|
|
1934
|
-
const r = this.replacementTimeRange(e, i);
|
|
1935
|
-
if (!r || !this.gl || e.media.url === this.manifest?.media.url)
|
|
1936
|
-
return !1;
|
|
1937
|
-
const n = $(r, i.time ?? r[0]);
|
|
1938
|
-
this.standby?.field.manifest.media.url !== e.media.url && (this.discardStandby(), this.standby = { field: this.createField(e), time: n });
|
|
1939
|
-
const s = this.standby;
|
|
1940
|
-
return s.time = n, s.field.focus(n), s.field.prime(n).catch(() => {
|
|
1941
|
-
this.standby === s && this.discardStandby();
|
|
1942
|
-
}), !0;
|
|
1943
|
-
}
|
|
1944
|
-
discardStandby() {
|
|
1945
|
-
this.standby?.field.destroy(), this.standby = null;
|
|
1946
|
-
}
|
|
1947
|
-
/** Clamped time range of a compatible replacement, else null. */
|
|
1948
|
-
replacementTimeRange(e, i) {
|
|
1949
|
-
const r = this.manifest;
|
|
1950
|
-
if (!r || e.encoding.kind !== r.encoding.kind || e.media.width !== r.media.width || e.media.height !== r.media.height || e.mask.width !== r.mask.width || e.mask.height !== r.mask.height)
|
|
1951
|
-
return null;
|
|
1952
|
-
const n = J(
|
|
1953
|
-
X(e),
|
|
1954
|
-
i.timeRange
|
|
1955
|
-
);
|
|
1956
|
-
return n[0] <= n[1] ? n : null;
|
|
1957
|
-
}
|
|
1958
|
-
async play() {
|
|
1959
|
-
if (!this.field || this.pendingField || this.awaitingNext) {
|
|
1960
|
-
this.playOnReady = !0, this.clock.setPlaying(!0);
|
|
1961
|
-
return;
|
|
1962
|
-
}
|
|
1963
|
-
this.failed && this.prepare(this.field, this.clock.ms).catch(
|
|
1964
|
-
(r) => this.reportError(r)
|
|
1965
|
-
);
|
|
1966
|
-
const e = this.endEmitted;
|
|
1967
|
-
this.endEmitted = !1;
|
|
1968
|
-
const i = this.playbackRange(this.field);
|
|
1969
|
-
e && this.setTime(i[0]), this.lastTick = null, this.clock.setPlaying(!0), this.repaint();
|
|
1970
|
-
}
|
|
1971
|
-
pause() {
|
|
1972
|
-
const e = this.playOnReady && !this.clock.playing;
|
|
1973
|
-
if (this.playOnReady = !1, this.awaitingNext = !1, this.clock.setPlaying(!1), this.field && !this.pendingField && !this.seeking && !this.endEmitted) {
|
|
1974
|
-
const { index: i } = v(this.field.times, this.clock.ms);
|
|
1975
|
-
this.prepare(this.field, this.field.times[i]).catch(
|
|
1976
|
-
(r) => this.reportError(r)
|
|
1977
|
-
);
|
|
1978
|
-
}
|
|
1979
|
-
e && this.emit("playbackChange", !1), this.lastTick = null, this.repaint();
|
|
1980
|
-
}
|
|
1981
|
-
isPlaying() {
|
|
1982
|
-
return this.clock.playing || this.playOnReady;
|
|
1983
|
-
}
|
|
1984
|
-
reachEnd() {
|
|
1985
|
-
this.endEmitted || (this.endEmitted = !0, this.exactTime = this.clock.ms, this.lastTick = null, this.standby ? (this.awaitingNext = !0, this.playOnReady = !0) : this.clock.setPlaying(!1), this.emit("playbackEnd"));
|
|
1986
|
-
}
|
|
1987
|
-
setLoop(e) {
|
|
1988
|
-
this.loop = e;
|
|
1989
|
-
}
|
|
1990
|
-
setPlaybackRate(e) {
|
|
1991
|
-
if (!Number.isFinite(e) || e <= 0)
|
|
1992
|
-
throw new Error("GeoVideo playback rate must be positive");
|
|
1993
|
-
this.playbackRate = e, this.stepsPerSecond = void 0;
|
|
1994
|
-
}
|
|
1995
|
-
setTimeRange(e) {
|
|
1996
|
-
if (!Number.isFinite(e[0]) || !Number.isFinite(e[1]) || e[0] > e[1])
|
|
1997
|
-
throw new Error("Invalid GeoVideo time range");
|
|
1998
|
-
const i = J(
|
|
1999
|
-
this.manifest ? X(this.manifest) : e,
|
|
2000
|
-
e
|
|
2001
|
-
);
|
|
2002
|
-
if (i[0] > i[1])
|
|
2003
|
-
throw new Error(
|
|
2004
|
-
"GeoVideo time range does not overlap the manifest timeline"
|
|
2005
|
-
);
|
|
2006
|
-
this.requestedTimeRange = e, this.timeRange = i, this.setTime(
|
|
2007
|
-
this.pendingField ? this.requestedTime ?? i[0] : this.clock.ms
|
|
2008
|
-
);
|
|
2009
|
-
}
|
|
2010
|
-
playbackRange(e) {
|
|
2011
|
-
return e.manifest.timeline.kind === "snapshot-loop" ? [e.times[0], e.times[e.times.length - 1]] : this.timeRange ?? [
|
|
2012
|
-
e.times[0],
|
|
2013
|
-
e.times[e.times.length - 1]
|
|
2014
|
-
];
|
|
2015
|
-
}
|
|
2016
|
-
createField(e) {
|
|
2017
|
-
const i = new Xt(this.gl, e, {
|
|
2018
|
-
nearestMask: !0,
|
|
2019
|
-
animateSnapshot: !0,
|
|
2020
|
-
onError: (r) => {
|
|
2021
|
-
this.field === i && !this.seeking && this.reportError(r);
|
|
2022
|
-
},
|
|
2023
|
-
onReady: () => this.repaint()
|
|
2024
|
-
});
|
|
2025
|
-
return i;
|
|
2026
|
-
}
|
|
2027
|
-
reportError(e) {
|
|
2028
|
-
const i = e instanceof Error ? e : new Error(String(e));
|
|
2029
|
-
i.name === "AbortError" || this.destroyed || (this.playOnReady = !1, this.awaitingNext = !1, this.failed = !0, this.seeking = !0, this.clock.setPlaying(!1), this.emit("status", { phase: "error", error: i }), this.emit("error", i));
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
function H(t) {
|
|
2033
|
-
const { start: e, end: i } = t.temporal ?? {};
|
|
2034
|
-
return {
|
|
2035
|
-
source: t,
|
|
2036
|
-
start: Date.parse(e ?? ""),
|
|
2037
|
-
end: Date.parse(i ?? e ?? "")
|
|
2038
|
-
};
|
|
2039
|
-
}
|
|
2040
|
-
function Ui(t, e, i = {}) {
|
|
2041
|
-
const r = t.filter((s) => s.id === e.id && s.temporal?.start != null).map(H), n = Mt(
|
|
2042
|
-
r,
|
|
2043
|
-
Date.parse(e.temporal?.end ?? ""),
|
|
2044
|
-
i
|
|
2045
|
-
);
|
|
2046
|
-
return n ? { source: n.chunk.source, time: n.time } : null;
|
|
2047
|
-
}
|
|
2048
|
-
function Mi(t, e) {
|
|
2049
|
-
return Dt(H(t), e.map(H))?.source ?? null;
|
|
2050
|
-
}
|
|
2051
|
-
function Di(t, e = {}) {
|
|
2052
|
-
const i = e.start ?? -1 / 0, r = e.end ?? 1 / 0, n = t.map(H).filter((a) => a.end >= i && a.start <= r).sort((a, c) => a.start - c.start);
|
|
2053
|
-
if (n.length === 0)
|
|
2054
|
-
return;
|
|
2055
|
-
if (e.time == null)
|
|
2056
|
-
return n[n.length - 1].source;
|
|
2057
|
-
const s = Math.min(r, Math.max(i, e.time)), o = (a) => s < a.start ? a.start - s : Math.max(0, s - a.end);
|
|
2058
|
-
return n.reduce(
|
|
2059
|
-
(a, c) => o(c) <= o(a) ? c : a
|
|
2060
|
-
).source;
|
|
2061
|
-
}
|
|
2062
|
-
const qt = /^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/;
|
|
2063
|
-
function Wt(t) {
|
|
2064
|
-
return t instanceof Date ? t.getTime() : typeof t == "number" ? t : new Date(t).getTime();
|
|
2065
|
-
}
|
|
2066
|
-
function he(t, e) {
|
|
2067
|
-
const i = Wt(t);
|
|
2068
|
-
if (!Number.isFinite(i))
|
|
2069
|
-
throw new Error(`Invalid ${e}`);
|
|
2070
|
-
return i;
|
|
2071
|
-
}
|
|
2072
|
-
function Te(t, e) {
|
|
2073
|
-
const i = e.match(qt);
|
|
2074
|
-
if (!i)
|
|
2075
|
-
throw new Error(`Invalid trailing time duration: ${e}`);
|
|
2076
|
-
const r = i.slice(1).map((A) => Number(A ?? 0));
|
|
2077
|
-
if (!r.some((A) => A > 0))
|
|
2078
|
-
throw new Error("Trailing time duration must be positive");
|
|
2079
|
-
const [n, s, o, a, c, l, d] = r, h = new Date(t), p = h.getUTCFullYear() * 12 + h.getUTCMonth() - n * 12 - s, m = Math.floor(p / 12), E = (p % 12 + 12) % 12, w = new Date(Date.UTC(m, E + 1, 0)).getUTCDate();
|
|
2080
|
-
return Date.UTC(
|
|
2081
|
-
m,
|
|
2082
|
-
E,
|
|
2083
|
-
Math.min(h.getUTCDate(), w),
|
|
2084
|
-
h.getUTCHours(),
|
|
2085
|
-
h.getUTCMinutes(),
|
|
2086
|
-
h.getUTCSeconds(),
|
|
2087
|
-
h.getUTCMilliseconds()
|
|
2088
|
-
) - (((o * 7 + a) * 24 + c) * 60 + l) * 6e4 - d * 1e3;
|
|
2089
|
-
}
|
|
2090
|
-
function Pi(t, [e, i]) {
|
|
2091
|
-
let r = e, n = i;
|
|
2092
|
-
if (typeof t.trailing == "string" ? r = Te(i, t.trailing) : (t.start != null && (r = he(t.start, "time range start")), t.end != null && (n = he(t.end, "time range end"))), r > n)
|
|
2093
|
-
throw new Error("Time range start must not follow its end");
|
|
2094
|
-
return [Math.max(e, r), Math.min(i, n)];
|
|
2095
|
-
}
|
|
2096
|
-
const Ht = (t) => typeof t == "object" && t !== null && !Array.isArray(t);
|
|
2097
|
-
function Gi(t, e) {
|
|
2098
|
-
if (!Ht(t))
|
|
2099
|
-
throw new Error(`${e} must be an object`);
|
|
2100
|
-
for (const s of Object.keys(t))
|
|
2101
|
-
if (s !== "start" && s !== "end" && s !== "trailing")
|
|
2102
|
-
throw new Error(`${e}.${s} is not a time range key`);
|
|
2103
|
-
if (t.trailing !== void 0) {
|
|
2104
|
-
if (t.start !== void 0 || t.end !== void 0)
|
|
2105
|
-
throw new Error(`${e}.trailing excludes start and end`);
|
|
2106
|
-
if (typeof t.trailing != "string")
|
|
2107
|
-
throw new Error(`${e}.trailing must be an ISO 8601 duration`);
|
|
2108
|
-
return Te(0, t.trailing), { trailing: t.trailing };
|
|
2109
|
-
}
|
|
2110
|
-
const i = (s) => {
|
|
2111
|
-
const o = t[s];
|
|
2112
|
-
if (o !== void 0) {
|
|
2113
|
-
if (typeof o != "string" || !Number.isFinite(Date.parse(o)))
|
|
2114
|
-
throw new Error(`${e}.${s} is not a date`);
|
|
2115
|
-
return o;
|
|
2116
|
-
}
|
|
2117
|
-
}, r = i("start"), n = i("end");
|
|
2118
|
-
if (r !== void 0 && n !== void 0 && Date.parse(r) > Date.parse(n))
|
|
2119
|
-
throw new Error(`${e}.start must not follow its end`);
|
|
2120
|
-
return {
|
|
2121
|
-
...r !== void 0 && { start: r },
|
|
2122
|
-
...n !== void 0 && { end: n }
|
|
2123
|
-
};
|
|
2124
|
-
}
|
|
2125
|
-
function Ni(t, e) {
|
|
2126
|
-
return !!t && !!e && t.name === e.name && t.units === e.units && t.positive === e.positive && t.value === e.value;
|
|
2127
|
-
}
|
|
2128
|
-
function q(t) {
|
|
2129
|
-
const e = t;
|
|
2130
|
-
return !!e && typeof e.name == "string" && typeof e.units == "string" && typeof e.positive == "string" && Number.isFinite(e.value);
|
|
2131
|
-
}
|
|
2132
|
-
function zt(t) {
|
|
2133
|
-
const e = t.depths;
|
|
2134
|
-
if (e === void 0)
|
|
2135
|
-
return t.surface === void 0 || q(t.surface);
|
|
2136
|
-
const i = t.surface ?? e?.[0];
|
|
2137
|
-
if (!Array.isArray(e) || !q(i))
|
|
2138
|
-
return e?.length === 0;
|
|
2139
|
-
const r = new Set(t.surface ? [i.value] : []);
|
|
2140
|
-
return e.every((n) => {
|
|
2141
|
-
const s = q(n) && typeof n.indexUrl == "string" && n.name === i.name && n.units === i.units && n.positive === i.positive && !r.has(n.value);
|
|
2142
|
-
return r.add(n.value), s;
|
|
2143
|
-
});
|
|
2144
|
-
}
|
|
2145
|
-
function Ii(t) {
|
|
2146
|
-
return t.type === "geovideo" && typeof t.indexUrl == "string";
|
|
2147
|
-
}
|
|
2148
|
-
function Li(t, e) {
|
|
2149
|
-
return t.id === e.id && (t.type !== "geovideo" || e.type !== "geovideo" || t.manifestUrl === e.manifestUrl);
|
|
2150
|
-
}
|
|
2151
|
-
function ee(t) {
|
|
2152
|
-
return typeof t == "string" && Number.isFinite(Date.parse(t));
|
|
2153
|
-
}
|
|
2154
|
-
function Yt(t) {
|
|
2155
|
-
const e = t.times;
|
|
2156
|
-
if (!Array.isArray(e) || e.length !== t.samples || e[0] !== t.start || e[e.length - 1] !== t.end)
|
|
2157
|
-
return !1;
|
|
2158
|
-
let i = -1 / 0;
|
|
2159
|
-
for (const r of e) {
|
|
2160
|
-
const n = ee(r) ? Date.parse(r) : NaN;
|
|
2161
|
-
if (!(n > i))
|
|
2162
|
-
return !1;
|
|
2163
|
-
i = n;
|
|
2164
|
-
}
|
|
2165
|
-
return !0;
|
|
2166
|
-
}
|
|
2167
|
-
function jt(t) {
|
|
2168
|
-
const e = t;
|
|
2169
|
-
if (!e || e.schemaVersion !== 1 || e.type !== "geovideo-index" || !Array.isArray(e.chunks))
|
|
2170
|
-
throw new Error("Unsupported GeoVideo index");
|
|
2171
|
-
if (!zt(e) || e.vertical !== void 0 && !q(e.vertical))
|
|
2172
|
-
throw new Error("Invalid GeoVideo index levels");
|
|
2173
|
-
for (const i of e.chunks)
|
|
2174
|
-
if (!ee(i?.start) || !ee(i.end) || Date.parse(i.end) < Date.parse(i.start) || typeof i.manifestUrl != "string" || i.times !== void 0 && !Yt(i))
|
|
2175
|
-
throw new Error("Invalid GeoVideo index chunk");
|
|
2176
|
-
return e;
|
|
2177
|
-
}
|
|
2178
|
-
async function Ci(t, e) {
|
|
2179
|
-
const i = await fetch(t, { signal: e });
|
|
2180
|
-
if (!i.ok)
|
|
2181
|
-
throw new Error(
|
|
2182
|
-
`GeoVideo index request failed (${i.status}): ${t}`
|
|
2183
|
-
);
|
|
2184
|
-
return jt(await i.json());
|
|
2185
|
-
}
|
|
2186
|
-
function be(t) {
|
|
2187
|
-
return typeof document < "u" ? new URL(t, document.baseURI).href : t;
|
|
2188
|
-
}
|
|
2189
|
-
function Kt(t, e) {
|
|
2190
|
-
const i = be(e);
|
|
2191
|
-
return t.chunks.map((r) => ({
|
|
2192
|
-
key: r.key,
|
|
2193
|
-
manifestUrl: new URL(r.manifestUrl, i).href,
|
|
2194
|
-
start: Date.parse(r.start),
|
|
2195
|
-
end: Date.parse(r.end),
|
|
2196
|
-
samples: r.samples,
|
|
2197
|
-
...r.times ? { times: r.times.map(Date.parse) } : {},
|
|
2198
|
-
...r.provisional ? { provisional: !0 } : {}
|
|
2199
|
-
}));
|
|
2200
|
-
}
|
|
2201
|
-
function Qt(t, e, i) {
|
|
2202
|
-
if (e.sourceId !== t.id || e.catalogEntryId !== i.id)
|
|
2203
|
-
throw new Error(
|
|
2204
|
-
`GeoVideo index identity does not match catalog entry/source: ${t.id}`
|
|
2205
|
-
);
|
|
2206
|
-
}
|
|
2207
|
-
function Vi(t, e, i) {
|
|
2208
|
-
Qt(t, e, i);
|
|
2209
|
-
const r = Kt(e, t.indexUrl);
|
|
2210
|
-
return e.chunks.map(
|
|
2211
|
-
(n, s) => ({
|
|
2212
|
-
id: t.id,
|
|
2213
|
-
type: "geovideo",
|
|
2214
|
-
title: t.title,
|
|
2215
|
-
provenance: t.provenance,
|
|
2216
|
-
temporal: {
|
|
2217
|
-
mode: "fixed",
|
|
2218
|
-
cadence: t.temporal?.cadence,
|
|
2219
|
-
start: n.start,
|
|
2220
|
-
end: n.end
|
|
2221
|
-
},
|
|
2222
|
-
manifestUrl: r[s].manifestUrl
|
|
2223
|
-
})
|
|
2224
|
-
);
|
|
2225
|
-
}
|
|
2226
|
-
function Oi(t, e) {
|
|
2227
|
-
return new URL(t.indexUrl, be(e)).href;
|
|
2228
|
-
}
|
|
2229
|
-
export {
|
|
2230
|
-
bi as $,
|
|
2231
|
-
Li as A,
|
|
2232
|
-
ki as B,
|
|
2233
|
-
me as C,
|
|
2234
|
-
mi as D,
|
|
2235
|
-
Di as E,
|
|
2236
|
-
ui as F,
|
|
2237
|
-
Ri as G,
|
|
2238
|
-
Ii as H,
|
|
2239
|
-
Ui as I,
|
|
2240
|
-
Pi as J,
|
|
2241
|
-
Oi as K,
|
|
2242
|
-
Ci as L,
|
|
2243
|
-
Vi as M,
|
|
2244
|
-
Kt as N,
|
|
2245
|
-
Ai as O,
|
|
2246
|
-
le as P,
|
|
2247
|
-
Ti as Q,
|
|
2248
|
-
wi as R,
|
|
2249
|
-
_i as S,
|
|
2250
|
-
Ei as T,
|
|
2251
|
-
Fi as U,
|
|
2252
|
-
$t as V,
|
|
2253
|
-
At as W,
|
|
2254
|
-
Xt as X,
|
|
2255
|
-
Ee as Y,
|
|
2256
|
-
_t as Z,
|
|
2257
|
-
Ut as _,
|
|
2258
|
-
oi as a,
|
|
2259
|
-
yi as a0,
|
|
2260
|
-
gi as a1,
|
|
2261
|
-
qe as a2,
|
|
2262
|
-
Qt as a3,
|
|
2263
|
-
ge as a4,
|
|
2264
|
-
ae as a5,
|
|
2265
|
-
st as a6,
|
|
2266
|
-
Pt as a7,
|
|
2267
|
-
Mt as a8,
|
|
2268
|
-
Mi as a9,
|
|
2269
|
-
Dt as aa,
|
|
2270
|
-
Gi as ab,
|
|
2271
|
-
xt as ac,
|
|
2272
|
-
Te as ad,
|
|
2273
|
-
v as ae,
|
|
2274
|
-
Z as af,
|
|
2275
|
-
jt as ag,
|
|
2276
|
-
Bt as ah,
|
|
2277
|
-
ci as b,
|
|
2278
|
-
ei as c,
|
|
2279
|
-
ri as d,
|
|
2280
|
-
ni as e,
|
|
2281
|
-
ai as f,
|
|
2282
|
-
li as g,
|
|
2283
|
-
ti as h,
|
|
2284
|
-
si as i,
|
|
2285
|
-
xi as j,
|
|
2286
|
-
ii as k,
|
|
2287
|
-
di as l,
|
|
2288
|
-
hi as m,
|
|
2289
|
-
Si as n,
|
|
2290
|
-
pi as o,
|
|
2291
|
-
pt as p,
|
|
2292
|
-
yt as q,
|
|
2293
|
-
Je as r,
|
|
2294
|
-
fi as s,
|
|
2295
|
-
Ke as t,
|
|
2296
|
-
Et as u,
|
|
2297
|
-
vi as v,
|
|
2298
|
-
Jt as w,
|
|
2299
|
-
he as x,
|
|
2300
|
-
Ni as y,
|
|
2301
|
-
M as z
|
|
2302
|
-
};
|