@kenzuya/mediabunny 1.26.0 → 1.28.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bundles/{mediabunny.mjs → mediabunny.js} +21963 -21388
- package/dist/bundles/mediabunny.min.js +490 -0
- package/dist/modules/shared/mp3-misc.d.ts.map +1 -1
- package/dist/modules/src/adts/adts-demuxer.d.ts +6 -6
- package/dist/modules/src/adts/adts-demuxer.d.ts.map +1 -1
- package/dist/modules/src/adts/adts-muxer.d.ts +4 -4
- package/dist/modules/src/adts/adts-muxer.d.ts.map +1 -1
- package/dist/modules/src/adts/adts-reader.d.ts +1 -1
- package/dist/modules/src/adts/adts-reader.d.ts.map +1 -1
- package/dist/modules/src/avi/avi-demuxer.d.ts +44 -0
- package/dist/modules/src/avi/avi-demuxer.d.ts.map +1 -0
- package/dist/modules/src/avi/avi-misc.d.ts +88 -0
- package/dist/modules/src/avi/avi-misc.d.ts.map +1 -0
- package/dist/modules/src/avi/avi-muxer.d.ts +45 -0
- package/dist/modules/src/avi/avi-muxer.d.ts.map +1 -0
- package/dist/modules/src/avi/riff-writer.d.ts +26 -0
- package/dist/modules/src/avi/riff-writer.d.ts.map +1 -0
- package/dist/modules/src/codec-data.d.ts +8 -3
- package/dist/modules/src/codec-data.d.ts.map +1 -1
- package/dist/modules/src/codec.d.ts +10 -10
- package/dist/modules/src/codec.d.ts.map +1 -1
- package/dist/modules/src/conversion.d.ts +33 -16
- package/dist/modules/src/conversion.d.ts.map +1 -1
- package/dist/modules/src/custom-coder.d.ts +8 -8
- package/dist/modules/src/custom-coder.d.ts.map +1 -1
- package/dist/modules/src/demuxer.d.ts +3 -3
- package/dist/modules/src/demuxer.d.ts.map +1 -1
- package/dist/modules/src/encode.d.ts +8 -8
- package/dist/modules/src/encode.d.ts.map +1 -1
- package/dist/modules/src/flac/flac-demuxer.d.ts +7 -7
- package/dist/modules/src/flac/flac-demuxer.d.ts.map +1 -1
- package/dist/modules/src/flac/flac-misc.d.ts +3 -3
- package/dist/modules/src/flac/flac-misc.d.ts.map +1 -1
- package/dist/modules/src/flac/flac-muxer.d.ts +5 -5
- package/dist/modules/src/flac/flac-muxer.d.ts.map +1 -1
- package/dist/modules/src/id3.d.ts +3 -3
- package/dist/modules/src/id3.d.ts.map +1 -1
- package/dist/modules/src/index.d.ts +20 -20
- package/dist/modules/src/index.d.ts.map +1 -1
- package/dist/modules/src/input-format.d.ts +22 -0
- package/dist/modules/src/input-format.d.ts.map +1 -1
- package/dist/modules/src/input-track.d.ts +8 -8
- package/dist/modules/src/input-track.d.ts.map +1 -1
- package/dist/modules/src/input.d.ts +12 -12
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts +2 -2
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts +12 -12
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-misc.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts +11 -11
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-reader.d.ts +2 -2
- package/dist/modules/src/isobmff/isobmff-reader.d.ts.map +1 -1
- package/dist/modules/src/matroska/ebml.d.ts +3 -3
- package/dist/modules/src/matroska/ebml.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-demuxer.d.ts +13 -13
- package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-input.d.ts +33 -0
- package/dist/modules/src/matroska/matroska-input.d.ts.map +1 -0
- package/dist/modules/src/matroska/matroska-misc.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-muxer.d.ts +5 -5
- package/dist/modules/src/matroska/matroska-muxer.d.ts.map +1 -1
- package/dist/modules/src/media-sink.d.ts +5 -5
- package/dist/modules/src/media-sink.d.ts.map +1 -1
- package/dist/modules/src/media-source.d.ts +22 -4
- package/dist/modules/src/media-source.d.ts.map +1 -1
- package/dist/modules/src/metadata.d.ts +2 -2
- package/dist/modules/src/metadata.d.ts.map +1 -1
- package/dist/modules/src/misc.d.ts +5 -4
- package/dist/modules/src/misc.d.ts.map +1 -1
- package/dist/modules/src/mp3/mp3-demuxer.d.ts +7 -7
- package/dist/modules/src/mp3/mp3-demuxer.d.ts.map +1 -1
- package/dist/modules/src/mp3/mp3-muxer.d.ts +4 -4
- package/dist/modules/src/mp3/mp3-muxer.d.ts.map +1 -1
- package/dist/modules/src/mp3/mp3-reader.d.ts +2 -2
- package/dist/modules/src/mp3/mp3-reader.d.ts.map +1 -1
- package/dist/modules/src/mp3/mp3-writer.d.ts +1 -1
- package/dist/modules/src/mp3/mp3-writer.d.ts.map +1 -1
- package/dist/modules/src/muxer.d.ts +4 -4
- package/dist/modules/src/muxer.d.ts.map +1 -1
- package/dist/modules/src/node.d.ts +1 -1
- package/dist/modules/src/ogg/ogg-demuxer.d.ts +7 -7
- package/dist/modules/src/ogg/ogg-demuxer.d.ts.map +1 -1
- package/dist/modules/src/ogg/ogg-misc.d.ts +1 -1
- package/dist/modules/src/ogg/ogg-misc.d.ts.map +1 -1
- package/dist/modules/src/ogg/ogg-muxer.d.ts +5 -5
- package/dist/modules/src/ogg/ogg-muxer.d.ts.map +1 -1
- package/dist/modules/src/ogg/ogg-reader.d.ts +1 -1
- package/dist/modules/src/ogg/ogg-reader.d.ts.map +1 -1
- package/dist/modules/src/output-format.d.ts +51 -6
- package/dist/modules/src/output-format.d.ts.map +1 -1
- package/dist/modules/src/output.d.ts +13 -13
- package/dist/modules/src/output.d.ts.map +1 -1
- package/dist/modules/src/packet.d.ts +1 -1
- package/dist/modules/src/packet.d.ts.map +1 -1
- package/dist/modules/src/pcm.d.ts.map +1 -1
- package/dist/modules/src/reader.d.ts +2 -2
- package/dist/modules/src/reader.d.ts.map +1 -1
- package/dist/modules/src/sample.d.ts +57 -15
- package/dist/modules/src/sample.d.ts.map +1 -1
- package/dist/modules/src/source.d.ts +3 -3
- package/dist/modules/src/source.d.ts.map +1 -1
- package/dist/modules/src/subtitles.d.ts +1 -1
- package/dist/modules/src/subtitles.d.ts.map +1 -1
- package/dist/modules/src/target.d.ts +2 -2
- package/dist/modules/src/target.d.ts.map +1 -1
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/dist/modules/src/wave/riff-writer.d.ts +1 -1
- package/dist/modules/src/wave/riff-writer.d.ts.map +1 -1
- package/dist/modules/src/wave/wave-demuxer.d.ts +6 -6
- package/dist/modules/src/wave/wave-demuxer.d.ts.map +1 -1
- package/dist/modules/src/wave/wave-muxer.d.ts +4 -4
- package/dist/modules/src/wave/wave-muxer.d.ts.map +1 -1
- package/dist/modules/src/writer.d.ts +1 -1
- package/dist/modules/src/writer.d.ts.map +1 -1
- package/dist/packages/eac3/eac3.wasm +0 -0
- package/dist/packages/eac3/mediabunny-eac3.js +1058 -0
- package/dist/packages/eac3/mediabunny-eac3.min.js +44 -0
- package/dist/packages/mp3-encoder/mediabunny-mp3-encoder.js +694 -0
- package/dist/packages/mp3-encoder/mediabunny-mp3-encoder.min.js +58 -0
- package/dist/packages/mpeg4/mediabunny-mpeg4.js +1198 -0
- package/dist/packages/mpeg4/mediabunny-mpeg4.min.js +44 -0
- package/dist/packages/mpeg4/xvid.wasm +0 -0
- package/package.json +18 -57
- package/dist/bundles/mediabunny.cjs +0 -26140
- package/dist/bundles/mediabunny.min.cjs +0 -147
- package/dist/bundles/mediabunny.min.mjs +0 -146
- package/dist/mediabunny.d.ts +0 -3319
- package/dist/modules/shared/mp3-misc.js +0 -147
- package/dist/modules/src/adts/adts-demuxer.js +0 -239
- package/dist/modules/src/adts/adts-muxer.js +0 -80
- package/dist/modules/src/adts/adts-reader.js +0 -63
- package/dist/modules/src/codec-data.js +0 -1730
- package/dist/modules/src/codec.js +0 -869
- package/dist/modules/src/conversion.js +0 -1459
- package/dist/modules/src/custom-coder.js +0 -117
- package/dist/modules/src/demuxer.js +0 -12
- package/dist/modules/src/encode.js +0 -442
- package/dist/modules/src/flac/flac-demuxer.js +0 -504
- package/dist/modules/src/flac/flac-misc.js +0 -135
- package/dist/modules/src/flac/flac-muxer.js +0 -222
- package/dist/modules/src/id3.js +0 -848
- package/dist/modules/src/index.js +0 -28
- package/dist/modules/src/input-format.js +0 -480
- package/dist/modules/src/input-track.js +0 -372
- package/dist/modules/src/input.js +0 -188
- package/dist/modules/src/isobmff/isobmff-boxes.js +0 -1480
- package/dist/modules/src/isobmff/isobmff-demuxer.js +0 -2618
- package/dist/modules/src/isobmff/isobmff-misc.js +0 -20
- package/dist/modules/src/isobmff/isobmff-muxer.js +0 -966
- package/dist/modules/src/isobmff/isobmff-reader.js +0 -72
- package/dist/modules/src/matroska/ebml.js +0 -653
- package/dist/modules/src/matroska/matroska-demuxer.js +0 -2133
- package/dist/modules/src/matroska/matroska-misc.js +0 -20
- package/dist/modules/src/matroska/matroska-muxer.js +0 -1017
- package/dist/modules/src/media-sink.js +0 -1736
- package/dist/modules/src/media-source.js +0 -1825
- package/dist/modules/src/metadata.js +0 -193
- package/dist/modules/src/misc.js +0 -623
- package/dist/modules/src/mp3/mp3-demuxer.js +0 -285
- package/dist/modules/src/mp3/mp3-muxer.js +0 -123
- package/dist/modules/src/mp3/mp3-reader.js +0 -26
- package/dist/modules/src/mp3/mp3-writer.js +0 -78
- package/dist/modules/src/muxer.js +0 -50
- package/dist/modules/src/node.js +0 -9
- package/dist/modules/src/ogg/ogg-demuxer.js +0 -763
- package/dist/modules/src/ogg/ogg-misc.js +0 -78
- package/dist/modules/src/ogg/ogg-muxer.js +0 -353
- package/dist/modules/src/ogg/ogg-reader.js +0 -65
- package/dist/modules/src/output-format.js +0 -527
- package/dist/modules/src/output.js +0 -300
- package/dist/modules/src/packet.js +0 -182
- package/dist/modules/src/pcm.js +0 -85
- package/dist/modules/src/reader.js +0 -236
- package/dist/modules/src/sample.js +0 -1056
- package/dist/modules/src/source.js +0 -1182
- package/dist/modules/src/subtitles.js +0 -575
- package/dist/modules/src/target.js +0 -140
- package/dist/modules/src/wave/riff-writer.js +0 -30
- package/dist/modules/src/wave/wave-demuxer.js +0 -447
- package/dist/modules/src/wave/wave-muxer.js +0 -318
- package/dist/modules/src/writer.js +0 -370
- package/src/adts/adts-demuxer.ts +0 -331
- package/src/adts/adts-muxer.ts +0 -111
- package/src/adts/adts-reader.ts +0 -85
- package/src/codec-data.ts +0 -2078
- package/src/codec.ts +0 -1092
- package/src/conversion.ts +0 -2112
- package/src/custom-coder.ts +0 -197
- package/src/demuxer.ts +0 -24
- package/src/encode.ts +0 -739
- package/src/flac/flac-demuxer.ts +0 -730
- package/src/flac/flac-misc.ts +0 -164
- package/src/flac/flac-muxer.ts +0 -320
- package/src/id3.ts +0 -925
- package/src/index.ts +0 -221
- package/src/input-format.ts +0 -541
- package/src/input-track.ts +0 -529
- package/src/input.ts +0 -235
- package/src/isobmff/isobmff-boxes.ts +0 -1719
- package/src/isobmff/isobmff-demuxer.ts +0 -3190
- package/src/isobmff/isobmff-misc.ts +0 -29
- package/src/isobmff/isobmff-muxer.ts +0 -1348
- package/src/isobmff/isobmff-reader.ts +0 -91
- package/src/matroska/ebml.ts +0 -730
- package/src/matroska/matroska-demuxer.ts +0 -2481
- package/src/matroska/matroska-misc.ts +0 -29
- package/src/matroska/matroska-muxer.ts +0 -1276
- package/src/media-sink.ts +0 -2179
- package/src/media-source.ts +0 -2243
- package/src/metadata.ts +0 -320
- package/src/misc.ts +0 -798
- package/src/mp3/mp3-demuxer.ts +0 -383
- package/src/mp3/mp3-muxer.ts +0 -166
- package/src/mp3/mp3-reader.ts +0 -34
- package/src/mp3/mp3-writer.ts +0 -120
- package/src/muxer.ts +0 -88
- package/src/node.ts +0 -11
- package/src/ogg/ogg-demuxer.ts +0 -1053
- package/src/ogg/ogg-misc.ts +0 -116
- package/src/ogg/ogg-muxer.ts +0 -497
- package/src/ogg/ogg-reader.ts +0 -93
- package/src/output-format.ts +0 -945
- package/src/output.ts +0 -488
- package/src/packet.ts +0 -263
- package/src/pcm.ts +0 -112
- package/src/reader.ts +0 -323
- package/src/sample.ts +0 -1461
- package/src/source.ts +0 -1688
- package/src/subtitles.ts +0 -711
- package/src/target.ts +0 -204
- package/src/tsconfig.json +0 -16
- package/src/wave/riff-writer.ts +0 -36
- package/src/wave/wave-demuxer.ts +0 -529
- package/src/wave/wave-muxer.ts +0 -371
- package/src/writer.ts +0 -490
|
@@ -0,0 +1,1058 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2025-present, Vanilagy and contributors
|
|
3
|
+
*
|
|
4
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
5
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
6
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// src/misc.ts
|
|
10
|
+
/*!
|
|
11
|
+
* Copyright (c) 2025-present, Vanilagy and contributors
|
|
12
|
+
*
|
|
13
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
14
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
15
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
16
|
+
*/
|
|
17
|
+
var toDataView = (source) => {
|
|
18
|
+
if (source.constructor === DataView) {
|
|
19
|
+
return source;
|
|
20
|
+
}
|
|
21
|
+
if (ArrayBuffer.isView(source)) {
|
|
22
|
+
return new DataView(source.buffer, source.byteOffset, source.byteLength);
|
|
23
|
+
}
|
|
24
|
+
if (typeof SharedArrayBuffer !== "undefined" && source instanceof SharedArrayBuffer) {
|
|
25
|
+
return new DataView(source);
|
|
26
|
+
}
|
|
27
|
+
return new DataView(source);
|
|
28
|
+
};
|
|
29
|
+
var textDecoder = new TextDecoder;
|
|
30
|
+
var textEncoder = new TextEncoder;
|
|
31
|
+
var invertObject = (object) => {
|
|
32
|
+
return Object.fromEntries(Object.entries(object).map(([key, value]) => [value, key]));
|
|
33
|
+
};
|
|
34
|
+
var COLOR_PRIMARIES_MAP = {
|
|
35
|
+
bt709: 1,
|
|
36
|
+
bt470bg: 5,
|
|
37
|
+
smpte170m: 6,
|
|
38
|
+
bt2020: 9,
|
|
39
|
+
smpte432: 12
|
|
40
|
+
};
|
|
41
|
+
var COLOR_PRIMARIES_MAP_INVERSE = invertObject(COLOR_PRIMARIES_MAP);
|
|
42
|
+
var TRANSFER_CHARACTERISTICS_MAP = {
|
|
43
|
+
bt709: 1,
|
|
44
|
+
smpte170m: 6,
|
|
45
|
+
linear: 8,
|
|
46
|
+
"iec61966-2-1": 13,
|
|
47
|
+
pq: 16,
|
|
48
|
+
hlg: 18
|
|
49
|
+
};
|
|
50
|
+
var TRANSFER_CHARACTERISTICS_MAP_INVERSE = invertObject(TRANSFER_CHARACTERISTICS_MAP);
|
|
51
|
+
var MATRIX_COEFFICIENTS_MAP = {
|
|
52
|
+
rgb: 0,
|
|
53
|
+
bt709: 1,
|
|
54
|
+
bt470bg: 5,
|
|
55
|
+
smpte170m: 6,
|
|
56
|
+
"bt2020-ncl": 9
|
|
57
|
+
};
|
|
58
|
+
var MATRIX_COEFFICIENTS_MAP_INVERSE = invertObject(MATRIX_COEFFICIENTS_MAP);
|
|
59
|
+
var isAllowSharedBufferSource = (x) => {
|
|
60
|
+
return x instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && x instanceof SharedArrayBuffer || ArrayBuffer.isView(x);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
class AsyncMutex {
|
|
64
|
+
currentPromise = Promise.resolve();
|
|
65
|
+
async acquire() {
|
|
66
|
+
let resolver;
|
|
67
|
+
const nextPromise = new Promise((resolve) => {
|
|
68
|
+
resolver = resolve;
|
|
69
|
+
});
|
|
70
|
+
const currentPromiseAlias = this.currentPromise;
|
|
71
|
+
this.currentPromise = nextPromise;
|
|
72
|
+
await currentPromiseAlias;
|
|
73
|
+
return resolver;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
var clamp = (value, min, max) => {
|
|
77
|
+
return Math.max(min, Math.min(max, value));
|
|
78
|
+
};
|
|
79
|
+
var SECOND_TO_MICROSECOND_FACTOR = 1e6 * (1 + Number.EPSILON);
|
|
80
|
+
class CallSerializer {
|
|
81
|
+
currentPromise = Promise.resolve();
|
|
82
|
+
call(fn) {
|
|
83
|
+
return this.currentPromise = this.currentPromise.then(fn);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
var polyfillSymbolDispose = () => {
|
|
87
|
+
Symbol.dispose ??= Symbol("Symbol.dispose");
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/custom-coder.ts
|
|
91
|
+
/*!
|
|
92
|
+
* Copyright (c) 2025-present, Vanilagy and contributors
|
|
93
|
+
*
|
|
94
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
95
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
96
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
class CustomVideoDecoder {
|
|
100
|
+
codec;
|
|
101
|
+
config;
|
|
102
|
+
onSample;
|
|
103
|
+
static supports(codec, config) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class CustomAudioDecoder {
|
|
109
|
+
codec;
|
|
110
|
+
config;
|
|
111
|
+
onSample;
|
|
112
|
+
static supports(codec, config) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
class CustomVideoEncoder {
|
|
118
|
+
codec;
|
|
119
|
+
config;
|
|
120
|
+
onPacket;
|
|
121
|
+
static supports(codec, config) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
class CustomAudioEncoder {
|
|
127
|
+
codec;
|
|
128
|
+
config;
|
|
129
|
+
onPacket;
|
|
130
|
+
static supports(codec, config) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
var customVideoDecoders = [];
|
|
135
|
+
var customAudioDecoders = [];
|
|
136
|
+
var customVideoEncoders = [];
|
|
137
|
+
var customAudioEncoders = [];
|
|
138
|
+
var registerDecoder = (decoder) => {
|
|
139
|
+
if (decoder.prototype instanceof CustomVideoDecoder) {
|
|
140
|
+
const casted = decoder;
|
|
141
|
+
if (customVideoDecoders.includes(casted)) {
|
|
142
|
+
console.warn("Video decoder already registered.");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
customVideoDecoders.push(casted);
|
|
146
|
+
} else if (decoder.prototype instanceof CustomAudioDecoder) {
|
|
147
|
+
const casted = decoder;
|
|
148
|
+
if (customAudioDecoders.includes(casted)) {
|
|
149
|
+
console.warn("Audio decoder already registered.");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
customAudioDecoders.push(casted);
|
|
153
|
+
} else {
|
|
154
|
+
throw new TypeError("Decoder must be a CustomVideoDecoder or CustomAudioDecoder.");
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var registerEncoder = (encoder) => {
|
|
158
|
+
if (encoder.prototype instanceof CustomVideoEncoder) {
|
|
159
|
+
const casted = encoder;
|
|
160
|
+
if (customVideoEncoders.includes(casted)) {
|
|
161
|
+
console.warn("Video encoder already registered.");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
customVideoEncoders.push(casted);
|
|
165
|
+
} else if (encoder.prototype instanceof CustomAudioEncoder) {
|
|
166
|
+
const casted = encoder;
|
|
167
|
+
if (customAudioEncoders.includes(casted)) {
|
|
168
|
+
console.warn("Audio encoder already registered.");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
customAudioEncoders.push(casted);
|
|
172
|
+
} else {
|
|
173
|
+
throw new TypeError("Encoder must be a CustomVideoEncoder or CustomAudioEncoder.");
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/packet.ts
|
|
178
|
+
/*!
|
|
179
|
+
* Copyright (c) 2025-present, Vanilagy and contributors
|
|
180
|
+
*
|
|
181
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
182
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
183
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
184
|
+
*/
|
|
185
|
+
var PLACEHOLDER_DATA = new Uint8Array(0);
|
|
186
|
+
|
|
187
|
+
class EncodedPacket {
|
|
188
|
+
data;
|
|
189
|
+
type;
|
|
190
|
+
timestamp;
|
|
191
|
+
duration;
|
|
192
|
+
sequenceNumber;
|
|
193
|
+
byteLength;
|
|
194
|
+
sideData;
|
|
195
|
+
constructor(data, type, timestamp, duration, sequenceNumber = -1, byteLength, sideData) {
|
|
196
|
+
this.data = data;
|
|
197
|
+
this.type = type;
|
|
198
|
+
this.timestamp = timestamp;
|
|
199
|
+
this.duration = duration;
|
|
200
|
+
this.sequenceNumber = sequenceNumber;
|
|
201
|
+
if (data === PLACEHOLDER_DATA && byteLength === undefined) {
|
|
202
|
+
throw new Error("Internal error: byteLength must be explicitly provided when constructing metadata-only packets.");
|
|
203
|
+
}
|
|
204
|
+
if (byteLength === undefined) {
|
|
205
|
+
byteLength = data.byteLength;
|
|
206
|
+
}
|
|
207
|
+
if (!(data instanceof Uint8Array)) {
|
|
208
|
+
throw new TypeError("data must be a Uint8Array.");
|
|
209
|
+
}
|
|
210
|
+
if (type !== "key" && type !== "delta") {
|
|
211
|
+
throw new TypeError('type must be either "key" or "delta".');
|
|
212
|
+
}
|
|
213
|
+
if (!Number.isFinite(timestamp)) {
|
|
214
|
+
throw new TypeError("timestamp must be a number.");
|
|
215
|
+
}
|
|
216
|
+
if (!Number.isFinite(duration) || duration < 0) {
|
|
217
|
+
throw new TypeError("duration must be a non-negative number.");
|
|
218
|
+
}
|
|
219
|
+
if (!Number.isFinite(sequenceNumber)) {
|
|
220
|
+
throw new TypeError("sequenceNumber must be a number.");
|
|
221
|
+
}
|
|
222
|
+
if (!Number.isInteger(byteLength) || byteLength < 0) {
|
|
223
|
+
throw new TypeError("byteLength must be a non-negative integer.");
|
|
224
|
+
}
|
|
225
|
+
if (sideData !== undefined && (typeof sideData !== "object" || !sideData)) {
|
|
226
|
+
throw new TypeError("sideData, when provided, must be an object.");
|
|
227
|
+
}
|
|
228
|
+
if (sideData?.alpha !== undefined && !(sideData.alpha instanceof Uint8Array)) {
|
|
229
|
+
throw new TypeError("sideData.alpha, when provided, must be a Uint8Array.");
|
|
230
|
+
}
|
|
231
|
+
if (sideData?.alphaByteLength !== undefined && (!Number.isInteger(sideData.alphaByteLength) || sideData.alphaByteLength < 0)) {
|
|
232
|
+
throw new TypeError("sideData.alphaByteLength, when provided, must be a non-negative integer.");
|
|
233
|
+
}
|
|
234
|
+
this.byteLength = byteLength;
|
|
235
|
+
this.sideData = sideData ?? {};
|
|
236
|
+
if (this.sideData.alpha && this.sideData.alphaByteLength === undefined) {
|
|
237
|
+
this.sideData.alphaByteLength = this.sideData.alpha.byteLength;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
get isMetadataOnly() {
|
|
241
|
+
return this.data === PLACEHOLDER_DATA;
|
|
242
|
+
}
|
|
243
|
+
get microsecondTimestamp() {
|
|
244
|
+
return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.timestamp);
|
|
245
|
+
}
|
|
246
|
+
get microsecondDuration() {
|
|
247
|
+
return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.duration);
|
|
248
|
+
}
|
|
249
|
+
toEncodedVideoChunk() {
|
|
250
|
+
if (this.isMetadataOnly) {
|
|
251
|
+
throw new TypeError("Metadata-only packets cannot be converted to a video chunk.");
|
|
252
|
+
}
|
|
253
|
+
if (typeof EncodedVideoChunk === "undefined") {
|
|
254
|
+
throw new Error("Your browser does not support EncodedVideoChunk.");
|
|
255
|
+
}
|
|
256
|
+
return new EncodedVideoChunk({
|
|
257
|
+
data: this.data,
|
|
258
|
+
type: this.type,
|
|
259
|
+
timestamp: this.microsecondTimestamp,
|
|
260
|
+
duration: this.microsecondDuration
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
alphaToEncodedVideoChunk(type = this.type) {
|
|
264
|
+
if (!this.sideData.alpha) {
|
|
265
|
+
throw new TypeError("This packet does not contain alpha side data.");
|
|
266
|
+
}
|
|
267
|
+
if (this.isMetadataOnly) {
|
|
268
|
+
throw new TypeError("Metadata-only packets cannot be converted to a video chunk.");
|
|
269
|
+
}
|
|
270
|
+
if (typeof EncodedVideoChunk === "undefined") {
|
|
271
|
+
throw new Error("Your browser does not support EncodedVideoChunk.");
|
|
272
|
+
}
|
|
273
|
+
return new EncodedVideoChunk({
|
|
274
|
+
data: this.sideData.alpha,
|
|
275
|
+
type,
|
|
276
|
+
timestamp: this.microsecondTimestamp,
|
|
277
|
+
duration: this.microsecondDuration
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
toEncodedAudioChunk() {
|
|
281
|
+
if (this.isMetadataOnly) {
|
|
282
|
+
throw new TypeError("Metadata-only packets cannot be converted to an audio chunk.");
|
|
283
|
+
}
|
|
284
|
+
if (typeof EncodedAudioChunk === "undefined") {
|
|
285
|
+
throw new Error("Your browser does not support EncodedAudioChunk.");
|
|
286
|
+
}
|
|
287
|
+
return new EncodedAudioChunk({
|
|
288
|
+
data: this.data,
|
|
289
|
+
type: this.type,
|
|
290
|
+
timestamp: this.microsecondTimestamp,
|
|
291
|
+
duration: this.microsecondDuration
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
static fromEncodedChunk(chunk, sideData) {
|
|
295
|
+
if (!(chunk instanceof EncodedVideoChunk || chunk instanceof EncodedAudioChunk)) {
|
|
296
|
+
throw new TypeError("chunk must be an EncodedVideoChunk or EncodedAudioChunk.");
|
|
297
|
+
}
|
|
298
|
+
const data = new Uint8Array(chunk.byteLength);
|
|
299
|
+
chunk.copyTo(data);
|
|
300
|
+
return new EncodedPacket(data, chunk.type, chunk.timestamp / 1e6, (chunk.duration ?? 0) / 1e6, undefined, undefined, sideData);
|
|
301
|
+
}
|
|
302
|
+
clone(options) {
|
|
303
|
+
if (options !== undefined && (typeof options !== "object" || options === null)) {
|
|
304
|
+
throw new TypeError("options, when provided, must be an object.");
|
|
305
|
+
}
|
|
306
|
+
if (options?.timestamp !== undefined && !Number.isFinite(options.timestamp)) {
|
|
307
|
+
throw new TypeError("options.timestamp, when provided, must be a number.");
|
|
308
|
+
}
|
|
309
|
+
if (options?.duration !== undefined && !Number.isFinite(options.duration)) {
|
|
310
|
+
throw new TypeError("options.duration, when provided, must be a number.");
|
|
311
|
+
}
|
|
312
|
+
return new EncodedPacket(this.data, this.type, options?.timestamp ?? this.timestamp, options?.duration ?? this.duration, this.sequenceNumber, this.byteLength);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/sample.ts
|
|
317
|
+
/*!
|
|
318
|
+
* Copyright (c) 2025-present, Vanilagy and contributors
|
|
319
|
+
*
|
|
320
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
321
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
322
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
323
|
+
*/
|
|
324
|
+
polyfillSymbolDispose();
|
|
325
|
+
var lastVideoGcErrorLog = -Infinity;
|
|
326
|
+
var lastAudioGcErrorLog = -Infinity;
|
|
327
|
+
var finalizationRegistry = null;
|
|
328
|
+
if (typeof FinalizationRegistry !== "undefined") {
|
|
329
|
+
finalizationRegistry = new FinalizationRegistry((value) => {
|
|
330
|
+
const now = Date.now();
|
|
331
|
+
if (value.type === "video") {
|
|
332
|
+
if (now - lastVideoGcErrorLog >= 1000) {
|
|
333
|
+
console.error(`A VideoSample was garbage collected without first being closed. For proper resource management,` + ` make sure to call close() on all your VideoSamples as soon as you're done using them.`);
|
|
334
|
+
lastVideoGcErrorLog = now;
|
|
335
|
+
}
|
|
336
|
+
if (typeof VideoFrame !== "undefined" && value.data instanceof VideoFrame) {
|
|
337
|
+
value.data.close();
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
if (now - lastAudioGcErrorLog >= 1000) {
|
|
341
|
+
console.error(`An AudioSample was garbage collected without first being closed. For proper resource management,` + ` make sure to call close() on all your AudioSamples as soon as you're done using them.`);
|
|
342
|
+
lastAudioGcErrorLog = now;
|
|
343
|
+
}
|
|
344
|
+
if (typeof AudioData !== "undefined" && value.data instanceof AudioData) {
|
|
345
|
+
value.data.close();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
var VIDEO_SAMPLE_PIXEL_FORMATS = [
|
|
351
|
+
"I420",
|
|
352
|
+
"I420P10",
|
|
353
|
+
"I420P12",
|
|
354
|
+
"I420A",
|
|
355
|
+
"I420AP10",
|
|
356
|
+
"I420AP12",
|
|
357
|
+
"I422",
|
|
358
|
+
"I422P10",
|
|
359
|
+
"I422P12",
|
|
360
|
+
"I422A",
|
|
361
|
+
"I422AP10",
|
|
362
|
+
"I422AP12",
|
|
363
|
+
"I444",
|
|
364
|
+
"I444P10",
|
|
365
|
+
"I444P12",
|
|
366
|
+
"I444A",
|
|
367
|
+
"I444AP10",
|
|
368
|
+
"I444AP12",
|
|
369
|
+
"NV12",
|
|
370
|
+
"RGBA",
|
|
371
|
+
"RGBX",
|
|
372
|
+
"BGRA",
|
|
373
|
+
"BGRX"
|
|
374
|
+
];
|
|
375
|
+
var VIDEO_SAMPLE_PIXEL_FORMATS_SET = new Set(VIDEO_SAMPLE_PIXEL_FORMATS);
|
|
376
|
+
var AUDIO_SAMPLE_FORMATS = new Set([
|
|
377
|
+
"f32",
|
|
378
|
+
"f32-planar",
|
|
379
|
+
"s16",
|
|
380
|
+
"s16-planar",
|
|
381
|
+
"s32",
|
|
382
|
+
"s32-planar",
|
|
383
|
+
"u8",
|
|
384
|
+
"u8-planar"
|
|
385
|
+
]);
|
|
386
|
+
|
|
387
|
+
class AudioSample {
|
|
388
|
+
_data;
|
|
389
|
+
_closed = false;
|
|
390
|
+
format;
|
|
391
|
+
sampleRate;
|
|
392
|
+
numberOfFrames;
|
|
393
|
+
numberOfChannels;
|
|
394
|
+
duration;
|
|
395
|
+
timestamp;
|
|
396
|
+
get microsecondTimestamp() {
|
|
397
|
+
return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.timestamp);
|
|
398
|
+
}
|
|
399
|
+
get microsecondDuration() {
|
|
400
|
+
return Math.trunc(SECOND_TO_MICROSECOND_FACTOR * this.duration);
|
|
401
|
+
}
|
|
402
|
+
constructor(init) {
|
|
403
|
+
if (isAudioData(init)) {
|
|
404
|
+
if (init.format === null) {
|
|
405
|
+
throw new TypeError("AudioData with null format is not supported.");
|
|
406
|
+
}
|
|
407
|
+
this._data = init;
|
|
408
|
+
this.format = init.format;
|
|
409
|
+
this.sampleRate = init.sampleRate;
|
|
410
|
+
this.numberOfFrames = init.numberOfFrames;
|
|
411
|
+
this.numberOfChannels = init.numberOfChannels;
|
|
412
|
+
this.timestamp = init.timestamp / 1e6;
|
|
413
|
+
this.duration = init.numberOfFrames / init.sampleRate;
|
|
414
|
+
} else {
|
|
415
|
+
if (!init || typeof init !== "object") {
|
|
416
|
+
throw new TypeError("Invalid AudioDataInit: must be an object.");
|
|
417
|
+
}
|
|
418
|
+
if (!AUDIO_SAMPLE_FORMATS.has(init.format)) {
|
|
419
|
+
throw new TypeError("Invalid AudioDataInit: invalid format.");
|
|
420
|
+
}
|
|
421
|
+
if (!Number.isFinite(init.sampleRate) || init.sampleRate <= 0) {
|
|
422
|
+
throw new TypeError("Invalid AudioDataInit: sampleRate must be > 0.");
|
|
423
|
+
}
|
|
424
|
+
if (!Number.isInteger(init.numberOfChannels) || init.numberOfChannels === 0) {
|
|
425
|
+
throw new TypeError("Invalid AudioDataInit: numberOfChannels must be an integer > 0.");
|
|
426
|
+
}
|
|
427
|
+
if (!Number.isFinite(init?.timestamp)) {
|
|
428
|
+
throw new TypeError("init.timestamp must be a number.");
|
|
429
|
+
}
|
|
430
|
+
const numberOfFrames = init.data.byteLength / (getBytesPerSample(init.format) * init.numberOfChannels);
|
|
431
|
+
if (!Number.isInteger(numberOfFrames)) {
|
|
432
|
+
throw new TypeError("Invalid AudioDataInit: data size is not a multiple of frame size.");
|
|
433
|
+
}
|
|
434
|
+
this.format = init.format;
|
|
435
|
+
this.sampleRate = init.sampleRate;
|
|
436
|
+
this.numberOfFrames = numberOfFrames;
|
|
437
|
+
this.numberOfChannels = init.numberOfChannels;
|
|
438
|
+
this.timestamp = init.timestamp;
|
|
439
|
+
this.duration = numberOfFrames / init.sampleRate;
|
|
440
|
+
let dataBuffer;
|
|
441
|
+
if (init.data instanceof ArrayBuffer) {
|
|
442
|
+
dataBuffer = new Uint8Array(init.data);
|
|
443
|
+
} else if (ArrayBuffer.isView(init.data)) {
|
|
444
|
+
dataBuffer = new Uint8Array(init.data.buffer, init.data.byteOffset, init.data.byteLength);
|
|
445
|
+
} else {
|
|
446
|
+
throw new TypeError("Invalid AudioDataInit: data is not a BufferSource.");
|
|
447
|
+
}
|
|
448
|
+
const expectedSize = this.numberOfFrames * this.numberOfChannels * getBytesPerSample(this.format);
|
|
449
|
+
if (dataBuffer.byteLength < expectedSize) {
|
|
450
|
+
throw new TypeError("Invalid AudioDataInit: insufficient data size.");
|
|
451
|
+
}
|
|
452
|
+
this._data = dataBuffer;
|
|
453
|
+
}
|
|
454
|
+
finalizationRegistry?.register(this, { type: "audio", data: this._data }, this);
|
|
455
|
+
}
|
|
456
|
+
allocationSize(options) {
|
|
457
|
+
if (!options || typeof options !== "object") {
|
|
458
|
+
throw new TypeError("options must be an object.");
|
|
459
|
+
}
|
|
460
|
+
if (!Number.isInteger(options.planeIndex) || options.planeIndex < 0) {
|
|
461
|
+
throw new TypeError("planeIndex must be a non-negative integer.");
|
|
462
|
+
}
|
|
463
|
+
if (options.format !== undefined && !AUDIO_SAMPLE_FORMATS.has(options.format)) {
|
|
464
|
+
throw new TypeError("Invalid format.");
|
|
465
|
+
}
|
|
466
|
+
if (options.frameOffset !== undefined && (!Number.isInteger(options.frameOffset) || options.frameOffset < 0)) {
|
|
467
|
+
throw new TypeError("frameOffset must be a non-negative integer.");
|
|
468
|
+
}
|
|
469
|
+
if (options.frameCount !== undefined && (!Number.isInteger(options.frameCount) || options.frameCount < 0)) {
|
|
470
|
+
throw new TypeError("frameCount must be a non-negative integer.");
|
|
471
|
+
}
|
|
472
|
+
if (this._closed) {
|
|
473
|
+
throw new Error("AudioSample is closed.");
|
|
474
|
+
}
|
|
475
|
+
const destFormat = options.format ?? this.format;
|
|
476
|
+
const frameOffset = options.frameOffset ?? 0;
|
|
477
|
+
if (frameOffset >= this.numberOfFrames) {
|
|
478
|
+
throw new RangeError("frameOffset out of range");
|
|
479
|
+
}
|
|
480
|
+
const copyFrameCount = options.frameCount !== undefined ? options.frameCount : this.numberOfFrames - frameOffset;
|
|
481
|
+
if (copyFrameCount > this.numberOfFrames - frameOffset) {
|
|
482
|
+
throw new RangeError("frameCount out of range");
|
|
483
|
+
}
|
|
484
|
+
const bytesPerSample = getBytesPerSample(destFormat);
|
|
485
|
+
const isPlanar = formatIsPlanar(destFormat);
|
|
486
|
+
if (isPlanar && options.planeIndex >= this.numberOfChannels) {
|
|
487
|
+
throw new RangeError("planeIndex out of range");
|
|
488
|
+
}
|
|
489
|
+
if (!isPlanar && options.planeIndex !== 0) {
|
|
490
|
+
throw new RangeError("planeIndex out of range");
|
|
491
|
+
}
|
|
492
|
+
const elementCount = isPlanar ? copyFrameCount : copyFrameCount * this.numberOfChannels;
|
|
493
|
+
return elementCount * bytesPerSample;
|
|
494
|
+
}
|
|
495
|
+
copyTo(destination, options) {
|
|
496
|
+
if (!isAllowSharedBufferSource(destination)) {
|
|
497
|
+
throw new TypeError("destination must be an ArrayBuffer or an ArrayBuffer view.");
|
|
498
|
+
}
|
|
499
|
+
if (!options || typeof options !== "object") {
|
|
500
|
+
throw new TypeError("options must be an object.");
|
|
501
|
+
}
|
|
502
|
+
if (!Number.isInteger(options.planeIndex) || options.planeIndex < 0) {
|
|
503
|
+
throw new TypeError("planeIndex must be a non-negative integer.");
|
|
504
|
+
}
|
|
505
|
+
if (options.format !== undefined && !AUDIO_SAMPLE_FORMATS.has(options.format)) {
|
|
506
|
+
throw new TypeError("Invalid format.");
|
|
507
|
+
}
|
|
508
|
+
if (options.frameOffset !== undefined && (!Number.isInteger(options.frameOffset) || options.frameOffset < 0)) {
|
|
509
|
+
throw new TypeError("frameOffset must be a non-negative integer.");
|
|
510
|
+
}
|
|
511
|
+
if (options.frameCount !== undefined && (!Number.isInteger(options.frameCount) || options.frameCount < 0)) {
|
|
512
|
+
throw new TypeError("frameCount must be a non-negative integer.");
|
|
513
|
+
}
|
|
514
|
+
if (this._closed) {
|
|
515
|
+
throw new Error("AudioSample is closed.");
|
|
516
|
+
}
|
|
517
|
+
const { planeIndex, format, frameCount: optFrameCount, frameOffset: optFrameOffset } = options;
|
|
518
|
+
const destFormat = format ?? this.format;
|
|
519
|
+
if (!destFormat)
|
|
520
|
+
throw new Error("Destination format not determined");
|
|
521
|
+
const numFrames = this.numberOfFrames;
|
|
522
|
+
const numChannels = this.numberOfChannels;
|
|
523
|
+
const frameOffset = optFrameOffset ?? 0;
|
|
524
|
+
if (frameOffset >= numFrames) {
|
|
525
|
+
throw new RangeError("frameOffset out of range");
|
|
526
|
+
}
|
|
527
|
+
const copyFrameCount = optFrameCount !== undefined ? optFrameCount : numFrames - frameOffset;
|
|
528
|
+
if (copyFrameCount > numFrames - frameOffset) {
|
|
529
|
+
throw new RangeError("frameCount out of range");
|
|
530
|
+
}
|
|
531
|
+
const destBytesPerSample = getBytesPerSample(destFormat);
|
|
532
|
+
const destIsPlanar = formatIsPlanar(destFormat);
|
|
533
|
+
if (destIsPlanar && planeIndex >= numChannels) {
|
|
534
|
+
throw new RangeError("planeIndex out of range");
|
|
535
|
+
}
|
|
536
|
+
if (!destIsPlanar && planeIndex !== 0) {
|
|
537
|
+
throw new RangeError("planeIndex out of range");
|
|
538
|
+
}
|
|
539
|
+
const destElementCount = destIsPlanar ? copyFrameCount : copyFrameCount * numChannels;
|
|
540
|
+
const requiredSize = destElementCount * destBytesPerSample;
|
|
541
|
+
if (destination.byteLength < requiredSize) {
|
|
542
|
+
throw new RangeError("Destination buffer is too small");
|
|
543
|
+
}
|
|
544
|
+
const destView = toDataView(destination);
|
|
545
|
+
const writeFn = getWriteFunction(destFormat);
|
|
546
|
+
if (isAudioData(this._data)) {
|
|
547
|
+
if (destIsPlanar) {
|
|
548
|
+
if (destFormat === "f32-planar") {
|
|
549
|
+
this._data.copyTo(destination, {
|
|
550
|
+
planeIndex,
|
|
551
|
+
frameOffset,
|
|
552
|
+
frameCount: copyFrameCount,
|
|
553
|
+
format: "f32-planar"
|
|
554
|
+
});
|
|
555
|
+
} else {
|
|
556
|
+
const tempBuffer = new ArrayBuffer(copyFrameCount * 4);
|
|
557
|
+
const tempArray = new Float32Array(tempBuffer);
|
|
558
|
+
this._data.copyTo(tempArray, {
|
|
559
|
+
planeIndex,
|
|
560
|
+
frameOffset,
|
|
561
|
+
frameCount: copyFrameCount,
|
|
562
|
+
format: "f32-planar"
|
|
563
|
+
});
|
|
564
|
+
const tempView = new DataView(tempBuffer);
|
|
565
|
+
for (let i = 0;i < copyFrameCount; i++) {
|
|
566
|
+
const destOffset = i * destBytesPerSample;
|
|
567
|
+
const sample = tempView.getFloat32(i * 4, true);
|
|
568
|
+
writeFn(destView, destOffset, sample);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
} else {
|
|
572
|
+
const numCh = numChannels;
|
|
573
|
+
const temp = new Float32Array(copyFrameCount);
|
|
574
|
+
for (let ch = 0;ch < numCh; ch++) {
|
|
575
|
+
this._data.copyTo(temp, {
|
|
576
|
+
planeIndex: ch,
|
|
577
|
+
frameOffset,
|
|
578
|
+
frameCount: copyFrameCount,
|
|
579
|
+
format: "f32-planar"
|
|
580
|
+
});
|
|
581
|
+
for (let i = 0;i < copyFrameCount; i++) {
|
|
582
|
+
const destIndex = i * numCh + ch;
|
|
583
|
+
const destOffset = destIndex * destBytesPerSample;
|
|
584
|
+
writeFn(destView, destOffset, temp[i]);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
} else {
|
|
589
|
+
const uint8Data = this._data;
|
|
590
|
+
const srcView = toDataView(uint8Data);
|
|
591
|
+
const srcFormat = this.format;
|
|
592
|
+
const readFn = getReadFunction(srcFormat);
|
|
593
|
+
const srcBytesPerSample = getBytesPerSample(srcFormat);
|
|
594
|
+
const srcIsPlanar = formatIsPlanar(srcFormat);
|
|
595
|
+
for (let i = 0;i < copyFrameCount; i++) {
|
|
596
|
+
if (destIsPlanar) {
|
|
597
|
+
const destOffset = i * destBytesPerSample;
|
|
598
|
+
let srcOffset;
|
|
599
|
+
if (srcIsPlanar) {
|
|
600
|
+
srcOffset = (planeIndex * numFrames + (i + frameOffset)) * srcBytesPerSample;
|
|
601
|
+
} else {
|
|
602
|
+
srcOffset = ((i + frameOffset) * numChannels + planeIndex) * srcBytesPerSample;
|
|
603
|
+
}
|
|
604
|
+
const normalized = readFn(srcView, srcOffset);
|
|
605
|
+
writeFn(destView, destOffset, normalized);
|
|
606
|
+
} else {
|
|
607
|
+
for (let ch = 0;ch < numChannels; ch++) {
|
|
608
|
+
const destIndex = i * numChannels + ch;
|
|
609
|
+
const destOffset = destIndex * destBytesPerSample;
|
|
610
|
+
let srcOffset;
|
|
611
|
+
if (srcIsPlanar) {
|
|
612
|
+
srcOffset = (ch * numFrames + (i + frameOffset)) * srcBytesPerSample;
|
|
613
|
+
} else {
|
|
614
|
+
srcOffset = ((i + frameOffset) * numChannels + ch) * srcBytesPerSample;
|
|
615
|
+
}
|
|
616
|
+
const normalized = readFn(srcView, srcOffset);
|
|
617
|
+
writeFn(destView, destOffset, normalized);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
clone() {
|
|
624
|
+
if (this._closed) {
|
|
625
|
+
throw new Error("AudioSample is closed.");
|
|
626
|
+
}
|
|
627
|
+
if (isAudioData(this._data)) {
|
|
628
|
+
const sample = new AudioSample(this._data.clone());
|
|
629
|
+
sample.setTimestamp(this.timestamp);
|
|
630
|
+
return sample;
|
|
631
|
+
}
|
|
632
|
+
return new AudioSample({
|
|
633
|
+
format: this.format,
|
|
634
|
+
sampleRate: this.sampleRate,
|
|
635
|
+
numberOfFrames: this.numberOfFrames,
|
|
636
|
+
numberOfChannels: this.numberOfChannels,
|
|
637
|
+
timestamp: this.timestamp,
|
|
638
|
+
data: this._data
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
close() {
|
|
642
|
+
if (this._closed) {
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
finalizationRegistry?.unregister(this);
|
|
646
|
+
if (isAudioData(this._data)) {
|
|
647
|
+
this._data.close();
|
|
648
|
+
} else {
|
|
649
|
+
this._data = new Uint8Array(0);
|
|
650
|
+
}
|
|
651
|
+
this._closed = true;
|
|
652
|
+
}
|
|
653
|
+
toAudioData() {
|
|
654
|
+
if (this._closed) {
|
|
655
|
+
throw new Error("AudioSample is closed.");
|
|
656
|
+
}
|
|
657
|
+
if (isAudioData(this._data)) {
|
|
658
|
+
if (this._data.timestamp === this.microsecondTimestamp) {
|
|
659
|
+
return this._data.clone();
|
|
660
|
+
}
|
|
661
|
+
if (formatIsPlanar(this.format)) {
|
|
662
|
+
const size = this.allocationSize({
|
|
663
|
+
planeIndex: 0,
|
|
664
|
+
format: this.format
|
|
665
|
+
});
|
|
666
|
+
const data2 = new ArrayBuffer(size * this.numberOfChannels);
|
|
667
|
+
for (let i = 0;i < this.numberOfChannels; i++) {
|
|
668
|
+
this.copyTo(new Uint8Array(data2, i * size, size), {
|
|
669
|
+
planeIndex: i,
|
|
670
|
+
format: this.format
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
return new AudioData({
|
|
674
|
+
format: this.format,
|
|
675
|
+
sampleRate: this.sampleRate,
|
|
676
|
+
numberOfFrames: this.numberOfFrames,
|
|
677
|
+
numberOfChannels: this.numberOfChannels,
|
|
678
|
+
timestamp: this.microsecondTimestamp,
|
|
679
|
+
data: data2
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
const data = new ArrayBuffer(this.allocationSize({ planeIndex: 0, format: this.format }));
|
|
683
|
+
this.copyTo(data, { planeIndex: 0, format: this.format });
|
|
684
|
+
return new AudioData({
|
|
685
|
+
format: this.format,
|
|
686
|
+
sampleRate: this.sampleRate,
|
|
687
|
+
numberOfFrames: this.numberOfFrames,
|
|
688
|
+
numberOfChannels: this.numberOfChannels,
|
|
689
|
+
timestamp: this.microsecondTimestamp,
|
|
690
|
+
data
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
return new AudioData({
|
|
694
|
+
format: this.format,
|
|
695
|
+
sampleRate: this.sampleRate,
|
|
696
|
+
numberOfFrames: this.numberOfFrames,
|
|
697
|
+
numberOfChannels: this.numberOfChannels,
|
|
698
|
+
timestamp: this.microsecondTimestamp,
|
|
699
|
+
data: this._data.buffer instanceof ArrayBuffer ? this._data.buffer : this._data.slice()
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
toAudioBuffer() {
|
|
703
|
+
if (this._closed) {
|
|
704
|
+
throw new Error("AudioSample is closed.");
|
|
705
|
+
}
|
|
706
|
+
const audioBuffer = new AudioBuffer({
|
|
707
|
+
numberOfChannels: this.numberOfChannels,
|
|
708
|
+
length: this.numberOfFrames,
|
|
709
|
+
sampleRate: this.sampleRate
|
|
710
|
+
});
|
|
711
|
+
const dataBytes = new Float32Array(this.allocationSize({ planeIndex: 0, format: "f32-planar" }) / 4);
|
|
712
|
+
for (let i = 0;i < this.numberOfChannels; i++) {
|
|
713
|
+
this.copyTo(dataBytes, { planeIndex: i, format: "f32-planar" });
|
|
714
|
+
audioBuffer.copyToChannel(dataBytes, i);
|
|
715
|
+
}
|
|
716
|
+
return audioBuffer;
|
|
717
|
+
}
|
|
718
|
+
setTimestamp(newTimestamp) {
|
|
719
|
+
if (!Number.isFinite(newTimestamp)) {
|
|
720
|
+
throw new TypeError("newTimestamp must be a number.");
|
|
721
|
+
}
|
|
722
|
+
this.timestamp = newTimestamp;
|
|
723
|
+
}
|
|
724
|
+
[Symbol.dispose]() {
|
|
725
|
+
this.close();
|
|
726
|
+
}
|
|
727
|
+
static *_fromAudioBuffer(audioBuffer, timestamp) {
|
|
728
|
+
if (!(audioBuffer instanceof AudioBuffer)) {
|
|
729
|
+
throw new TypeError("audioBuffer must be an AudioBuffer.");
|
|
730
|
+
}
|
|
731
|
+
const MAX_FLOAT_COUNT = 48000 * 5;
|
|
732
|
+
const numberOfChannels = audioBuffer.numberOfChannels;
|
|
733
|
+
const sampleRate = audioBuffer.sampleRate;
|
|
734
|
+
const totalFrames = audioBuffer.length;
|
|
735
|
+
const maxFramesPerChunk = Math.floor(MAX_FLOAT_COUNT / numberOfChannels);
|
|
736
|
+
let currentRelativeFrame = 0;
|
|
737
|
+
let remainingFrames = totalFrames;
|
|
738
|
+
while (remainingFrames > 0) {
|
|
739
|
+
const framesToCopy = Math.min(maxFramesPerChunk, remainingFrames);
|
|
740
|
+
const chunkData = new Float32Array(numberOfChannels * framesToCopy);
|
|
741
|
+
for (let channel = 0;channel < numberOfChannels; channel++) {
|
|
742
|
+
audioBuffer.copyFromChannel(chunkData.subarray(channel * framesToCopy, (channel + 1) * framesToCopy), channel, currentRelativeFrame);
|
|
743
|
+
}
|
|
744
|
+
yield new AudioSample({
|
|
745
|
+
format: "f32-planar",
|
|
746
|
+
sampleRate,
|
|
747
|
+
numberOfFrames: framesToCopy,
|
|
748
|
+
numberOfChannels,
|
|
749
|
+
timestamp: timestamp + currentRelativeFrame / sampleRate,
|
|
750
|
+
data: chunkData
|
|
751
|
+
});
|
|
752
|
+
currentRelativeFrame += framesToCopy;
|
|
753
|
+
remainingFrames -= framesToCopy;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
static fromAudioBuffer(audioBuffer, timestamp) {
|
|
757
|
+
if (!(audioBuffer instanceof AudioBuffer)) {
|
|
758
|
+
throw new TypeError("audioBuffer must be an AudioBuffer.");
|
|
759
|
+
}
|
|
760
|
+
const MAX_FLOAT_COUNT = 48000 * 5;
|
|
761
|
+
const numberOfChannels = audioBuffer.numberOfChannels;
|
|
762
|
+
const sampleRate = audioBuffer.sampleRate;
|
|
763
|
+
const totalFrames = audioBuffer.length;
|
|
764
|
+
const maxFramesPerChunk = Math.floor(MAX_FLOAT_COUNT / numberOfChannels);
|
|
765
|
+
let currentRelativeFrame = 0;
|
|
766
|
+
let remainingFrames = totalFrames;
|
|
767
|
+
const result = [];
|
|
768
|
+
while (remainingFrames > 0) {
|
|
769
|
+
const framesToCopy = Math.min(maxFramesPerChunk, remainingFrames);
|
|
770
|
+
const chunkData = new Float32Array(numberOfChannels * framesToCopy);
|
|
771
|
+
for (let channel = 0;channel < numberOfChannels; channel++) {
|
|
772
|
+
audioBuffer.copyFromChannel(chunkData.subarray(channel * framesToCopy, (channel + 1) * framesToCopy), channel, currentRelativeFrame);
|
|
773
|
+
}
|
|
774
|
+
const audioSample = new AudioSample({
|
|
775
|
+
format: "f32-planar",
|
|
776
|
+
sampleRate,
|
|
777
|
+
numberOfFrames: framesToCopy,
|
|
778
|
+
numberOfChannels,
|
|
779
|
+
timestamp: timestamp + currentRelativeFrame / sampleRate,
|
|
780
|
+
data: chunkData
|
|
781
|
+
});
|
|
782
|
+
result.push(audioSample);
|
|
783
|
+
currentRelativeFrame += framesToCopy;
|
|
784
|
+
remainingFrames -= framesToCopy;
|
|
785
|
+
}
|
|
786
|
+
return result;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
var getBytesPerSample = (format) => {
|
|
790
|
+
switch (format) {
|
|
791
|
+
case "u8":
|
|
792
|
+
case "u8-planar":
|
|
793
|
+
return 1;
|
|
794
|
+
case "s16":
|
|
795
|
+
case "s16-planar":
|
|
796
|
+
return 2;
|
|
797
|
+
case "s32":
|
|
798
|
+
case "s32-planar":
|
|
799
|
+
return 4;
|
|
800
|
+
case "f32":
|
|
801
|
+
case "f32-planar":
|
|
802
|
+
return 4;
|
|
803
|
+
default:
|
|
804
|
+
throw new Error("Unknown AudioSampleFormat");
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
var formatIsPlanar = (format) => {
|
|
808
|
+
switch (format) {
|
|
809
|
+
case "u8-planar":
|
|
810
|
+
case "s16-planar":
|
|
811
|
+
case "s32-planar":
|
|
812
|
+
case "f32-planar":
|
|
813
|
+
return true;
|
|
814
|
+
default:
|
|
815
|
+
return false;
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
var getReadFunction = (format) => {
|
|
819
|
+
switch (format) {
|
|
820
|
+
case "u8":
|
|
821
|
+
case "u8-planar":
|
|
822
|
+
return (view, offset) => (view.getUint8(offset) - 128) / 128;
|
|
823
|
+
case "s16":
|
|
824
|
+
case "s16-planar":
|
|
825
|
+
return (view, offset) => view.getInt16(offset, true) / 32768;
|
|
826
|
+
case "s32":
|
|
827
|
+
case "s32-planar":
|
|
828
|
+
return (view, offset) => view.getInt32(offset, true) / 2147483648;
|
|
829
|
+
case "f32":
|
|
830
|
+
case "f32-planar":
|
|
831
|
+
return (view, offset) => view.getFloat32(offset, true);
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
var getWriteFunction = (format) => {
|
|
835
|
+
switch (format) {
|
|
836
|
+
case "u8":
|
|
837
|
+
case "u8-planar":
|
|
838
|
+
return (view, offset, value) => view.setUint8(offset, clamp((value + 1) * 127.5, 0, 255));
|
|
839
|
+
case "s16":
|
|
840
|
+
case "s16-planar":
|
|
841
|
+
return (view, offset, value) => view.setInt16(offset, clamp(Math.round(value * 32767), -32768, 32767), true);
|
|
842
|
+
case "s32":
|
|
843
|
+
case "s32-planar":
|
|
844
|
+
return (view, offset, value) => view.setInt32(offset, clamp(Math.round(value * 2147483647), -2147483648, 2147483647), true);
|
|
845
|
+
case "f32":
|
|
846
|
+
case "f32-planar":
|
|
847
|
+
return (view, offset, value) => view.setFloat32(offset, value, true);
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
var isAudioData = (x) => {
|
|
851
|
+
return typeof AudioData !== "undefined" && x instanceof AudioData;
|
|
852
|
+
};
|
|
853
|
+
// src/index.ts
|
|
854
|
+
/*!
|
|
855
|
+
* Copyright (c) 2025-present, Vanilagy and contributors
|
|
856
|
+
*
|
|
857
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
858
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
859
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
860
|
+
*/
|
|
861
|
+
|
|
862
|
+
// packages/eac3/src/index.ts
|
|
863
|
+
/*!
|
|
864
|
+
* Copyright (c) 2025-present, Vanilagy and contributors (Wiedy Mi)
|
|
865
|
+
*
|
|
866
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
867
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
868
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
869
|
+
*/
|
|
870
|
+
var decodeWorkerUrl = new URL("./decode.worker.ts", import.meta.url);
|
|
871
|
+
var encodeWorkerUrl = new URL("./encode.worker.ts", import.meta.url);
|
|
872
|
+
var createWorker = (url) => {
|
|
873
|
+
return new Worker(url, { type: "module" });
|
|
874
|
+
};
|
|
875
|
+
var AV_CODEC_ID_AC3 = 86019;
|
|
876
|
+
var AV_CODEC_ID_EAC3 = 86056;
|
|
877
|
+
|
|
878
|
+
class Eac3Decoder extends CustomAudioDecoder {
|
|
879
|
+
worker = null;
|
|
880
|
+
nextMessageId = 0;
|
|
881
|
+
pendingMessages = new Map;
|
|
882
|
+
static supports(codec, _config) {
|
|
883
|
+
return codec === "eac3" || codec === "ac3";
|
|
884
|
+
}
|
|
885
|
+
async init() {
|
|
886
|
+
this.worker = createWorker(decodeWorkerUrl);
|
|
887
|
+
const onMessage = (event) => {
|
|
888
|
+
const data = event.data;
|
|
889
|
+
const pending = this.pendingMessages.get(data.id);
|
|
890
|
+
assert2(pending !== undefined);
|
|
891
|
+
this.pendingMessages.delete(data.id);
|
|
892
|
+
if (data.success) {
|
|
893
|
+
pending.resolve(data.data);
|
|
894
|
+
} else {
|
|
895
|
+
pending.reject(data.error);
|
|
896
|
+
}
|
|
897
|
+
};
|
|
898
|
+
this.worker.addEventListener("message", onMessage);
|
|
899
|
+
await this.sendCommand({
|
|
900
|
+
type: "init",
|
|
901
|
+
data: {
|
|
902
|
+
sampleRate: this.config.sampleRate,
|
|
903
|
+
channels: this.config.numberOfChannels,
|
|
904
|
+
codec: this.codec
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
async decode(packet) {
|
|
909
|
+
const packetData = packet.data.slice().buffer;
|
|
910
|
+
const result = await this.sendCommand({
|
|
911
|
+
type: "decode",
|
|
912
|
+
data: { packetData }
|
|
913
|
+
}, [packetData]);
|
|
914
|
+
if (!result || !("pcmData" in result)) {
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
const audioSample = new AudioSample({
|
|
918
|
+
data: new Float32Array(result.pcmData),
|
|
919
|
+
format: "f32",
|
|
920
|
+
numberOfChannels: result.channels,
|
|
921
|
+
sampleRate: result.sampleRate,
|
|
922
|
+
timestamp: packet.timestamp
|
|
923
|
+
});
|
|
924
|
+
this.onSample(audioSample);
|
|
925
|
+
}
|
|
926
|
+
async flush() {
|
|
927
|
+
await this.sendCommand({ type: "flush" });
|
|
928
|
+
}
|
|
929
|
+
close() {
|
|
930
|
+
if (this.worker) {
|
|
931
|
+
this.sendCommand({ type: "close" });
|
|
932
|
+
this.worker.terminate();
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
sendCommand(command, transferables) {
|
|
936
|
+
return new Promise((resolve, reject) => {
|
|
937
|
+
const id = this.nextMessageId++;
|
|
938
|
+
this.pendingMessages.set(id, { resolve, reject });
|
|
939
|
+
assert2(this.worker);
|
|
940
|
+
if (transferables) {
|
|
941
|
+
this.worker.postMessage({ id, command }, transferables);
|
|
942
|
+
} else {
|
|
943
|
+
this.worker.postMessage({ id, command });
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
class Eac3Encoder extends CustomAudioEncoder {
|
|
950
|
+
worker = null;
|
|
951
|
+
nextMessageId = 0;
|
|
952
|
+
pendingMessages = new Map;
|
|
953
|
+
currentTimestamp = 0;
|
|
954
|
+
chunkMetadata = {};
|
|
955
|
+
static supports(codec, _config) {
|
|
956
|
+
return codec === "eac3" || codec === "ac3";
|
|
957
|
+
}
|
|
958
|
+
async init() {
|
|
959
|
+
this.worker = createWorker(encodeWorkerUrl);
|
|
960
|
+
const onMessage = (event) => {
|
|
961
|
+
const data = event.data;
|
|
962
|
+
const pending = this.pendingMessages.get(data.id);
|
|
963
|
+
assert2(pending !== undefined);
|
|
964
|
+
this.pendingMessages.delete(data.id);
|
|
965
|
+
if (data.success) {
|
|
966
|
+
pending.resolve(data.data);
|
|
967
|
+
} else {
|
|
968
|
+
pending.reject(data.error);
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
this.worker.addEventListener("message", onMessage);
|
|
972
|
+
assert2(this.config.bitrate);
|
|
973
|
+
await this.sendCommand({
|
|
974
|
+
type: "init",
|
|
975
|
+
data: {
|
|
976
|
+
sampleRate: this.config.sampleRate,
|
|
977
|
+
channels: this.config.numberOfChannels,
|
|
978
|
+
bitrate: this.config.bitrate,
|
|
979
|
+
codec: this.codec
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
this.chunkMetadata = {
|
|
983
|
+
decoderConfig: {
|
|
984
|
+
codec: this.codec === "eac3" ? "ec-3" : "ac3",
|
|
985
|
+
numberOfChannels: this.config.numberOfChannels,
|
|
986
|
+
sampleRate: this.config.sampleRate
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
async encode(audioSample) {
|
|
991
|
+
const sizePerChannel = audioSample.allocationSize({
|
|
992
|
+
format: "f32-planar",
|
|
993
|
+
planeIndex: 0
|
|
994
|
+
});
|
|
995
|
+
const requiredBytes = audioSample.numberOfChannels * sizePerChannel;
|
|
996
|
+
const audioData = new ArrayBuffer(requiredBytes);
|
|
997
|
+
const audioBytes = new Uint8Array(audioData);
|
|
998
|
+
for (let i = 0;i < audioSample.numberOfChannels; i++) {
|
|
999
|
+
audioSample.copyTo(audioBytes.subarray(i * sizePerChannel), {
|
|
1000
|
+
format: "f32-planar",
|
|
1001
|
+
planeIndex: i
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
const result = await this.sendCommand({
|
|
1005
|
+
type: "encode",
|
|
1006
|
+
data: {
|
|
1007
|
+
pcmData: audioData,
|
|
1008
|
+
numberOfFrames: audioSample.numberOfFrames
|
|
1009
|
+
}
|
|
1010
|
+
}, [audioData]);
|
|
1011
|
+
assert2(result && "encodedData" in result);
|
|
1012
|
+
const duration = audioSample.numberOfFrames / this.config.sampleRate;
|
|
1013
|
+
const encodedPacket = new EncodedPacket(new Uint8Array(result.encodedData), "key", this.currentTimestamp, duration);
|
|
1014
|
+
this.onPacket(encodedPacket, this.currentTimestamp === 0 ? this.chunkMetadata : undefined);
|
|
1015
|
+
if (this.currentTimestamp === 0) {
|
|
1016
|
+
this.chunkMetadata = {};
|
|
1017
|
+
}
|
|
1018
|
+
this.currentTimestamp += duration;
|
|
1019
|
+
}
|
|
1020
|
+
async flush() {
|
|
1021
|
+
await this.sendCommand({ type: "flush" });
|
|
1022
|
+
}
|
|
1023
|
+
close() {
|
|
1024
|
+
if (this.worker) {
|
|
1025
|
+
this.sendCommand({ type: "close" });
|
|
1026
|
+
this.worker.terminate();
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
sendCommand(command, transferables) {
|
|
1030
|
+
return new Promise((resolve, reject) => {
|
|
1031
|
+
const id = this.nextMessageId++;
|
|
1032
|
+
this.pendingMessages.set(id, { resolve, reject });
|
|
1033
|
+
assert2(this.worker);
|
|
1034
|
+
if (transferables) {
|
|
1035
|
+
this.worker.postMessage({ id, command }, transferables);
|
|
1036
|
+
} else {
|
|
1037
|
+
this.worker.postMessage({ id, command });
|
|
1038
|
+
}
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
var registerEac3Decoder = () => {
|
|
1043
|
+
registerDecoder(Eac3Decoder);
|
|
1044
|
+
};
|
|
1045
|
+
var registerEac3Encoder = () => {
|
|
1046
|
+
registerEncoder(Eac3Encoder);
|
|
1047
|
+
};
|
|
1048
|
+
function assert2(x) {
|
|
1049
|
+
if (!x) {
|
|
1050
|
+
throw new Error("Assertion failed.");
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
export {
|
|
1054
|
+
registerEac3Encoder,
|
|
1055
|
+
registerEac3Decoder,
|
|
1056
|
+
AV_CODEC_ID_EAC3,
|
|
1057
|
+
AV_CODEC_ID_AC3
|
|
1058
|
+
};
|