@mediabunny/server 1.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +276 -0
  3. package/dist/bundles/mediabunny-server.cjs +3361 -0
  4. package/dist/bundles/mediabunny-server.min.cjs +10 -0
  5. package/dist/bundles/mediabunny-server.min.mjs +9 -0
  6. package/dist/bundles/mediabunny-server.mjs +3334 -0
  7. package/dist/mediabunny-server.d.ts +105 -0
  8. package/dist/modules/src/audio-decoder.d.ts +21 -0
  9. package/dist/modules/src/audio-decoder.d.ts.map +1 -0
  10. package/dist/modules/src/audio-decoder.js +132 -0
  11. package/dist/modules/src/audio-encoder.d.ts +35 -0
  12. package/dist/modules/src/audio-encoder.d.ts.map +1 -0
  13. package/dist/modules/src/audio-encoder.js +329 -0
  14. package/dist/modules/src/audio-sample.d.ts +38 -0
  15. package/dist/modules/src/audio-sample.d.ts.map +1 -0
  16. package/dist/modules/src/audio-sample.js +119 -0
  17. package/dist/modules/src/index.d.ts +39 -0
  18. package/dist/modules/src/index.d.ts.map +1 -0
  19. package/dist/modules/src/index.js +132 -0
  20. package/dist/modules/src/misc.d.ts +26 -0
  21. package/dist/modules/src/misc.d.ts.map +1 -0
  22. package/dist/modules/src/misc.js +255 -0
  23. package/dist/modules/src/video-decoder.d.ts +30 -0
  24. package/dist/modules/src/video-decoder.d.ts.map +1 -0
  25. package/dist/modules/src/video-decoder.js +214 -0
  26. package/dist/modules/src/video-encoder.d.ts +35 -0
  27. package/dist/modules/src/video-encoder.d.ts.map +1 -0
  28. package/dist/modules/src/video-encoder.js +474 -0
  29. package/dist/modules/src/video-sample.d.ts +45 -0
  30. package/dist/modules/src/video-sample.d.ts.map +1 -0
  31. package/dist/modules/src/video-sample.js +276 -0
  32. package/dist/modules/tsconfig.tsbuildinfo +1 -0
  33. package/package.json +59 -0
  34. package/src/audio-decoder.ts +120 -0
  35. package/src/audio-encoder.ts +396 -0
  36. package/src/audio-sample.ts +101 -0
  37. package/src/index.ts +104 -0
  38. package/src/misc.ts +242 -0
  39. package/src/video-decoder.ts +224 -0
  40. package/src/video-encoder.ts +568 -0
  41. package/src/video-sample.ts +313 -0
@@ -0,0 +1,3361 @@
1
+ /*!
2
+ * Copyright (c) 2026-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
+ "use strict";
9
+ var MediabunnyServer = (() => {
10
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
17
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
18
+ }) : x)(function(x) {
19
+ if (typeof require !== "undefined") return require.apply(this, arguments);
20
+ throw Error('Dynamic require of "' + x + '" is not supported');
21
+ });
22
+ var __export = (target, all) => {
23
+ for (var name in all)
24
+ __defProp(target, name, { get: all[name], enumerable: true });
25
+ };
26
+ var __copyProps = (to, from, except, desc) => {
27
+ if (from && typeof from === "object" || typeof from === "function") {
28
+ for (let key of __getOwnPropNames(from))
29
+ if (!__hasOwnProp.call(to, key) && key !== except)
30
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
31
+ }
32
+ return to;
33
+ };
34
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
35
+ // If the importer is in node compatibility mode or this is not an ESM
36
+ // file that has been converted to a CommonJS file using a Babel-
37
+ // compatible transform (i.e. "__esModule" has not been set), then set
38
+ // "default" to the CommonJS "module.exports" for node compatibility.
39
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
40
+ mod
41
+ ));
42
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
43
+
44
+ // packages/server/src/index.ts
45
+ var index_exports = {};
46
+ __export(index_exports, {
47
+ AvFrameAudioSampleResource: () => AvFrameAudioSampleResource,
48
+ AvFrameVideoSampleResource: () => AvFrameVideoSampleResource,
49
+ registerMediabunnyServer: () => registerMediabunnyServer,
50
+ toAvFrame: () => toAvFrame
51
+ });
52
+ var import_mediabunny7 = __require("mediabunny");
53
+ var NodeAv8 = __toESM(__require("node-av"));
54
+
55
+ // packages/server/src/video-decoder.ts
56
+ var import_mediabunny2 = __require("mediabunny");
57
+ var NodeAv3 = __toESM(__require("node-av"));
58
+
59
+ // packages/server/src/misc.ts
60
+ var NodeAv = __toESM(__require("node-av"));
61
+ var CODEC_TO_CODEC_ID = {
62
+ avc: NodeAv.AV_CODEC_ID_H264,
63
+ hevc: NodeAv.AV_CODEC_ID_HEVC,
64
+ vp8: NodeAv.AV_CODEC_ID_VP8,
65
+ vp9: NodeAv.AV_CODEC_ID_VP9,
66
+ av1: NodeAv.AV_CODEC_ID_AV1,
67
+ aac: NodeAv.AV_CODEC_ID_AAC,
68
+ opus: NodeAv.AV_CODEC_ID_OPUS,
69
+ mp3: NodeAv.AV_CODEC_ID_MP3,
70
+ vorbis: NodeAv.AV_CODEC_ID_VORBIS,
71
+ flac: NodeAv.AV_CODEC_ID_FLAC,
72
+ ac3: NodeAv.AV_CODEC_ID_AC3,
73
+ eac3: NodeAv.AV_CODEC_ID_EAC3
74
+ };
75
+ var cachedHardwareContext = void 0;
76
+ var getHardwareContext = () => {
77
+ if (cachedHardwareContext === void 0) {
78
+ cachedHardwareContext = NodeAv.HardwareContext.auto();
79
+ }
80
+ return cachedHardwareContext;
81
+ };
82
+ var hardwareDecoderCodecCache = /* @__PURE__ */ new Map();
83
+ var getHardwareDecoderCodec = (codecId) => {
84
+ if (!hardwareDecoderCodecCache.has(codecId)) {
85
+ const hw = getHardwareContext();
86
+ hardwareDecoderCodecCache.set(codecId, hw?.getDecoderCodec(codecId) ?? null);
87
+ }
88
+ return hardwareDecoderCodecCache.get(codecId);
89
+ };
90
+ var hardwareEncoderCodecCache = /* @__PURE__ */ new Map();
91
+ var getHardwareEncoderCodec = (codecId) => {
92
+ if (!hardwareEncoderCodecCache.has(codecId)) {
93
+ const hw = getHardwareContext();
94
+ hardwareEncoderCodecCache.set(codecId, hw?.getEncoderCodec(codecId) ?? null);
95
+ }
96
+ return hardwareEncoderCodecCache.get(codecId);
97
+ };
98
+ var mapColorPrimaries = (primaries) => {
99
+ switch (primaries) {
100
+ case "bt709":
101
+ return NodeAv.AVCOL_PRI_BT709;
102
+ case "bt470bg":
103
+ return NodeAv.AVCOL_PRI_BT470BG;
104
+ case "smpte170m":
105
+ return NodeAv.AVCOL_PRI_SMPTE170M;
106
+ case "bt2020":
107
+ return NodeAv.AVCOL_PRI_BT2020;
108
+ case "smpte432":
109
+ return NodeAv.AVCOL_PRI_SMPTE432;
110
+ }
111
+ return null;
112
+ };
113
+ var unmapColorPrimaries = (primaries) => {
114
+ switch (primaries) {
115
+ case NodeAv.AVCOL_PRI_BT709:
116
+ return "bt709";
117
+ case NodeAv.AVCOL_PRI_BT470BG:
118
+ return "bt470bg";
119
+ case NodeAv.AVCOL_PRI_SMPTE170M:
120
+ return "smpte170m";
121
+ case NodeAv.AVCOL_PRI_BT2020:
122
+ return "bt2020";
123
+ case NodeAv.AVCOL_PRI_SMPTE432:
124
+ return "smpte432";
125
+ }
126
+ return null;
127
+ };
128
+ var mapTransferCharacteristics = (transfer) => {
129
+ switch (transfer) {
130
+ case "bt709":
131
+ return NodeAv.AVCOL_TRC_BT709;
132
+ case "smpte170m":
133
+ return NodeAv.AVCOL_TRC_SMPTE170M;
134
+ case "iec61966-2-1":
135
+ return NodeAv.AVCOL_TRC_IEC61966_2_1;
136
+ case "linear":
137
+ return NodeAv.AVCOL_TRC_LINEAR;
138
+ case "pq":
139
+ return NodeAv.AVCOL_TRC_SMPTE2084;
140
+ case "hlg":
141
+ return NodeAv.AVCOL_TRC_ARIB_STD_B67;
142
+ }
143
+ return null;
144
+ };
145
+ var unmapTransferCharacteristics = (transfer) => {
146
+ switch (transfer) {
147
+ case NodeAv.AVCOL_TRC_BT709:
148
+ return "bt709";
149
+ case NodeAv.AVCOL_TRC_SMPTE170M:
150
+ return "smpte170m";
151
+ case NodeAv.AVCOL_TRC_IEC61966_2_1:
152
+ return "iec61966-2-1";
153
+ case NodeAv.AVCOL_TRC_LINEAR:
154
+ return "linear";
155
+ case NodeAv.AVCOL_TRC_SMPTE2084:
156
+ return "pq";
157
+ case NodeAv.AVCOL_TRC_ARIB_STD_B67:
158
+ return "hlg";
159
+ }
160
+ return null;
161
+ };
162
+ var mapMatrixCoefficients = (matrix) => {
163
+ switch (matrix) {
164
+ case "rgb":
165
+ return NodeAv.AVCOL_SPC_RGB;
166
+ case "bt709":
167
+ return NodeAv.AVCOL_SPC_BT709;
168
+ case "bt470bg":
169
+ return NodeAv.AVCOL_SPC_BT470BG;
170
+ case "smpte170m":
171
+ return NodeAv.AVCOL_SPC_SMPTE170M;
172
+ case "bt2020-ncl":
173
+ return NodeAv.AVCOL_SPC_BT2020_NCL;
174
+ }
175
+ return null;
176
+ };
177
+ var unmapMatrixCoefficients = (matrix) => {
178
+ switch (matrix) {
179
+ case NodeAv.AVCOL_SPC_RGB:
180
+ return "rgb";
181
+ case NodeAv.AVCOL_SPC_BT709:
182
+ return "bt709";
183
+ case NodeAv.AVCOL_SPC_BT470BG:
184
+ return "bt470bg";
185
+ case NodeAv.AVCOL_SPC_SMPTE170M:
186
+ return "smpte170m";
187
+ case NodeAv.AVCOL_SPC_BT2020_NCL:
188
+ return "bt2020-ncl";
189
+ }
190
+ return null;
191
+ };
192
+ var toPixelFormat = (ffmpegPixelFormat) => {
193
+ switch (ffmpegPixelFormat) {
194
+ case NodeAv.AV_PIX_FMT_YUV420P:
195
+ return "I420";
196
+ // "deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range"
197
+ case NodeAv.AV_PIX_FMT_YUVJ420P:
198
+ return "I420";
199
+ case NodeAv.AV_PIX_FMT_YUV420P10LE:
200
+ return "I420P10";
201
+ case NodeAv.AV_PIX_FMT_YUV420P12LE:
202
+ return "I420P12";
203
+ case NodeAv.AV_PIX_FMT_YUVA420P:
204
+ return "I420A";
205
+ case NodeAv.AV_PIX_FMT_YUVA420P10LE:
206
+ return "I420AP10";
207
+ case NodeAv.AV_PIX_FMT_YUV422P:
208
+ return "I422";
209
+ // "deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range"
210
+ case NodeAv.AV_PIX_FMT_YUVJ422P:
211
+ return "I422";
212
+ case NodeAv.AV_PIX_FMT_YUV422P10LE:
213
+ return "I422P10";
214
+ case NodeAv.AV_PIX_FMT_YUV422P12LE:
215
+ return "I422P12";
216
+ case NodeAv.AV_PIX_FMT_YUVA422P:
217
+ return "I422A";
218
+ case NodeAv.AV_PIX_FMT_YUVA422P10LE:
219
+ return "I422AP10";
220
+ case NodeAv.AV_PIX_FMT_YUVA422P12LE:
221
+ return "I422AP12";
222
+ case NodeAv.AV_PIX_FMT_YUV444P:
223
+ return "I444";
224
+ // "deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range"
225
+ case NodeAv.AV_PIX_FMT_YUVJ444P:
226
+ return "I444";
227
+ case NodeAv.AV_PIX_FMT_YUV444P10LE:
228
+ return "I444P10";
229
+ case NodeAv.AV_PIX_FMT_YUV444P12LE:
230
+ return "I444P12";
231
+ case NodeAv.AV_PIX_FMT_YUVA444P:
232
+ return "I444A";
233
+ case NodeAv.AV_PIX_FMT_YUVA444P10LE:
234
+ return "I444AP10";
235
+ case NodeAv.AV_PIX_FMT_YUVA444P12LE:
236
+ return "I444AP12";
237
+ case NodeAv.AV_PIX_FMT_NV12:
238
+ return "NV12";
239
+ case NodeAv.AV_PIX_FMT_RGBA:
240
+ return "RGBA";
241
+ case NodeAv.AV_PIX_FMT_RGB0:
242
+ return "RGBX";
243
+ case NodeAv.AV_PIX_FMT_BGRA:
244
+ return "BGRA";
245
+ case NodeAv.AV_PIX_FMT_BGR0:
246
+ return "BGRX";
247
+ default:
248
+ return null;
249
+ }
250
+ };
251
+ var fromPixelFormat = (pixelFormat) => {
252
+ switch (pixelFormat) {
253
+ case "I420":
254
+ return NodeAv.AV_PIX_FMT_YUV420P;
255
+ case "I420P10":
256
+ return NodeAv.AV_PIX_FMT_YUV420P10LE;
257
+ case "I420P12":
258
+ return NodeAv.AV_PIX_FMT_YUV420P12LE;
259
+ case "I420A":
260
+ return NodeAv.AV_PIX_FMT_YUVA420P;
261
+ case "I420AP10":
262
+ return NodeAv.AV_PIX_FMT_YUVA420P10LE;
263
+ case "I422":
264
+ return NodeAv.AV_PIX_FMT_YUV422P;
265
+ case "I422P10":
266
+ return NodeAv.AV_PIX_FMT_YUV422P10LE;
267
+ case "I422P12":
268
+ return NodeAv.AV_PIX_FMT_YUV422P12LE;
269
+ case "I422A":
270
+ return NodeAv.AV_PIX_FMT_YUVA422P;
271
+ case "I422AP10":
272
+ return NodeAv.AV_PIX_FMT_YUVA422P10LE;
273
+ case "I422AP12":
274
+ return NodeAv.AV_PIX_FMT_YUVA422P12LE;
275
+ case "I444":
276
+ return NodeAv.AV_PIX_FMT_YUV444P;
277
+ case "I444P10":
278
+ return NodeAv.AV_PIX_FMT_YUV444P10LE;
279
+ case "I444P12":
280
+ return NodeAv.AV_PIX_FMT_YUV444P12LE;
281
+ case "I444A":
282
+ return NodeAv.AV_PIX_FMT_YUVA444P;
283
+ case "I444AP10":
284
+ return NodeAv.AV_PIX_FMT_YUVA444P10LE;
285
+ case "I444AP12":
286
+ return NodeAv.AV_PIX_FMT_YUVA444P12LE;
287
+ case "NV12":
288
+ return NodeAv.AV_PIX_FMT_NV12;
289
+ case "RGBA":
290
+ return NodeAv.AV_PIX_FMT_RGBA;
291
+ case "RGBX":
292
+ return NodeAv.AV_PIX_FMT_RGB0;
293
+ case "BGRA":
294
+ return NodeAv.AV_PIX_FMT_BGRA;
295
+ case "BGRX":
296
+ return NodeAv.AV_PIX_FMT_BGR0;
297
+ default:
298
+ return NodeAv.AV_PIX_FMT_NONE;
299
+ }
300
+ };
301
+ var toAudioSampleFormat = (ffmpegSampleFormat) => {
302
+ switch (ffmpegSampleFormat) {
303
+ case NodeAv.AV_SAMPLE_FMT_U8:
304
+ return "u8";
305
+ case NodeAv.AV_SAMPLE_FMT_S16:
306
+ return "s16";
307
+ case NodeAv.AV_SAMPLE_FMT_S32:
308
+ return "s32";
309
+ case NodeAv.AV_SAMPLE_FMT_FLT:
310
+ return "f32";
311
+ case NodeAv.AV_SAMPLE_FMT_U8P:
312
+ return "u8-planar";
313
+ case NodeAv.AV_SAMPLE_FMT_S16P:
314
+ return "s16-planar";
315
+ case NodeAv.AV_SAMPLE_FMT_S32P:
316
+ return "s32-planar";
317
+ case NodeAv.AV_SAMPLE_FMT_FLTP:
318
+ return "f32-planar";
319
+ default:
320
+ return null;
321
+ }
322
+ };
323
+ var fromAudioSampleFormat = (sampleFormat) => {
324
+ switch (sampleFormat) {
325
+ case "u8":
326
+ return NodeAv.AV_SAMPLE_FMT_U8;
327
+ case "s16":
328
+ return NodeAv.AV_SAMPLE_FMT_S16;
329
+ case "s32":
330
+ return NodeAv.AV_SAMPLE_FMT_S32;
331
+ case "f32":
332
+ return NodeAv.AV_SAMPLE_FMT_FLT;
333
+ case "u8-planar":
334
+ return NodeAv.AV_SAMPLE_FMT_U8P;
335
+ case "s16-planar":
336
+ return NodeAv.AV_SAMPLE_FMT_S16P;
337
+ case "s32-planar":
338
+ return NodeAv.AV_SAMPLE_FMT_S32P;
339
+ case "f32-planar":
340
+ return NodeAv.AV_SAMPLE_FMT_FLTP;
341
+ default:
342
+ return NodeAv.AV_SAMPLE_FMT_NONE;
343
+ }
344
+ };
345
+ var getChannelLayout = (numChannels) => {
346
+ switch (numChannels) {
347
+ case 1:
348
+ return NodeAv.AV_CHANNEL_LAYOUT_MONO;
349
+ case 2:
350
+ return NodeAv.AV_CHANNEL_LAYOUT_STEREO;
351
+ case 4:
352
+ return NodeAv.AV_CHANNEL_LAYOUT_QUAD;
353
+ case 6:
354
+ return NodeAv.AV_CHANNEL_LAYOUT_5POINT1_BACK;
355
+ case 8:
356
+ return NodeAv.AV_CHANNEL_LAYOUT_7POINT1;
357
+ default:
358
+ return { nbChannels: numChannels, order: NodeAv.AV_CHANNEL_ORDER_UNSPEC, mask: 0n };
359
+ }
360
+ };
361
+ var LIBVPX_VP9 = "libvpx-vp9";
362
+
363
+ // src/misc.ts
364
+ function assert(x) {
365
+ if (!x) {
366
+ throw new Error("Assertion failed.");
367
+ }
368
+ }
369
+ var last = (arr) => {
370
+ return arr && arr[arr.length - 1];
371
+ };
372
+ var readExpGolomb = (bitstream) => {
373
+ let leadingZeroBits = 0;
374
+ while (bitstream.readBits(1) === 0 && leadingZeroBits < 32) {
375
+ leadingZeroBits++;
376
+ }
377
+ if (leadingZeroBits >= 32) {
378
+ throw new Error("Invalid exponential-Golomb code.");
379
+ }
380
+ const result = (1 << leadingZeroBits) - 1 + bitstream.readBits(leadingZeroBits);
381
+ return result;
382
+ };
383
+ var readSignedExpGolomb = (bitstream) => {
384
+ const codeNum = readExpGolomb(bitstream);
385
+ return (codeNum & 1) === 0 ? -(codeNum >> 1) : codeNum + 1 >> 1;
386
+ };
387
+ var toUint8Array = (source) => {
388
+ if (source.constructor === Uint8Array) {
389
+ return source;
390
+ } else if (ArrayBuffer.isView(source)) {
391
+ return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
392
+ } else {
393
+ return new Uint8Array(source);
394
+ }
395
+ };
396
+ var toDataView = (source) => {
397
+ if (source.constructor === DataView) {
398
+ return source;
399
+ } else if (ArrayBuffer.isView(source)) {
400
+ return new DataView(source.buffer, source.byteOffset, source.byteLength);
401
+ } else {
402
+ return new DataView(source);
403
+ }
404
+ };
405
+ var COLOR_PRIMARIES_MAP = {
406
+ bt709: 1,
407
+ // ITU-R BT.709
408
+ bt470bg: 5,
409
+ // ITU-R BT.470BG
410
+ smpte170m: 6,
411
+ // ITU-R BT.601 525 - SMPTE 170M
412
+ bt2020: 9,
413
+ // ITU-R BT.202
414
+ smpte432: 12
415
+ // SMPTE EG 432-1
416
+ };
417
+ var TRANSFER_CHARACTERISTICS_MAP = {
418
+ "bt709": 1,
419
+ // ITU-R BT.709
420
+ "smpte170m": 6,
421
+ // SMPTE 170M
422
+ "linear": 8,
423
+ // Linear transfer characteristics
424
+ "iec61966-2-1": 13,
425
+ // IEC 61966-2-1
426
+ "pq": 16,
427
+ // Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system
428
+ "hlg": 18
429
+ // Rec. ITU-R BT.2100-2 hybrid loggamma (HLG) system
430
+ };
431
+ var MATRIX_COEFFICIENTS_MAP = {
432
+ "rgb": 0,
433
+ // Identity
434
+ "bt709": 1,
435
+ // ITU-R BT.709
436
+ "bt470bg": 5,
437
+ // ITU-R BT.470BG
438
+ "smpte170m": 6,
439
+ // SMPTE 170M
440
+ "bt2020-ncl": 9
441
+ // ITU-R BT.2020-2 (non-constant luminance)
442
+ };
443
+ var bytesToHexString = (bytes) => {
444
+ return [...bytes].map((x) => x.toString(16).padStart(2, "0")).join("");
445
+ };
446
+ var reverseBitsU32 = (x) => {
447
+ x = x >> 1 & 1431655765 | (x & 1431655765) << 1;
448
+ x = x >> 2 & 858993459 | (x & 858993459) << 2;
449
+ x = x >> 4 & 252645135 | (x & 252645135) << 4;
450
+ x = x >> 8 & 16711935 | (x & 16711935) << 8;
451
+ x = x >> 16 & 65535 | (x & 65535) << 16;
452
+ return x >>> 0;
453
+ };
454
+ var binarySearchLessOrEqual = (arr, key, valueGetter) => {
455
+ let low = 0;
456
+ let high = arr.length - 1;
457
+ let ans = -1;
458
+ while (low <= high) {
459
+ const mid = low + (high - low + 1) / 2 | 0;
460
+ const midVal = valueGetter(arr[mid]);
461
+ if (midVal <= key) {
462
+ ans = mid;
463
+ low = mid + 1;
464
+ } else {
465
+ high = mid - 1;
466
+ }
467
+ }
468
+ return ans;
469
+ };
470
+ var SECOND_TO_MICROSECOND_FACTOR = 1e6 * (1 + Number.EPSILON);
471
+ var simplifyRational = (rational) => {
472
+ assert(Number.isInteger(rational.num));
473
+ assert(Number.isInteger(rational.den));
474
+ assert(rational.den !== 0);
475
+ let a = Math.abs(rational.num);
476
+ let b = Math.abs(rational.den);
477
+ while (b !== 0) {
478
+ const t = a % b;
479
+ a = b;
480
+ b = t;
481
+ }
482
+ const gcd = a || 1;
483
+ return {
484
+ num: rational.num / gcd,
485
+ den: rational.den / gcd
486
+ };
487
+ };
488
+
489
+ // packages/server/src/video-sample.ts
490
+ var import_mediabunny = __require("mediabunny");
491
+ var NodeAv2 = __toESM(__require("node-av"));
492
+ var JPEG_RANGE_PIX_FORMATS = /* @__PURE__ */ new Set([
493
+ NodeAv2.AV_PIX_FMT_YUVJ411P,
494
+ NodeAv2.AV_PIX_FMT_YUVJ420P,
495
+ NodeAv2.AV_PIX_FMT_YUVJ422P,
496
+ NodeAv2.AV_PIX_FMT_YUVJ440P,
497
+ NodeAv2.AV_PIX_FMT_YUVJ444P
498
+ ]);
499
+ var AvFrameVideoSampleResource = class _AvFrameVideoSampleResource extends import_mediabunny.VideoSampleResource {
500
+ /**
501
+ * The NodeAV [`Frame`](https://seydx.github.io/node-av/api/lib/classes/Frame.html) instance backing this resource.
502
+ * Access throws if the resource has already been closed.
503
+ */
504
+ get frame() {
505
+ if (!this._frame) {
506
+ throw new Error("AvFrameVideoSampleResource has been closed.");
507
+ }
508
+ return this._frame;
509
+ }
510
+ constructor(frame) {
511
+ super();
512
+ if (frame.getMediaType() !== NodeAv2.AVMEDIA_TYPE_VIDEO) {
513
+ throw new Error("AvFrameVideoSampleResource must be initialized with a video frame.");
514
+ }
515
+ this._frame = frame;
516
+ }
517
+ getFormat() {
518
+ return toPixelFormat(this.frame.format);
519
+ }
520
+ getCodedWidth() {
521
+ return this.frame.width;
522
+ }
523
+ getCodedHeight() {
524
+ return this.frame.height;
525
+ }
526
+ getSquarePixelWidth() {
527
+ if (this.frame.sampleAspectRatio.num > this.frame.sampleAspectRatio.den) {
528
+ return Math.round(this.frame.width * this.frame.sampleAspectRatio.num / this.frame.sampleAspectRatio.den);
529
+ } else {
530
+ return this.frame.width;
531
+ }
532
+ }
533
+ getSquarePixelHeight() {
534
+ if (this.frame.sampleAspectRatio.num > this.frame.sampleAspectRatio.den) {
535
+ return this.frame.height;
536
+ } else {
537
+ return Math.round(this.frame.height * this.frame.sampleAspectRatio.den / this.frame.sampleAspectRatio.num);
538
+ }
539
+ }
540
+ getColorSpace() {
541
+ return new import_mediabunny.VideoSampleColorSpace({
542
+ primaries: unmapColorPrimaries(this.frame.colorPrimaries),
543
+ transfer: unmapTransferCharacteristics(this.frame.colorTrc),
544
+ matrix: unmapMatrixCoefficients(this.frame.colorSpace),
545
+ fullRange: this.frame.colorRange === NodeAv2.AVCOL_RANGE_JPEG || JPEG_RANGE_PIX_FORMATS.has(this.frame.format) ? true : this.frame.colorRange === NodeAv2.AVCOL_RANGE_MPEG ? false : null
546
+ });
547
+ }
548
+ close() {
549
+ this.frame.free();
550
+ this._frame = null;
551
+ }
552
+ getDataPlanes() {
553
+ assert(this.frame.data);
554
+ return this.frame.data.map((data, i) => ({
555
+ data: toUint8Array(data),
556
+ stride: this.frame.linesize[i]
557
+ }));
558
+ }
559
+ async toRgbSample(init, colorSpace) {
560
+ const width = this.frame.width;
561
+ const height = this.frame.height;
562
+ const scaler = new NodeAv2.SoftwareScaleContext();
563
+ const srcFmt = this.frame.format;
564
+ const dstFmt = fromPixelFormat("RGBA");
565
+ scaler.getContext(
566
+ width,
567
+ height,
568
+ srcFmt,
569
+ width,
570
+ height,
571
+ dstFmt,
572
+ NodeAv2.SWS_BILINEAR
573
+ );
574
+ const dstFrame = new NodeAv2.Frame();
575
+ dstFrame.width = width;
576
+ dstFrame.height = height;
577
+ dstFrame.format = dstFmt;
578
+ dstFrame.alloc();
579
+ dstFrame.allocBuffer();
580
+ const srcFrame = this.frame;
581
+ try {
582
+ await scaler.scaleFrame(dstFrame, srcFrame);
583
+ } finally {
584
+ scaler.freeContext();
585
+ }
586
+ dstFrame.sampleAspectRatio = srcFrame.sampleAspectRatio;
587
+ return new import_mediabunny.VideoSample(new _AvFrameVideoSampleResource(dstFrame), init);
588
+ }
589
+ };
590
+ var copyVideoSampleToAvFrame = async (sample, frame, lastBuffer) => {
591
+ assert(sample.format !== null);
592
+ frame.format = fromPixelFormat(sample.format);
593
+ frame.width = sample.codedWidth;
594
+ frame.height = sample.codedHeight;
595
+ frame.sampleAspectRatio = new NodeAv2.Rational(
596
+ sample.pixelAspectRatio.num,
597
+ sample.pixelAspectRatio.den
598
+ );
599
+ frame.colorPrimaries = mapColorPrimaries(sample.colorSpace.primaries ?? "unknown") ?? NodeAv2.AVCOL_PRI_UNSPECIFIED;
600
+ frame.colorSpace = mapMatrixCoefficients(sample.colorSpace.matrix ?? "unknown") ?? NodeAv2.AVCOL_SPC_UNSPECIFIED;
601
+ frame.colorTrc = mapTransferCharacteristics(sample.colorSpace.transfer ?? "unknown") ?? NodeAv2.AVCOL_TRC_UNSPECIFIED;
602
+ frame.colorRange = sample.colorSpace.fullRange === false ? NodeAv2.AVCOL_RANGE_MPEG : sample.colorSpace.fullRange === true ? NodeAv2.AVCOL_RANGE_JPEG : NodeAv2.AVCOL_RANGE_UNSPECIFIED;
603
+ const size = sample.allocationSize();
604
+ if (!lastBuffer || lastBuffer.byteLength !== size) {
605
+ lastBuffer = Buffer.from({ length: size });
606
+ }
607
+ await sample.copyTo(lastBuffer);
608
+ frame.fromBuffer(lastBuffer);
609
+ return lastBuffer;
610
+ };
611
+ var transformVideoSample = async (sample, description) => {
612
+ let srcFrame;
613
+ let srcFrameOwned = false;
614
+ if (sample._data instanceof AvFrameVideoSampleResource) {
615
+ srcFrame = sample._data.frame;
616
+ } else {
617
+ if (sample.format === null) {
618
+ return null;
619
+ }
620
+ srcFrame = new NodeAv2.Frame();
621
+ srcFrame.alloc();
622
+ srcFrameOwned = true;
623
+ await copyVideoSampleToAvFrame(sample, srcFrame, null);
624
+ }
625
+ const chain = [];
626
+ if (sample.squarePixelWidth !== sample.codedWidth || sample.squarePixelHeight !== sample.codedHeight) {
627
+ chain.push(`scale=${sample.squarePixelWidth}:${sample.squarePixelHeight}`);
628
+ chain.push("setsar=1");
629
+ }
630
+ if (description.rotation === 90) {
631
+ chain.push("transpose=1");
632
+ } else if (description.rotation === 180) {
633
+ chain.push("transpose=1,transpose=1");
634
+ } else if (description.rotation === 270) {
635
+ chain.push("transpose=2");
636
+ }
637
+ chain.push(`crop=${Math.round(description.crop.width)}:${Math.round(description.crop.height)}:${Math.round(description.crop.left)}:${Math.round(description.crop.top)}`);
638
+ if (description.fit === "fill") {
639
+ chain.push(`scale=${description.width}:${description.height}`);
640
+ } else if (description.fit === "contain") {
641
+ chain.push(`scale=${description.width}:${description.height}:force_original_aspect_ratio=decrease`);
642
+ chain.push(`pad=${description.width}:${description.height}:(ow-iw)/2:(oh-ih)/2:color=black@0`);
643
+ } else if (description.fit === "cover") {
644
+ chain.push(`scale=${description.width}:${description.height}:force_original_aspect_ratio=increase`);
645
+ chain.push(`crop=${description.width}:${description.height}`);
646
+ }
647
+ chain.push("setsar=1");
648
+ const graph = new NodeAv2.FilterGraph();
649
+ graph.alloc();
650
+ try {
651
+ const srcArgs = `video_size=${srcFrame.width}x${srcFrame.height}:pix_fmt=${srcFrame.format}:time_base=1/1000000:pixel_aspect=${sample.pixelAspectRatio.num}/${sample.pixelAspectRatio.den}`;
652
+ const bufferSrc = graph.createFilter(NodeAv2.Filter.getByName("buffer"), "src", srcArgs);
653
+ const bufferSink = graph.createFilter(NodeAv2.Filter.getByName("buffersink"), "sink");
654
+ assert(bufferSrc && bufferSink);
655
+ const outputs = NodeAv2.FilterInOut.createList([{ name: "in", filterCtx: bufferSrc, padIdx: 0 }]);
656
+ const inputs = NodeAv2.FilterInOut.createList([{ name: "out", filterCtx: bufferSink, padIdx: 0 }]);
657
+ const parseRet = graph.parsePtr(`[in]${chain.join(",")}[out]`, inputs, outputs);
658
+ NodeAv2.FFmpegError.throwIfError(parseRet, "FilterGraph.parsePtr");
659
+ const configRet = await graph.config();
660
+ NodeAv2.FFmpegError.throwIfError(configRet, "FilterGraph.config");
661
+ const addRet = await bufferSrc.buffersrcAddFrame(srcFrame);
662
+ NodeAv2.FFmpegError.throwIfError(addRet, "buffersrcAddFrame");
663
+ await bufferSrc.buffersrcAddFrame(null);
664
+ const dstFrame = new NodeAv2.Frame();
665
+ dstFrame.alloc();
666
+ const getRet = await bufferSink.buffersinkGetFrame(dstFrame);
667
+ NodeAv2.FFmpegError.throwIfError(getRet, "buffersinkGetFrame");
668
+ return new import_mediabunny.VideoSample(new AvFrameVideoSampleResource(dstFrame), {
669
+ timestamp: sample.timestamp,
670
+ duration: sample.duration,
671
+ rotation: 0
672
+ // baked in by the filter graph
673
+ });
674
+ } finally {
675
+ graph.free();
676
+ if (srcFrameOwned) {
677
+ srcFrame.free();
678
+ }
679
+ }
680
+ };
681
+
682
+ // packages/server/src/video-decoder.ts
683
+ var NodeAvVideoDecoder = class extends import_mediabunny2.CustomVideoDecoder {
684
+ constructor() {
685
+ super(...arguments);
686
+ this.codecContext = null;
687
+ // Bookkeeping to restore the original timing information
688
+ this.preciseTimings = [];
689
+ }
690
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
691
+ static supports(codec, config) {
692
+ return codec === "avc" || codec === "hevc" || codec === "vp8" || codec === "vp9" || codec === "av1";
693
+ }
694
+ async init() {
695
+ this.frame = new NodeAv3.Frame();
696
+ this.frame.alloc();
697
+ this.packet = new NodeAv3.Packet();
698
+ this.packet.alloc();
699
+ }
700
+ async initCodecContext(packet) {
701
+ assert(this.codecContext === null);
702
+ const codecId = CODEC_TO_CODEC_ID[this.codec];
703
+ assert(codecId !== void 0);
704
+ let codec;
705
+ if (this.codec === "vp9" && packet.sideData.alpha) {
706
+ codec = NodeAv3.Codec.findDecoderByName(LIBVPX_VP9) ?? NodeAv3.Codec.findDecoder(codecId);
707
+ } else if (
708
+ // This check used to be "is not prefer-hardware", meaning it would default to using software decode. I
709
+ // didn't leave a comment for that back then so I actually don't know what it was for. I'm sure it was to
710
+ // work around an issue but, I don't know. Not using hardware decode at all by defaults feels wrong to me,
711
+ // so I changed it to what it is right now. If an issue is encountered, I can always change it.
712
+ this.config.hardwareAcceleration === "prefer-software" || this.codec === "av1"
713
+ ) {
714
+ codec = NodeAv3.Codec.findDecoder(codecId);
715
+ } else {
716
+ codec = getHardwareDecoderCodec(codecId) ?? NodeAv3.Codec.findDecoder(codecId);
717
+ }
718
+ if (!codec) {
719
+ throw new Error(`Unable to obtain libav codec for '${this.codec}'.`);
720
+ }
721
+ const codecContext = new NodeAv3.CodecContext();
722
+ codecContext.allocContext3(codec);
723
+ this.pixelAspectRatio = simplifyRational({
724
+ num: (this.config.displayAspectWidth ?? this.config.codedWidth ?? 0) * (this.config.codedHeight ?? 0),
725
+ den: (this.config.displayAspectHeight ?? this.config.codedHeight ?? 0) * (this.config.codedWidth ?? 0) || 1
726
+ });
727
+ codecContext.width = this.config.codedWidth ?? 0;
728
+ codecContext.height = this.config.codedHeight ?? 0;
729
+ codecContext.codecType = NodeAv3.AVMEDIA_TYPE_VIDEO;
730
+ codecContext.codecId = codecId;
731
+ codecContext.extraData = this.config.description ? Buffer.from(toUint8Array(this.config.description)) : null;
732
+ codecContext.sampleAspectRatio = new NodeAv3.Rational(this.pixelAspectRatio.num, this.pixelAspectRatio.den);
733
+ const ret = await codecContext.open2();
734
+ NodeAv3.FFmpegError.throwIfError(ret, "Open codec context");
735
+ this.codecContext = codecContext;
736
+ }
737
+ async decode(packet) {
738
+ if (this.codecContext === null) {
739
+ await this.initCodecContext(packet);
740
+ assert(this.codecContext);
741
+ }
742
+ this.packet.isKeyframe = packet.type === "key";
743
+ this.packet.data = Buffer.from(packet.data);
744
+ this.packet.timeBase = { num: 1, den: 1e6 };
745
+ this.packet.pts = BigInt(packet.microsecondTimestamp);
746
+ this.packet.dts = NodeAv3.AV_NOPTS_VALUE;
747
+ this.packet.duration = BigInt(packet.microsecondDuration);
748
+ if (packet.sideData.alpha) {
749
+ const matroskaBlockAdditional = Buffer.alloc(8 + packet.sideData.alpha.byteLength);
750
+ matroskaBlockAdditional[7] = 1;
751
+ matroskaBlockAdditional.set(packet.sideData.alpha, 8);
752
+ this.packet.addSideData(NodeAv3.AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, matroskaBlockAdditional);
753
+ }
754
+ const preciseTimingIndex = binarySearchLessOrEqual(
755
+ this.preciseTimings,
756
+ packet.microsecondTimestamp,
757
+ (x) => x.microsecondTimestamp
758
+ );
759
+ const existingEntry = preciseTimingIndex !== -1 ? this.preciseTimings[preciseTimingIndex] : null;
760
+ if (existingEntry && existingEntry.microsecondTimestamp === packet.microsecondTimestamp) {
761
+ if (existingEntry.timestamp !== packet.timestamp) {
762
+ existingEntry.timestampIsValid = false;
763
+ }
764
+ if (existingEntry.duration !== packet.duration) {
765
+ existingEntry.durationIsValid = false;
766
+ }
767
+ } else {
768
+ this.preciseTimings.splice(preciseTimingIndex + 1, 0, {
769
+ microsecondTimestamp: packet.microsecondTimestamp,
770
+ timestamp: packet.timestamp,
771
+ duration: packet.duration,
772
+ timestampIsValid: true,
773
+ durationIsValid: true
774
+ });
775
+ if (this.preciseTimings.length > 128) {
776
+ this.preciseTimings.shift();
777
+ }
778
+ }
779
+ const ret = await this.codecContext.sendPacket(this.packet);
780
+ NodeAv3.FFmpegError.throwIfError(ret, "Send packet");
781
+ while (true) {
782
+ const receiveRet = await this.codecContext.receiveFrame(this.frame);
783
+ if (receiveRet === NodeAv3.AVERROR_EAGAIN || receiveRet === NodeAv3.AVERROR_EOF) {
784
+ break;
785
+ }
786
+ this.receiveFrame(receiveRet);
787
+ }
788
+ }
789
+ receiveFrame(ret) {
790
+ NodeAv3.FFmpegError.throwIfError(ret, "Receive frame");
791
+ this.frame.sampleAspectRatio = new NodeAv3.Rational(this.pixelAspectRatio.num, this.pixelAspectRatio.den);
792
+ let timestamp = Number(this.frame.pts) / 1e6;
793
+ let duration = Number(this.frame.duration) / 1e6;
794
+ const preciseTimingIndex = binarySearchLessOrEqual(
795
+ this.preciseTimings,
796
+ Number(this.frame.pts),
797
+ (x) => x.microsecondTimestamp
798
+ );
799
+ const entry = preciseTimingIndex !== -1 ? this.preciseTimings[preciseTimingIndex] : null;
800
+ if (entry && entry.microsecondTimestamp === Number(this.frame.pts)) {
801
+ if (entry.timestampIsValid) {
802
+ timestamp = entry.timestamp;
803
+ }
804
+ if (entry.durationIsValid) {
805
+ duration = entry.duration;
806
+ }
807
+ }
808
+ const clone = this.frame.clone();
809
+ if (!clone) {
810
+ throw new Error("Frame clone allocation failed.");
811
+ }
812
+ this.onSample(new import_mediabunny2.VideoSample(new AvFrameVideoSampleResource(clone), {
813
+ timestamp,
814
+ duration
815
+ }));
816
+ }
817
+ async flush() {
818
+ if (!this.codecContext) {
819
+ return;
820
+ }
821
+ const ret = await this.codecContext.sendPacket(null);
822
+ NodeAv3.FFmpegError.throwIfError(ret, "Flush decoder");
823
+ while (true) {
824
+ const receiveRet = await this.codecContext.receiveFrame(this.frame);
825
+ if (receiveRet === NodeAv3.AVERROR_EAGAIN || receiveRet === NodeAv3.AVERROR_EOF) {
826
+ break;
827
+ }
828
+ this.receiveFrame(receiveRet);
829
+ }
830
+ this.codecContext.flushBuffers();
831
+ }
832
+ close() {
833
+ this.codecContext?.freeContext();
834
+ this.frame.free();
835
+ this.packet.free();
836
+ }
837
+ };
838
+
839
+ // packages/server/src/video-encoder.ts
840
+ var import_mediabunny3 = __require("mediabunny");
841
+ var NodeAv4 = __toESM(__require("node-av"));
842
+
843
+ // shared/bitstream.ts
844
+ var Bitstream = class _Bitstream {
845
+ constructor(bytes) {
846
+ this.bytes = bytes;
847
+ /** Current offset in bits. */
848
+ this.pos = 0;
849
+ }
850
+ seekToByte(byteOffset) {
851
+ this.pos = 8 * byteOffset;
852
+ }
853
+ readBit() {
854
+ const byteIndex = Math.floor(this.pos / 8);
855
+ const byte = this.bytes[byteIndex] ?? 0;
856
+ const bitIndex = 7 - (this.pos & 7);
857
+ const bit = (byte & 1 << bitIndex) >> bitIndex;
858
+ this.pos++;
859
+ return bit;
860
+ }
861
+ readBits(n) {
862
+ if (n === 1) {
863
+ return this.readBit();
864
+ }
865
+ let result = 0;
866
+ for (let i = 0; i < n; i++) {
867
+ result <<= 1;
868
+ result |= this.readBit();
869
+ }
870
+ return result;
871
+ }
872
+ writeBits(n, value) {
873
+ const end = this.pos + n;
874
+ for (let i = this.pos; i < end; i++) {
875
+ const byteIndex = Math.floor(i / 8);
876
+ let byte = this.bytes[byteIndex];
877
+ const bitIndex = 7 - (i & 7);
878
+ byte &= ~(1 << bitIndex);
879
+ byte |= (value & 1 << end - i - 1) >> end - i - 1 << bitIndex;
880
+ this.bytes[byteIndex] = byte;
881
+ }
882
+ this.pos = end;
883
+ }
884
+ readAlignedByte() {
885
+ if (this.pos % 8 !== 0) {
886
+ throw new Error("Bitstream is not byte-aligned.");
887
+ }
888
+ const byteIndex = this.pos / 8;
889
+ const byte = this.bytes[byteIndex] ?? 0;
890
+ this.pos += 8;
891
+ return byte;
892
+ }
893
+ skipBits(n) {
894
+ this.pos += n;
895
+ }
896
+ getBitsLeft() {
897
+ return this.bytes.length * 8 - this.pos;
898
+ }
899
+ clone() {
900
+ const clone = new _Bitstream(this.bytes);
901
+ clone.pos = this.pos;
902
+ return clone;
903
+ }
904
+ };
905
+
906
+ // shared/aac-misc.ts
907
+ var aacFrequencyTable = [
908
+ 96e3,
909
+ 88200,
910
+ 64e3,
911
+ 48e3,
912
+ 44100,
913
+ 32e3,
914
+ 24e3,
915
+ 22050,
916
+ 16e3,
917
+ 12e3,
918
+ 11025,
919
+ 8e3,
920
+ 7350
921
+ ];
922
+ var aacChannelMap = [-1, 1, 2, 3, 4, 5, 6, 8];
923
+ var parseAacAudioSpecificConfig = (bytes) => {
924
+ if (!bytes || bytes.byteLength < 2) {
925
+ throw new TypeError("AAC description must be at least 2 bytes long.");
926
+ }
927
+ const bitstream = new Bitstream(bytes);
928
+ let objectType = bitstream.readBits(5);
929
+ if (objectType === 31) {
930
+ objectType = 32 + bitstream.readBits(6);
931
+ }
932
+ const frequencyIndex = bitstream.readBits(4);
933
+ let sampleRate = null;
934
+ if (frequencyIndex === 15) {
935
+ sampleRate = bitstream.readBits(24);
936
+ } else {
937
+ if (frequencyIndex < aacFrequencyTable.length) {
938
+ sampleRate = aacFrequencyTable[frequencyIndex];
939
+ }
940
+ }
941
+ const channelConfiguration = bitstream.readBits(4);
942
+ let numberOfChannels = null;
943
+ if (channelConfiguration >= 1 && channelConfiguration <= 7) {
944
+ numberOfChannels = aacChannelMap[channelConfiguration];
945
+ }
946
+ return {
947
+ objectType,
948
+ frequencyIndex,
949
+ sampleRate,
950
+ channelConfiguration,
951
+ numberOfChannels
952
+ };
953
+ };
954
+ var buildAdtsHeaderTemplate = (config) => {
955
+ const header = new Uint8Array(7);
956
+ const bitstream = new Bitstream(header);
957
+ const { objectType, frequencyIndex, channelConfiguration } = config;
958
+ const profile = objectType - 1;
959
+ bitstream.writeBits(12, 4095);
960
+ bitstream.writeBits(1, 0);
961
+ bitstream.writeBits(2, 0);
962
+ bitstream.writeBits(1, 1);
963
+ bitstream.writeBits(2, profile);
964
+ bitstream.writeBits(4, frequencyIndex);
965
+ bitstream.writeBits(1, 0);
966
+ bitstream.writeBits(3, channelConfiguration);
967
+ bitstream.writeBits(1, 0);
968
+ bitstream.writeBits(1, 0);
969
+ bitstream.writeBits(1, 0);
970
+ bitstream.writeBits(1, 0);
971
+ bitstream.skipBits(13);
972
+ bitstream.writeBits(11, 2047);
973
+ bitstream.writeBits(2, 0);
974
+ return { header, bitstream };
975
+ };
976
+
977
+ // src/codec.ts
978
+ var PCM_AUDIO_CODECS = [
979
+ "pcm-s16",
980
+ // We don't prefix 'le' so we're compatible with the WebCodecs-registered PCM codec strings
981
+ "pcm-s16be",
982
+ "pcm-s24",
983
+ "pcm-s24be",
984
+ "pcm-s32",
985
+ "pcm-s32be",
986
+ "pcm-f32",
987
+ "pcm-f32be",
988
+ "pcm-f64",
989
+ "pcm-f64be",
990
+ "pcm-u8",
991
+ "pcm-s8",
992
+ "ulaw",
993
+ "alaw"
994
+ ];
995
+ var NON_PCM_AUDIO_CODECS = [
996
+ "aac",
997
+ "opus",
998
+ "mp3",
999
+ "vorbis",
1000
+ "flac",
1001
+ "ac3",
1002
+ "eac3"
1003
+ ];
1004
+ var AUDIO_CODECS = [
1005
+ ...NON_PCM_AUDIO_CODECS,
1006
+ ...PCM_AUDIO_CODECS
1007
+ ];
1008
+ var AVC_LEVEL_TABLE = [
1009
+ { maxMacroblocks: 99, maxBitrate: 64e3, maxDpbMbs: 396, level: 10 },
1010
+ // Level 1
1011
+ { maxMacroblocks: 396, maxBitrate: 192e3, maxDpbMbs: 900, level: 11 },
1012
+ // Level 1.1
1013
+ { maxMacroblocks: 396, maxBitrate: 384e3, maxDpbMbs: 2376, level: 12 },
1014
+ // Level 1.2
1015
+ { maxMacroblocks: 396, maxBitrate: 768e3, maxDpbMbs: 2376, level: 13 },
1016
+ // Level 1.3
1017
+ { maxMacroblocks: 396, maxBitrate: 2e6, maxDpbMbs: 2376, level: 20 },
1018
+ // Level 2
1019
+ { maxMacroblocks: 792, maxBitrate: 4e6, maxDpbMbs: 4752, level: 21 },
1020
+ // Level 2.1
1021
+ { maxMacroblocks: 1620, maxBitrate: 4e6, maxDpbMbs: 8100, level: 22 },
1022
+ // Level 2.2
1023
+ { maxMacroblocks: 1620, maxBitrate: 1e7, maxDpbMbs: 8100, level: 30 },
1024
+ // Level 3
1025
+ { maxMacroblocks: 3600, maxBitrate: 14e6, maxDpbMbs: 18e3, level: 31 },
1026
+ // Level 3.1
1027
+ { maxMacroblocks: 5120, maxBitrate: 2e7, maxDpbMbs: 20480, level: 32 },
1028
+ // Level 3.2
1029
+ { maxMacroblocks: 8192, maxBitrate: 2e7, maxDpbMbs: 32768, level: 40 },
1030
+ // Level 4
1031
+ { maxMacroblocks: 8192, maxBitrate: 5e7, maxDpbMbs: 32768, level: 41 },
1032
+ // Level 4.1
1033
+ { maxMacroblocks: 8704, maxBitrate: 5e7, maxDpbMbs: 34816, level: 42 },
1034
+ // Level 4.2
1035
+ { maxMacroblocks: 22080, maxBitrate: 135e6, maxDpbMbs: 110400, level: 50 },
1036
+ // Level 5
1037
+ { maxMacroblocks: 36864, maxBitrate: 24e7, maxDpbMbs: 184320, level: 51 },
1038
+ // Level 5.1
1039
+ { maxMacroblocks: 36864, maxBitrate: 24e7, maxDpbMbs: 184320, level: 52 },
1040
+ // Level 5.2
1041
+ { maxMacroblocks: 139264, maxBitrate: 24e7, maxDpbMbs: 696320, level: 60 },
1042
+ // Level 6
1043
+ { maxMacroblocks: 139264, maxBitrate: 48e7, maxDpbMbs: 696320, level: 61 },
1044
+ // Level 6.1
1045
+ { maxMacroblocks: 139264, maxBitrate: 8e8, maxDpbMbs: 696320, level: 62 }
1046
+ // Level 6.2
1047
+ ];
1048
+ var VP9_LEVEL_TABLE = [
1049
+ { maxPictureSize: 36864, maxBitrate: 2e5, level: 10 },
1050
+ // Level 1
1051
+ { maxPictureSize: 73728, maxBitrate: 8e5, level: 11 },
1052
+ // Level 1.1
1053
+ { maxPictureSize: 122880, maxBitrate: 18e5, level: 20 },
1054
+ // Level 2
1055
+ { maxPictureSize: 245760, maxBitrate: 36e5, level: 21 },
1056
+ // Level 2.1
1057
+ { maxPictureSize: 552960, maxBitrate: 72e5, level: 30 },
1058
+ // Level 3
1059
+ { maxPictureSize: 983040, maxBitrate: 12e6, level: 31 },
1060
+ // Level 3.1
1061
+ { maxPictureSize: 2228224, maxBitrate: 18e6, level: 40 },
1062
+ // Level 4
1063
+ { maxPictureSize: 2228224, maxBitrate: 3e7, level: 41 },
1064
+ // Level 4.1
1065
+ { maxPictureSize: 8912896, maxBitrate: 6e7, level: 50 },
1066
+ // Level 5
1067
+ { maxPictureSize: 8912896, maxBitrate: 12e7, level: 51 },
1068
+ // Level 5.1
1069
+ { maxPictureSize: 8912896, maxBitrate: 18e7, level: 52 },
1070
+ // Level 5.2
1071
+ { maxPictureSize: 35651584, maxBitrate: 18e7, level: 60 },
1072
+ // Level 6
1073
+ { maxPictureSize: 35651584, maxBitrate: 24e7, level: 61 },
1074
+ // Level 6.1
1075
+ { maxPictureSize: 35651584, maxBitrate: 48e7, level: 62 }
1076
+ // Level 6.2
1077
+ ];
1078
+ var VP9_DEFAULT_SUFFIX = ".01.01.01.01.00";
1079
+ var AV1_DEFAULT_SUFFIX = ".0.110.01.01.01.0";
1080
+ var extractVideoCodecString = (trackInfo) => {
1081
+ const { codec, codecDescription, colorSpace, avcCodecInfo, hevcCodecInfo, vp9CodecInfo, av1CodecInfo } = trackInfo;
1082
+ if (codec === "avc") {
1083
+ assert(trackInfo.avcType !== null);
1084
+ if (avcCodecInfo) {
1085
+ const bytes = new Uint8Array([
1086
+ avcCodecInfo.avcProfileIndication,
1087
+ avcCodecInfo.profileCompatibility,
1088
+ avcCodecInfo.avcLevelIndication
1089
+ ]);
1090
+ return `avc${trackInfo.avcType}.${bytesToHexString(bytes)}`;
1091
+ }
1092
+ if (!codecDescription || codecDescription.byteLength < 4) {
1093
+ throw new TypeError("AVC decoder description is not provided or is not at least 4 bytes long.");
1094
+ }
1095
+ return `avc${trackInfo.avcType}.${bytesToHexString(codecDescription.subarray(1, 4))}`;
1096
+ } else if (codec === "hevc") {
1097
+ let generalProfileSpace;
1098
+ let generalProfileIdc;
1099
+ let compatibilityFlags;
1100
+ let generalTierFlag;
1101
+ let generalLevelIdc;
1102
+ let constraintFlags;
1103
+ if (hevcCodecInfo) {
1104
+ generalProfileSpace = hevcCodecInfo.generalProfileSpace;
1105
+ generalProfileIdc = hevcCodecInfo.generalProfileIdc;
1106
+ compatibilityFlags = reverseBitsU32(hevcCodecInfo.generalProfileCompatibilityFlags);
1107
+ generalTierFlag = hevcCodecInfo.generalTierFlag;
1108
+ generalLevelIdc = hevcCodecInfo.generalLevelIdc;
1109
+ constraintFlags = [...hevcCodecInfo.generalConstraintIndicatorFlags];
1110
+ } else {
1111
+ if (!codecDescription || codecDescription.byteLength < 23) {
1112
+ throw new TypeError("HEVC decoder description is not provided or is not at least 23 bytes long.");
1113
+ }
1114
+ const view = toDataView(codecDescription);
1115
+ const profileByte = view.getUint8(1);
1116
+ generalProfileSpace = profileByte >> 6 & 3;
1117
+ generalProfileIdc = profileByte & 31;
1118
+ compatibilityFlags = reverseBitsU32(view.getUint32(2));
1119
+ generalTierFlag = profileByte >> 5 & 1;
1120
+ generalLevelIdc = view.getUint8(12);
1121
+ constraintFlags = [];
1122
+ for (let i = 0; i < 6; i++) {
1123
+ constraintFlags.push(view.getUint8(6 + i));
1124
+ }
1125
+ }
1126
+ let codecString = "hev1.";
1127
+ codecString += ["", "A", "B", "C"][generalProfileSpace] + generalProfileIdc;
1128
+ codecString += ".";
1129
+ codecString += compatibilityFlags.toString(16).toUpperCase();
1130
+ codecString += ".";
1131
+ codecString += generalTierFlag === 0 ? "L" : "H";
1132
+ codecString += generalLevelIdc;
1133
+ while (constraintFlags.length > 0 && constraintFlags[constraintFlags.length - 1] === 0) {
1134
+ constraintFlags.pop();
1135
+ }
1136
+ if (constraintFlags.length > 0) {
1137
+ codecString += ".";
1138
+ codecString += constraintFlags.map((x) => x.toString(16).toUpperCase()).join(".");
1139
+ }
1140
+ return codecString;
1141
+ } else if (codec === "vp8") {
1142
+ return "vp8";
1143
+ } else if (codec === "vp9") {
1144
+ if (!vp9CodecInfo) {
1145
+ const pictureSize = trackInfo.width * trackInfo.height;
1146
+ let level2 = last(VP9_LEVEL_TABLE).level;
1147
+ for (const entry of VP9_LEVEL_TABLE) {
1148
+ if (pictureSize <= entry.maxPictureSize) {
1149
+ level2 = entry.level;
1150
+ break;
1151
+ }
1152
+ }
1153
+ return `vp09.00.${level2.toString().padStart(2, "0")}.08`;
1154
+ }
1155
+ const profile = vp9CodecInfo.profile.toString().padStart(2, "0");
1156
+ const level = vp9CodecInfo.level.toString().padStart(2, "0");
1157
+ const bitDepth = vp9CodecInfo.bitDepth.toString().padStart(2, "0");
1158
+ const chromaSubsampling = vp9CodecInfo.chromaSubsampling.toString().padStart(2, "0");
1159
+ const colourPrimaries = vp9CodecInfo.colourPrimaries.toString().padStart(2, "0");
1160
+ const transferCharacteristics = vp9CodecInfo.transferCharacteristics.toString().padStart(2, "0");
1161
+ const matrixCoefficients = vp9CodecInfo.matrixCoefficients.toString().padStart(2, "0");
1162
+ const videoFullRangeFlag = vp9CodecInfo.videoFullRangeFlag.toString().padStart(2, "0");
1163
+ let string = `vp09.${profile}.${level}.${bitDepth}.${chromaSubsampling}`;
1164
+ string += `.${colourPrimaries}.${transferCharacteristics}.${matrixCoefficients}.${videoFullRangeFlag}`;
1165
+ if (string.endsWith(VP9_DEFAULT_SUFFIX)) {
1166
+ string = string.slice(0, -VP9_DEFAULT_SUFFIX.length);
1167
+ }
1168
+ return string;
1169
+ } else if (codec === "av1") {
1170
+ if (!av1CodecInfo) {
1171
+ const pictureSize = trackInfo.width * trackInfo.height;
1172
+ let level2 = last(VP9_LEVEL_TABLE).level;
1173
+ for (const entry of VP9_LEVEL_TABLE) {
1174
+ if (pictureSize <= entry.maxPictureSize) {
1175
+ level2 = entry.level;
1176
+ break;
1177
+ }
1178
+ }
1179
+ return `av01.0.${level2.toString().padStart(2, "0")}M.08`;
1180
+ }
1181
+ const profile = av1CodecInfo.profile;
1182
+ const level = av1CodecInfo.level.toString().padStart(2, "0");
1183
+ const tier = av1CodecInfo.tier ? "H" : "M";
1184
+ const bitDepth = av1CodecInfo.bitDepth.toString().padStart(2, "0");
1185
+ const monochrome = av1CodecInfo.monochrome ? "1" : "0";
1186
+ const chromaSubsampling = 100 * av1CodecInfo.chromaSubsamplingX + 10 * av1CodecInfo.chromaSubsamplingY + 1 * (av1CodecInfo.chromaSubsamplingX && av1CodecInfo.chromaSubsamplingY ? av1CodecInfo.chromaSamplePosition : 0);
1187
+ const colorPrimaries = colorSpace?.primaries ? COLOR_PRIMARIES_MAP[colorSpace.primaries] : 1;
1188
+ const transferCharacteristics = colorSpace?.transfer ? TRANSFER_CHARACTERISTICS_MAP[colorSpace.transfer] : 1;
1189
+ const matrixCoefficients = colorSpace?.matrix ? MATRIX_COEFFICIENTS_MAP[colorSpace.matrix] : 1;
1190
+ const videoFullRangeFlag = colorSpace?.fullRange ? 1 : 0;
1191
+ let string = `av01.${profile}.${level}${tier}.${bitDepth}`;
1192
+ string += `.${monochrome}.${chromaSubsampling.toString().padStart(3, "0")}`;
1193
+ string += `.${colorPrimaries.toString().padStart(2, "0")}`;
1194
+ string += `.${transferCharacteristics.toString().padStart(2, "0")}`;
1195
+ string += `.${matrixCoefficients.toString().padStart(2, "0")}`;
1196
+ string += `.${videoFullRangeFlag}`;
1197
+ if (string.endsWith(AV1_DEFAULT_SUFFIX)) {
1198
+ string = string.slice(0, -AV1_DEFAULT_SUFFIX.length);
1199
+ }
1200
+ return string;
1201
+ }
1202
+ throw new TypeError(`Unhandled codec '${codec}'.`);
1203
+ };
1204
+
1205
+ // src/codec-data.ts
1206
+ var iterateNalUnitsInAnnexB = function* (packetData) {
1207
+ let i = 0;
1208
+ let nalStart = -1;
1209
+ while (i < packetData.length - 2) {
1210
+ const zeroIndex = packetData.indexOf(0, i);
1211
+ if (zeroIndex === -1 || zeroIndex >= packetData.length - 2) {
1212
+ break;
1213
+ }
1214
+ i = zeroIndex;
1215
+ let startCodeLength = 0;
1216
+ if (i + 3 < packetData.length && packetData[i + 1] === 0 && packetData[i + 2] === 0 && packetData[i + 3] === 1) {
1217
+ startCodeLength = 4;
1218
+ } else if (packetData[i + 1] === 0 && packetData[i + 2] === 1) {
1219
+ startCodeLength = 3;
1220
+ }
1221
+ if (startCodeLength === 0) {
1222
+ i++;
1223
+ continue;
1224
+ }
1225
+ if (nalStart !== -1 && i > nalStart) {
1226
+ yield {
1227
+ offset: nalStart,
1228
+ length: i - nalStart
1229
+ };
1230
+ }
1231
+ nalStart = i + startCodeLength;
1232
+ i = nalStart;
1233
+ }
1234
+ if (nalStart !== -1 && nalStart < packetData.length) {
1235
+ yield {
1236
+ offset: nalStart,
1237
+ length: packetData.length - nalStart
1238
+ };
1239
+ }
1240
+ };
1241
+ var extractNalUnitTypeForAvc = (byte) => {
1242
+ return byte & 31;
1243
+ };
1244
+ var removeEmulationPreventionBytes = (data) => {
1245
+ const result = [];
1246
+ const len = data.length;
1247
+ for (let i = 0; i < len; i++) {
1248
+ if (i + 2 < len && data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 3) {
1249
+ result.push(0, 0);
1250
+ i += 2;
1251
+ } else {
1252
+ result.push(data[i]);
1253
+ }
1254
+ }
1255
+ return new Uint8Array(result);
1256
+ };
1257
+ var ANNEX_B_START_CODE = new Uint8Array([0, 0, 0, 1]);
1258
+ var extractAvcDecoderConfigurationRecord = (packetData) => {
1259
+ try {
1260
+ const spsUnits = [];
1261
+ const ppsUnits = [];
1262
+ const spsExtUnits = [];
1263
+ for (const loc of iterateNalUnitsInAnnexB(packetData)) {
1264
+ const nalUnit = packetData.subarray(loc.offset, loc.offset + loc.length);
1265
+ const type = extractNalUnitTypeForAvc(nalUnit[0]);
1266
+ if (type === 7 /* SPS */) {
1267
+ spsUnits.push(nalUnit);
1268
+ } else if (type === 8 /* PPS */) {
1269
+ ppsUnits.push(nalUnit);
1270
+ } else if (type === 13 /* SPS_EXT */) {
1271
+ spsExtUnits.push(nalUnit);
1272
+ }
1273
+ }
1274
+ if (spsUnits.length === 0) {
1275
+ return null;
1276
+ }
1277
+ if (ppsUnits.length === 0) {
1278
+ return null;
1279
+ }
1280
+ const spsData = spsUnits[0];
1281
+ const spsInfo = parseAvcSps(spsData);
1282
+ assert(spsInfo !== null);
1283
+ const hasExtendedData = spsInfo.profileIdc === 100 || spsInfo.profileIdc === 110 || spsInfo.profileIdc === 122 || spsInfo.profileIdc === 144;
1284
+ return {
1285
+ configurationVersion: 1,
1286
+ avcProfileIndication: spsInfo.profileIdc,
1287
+ profileCompatibility: spsInfo.constraintFlags,
1288
+ avcLevelIndication: spsInfo.levelIdc,
1289
+ lengthSizeMinusOne: 3,
1290
+ // Typically 4 bytes for length field
1291
+ sequenceParameterSets: spsUnits,
1292
+ pictureParameterSets: ppsUnits,
1293
+ chromaFormat: hasExtendedData ? spsInfo.chromaFormatIdc : null,
1294
+ bitDepthLumaMinus8: hasExtendedData ? spsInfo.bitDepthLumaMinus8 : null,
1295
+ bitDepthChromaMinus8: hasExtendedData ? spsInfo.bitDepthChromaMinus8 : null,
1296
+ sequenceParameterSetExt: hasExtendedData ? spsExtUnits : null
1297
+ };
1298
+ } catch (error) {
1299
+ console.error("Error building AVC Decoder Configuration Record:", error);
1300
+ return null;
1301
+ }
1302
+ };
1303
+ var serializeAvcDecoderConfigurationRecord = (record) => {
1304
+ const bytes = [];
1305
+ bytes.push(record.configurationVersion);
1306
+ bytes.push(record.avcProfileIndication);
1307
+ bytes.push(record.profileCompatibility);
1308
+ bytes.push(record.avcLevelIndication);
1309
+ bytes.push(252 | record.lengthSizeMinusOne & 3);
1310
+ bytes.push(224 | record.sequenceParameterSets.length & 31);
1311
+ for (const sps of record.sequenceParameterSets) {
1312
+ const length = sps.byteLength;
1313
+ bytes.push(length >> 8);
1314
+ bytes.push(length & 255);
1315
+ for (let i = 0; i < length; i++) {
1316
+ bytes.push(sps[i]);
1317
+ }
1318
+ }
1319
+ bytes.push(record.pictureParameterSets.length);
1320
+ for (const pps of record.pictureParameterSets) {
1321
+ const length = pps.byteLength;
1322
+ bytes.push(length >> 8);
1323
+ bytes.push(length & 255);
1324
+ for (let i = 0; i < length; i++) {
1325
+ bytes.push(pps[i]);
1326
+ }
1327
+ }
1328
+ if (record.avcProfileIndication === 100 || record.avcProfileIndication === 110 || record.avcProfileIndication === 122 || record.avcProfileIndication === 144) {
1329
+ assert(record.chromaFormat !== null);
1330
+ assert(record.bitDepthLumaMinus8 !== null);
1331
+ assert(record.bitDepthChromaMinus8 !== null);
1332
+ assert(record.sequenceParameterSetExt !== null);
1333
+ bytes.push(252 | record.chromaFormat & 3);
1334
+ bytes.push(248 | record.bitDepthLumaMinus8 & 7);
1335
+ bytes.push(248 | record.bitDepthChromaMinus8 & 7);
1336
+ bytes.push(record.sequenceParameterSetExt.length);
1337
+ for (const spsExt of record.sequenceParameterSetExt) {
1338
+ const length = spsExt.byteLength;
1339
+ bytes.push(length >> 8);
1340
+ bytes.push(length & 255);
1341
+ for (let i = 0; i < length; i++) {
1342
+ bytes.push(spsExt[i]);
1343
+ }
1344
+ }
1345
+ }
1346
+ return new Uint8Array(bytes);
1347
+ };
1348
+ var AVC_HEVC_ASPECT_RATIO_IDC_TABLE = {
1349
+ 1: { num: 1, den: 1 },
1350
+ 2: { num: 12, den: 11 },
1351
+ 3: { num: 10, den: 11 },
1352
+ 4: { num: 16, den: 11 },
1353
+ 5: { num: 40, den: 33 },
1354
+ 6: { num: 24, den: 11 },
1355
+ 7: { num: 20, den: 11 },
1356
+ 8: { num: 32, den: 11 },
1357
+ 9: { num: 80, den: 33 },
1358
+ 10: { num: 18, den: 11 },
1359
+ 11: { num: 15, den: 11 },
1360
+ 12: { num: 64, den: 33 },
1361
+ 13: { num: 160, den: 99 },
1362
+ 14: { num: 4, den: 3 },
1363
+ 15: { num: 3, den: 2 },
1364
+ 16: { num: 2, den: 1 }
1365
+ };
1366
+ var parseAvcSps = (sps) => {
1367
+ try {
1368
+ const bitstream = new Bitstream(removeEmulationPreventionBytes(sps));
1369
+ bitstream.skipBits(1);
1370
+ bitstream.skipBits(2);
1371
+ const nalUnitType = bitstream.readBits(5);
1372
+ if (nalUnitType !== 7) {
1373
+ return null;
1374
+ }
1375
+ const profileIdc = bitstream.readAlignedByte();
1376
+ const constraintFlags = bitstream.readAlignedByte();
1377
+ const levelIdc = bitstream.readAlignedByte();
1378
+ readExpGolomb(bitstream);
1379
+ let chromaFormatIdc = 1;
1380
+ let bitDepthLumaMinus8 = 0;
1381
+ let bitDepthChromaMinus8 = 0;
1382
+ let separateColourPlaneFlag = 0;
1383
+ if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
1384
+ chromaFormatIdc = readExpGolomb(bitstream);
1385
+ if (chromaFormatIdc === 3) {
1386
+ separateColourPlaneFlag = bitstream.readBits(1);
1387
+ }
1388
+ bitDepthLumaMinus8 = readExpGolomb(bitstream);
1389
+ bitDepthChromaMinus8 = readExpGolomb(bitstream);
1390
+ bitstream.skipBits(1);
1391
+ const seqScalingMatrixPresentFlag = bitstream.readBits(1);
1392
+ if (seqScalingMatrixPresentFlag) {
1393
+ for (let i = 0; i < (chromaFormatIdc !== 3 ? 8 : 12); i++) {
1394
+ const seqScalingListPresentFlag = bitstream.readBits(1);
1395
+ if (seqScalingListPresentFlag) {
1396
+ const sizeOfScalingList = i < 6 ? 16 : 64;
1397
+ let lastScale = 8;
1398
+ let nextScale = 8;
1399
+ for (let j = 0; j < sizeOfScalingList; j++) {
1400
+ if (nextScale !== 0) {
1401
+ const deltaScale = readSignedExpGolomb(bitstream);
1402
+ nextScale = (lastScale + deltaScale + 256) % 256;
1403
+ }
1404
+ lastScale = nextScale === 0 ? lastScale : nextScale;
1405
+ }
1406
+ }
1407
+ }
1408
+ }
1409
+ }
1410
+ readExpGolomb(bitstream);
1411
+ const picOrderCntType = readExpGolomb(bitstream);
1412
+ if (picOrderCntType === 0) {
1413
+ readExpGolomb(bitstream);
1414
+ } else if (picOrderCntType === 1) {
1415
+ bitstream.skipBits(1);
1416
+ readSignedExpGolomb(bitstream);
1417
+ readSignedExpGolomb(bitstream);
1418
+ const numRefFramesInPicOrderCntCycle = readExpGolomb(bitstream);
1419
+ for (let i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
1420
+ readSignedExpGolomb(bitstream);
1421
+ }
1422
+ }
1423
+ readExpGolomb(bitstream);
1424
+ bitstream.skipBits(1);
1425
+ const picWidthInMbsMinus1 = readExpGolomb(bitstream);
1426
+ const picHeightInMapUnitsMinus1 = readExpGolomb(bitstream);
1427
+ const codedWidth = 16 * (picWidthInMbsMinus1 + 1);
1428
+ const codedHeight = 16 * (picHeightInMapUnitsMinus1 + 1);
1429
+ let displayWidth = codedWidth;
1430
+ let displayHeight = codedHeight;
1431
+ const frameMbsOnlyFlag = bitstream.readBits(1);
1432
+ if (!frameMbsOnlyFlag) {
1433
+ bitstream.skipBits(1);
1434
+ }
1435
+ bitstream.skipBits(1);
1436
+ const frameCroppingFlag = bitstream.readBits(1);
1437
+ if (frameCroppingFlag) {
1438
+ const frameCropLeftOffset = readExpGolomb(bitstream);
1439
+ const frameCropRightOffset = readExpGolomb(bitstream);
1440
+ const frameCropTopOffset = readExpGolomb(bitstream);
1441
+ const frameCropBottomOffset = readExpGolomb(bitstream);
1442
+ let cropUnitX;
1443
+ let cropUnitY;
1444
+ const chromaArrayType = separateColourPlaneFlag === 0 ? chromaFormatIdc : 0;
1445
+ if (chromaArrayType === 0) {
1446
+ cropUnitX = 1;
1447
+ cropUnitY = 2 - frameMbsOnlyFlag;
1448
+ } else {
1449
+ const subWidthC = chromaFormatIdc === 3 ? 1 : 2;
1450
+ const subHeightC = chromaFormatIdc === 1 ? 2 : 1;
1451
+ cropUnitX = subWidthC;
1452
+ cropUnitY = subHeightC * (2 - frameMbsOnlyFlag);
1453
+ }
1454
+ displayWidth -= cropUnitX * (frameCropLeftOffset + frameCropRightOffset);
1455
+ displayHeight -= cropUnitY * (frameCropTopOffset + frameCropBottomOffset);
1456
+ }
1457
+ let colourPrimaries = 2;
1458
+ let transferCharacteristics = 2;
1459
+ let matrixCoefficients = 2;
1460
+ let fullRangeFlag = 0;
1461
+ let pixelAspectRatio = { num: 1, den: 1 };
1462
+ let numReorderFrames = null;
1463
+ let maxDecFrameBuffering = null;
1464
+ const vuiParametersPresentFlag = bitstream.readBits(1);
1465
+ if (vuiParametersPresentFlag) {
1466
+ const aspectRatioInfoPresentFlag = bitstream.readBits(1);
1467
+ if (aspectRatioInfoPresentFlag) {
1468
+ const aspectRatioIdc = bitstream.readBits(8);
1469
+ if (aspectRatioIdc === 255) {
1470
+ pixelAspectRatio = {
1471
+ num: bitstream.readBits(16),
1472
+ den: bitstream.readBits(16)
1473
+ };
1474
+ } else {
1475
+ const aspectRatio = AVC_HEVC_ASPECT_RATIO_IDC_TABLE[aspectRatioIdc];
1476
+ if (aspectRatio) {
1477
+ pixelAspectRatio = aspectRatio;
1478
+ }
1479
+ }
1480
+ }
1481
+ const overscanInfoPresentFlag = bitstream.readBits(1);
1482
+ if (overscanInfoPresentFlag) {
1483
+ bitstream.skipBits(1);
1484
+ }
1485
+ const videoSignalTypePresentFlag = bitstream.readBits(1);
1486
+ if (videoSignalTypePresentFlag) {
1487
+ bitstream.skipBits(3);
1488
+ fullRangeFlag = bitstream.readBits(1);
1489
+ const colourDescriptionPresentFlag = bitstream.readBits(1);
1490
+ if (colourDescriptionPresentFlag) {
1491
+ colourPrimaries = bitstream.readBits(8);
1492
+ transferCharacteristics = bitstream.readBits(8);
1493
+ matrixCoefficients = bitstream.readBits(8);
1494
+ }
1495
+ }
1496
+ const chromaLocInfoPresentFlag = bitstream.readBits(1);
1497
+ if (chromaLocInfoPresentFlag) {
1498
+ readExpGolomb(bitstream);
1499
+ readExpGolomb(bitstream);
1500
+ }
1501
+ const timingInfoPresentFlag = bitstream.readBits(1);
1502
+ if (timingInfoPresentFlag) {
1503
+ bitstream.skipBits(32);
1504
+ bitstream.skipBits(32);
1505
+ bitstream.skipBits(1);
1506
+ }
1507
+ const nalHrdParametersPresentFlag = bitstream.readBits(1);
1508
+ if (nalHrdParametersPresentFlag) {
1509
+ skipAvcHrdParameters(bitstream);
1510
+ }
1511
+ const vclHrdParametersPresentFlag = bitstream.readBits(1);
1512
+ if (vclHrdParametersPresentFlag) {
1513
+ skipAvcHrdParameters(bitstream);
1514
+ }
1515
+ if (nalHrdParametersPresentFlag || vclHrdParametersPresentFlag) {
1516
+ bitstream.skipBits(1);
1517
+ }
1518
+ bitstream.skipBits(1);
1519
+ const bitstreamRestrictionFlag = bitstream.readBits(1);
1520
+ if (bitstreamRestrictionFlag) {
1521
+ bitstream.skipBits(1);
1522
+ readExpGolomb(bitstream);
1523
+ readExpGolomb(bitstream);
1524
+ readExpGolomb(bitstream);
1525
+ readExpGolomb(bitstream);
1526
+ numReorderFrames = readExpGolomb(bitstream);
1527
+ maxDecFrameBuffering = readExpGolomb(bitstream);
1528
+ }
1529
+ }
1530
+ if (numReorderFrames === null) {
1531
+ assert(maxDecFrameBuffering === null);
1532
+ const constraintSet3Flag = constraintFlags & 16;
1533
+ if ((profileIdc === 44 || profileIdc === 86 || profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244) && constraintSet3Flag) {
1534
+ numReorderFrames = 0;
1535
+ maxDecFrameBuffering = 0;
1536
+ } else {
1537
+ const picWidthInMbs = picWidthInMbsMinus1 + 1;
1538
+ const picHeightInMapUnits = picHeightInMapUnitsMinus1 + 1;
1539
+ const frameHeightInMbs = (2 - frameMbsOnlyFlag) * picHeightInMapUnits;
1540
+ const levelInfo = AVC_LEVEL_TABLE.find(
1541
+ (x) => x.level >= levelIdc
1542
+ ) ?? last(AVC_LEVEL_TABLE);
1543
+ const maxDpbFrames = Math.min(
1544
+ Math.floor(levelInfo.maxDpbMbs / (picWidthInMbs * frameHeightInMbs)),
1545
+ 16
1546
+ );
1547
+ numReorderFrames = maxDpbFrames;
1548
+ maxDecFrameBuffering = maxDpbFrames;
1549
+ }
1550
+ }
1551
+ assert(maxDecFrameBuffering !== null);
1552
+ return {
1553
+ profileIdc,
1554
+ constraintFlags,
1555
+ levelIdc,
1556
+ frameMbsOnlyFlag,
1557
+ chromaFormatIdc,
1558
+ bitDepthLumaMinus8,
1559
+ bitDepthChromaMinus8,
1560
+ codedWidth,
1561
+ codedHeight,
1562
+ displayWidth,
1563
+ displayHeight,
1564
+ pixelAspectRatio,
1565
+ colourPrimaries,
1566
+ matrixCoefficients,
1567
+ transferCharacteristics,
1568
+ fullRangeFlag,
1569
+ numReorderFrames,
1570
+ maxDecFrameBuffering
1571
+ };
1572
+ } catch (error) {
1573
+ console.error("Error parsing AVC SPS:", error);
1574
+ return null;
1575
+ }
1576
+ };
1577
+ var skipAvcHrdParameters = (bitstream) => {
1578
+ const cpb_cnt_minus1 = readExpGolomb(bitstream);
1579
+ bitstream.skipBits(4);
1580
+ bitstream.skipBits(4);
1581
+ for (let i = 0; i <= cpb_cnt_minus1; i++) {
1582
+ readExpGolomb(bitstream);
1583
+ readExpGolomb(bitstream);
1584
+ bitstream.skipBits(1);
1585
+ }
1586
+ bitstream.skipBits(5);
1587
+ bitstream.skipBits(5);
1588
+ bitstream.skipBits(5);
1589
+ bitstream.skipBits(5);
1590
+ };
1591
+ var extractNalUnitTypeForHevc = (byte) => {
1592
+ return byte >> 1 & 63;
1593
+ };
1594
+ var parseHevcSps = (sps) => {
1595
+ try {
1596
+ const bitstream = new Bitstream(removeEmulationPreventionBytes(sps));
1597
+ bitstream.skipBits(16);
1598
+ bitstream.readBits(4);
1599
+ const spsMaxSubLayersMinus1 = bitstream.readBits(3);
1600
+ const spsTemporalIdNestingFlag = bitstream.readBits(1);
1601
+ const {
1602
+ general_profile_space,
1603
+ general_tier_flag,
1604
+ general_profile_idc,
1605
+ general_profile_compatibility_flags,
1606
+ general_constraint_indicator_flags,
1607
+ general_level_idc
1608
+ } = parseProfileTierLevel(bitstream, spsMaxSubLayersMinus1);
1609
+ readExpGolomb(bitstream);
1610
+ const chromaFormatIdc = readExpGolomb(bitstream);
1611
+ let separateColourPlaneFlag = 0;
1612
+ if (chromaFormatIdc === 3) {
1613
+ separateColourPlaneFlag = bitstream.readBits(1);
1614
+ }
1615
+ const picWidthInLumaSamples = readExpGolomb(bitstream);
1616
+ const picHeightInLumaSamples = readExpGolomb(bitstream);
1617
+ let displayWidth = picWidthInLumaSamples;
1618
+ let displayHeight = picHeightInLumaSamples;
1619
+ if (bitstream.readBits(1)) {
1620
+ const confWinLeftOffset = readExpGolomb(bitstream);
1621
+ const confWinRightOffset = readExpGolomb(bitstream);
1622
+ const confWinTopOffset = readExpGolomb(bitstream);
1623
+ const confWinBottomOffset = readExpGolomb(bitstream);
1624
+ let subWidthC = 1;
1625
+ let subHeightC = 1;
1626
+ const chromaArrayType = separateColourPlaneFlag === 0 ? chromaFormatIdc : 0;
1627
+ if (chromaArrayType === 1) {
1628
+ subWidthC = 2;
1629
+ subHeightC = 2;
1630
+ } else if (chromaArrayType === 2) {
1631
+ subWidthC = 2;
1632
+ subHeightC = 1;
1633
+ }
1634
+ displayWidth -= (confWinLeftOffset + confWinRightOffset) * subWidthC;
1635
+ displayHeight -= (confWinTopOffset + confWinBottomOffset) * subHeightC;
1636
+ }
1637
+ const bitDepthLumaMinus8 = readExpGolomb(bitstream);
1638
+ const bitDepthChromaMinus8 = readExpGolomb(bitstream);
1639
+ readExpGolomb(bitstream);
1640
+ const spsSubLayerOrderingInfoPresentFlag = bitstream.readBits(1);
1641
+ const startI = spsSubLayerOrderingInfoPresentFlag ? 0 : spsMaxSubLayersMinus1;
1642
+ let spsMaxNumReorderPics = 0;
1643
+ for (let i = startI; i <= spsMaxSubLayersMinus1; i++) {
1644
+ readExpGolomb(bitstream);
1645
+ spsMaxNumReorderPics = readExpGolomb(bitstream);
1646
+ readExpGolomb(bitstream);
1647
+ }
1648
+ readExpGolomb(bitstream);
1649
+ readExpGolomb(bitstream);
1650
+ readExpGolomb(bitstream);
1651
+ readExpGolomb(bitstream);
1652
+ readExpGolomb(bitstream);
1653
+ readExpGolomb(bitstream);
1654
+ if (bitstream.readBits(1)) {
1655
+ if (bitstream.readBits(1)) {
1656
+ skipScalingListData(bitstream);
1657
+ }
1658
+ }
1659
+ bitstream.skipBits(1);
1660
+ bitstream.skipBits(1);
1661
+ if (bitstream.readBits(1)) {
1662
+ bitstream.skipBits(4);
1663
+ bitstream.skipBits(4);
1664
+ readExpGolomb(bitstream);
1665
+ readExpGolomb(bitstream);
1666
+ bitstream.skipBits(1);
1667
+ }
1668
+ const numShortTermRefPicSets = readExpGolomb(bitstream);
1669
+ skipAllStRefPicSets(bitstream, numShortTermRefPicSets);
1670
+ if (bitstream.readBits(1)) {
1671
+ const numLongTermRefPicsSps = readExpGolomb(bitstream);
1672
+ for (let i = 0; i < numLongTermRefPicsSps; i++) {
1673
+ readExpGolomb(bitstream);
1674
+ bitstream.skipBits(1);
1675
+ }
1676
+ }
1677
+ bitstream.skipBits(1);
1678
+ bitstream.skipBits(1);
1679
+ let colourPrimaries = 2;
1680
+ let transferCharacteristics = 2;
1681
+ let matrixCoefficients = 2;
1682
+ let fullRangeFlag = 0;
1683
+ let minSpatialSegmentationIdc = 0;
1684
+ let pixelAspectRatio = { num: 1, den: 1 };
1685
+ if (bitstream.readBits(1)) {
1686
+ const vui = parseHevcVui(bitstream, spsMaxSubLayersMinus1);
1687
+ pixelAspectRatio = vui.pixelAspectRatio;
1688
+ colourPrimaries = vui.colourPrimaries;
1689
+ transferCharacteristics = vui.transferCharacteristics;
1690
+ matrixCoefficients = vui.matrixCoefficients;
1691
+ fullRangeFlag = vui.fullRangeFlag;
1692
+ minSpatialSegmentationIdc = vui.minSpatialSegmentationIdc;
1693
+ }
1694
+ return {
1695
+ displayWidth,
1696
+ displayHeight,
1697
+ pixelAspectRatio,
1698
+ colourPrimaries,
1699
+ transferCharacteristics,
1700
+ matrixCoefficients,
1701
+ fullRangeFlag,
1702
+ maxDecFrameBuffering: spsMaxNumReorderPics + 1,
1703
+ spsMaxSubLayersMinus1,
1704
+ spsTemporalIdNestingFlag,
1705
+ generalProfileSpace: general_profile_space,
1706
+ generalTierFlag: general_tier_flag,
1707
+ generalProfileIdc: general_profile_idc,
1708
+ generalProfileCompatibilityFlags: general_profile_compatibility_flags,
1709
+ generalConstraintIndicatorFlags: general_constraint_indicator_flags,
1710
+ generalLevelIdc: general_level_idc,
1711
+ chromaFormatIdc,
1712
+ bitDepthLumaMinus8,
1713
+ bitDepthChromaMinus8,
1714
+ minSpatialSegmentationIdc
1715
+ };
1716
+ } catch (error) {
1717
+ console.error("Error parsing HEVC SPS:", error);
1718
+ return null;
1719
+ }
1720
+ };
1721
+ var extractHevcDecoderConfigurationRecord = (packetData) => {
1722
+ try {
1723
+ const vpsUnits = [];
1724
+ const spsUnits = [];
1725
+ const ppsUnits = [];
1726
+ const seiUnits = [];
1727
+ for (const loc of iterateNalUnitsInAnnexB(packetData)) {
1728
+ const nalUnit = packetData.subarray(loc.offset, loc.offset + loc.length);
1729
+ const type = extractNalUnitTypeForHevc(nalUnit[0]);
1730
+ if (type === 32 /* VPS_NUT */) {
1731
+ vpsUnits.push(nalUnit);
1732
+ } else if (type === 33 /* SPS_NUT */) {
1733
+ spsUnits.push(nalUnit);
1734
+ } else if (type === 34 /* PPS_NUT */) {
1735
+ ppsUnits.push(nalUnit);
1736
+ } else if (type === 39 /* PREFIX_SEI_NUT */ || type === 40 /* SUFFIX_SEI_NUT */) {
1737
+ seiUnits.push(nalUnit);
1738
+ }
1739
+ }
1740
+ if (spsUnits.length === 0 || ppsUnits.length === 0) return null;
1741
+ const spsInfo = parseHevcSps(spsUnits[0]);
1742
+ if (!spsInfo) return null;
1743
+ let parallelismType = 0;
1744
+ if (ppsUnits.length > 0) {
1745
+ const pps = ppsUnits[0];
1746
+ const ppsBitstream = new Bitstream(removeEmulationPreventionBytes(pps));
1747
+ ppsBitstream.skipBits(16);
1748
+ readExpGolomb(ppsBitstream);
1749
+ readExpGolomb(ppsBitstream);
1750
+ ppsBitstream.skipBits(1);
1751
+ ppsBitstream.skipBits(1);
1752
+ ppsBitstream.skipBits(3);
1753
+ ppsBitstream.skipBits(1);
1754
+ ppsBitstream.skipBits(1);
1755
+ readExpGolomb(ppsBitstream);
1756
+ readExpGolomb(ppsBitstream);
1757
+ readSignedExpGolomb(ppsBitstream);
1758
+ ppsBitstream.skipBits(1);
1759
+ ppsBitstream.skipBits(1);
1760
+ if (ppsBitstream.readBits(1)) {
1761
+ readExpGolomb(ppsBitstream);
1762
+ }
1763
+ readSignedExpGolomb(ppsBitstream);
1764
+ readSignedExpGolomb(ppsBitstream);
1765
+ ppsBitstream.skipBits(1);
1766
+ ppsBitstream.skipBits(1);
1767
+ ppsBitstream.skipBits(1);
1768
+ ppsBitstream.skipBits(1);
1769
+ const tiles_enabled_flag = ppsBitstream.readBits(1);
1770
+ const entropy_coding_sync_enabled_flag = ppsBitstream.readBits(1);
1771
+ if (!tiles_enabled_flag && !entropy_coding_sync_enabled_flag) parallelismType = 0;
1772
+ else if (tiles_enabled_flag && !entropy_coding_sync_enabled_flag) parallelismType = 2;
1773
+ else if (!tiles_enabled_flag && entropy_coding_sync_enabled_flag) parallelismType = 3;
1774
+ else parallelismType = 0;
1775
+ }
1776
+ const arrays = [
1777
+ ...vpsUnits.length ? [
1778
+ {
1779
+ arrayCompleteness: 1,
1780
+ nalUnitType: 32 /* VPS_NUT */,
1781
+ nalUnits: vpsUnits
1782
+ }
1783
+ ] : [],
1784
+ ...spsUnits.length ? [
1785
+ {
1786
+ arrayCompleteness: 1,
1787
+ nalUnitType: 33 /* SPS_NUT */,
1788
+ nalUnits: spsUnits
1789
+ }
1790
+ ] : [],
1791
+ ...ppsUnits.length ? [
1792
+ {
1793
+ arrayCompleteness: 1,
1794
+ nalUnitType: 34 /* PPS_NUT */,
1795
+ nalUnits: ppsUnits
1796
+ }
1797
+ ] : [],
1798
+ ...seiUnits.length ? [
1799
+ {
1800
+ arrayCompleteness: 1,
1801
+ nalUnitType: extractNalUnitTypeForHevc(seiUnits[0][0]),
1802
+ nalUnits: seiUnits
1803
+ }
1804
+ ] : []
1805
+ ];
1806
+ const record = {
1807
+ configurationVersion: 1,
1808
+ generalProfileSpace: spsInfo.generalProfileSpace,
1809
+ generalTierFlag: spsInfo.generalTierFlag,
1810
+ generalProfileIdc: spsInfo.generalProfileIdc,
1811
+ generalProfileCompatibilityFlags: spsInfo.generalProfileCompatibilityFlags,
1812
+ generalConstraintIndicatorFlags: spsInfo.generalConstraintIndicatorFlags,
1813
+ generalLevelIdc: spsInfo.generalLevelIdc,
1814
+ minSpatialSegmentationIdc: spsInfo.minSpatialSegmentationIdc,
1815
+ parallelismType,
1816
+ chromaFormatIdc: spsInfo.chromaFormatIdc,
1817
+ bitDepthLumaMinus8: spsInfo.bitDepthLumaMinus8,
1818
+ bitDepthChromaMinus8: spsInfo.bitDepthChromaMinus8,
1819
+ avgFrameRate: 0,
1820
+ constantFrameRate: 0,
1821
+ numTemporalLayers: spsInfo.spsMaxSubLayersMinus1 + 1,
1822
+ temporalIdNested: spsInfo.spsTemporalIdNestingFlag,
1823
+ lengthSizeMinusOne: 3,
1824
+ arrays
1825
+ };
1826
+ return record;
1827
+ } catch (error) {
1828
+ console.error("Error building HEVC Decoder Configuration Record:", error);
1829
+ return null;
1830
+ }
1831
+ };
1832
+ var parseProfileTierLevel = (bitstream, maxNumSubLayersMinus1) => {
1833
+ const general_profile_space = bitstream.readBits(2);
1834
+ const general_tier_flag = bitstream.readBits(1);
1835
+ const general_profile_idc = bitstream.readBits(5);
1836
+ let general_profile_compatibility_flags = 0;
1837
+ for (let i = 0; i < 32; i++) {
1838
+ general_profile_compatibility_flags = general_profile_compatibility_flags << 1 | bitstream.readBits(1);
1839
+ }
1840
+ const general_constraint_indicator_flags = new Uint8Array(6);
1841
+ for (let i = 0; i < 6; i++) {
1842
+ general_constraint_indicator_flags[i] = bitstream.readBits(8);
1843
+ }
1844
+ const general_level_idc = bitstream.readBits(8);
1845
+ const sub_layer_profile_present_flag = [];
1846
+ const sub_layer_level_present_flag = [];
1847
+ for (let i = 0; i < maxNumSubLayersMinus1; i++) {
1848
+ sub_layer_profile_present_flag.push(bitstream.readBits(1));
1849
+ sub_layer_level_present_flag.push(bitstream.readBits(1));
1850
+ }
1851
+ if (maxNumSubLayersMinus1 > 0) {
1852
+ for (let i = maxNumSubLayersMinus1; i < 8; i++) {
1853
+ bitstream.skipBits(2);
1854
+ }
1855
+ }
1856
+ for (let i = 0; i < maxNumSubLayersMinus1; i++) {
1857
+ if (sub_layer_profile_present_flag[i]) bitstream.skipBits(88);
1858
+ if (sub_layer_level_present_flag[i]) bitstream.skipBits(8);
1859
+ }
1860
+ return {
1861
+ general_profile_space,
1862
+ general_tier_flag,
1863
+ general_profile_idc,
1864
+ general_profile_compatibility_flags,
1865
+ general_constraint_indicator_flags,
1866
+ general_level_idc
1867
+ };
1868
+ };
1869
+ var skipScalingListData = (bitstream) => {
1870
+ for (let sizeId = 0; sizeId < 4; sizeId++) {
1871
+ for (let matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
1872
+ const scaling_list_pred_mode_flag = bitstream.readBits(1);
1873
+ if (!scaling_list_pred_mode_flag) {
1874
+ readExpGolomb(bitstream);
1875
+ } else {
1876
+ const coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
1877
+ if (sizeId > 1) {
1878
+ readSignedExpGolomb(bitstream);
1879
+ }
1880
+ for (let i = 0; i < coefNum; i++) {
1881
+ readSignedExpGolomb(bitstream);
1882
+ }
1883
+ }
1884
+ }
1885
+ }
1886
+ };
1887
+ var skipAllStRefPicSets = (bitstream, num_short_term_ref_pic_sets) => {
1888
+ const NumDeltaPocs = [];
1889
+ for (let stRpsIdx = 0; stRpsIdx < num_short_term_ref_pic_sets; stRpsIdx++) {
1890
+ NumDeltaPocs[stRpsIdx] = skipStRefPicSet(bitstream, stRpsIdx, num_short_term_ref_pic_sets, NumDeltaPocs);
1891
+ }
1892
+ };
1893
+ var skipStRefPicSet = (bitstream, stRpsIdx, num_short_term_ref_pic_sets, NumDeltaPocs) => {
1894
+ let NumDeltaPocsThis = 0;
1895
+ let inter_ref_pic_set_prediction_flag = 0;
1896
+ let RefRpsIdx = 0;
1897
+ if (stRpsIdx !== 0) {
1898
+ inter_ref_pic_set_prediction_flag = bitstream.readBits(1);
1899
+ }
1900
+ if (inter_ref_pic_set_prediction_flag) {
1901
+ if (stRpsIdx === num_short_term_ref_pic_sets) {
1902
+ const delta_idx_minus1 = readExpGolomb(bitstream);
1903
+ RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1);
1904
+ } else {
1905
+ RefRpsIdx = stRpsIdx - 1;
1906
+ }
1907
+ bitstream.readBits(1);
1908
+ readExpGolomb(bitstream);
1909
+ const numDelta = NumDeltaPocs[RefRpsIdx] ?? 0;
1910
+ for (let j = 0; j <= numDelta; j++) {
1911
+ const used_by_curr_pic_flag = bitstream.readBits(1);
1912
+ if (!used_by_curr_pic_flag) {
1913
+ bitstream.readBits(1);
1914
+ }
1915
+ }
1916
+ NumDeltaPocsThis = NumDeltaPocs[RefRpsIdx];
1917
+ } else {
1918
+ const num_negative_pics = readExpGolomb(bitstream);
1919
+ const num_positive_pics = readExpGolomb(bitstream);
1920
+ for (let i = 0; i < num_negative_pics; i++) {
1921
+ readExpGolomb(bitstream);
1922
+ bitstream.readBits(1);
1923
+ }
1924
+ for (let i = 0; i < num_positive_pics; i++) {
1925
+ readExpGolomb(bitstream);
1926
+ bitstream.readBits(1);
1927
+ }
1928
+ NumDeltaPocsThis = num_negative_pics + num_positive_pics;
1929
+ }
1930
+ return NumDeltaPocsThis;
1931
+ };
1932
+ var parseHevcVui = (bitstream, sps_max_sub_layers_minus1) => {
1933
+ let colourPrimaries = 2;
1934
+ let transferCharacteristics = 2;
1935
+ let matrixCoefficients = 2;
1936
+ let fullRangeFlag = 0;
1937
+ let minSpatialSegmentationIdc = 0;
1938
+ let pixelAspectRatio = { num: 1, den: 1 };
1939
+ if (bitstream.readBits(1)) {
1940
+ const aspect_ratio_idc = bitstream.readBits(8);
1941
+ if (aspect_ratio_idc === 255) {
1942
+ pixelAspectRatio = {
1943
+ num: bitstream.readBits(16),
1944
+ den: bitstream.readBits(16)
1945
+ };
1946
+ } else {
1947
+ const aspectRatio = AVC_HEVC_ASPECT_RATIO_IDC_TABLE[aspect_ratio_idc];
1948
+ if (aspectRatio) {
1949
+ pixelAspectRatio = aspectRatio;
1950
+ }
1951
+ }
1952
+ }
1953
+ if (bitstream.readBits(1)) {
1954
+ bitstream.readBits(1);
1955
+ }
1956
+ if (bitstream.readBits(1)) {
1957
+ bitstream.readBits(3);
1958
+ fullRangeFlag = bitstream.readBits(1);
1959
+ if (bitstream.readBits(1)) {
1960
+ colourPrimaries = bitstream.readBits(8);
1961
+ transferCharacteristics = bitstream.readBits(8);
1962
+ matrixCoefficients = bitstream.readBits(8);
1963
+ }
1964
+ }
1965
+ if (bitstream.readBits(1)) {
1966
+ readExpGolomb(bitstream);
1967
+ readExpGolomb(bitstream);
1968
+ }
1969
+ bitstream.readBits(1);
1970
+ bitstream.readBits(1);
1971
+ bitstream.readBits(1);
1972
+ if (bitstream.readBits(1)) {
1973
+ readExpGolomb(bitstream);
1974
+ readExpGolomb(bitstream);
1975
+ readExpGolomb(bitstream);
1976
+ readExpGolomb(bitstream);
1977
+ }
1978
+ if (bitstream.readBits(1)) {
1979
+ bitstream.readBits(32);
1980
+ bitstream.readBits(32);
1981
+ if (bitstream.readBits(1)) {
1982
+ readExpGolomb(bitstream);
1983
+ }
1984
+ if (bitstream.readBits(1)) {
1985
+ skipHevcHrdParameters(bitstream, true, sps_max_sub_layers_minus1);
1986
+ }
1987
+ }
1988
+ if (bitstream.readBits(1)) {
1989
+ bitstream.readBits(1);
1990
+ bitstream.readBits(1);
1991
+ bitstream.readBits(1);
1992
+ minSpatialSegmentationIdc = readExpGolomb(bitstream);
1993
+ readExpGolomb(bitstream);
1994
+ readExpGolomb(bitstream);
1995
+ readExpGolomb(bitstream);
1996
+ readExpGolomb(bitstream);
1997
+ }
1998
+ return {
1999
+ pixelAspectRatio,
2000
+ colourPrimaries,
2001
+ transferCharacteristics,
2002
+ matrixCoefficients,
2003
+ fullRangeFlag,
2004
+ minSpatialSegmentationIdc
2005
+ };
2006
+ };
2007
+ var skipHevcHrdParameters = (bitstream, commonInfPresentFlag, maxNumSubLayersMinus1) => {
2008
+ let nal_hrd_parameters_present_flag = false;
2009
+ let vcl_hrd_parameters_present_flag = false;
2010
+ let sub_pic_hrd_params_present_flag = false;
2011
+ if (commonInfPresentFlag) {
2012
+ nal_hrd_parameters_present_flag = bitstream.readBits(1) === 1;
2013
+ vcl_hrd_parameters_present_flag = bitstream.readBits(1) === 1;
2014
+ if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
2015
+ sub_pic_hrd_params_present_flag = bitstream.readBits(1) === 1;
2016
+ if (sub_pic_hrd_params_present_flag) {
2017
+ bitstream.readBits(8);
2018
+ bitstream.readBits(5);
2019
+ bitstream.readBits(1);
2020
+ bitstream.readBits(5);
2021
+ }
2022
+ bitstream.readBits(4);
2023
+ bitstream.readBits(4);
2024
+ if (sub_pic_hrd_params_present_flag) {
2025
+ bitstream.readBits(4);
2026
+ }
2027
+ bitstream.readBits(5);
2028
+ bitstream.readBits(5);
2029
+ bitstream.readBits(5);
2030
+ }
2031
+ }
2032
+ for (let i = 0; i <= maxNumSubLayersMinus1; i++) {
2033
+ const fixed_pic_rate_general_flag = bitstream.readBits(1) === 1;
2034
+ let fixed_pic_rate_within_cvs_flag = true;
2035
+ if (!fixed_pic_rate_general_flag) {
2036
+ fixed_pic_rate_within_cvs_flag = bitstream.readBits(1) === 1;
2037
+ }
2038
+ let low_delay_hrd_flag = false;
2039
+ if (fixed_pic_rate_within_cvs_flag) {
2040
+ readExpGolomb(bitstream);
2041
+ } else {
2042
+ low_delay_hrd_flag = bitstream.readBits(1) === 1;
2043
+ }
2044
+ let CpbCnt = 1;
2045
+ if (!low_delay_hrd_flag) {
2046
+ const cpb_cnt_minus1 = readExpGolomb(bitstream);
2047
+ CpbCnt = cpb_cnt_minus1 + 1;
2048
+ }
2049
+ if (nal_hrd_parameters_present_flag) {
2050
+ skipSubLayerHrdParameters(bitstream, CpbCnt, sub_pic_hrd_params_present_flag);
2051
+ }
2052
+ if (vcl_hrd_parameters_present_flag) {
2053
+ skipSubLayerHrdParameters(bitstream, CpbCnt, sub_pic_hrd_params_present_flag);
2054
+ }
2055
+ }
2056
+ };
2057
+ var skipSubLayerHrdParameters = (bitstream, CpbCnt, sub_pic_hrd_params_present_flag) => {
2058
+ for (let i = 0; i < CpbCnt; i++) {
2059
+ readExpGolomb(bitstream);
2060
+ readExpGolomb(bitstream);
2061
+ if (sub_pic_hrd_params_present_flag) {
2062
+ readExpGolomb(bitstream);
2063
+ readExpGolomb(bitstream);
2064
+ }
2065
+ bitstream.readBits(1);
2066
+ }
2067
+ };
2068
+ var serializeHevcDecoderConfigurationRecord = (record) => {
2069
+ const bytes = [];
2070
+ bytes.push(record.configurationVersion);
2071
+ bytes.push(
2072
+ (record.generalProfileSpace & 3) << 6 | (record.generalTierFlag & 1) << 5 | record.generalProfileIdc & 31
2073
+ );
2074
+ bytes.push(record.generalProfileCompatibilityFlags >>> 24 & 255);
2075
+ bytes.push(record.generalProfileCompatibilityFlags >>> 16 & 255);
2076
+ bytes.push(record.generalProfileCompatibilityFlags >>> 8 & 255);
2077
+ bytes.push(record.generalProfileCompatibilityFlags & 255);
2078
+ bytes.push(...record.generalConstraintIndicatorFlags);
2079
+ bytes.push(record.generalLevelIdc & 255);
2080
+ bytes.push(240 | record.minSpatialSegmentationIdc >> 8 & 15);
2081
+ bytes.push(record.minSpatialSegmentationIdc & 255);
2082
+ bytes.push(252 | record.parallelismType & 3);
2083
+ bytes.push(252 | record.chromaFormatIdc & 3);
2084
+ bytes.push(248 | record.bitDepthLumaMinus8 & 7);
2085
+ bytes.push(248 | record.bitDepthChromaMinus8 & 7);
2086
+ bytes.push(record.avgFrameRate >> 8 & 255);
2087
+ bytes.push(record.avgFrameRate & 255);
2088
+ bytes.push(
2089
+ (record.constantFrameRate & 3) << 6 | (record.numTemporalLayers & 7) << 3 | (record.temporalIdNested & 1) << 2 | record.lengthSizeMinusOne & 3
2090
+ );
2091
+ bytes.push(record.arrays.length & 255);
2092
+ for (const arr of record.arrays) {
2093
+ bytes.push(
2094
+ (arr.arrayCompleteness & 1) << 7 | 0 << 6 | arr.nalUnitType & 63
2095
+ );
2096
+ bytes.push(arr.nalUnits.length >> 8 & 255);
2097
+ bytes.push(arr.nalUnits.length & 255);
2098
+ for (const nal of arr.nalUnits) {
2099
+ bytes.push(nal.length >> 8 & 255);
2100
+ bytes.push(nal.length & 255);
2101
+ for (let i = 0; i < nal.length; i++) {
2102
+ bytes.push(nal[i]);
2103
+ }
2104
+ }
2105
+ }
2106
+ return new Uint8Array(bytes);
2107
+ };
2108
+ var extractVp9CodecInfoFromPacket = (packet) => {
2109
+ const bitstream = new Bitstream(packet);
2110
+ const frameMarker = bitstream.readBits(2);
2111
+ if (frameMarker !== 2) {
2112
+ return null;
2113
+ }
2114
+ const profileLowBit = bitstream.readBits(1);
2115
+ const profileHighBit = bitstream.readBits(1);
2116
+ const profile = (profileHighBit << 1) + profileLowBit;
2117
+ if (profile === 3) {
2118
+ bitstream.skipBits(1);
2119
+ }
2120
+ const showExistingFrame = bitstream.readBits(1);
2121
+ if (showExistingFrame === 1) {
2122
+ return null;
2123
+ }
2124
+ const frameType = bitstream.readBits(1);
2125
+ if (frameType !== 0) {
2126
+ return null;
2127
+ }
2128
+ bitstream.skipBits(2);
2129
+ const syncCode = bitstream.readBits(24);
2130
+ if (syncCode !== 4817730) {
2131
+ return null;
2132
+ }
2133
+ let bitDepth = 8;
2134
+ if (profile >= 2) {
2135
+ const tenOrTwelveBit = bitstream.readBits(1);
2136
+ bitDepth = tenOrTwelveBit ? 12 : 10;
2137
+ }
2138
+ const colorSpace = bitstream.readBits(3);
2139
+ let chromaSubsampling = 0;
2140
+ let videoFullRangeFlag = 0;
2141
+ if (colorSpace !== 7) {
2142
+ const colorRange = bitstream.readBits(1);
2143
+ videoFullRangeFlag = colorRange;
2144
+ if (profile === 1 || profile === 3) {
2145
+ const subsamplingX = bitstream.readBits(1);
2146
+ const subsamplingY = bitstream.readBits(1);
2147
+ chromaSubsampling = !subsamplingX && !subsamplingY ? 3 : subsamplingX && !subsamplingY ? 2 : 1;
2148
+ bitstream.skipBits(1);
2149
+ } else {
2150
+ chromaSubsampling = 1;
2151
+ }
2152
+ } else {
2153
+ chromaSubsampling = 3;
2154
+ videoFullRangeFlag = 1;
2155
+ }
2156
+ const widthMinusOne = bitstream.readBits(16);
2157
+ const heightMinusOne = bitstream.readBits(16);
2158
+ const width = widthMinusOne + 1;
2159
+ const height = heightMinusOne + 1;
2160
+ const pictureSize = width * height;
2161
+ let level = last(VP9_LEVEL_TABLE).level;
2162
+ for (const entry of VP9_LEVEL_TABLE) {
2163
+ if (pictureSize <= entry.maxPictureSize) {
2164
+ level = entry.level;
2165
+ break;
2166
+ }
2167
+ }
2168
+ const matrixCoefficients = colorSpace === 7 ? 0 : colorSpace === 2 ? 1 : colorSpace === 1 ? 6 : 2;
2169
+ const colourPrimaries = colorSpace === 2 ? 1 : colorSpace === 1 ? 6 : 2;
2170
+ const transferCharacteristics = colorSpace === 2 ? 1 : colorSpace === 1 ? 6 : 2;
2171
+ return {
2172
+ profile,
2173
+ level,
2174
+ bitDepth,
2175
+ chromaSubsampling,
2176
+ videoFullRangeFlag,
2177
+ colourPrimaries,
2178
+ transferCharacteristics,
2179
+ matrixCoefficients
2180
+ };
2181
+ };
2182
+ var iterateAv1PacketObus = function* (packet) {
2183
+ const bitstream = new Bitstream(packet);
2184
+ const readLeb128 = () => {
2185
+ let value = 0;
2186
+ for (let i = 0; i < 8; i++) {
2187
+ const byte = bitstream.readAlignedByte();
2188
+ value |= (byte & 127) << i * 7;
2189
+ if (!(byte & 128)) {
2190
+ break;
2191
+ }
2192
+ if (i === 7 && byte & 128) {
2193
+ return null;
2194
+ }
2195
+ }
2196
+ if (value >= 2 ** 32 - 1) {
2197
+ return null;
2198
+ }
2199
+ return value;
2200
+ };
2201
+ while (bitstream.getBitsLeft() >= 8) {
2202
+ bitstream.skipBits(1);
2203
+ const obuType = bitstream.readBits(4);
2204
+ const obuExtension = bitstream.readBits(1);
2205
+ const obuHasSizeField = bitstream.readBits(1);
2206
+ bitstream.skipBits(1);
2207
+ if (obuExtension) {
2208
+ bitstream.skipBits(8);
2209
+ }
2210
+ let obuSize;
2211
+ if (obuHasSizeField) {
2212
+ const obuSizeValue = readLeb128();
2213
+ if (obuSizeValue === null) return;
2214
+ obuSize = obuSizeValue;
2215
+ } else {
2216
+ obuSize = Math.floor(bitstream.getBitsLeft() / 8);
2217
+ }
2218
+ assert(bitstream.pos % 8 === 0);
2219
+ yield {
2220
+ type: obuType,
2221
+ data: packet.subarray(bitstream.pos / 8, bitstream.pos / 8 + obuSize)
2222
+ };
2223
+ bitstream.skipBits(obuSize * 8);
2224
+ }
2225
+ };
2226
+ var extractAv1CodecInfoFromPacket = (packet) => {
2227
+ for (const { type, data } of iterateAv1PacketObus(packet)) {
2228
+ if (type !== 1) {
2229
+ continue;
2230
+ }
2231
+ const bitstream = new Bitstream(data);
2232
+ const seqProfile = bitstream.readBits(3);
2233
+ const stillPicture = bitstream.readBits(1);
2234
+ const reducedStillPictureHeader = bitstream.readBits(1);
2235
+ let seqLevel = 0;
2236
+ let seqTier = 0;
2237
+ let bufferDelayLengthMinus1 = 0;
2238
+ if (reducedStillPictureHeader) {
2239
+ seqLevel = bitstream.readBits(5);
2240
+ } else {
2241
+ const timingInfoPresentFlag = bitstream.readBits(1);
2242
+ if (timingInfoPresentFlag) {
2243
+ bitstream.skipBits(32);
2244
+ bitstream.skipBits(32);
2245
+ const equalPictureInterval = bitstream.readBits(1);
2246
+ if (equalPictureInterval) {
2247
+ return null;
2248
+ }
2249
+ }
2250
+ const decoderModelInfoPresentFlag = bitstream.readBits(1);
2251
+ if (decoderModelInfoPresentFlag) {
2252
+ bufferDelayLengthMinus1 = bitstream.readBits(5);
2253
+ bitstream.skipBits(32);
2254
+ bitstream.skipBits(5);
2255
+ bitstream.skipBits(5);
2256
+ }
2257
+ const operatingPointsCntMinus1 = bitstream.readBits(5);
2258
+ for (let i = 0; i <= operatingPointsCntMinus1; i++) {
2259
+ bitstream.skipBits(12);
2260
+ const seqLevelIdx = bitstream.readBits(5);
2261
+ if (i === 0) {
2262
+ seqLevel = seqLevelIdx;
2263
+ }
2264
+ if (seqLevelIdx > 7) {
2265
+ const seqTierTemp = bitstream.readBits(1);
2266
+ if (i === 0) {
2267
+ seqTier = seqTierTemp;
2268
+ }
2269
+ }
2270
+ if (decoderModelInfoPresentFlag) {
2271
+ const decoderModelPresentForThisOp = bitstream.readBits(1);
2272
+ if (decoderModelPresentForThisOp) {
2273
+ const n = bufferDelayLengthMinus1 + 1;
2274
+ bitstream.skipBits(n);
2275
+ bitstream.skipBits(n);
2276
+ bitstream.skipBits(1);
2277
+ }
2278
+ }
2279
+ const initialDisplayDelayPresentFlag = bitstream.readBits(1);
2280
+ if (initialDisplayDelayPresentFlag) {
2281
+ bitstream.skipBits(4);
2282
+ }
2283
+ }
2284
+ }
2285
+ const frameWidthBitsMinus1 = bitstream.readBits(4);
2286
+ const frameHeightBitsMinus1 = bitstream.readBits(4);
2287
+ const n1 = frameWidthBitsMinus1 + 1;
2288
+ bitstream.skipBits(n1);
2289
+ const n2 = frameHeightBitsMinus1 + 1;
2290
+ bitstream.skipBits(n2);
2291
+ let frameIdNumbersPresentFlag = 0;
2292
+ if (reducedStillPictureHeader) {
2293
+ frameIdNumbersPresentFlag = 0;
2294
+ } else {
2295
+ frameIdNumbersPresentFlag = bitstream.readBits(1);
2296
+ }
2297
+ if (frameIdNumbersPresentFlag) {
2298
+ bitstream.skipBits(4);
2299
+ bitstream.skipBits(3);
2300
+ }
2301
+ bitstream.skipBits(1);
2302
+ bitstream.skipBits(1);
2303
+ bitstream.skipBits(1);
2304
+ if (!reducedStillPictureHeader) {
2305
+ bitstream.skipBits(1);
2306
+ bitstream.skipBits(1);
2307
+ bitstream.skipBits(1);
2308
+ bitstream.skipBits(1);
2309
+ const enableOrderHint = bitstream.readBits(1);
2310
+ if (enableOrderHint) {
2311
+ bitstream.skipBits(1);
2312
+ bitstream.skipBits(1);
2313
+ }
2314
+ const seqChooseScreenContentTools = bitstream.readBits(1);
2315
+ let seqForceScreenContentTools = 0;
2316
+ if (seqChooseScreenContentTools) {
2317
+ seqForceScreenContentTools = 2;
2318
+ } else {
2319
+ seqForceScreenContentTools = bitstream.readBits(1);
2320
+ }
2321
+ if (seqForceScreenContentTools > 0) {
2322
+ const seqChooseIntegerMv = bitstream.readBits(1);
2323
+ if (!seqChooseIntegerMv) {
2324
+ bitstream.skipBits(1);
2325
+ }
2326
+ }
2327
+ if (enableOrderHint) {
2328
+ bitstream.skipBits(3);
2329
+ }
2330
+ }
2331
+ bitstream.skipBits(1);
2332
+ bitstream.skipBits(1);
2333
+ bitstream.skipBits(1);
2334
+ const highBitdepth = bitstream.readBits(1);
2335
+ let bitDepth = 8;
2336
+ if (seqProfile === 2 && highBitdepth) {
2337
+ const twelveBit = bitstream.readBits(1);
2338
+ bitDepth = twelveBit ? 12 : 10;
2339
+ } else if (seqProfile <= 2) {
2340
+ bitDepth = highBitdepth ? 10 : 8;
2341
+ }
2342
+ let monochrome = 0;
2343
+ if (seqProfile !== 1) {
2344
+ monochrome = bitstream.readBits(1);
2345
+ }
2346
+ let chromaSubsamplingX = 1;
2347
+ let chromaSubsamplingY = 1;
2348
+ let chromaSamplePosition = 0;
2349
+ if (!monochrome) {
2350
+ if (seqProfile === 0) {
2351
+ chromaSubsamplingX = 1;
2352
+ chromaSubsamplingY = 1;
2353
+ } else if (seqProfile === 1) {
2354
+ chromaSubsamplingX = 0;
2355
+ chromaSubsamplingY = 0;
2356
+ } else {
2357
+ if (bitDepth === 12) {
2358
+ chromaSubsamplingX = bitstream.readBits(1);
2359
+ if (chromaSubsamplingX) {
2360
+ chromaSubsamplingY = bitstream.readBits(1);
2361
+ }
2362
+ }
2363
+ }
2364
+ if (chromaSubsamplingX && chromaSubsamplingY) {
2365
+ chromaSamplePosition = bitstream.readBits(2);
2366
+ }
2367
+ }
2368
+ return {
2369
+ profile: seqProfile,
2370
+ level: seqLevel,
2371
+ tier: seqTier,
2372
+ bitDepth,
2373
+ monochrome,
2374
+ chromaSubsamplingX,
2375
+ chromaSubsamplingY,
2376
+ chromaSamplePosition
2377
+ };
2378
+ }
2379
+ return null;
2380
+ };
2381
+ var AC3_FRAME_SIZES = [
2382
+ // frmsizecod, [48kHz, 44.1kHz, 32kHz] in bytes
2383
+ 64 * 2,
2384
+ 69 * 2,
2385
+ 96 * 2,
2386
+ 64 * 2,
2387
+ 70 * 2,
2388
+ 96 * 2,
2389
+ 80 * 2,
2390
+ 87 * 2,
2391
+ 120 * 2,
2392
+ 80 * 2,
2393
+ 88 * 2,
2394
+ 120 * 2,
2395
+ 96 * 2,
2396
+ 104 * 2,
2397
+ 144 * 2,
2398
+ 96 * 2,
2399
+ 105 * 2,
2400
+ 144 * 2,
2401
+ 112 * 2,
2402
+ 121 * 2,
2403
+ 168 * 2,
2404
+ 112 * 2,
2405
+ 122 * 2,
2406
+ 168 * 2,
2407
+ 128 * 2,
2408
+ 139 * 2,
2409
+ 192 * 2,
2410
+ 128 * 2,
2411
+ 140 * 2,
2412
+ 192 * 2,
2413
+ 160 * 2,
2414
+ 174 * 2,
2415
+ 240 * 2,
2416
+ 160 * 2,
2417
+ 175 * 2,
2418
+ 240 * 2,
2419
+ 192 * 2,
2420
+ 208 * 2,
2421
+ 288 * 2,
2422
+ 192 * 2,
2423
+ 209 * 2,
2424
+ 288 * 2,
2425
+ 224 * 2,
2426
+ 243 * 2,
2427
+ 336 * 2,
2428
+ 224 * 2,
2429
+ 244 * 2,
2430
+ 336 * 2,
2431
+ 256 * 2,
2432
+ 278 * 2,
2433
+ 384 * 2,
2434
+ 256 * 2,
2435
+ 279 * 2,
2436
+ 384 * 2,
2437
+ 320 * 2,
2438
+ 348 * 2,
2439
+ 480 * 2,
2440
+ 320 * 2,
2441
+ 349 * 2,
2442
+ 480 * 2,
2443
+ 384 * 2,
2444
+ 417 * 2,
2445
+ 576 * 2,
2446
+ 384 * 2,
2447
+ 418 * 2,
2448
+ 576 * 2,
2449
+ 448 * 2,
2450
+ 487 * 2,
2451
+ 672 * 2,
2452
+ 448 * 2,
2453
+ 488 * 2,
2454
+ 672 * 2,
2455
+ 512 * 2,
2456
+ 557 * 2,
2457
+ 768 * 2,
2458
+ 512 * 2,
2459
+ 558 * 2,
2460
+ 768 * 2,
2461
+ 640 * 2,
2462
+ 696 * 2,
2463
+ 960 * 2,
2464
+ 640 * 2,
2465
+ 697 * 2,
2466
+ 960 * 2,
2467
+ 768 * 2,
2468
+ 835 * 2,
2469
+ 1152 * 2,
2470
+ 768 * 2,
2471
+ 836 * 2,
2472
+ 1152 * 2,
2473
+ 896 * 2,
2474
+ 975 * 2,
2475
+ 1344 * 2,
2476
+ 896 * 2,
2477
+ 976 * 2,
2478
+ 1344 * 2,
2479
+ 1024 * 2,
2480
+ 1114 * 2,
2481
+ 1536 * 2,
2482
+ 1024 * 2,
2483
+ 1115 * 2,
2484
+ 1536 * 2,
2485
+ 1152 * 2,
2486
+ 1253 * 2,
2487
+ 1728 * 2,
2488
+ 1152 * 2,
2489
+ 1254 * 2,
2490
+ 1728 * 2,
2491
+ 1280 * 2,
2492
+ 1393 * 2,
2493
+ 1920 * 2,
2494
+ 1280 * 2,
2495
+ 1394 * 2,
2496
+ 1920 * 2
2497
+ ];
2498
+ var AC3_REGISTRATION_DESCRIPTOR = new Uint8Array([5, 4, 65, 67, 45, 51]);
2499
+ var EAC3_REGISTRATION_DESCRIPTOR = new Uint8Array([5, 4, 69, 65, 67, 51]);
2500
+
2501
+ // packages/server/src/video-encoder.ts
2502
+ var NodeAvVideoEncoder = class extends import_mediabunny3.CustomVideoEncoder {
2503
+ constructor() {
2504
+ super(...arguments);
2505
+ this.codecContext = null;
2506
+ this.lastBuffer = null;
2507
+ this.packetEmitted = false;
2508
+ this.scaler = null;
2509
+ this.lastScalerKey = null;
2510
+ this.dstFrame = null;
2511
+ // Bookkeeping to restore the original timing information
2512
+ this.preciseTimings = [];
2513
+ }
2514
+ static supports(codec, config) {
2515
+ return (codec === "avc" || codec === "hevc" || codec === "vp8" || codec === "vp9" || codec === "av1") && config.bitrateMode !== "quantizer";
2516
+ }
2517
+ async init() {
2518
+ this.frame = new NodeAv4.Frame();
2519
+ this.frame.alloc();
2520
+ this.frame.timeBase = new NodeAv4.Rational(1, 1e6);
2521
+ this.packet = new NodeAv4.Packet();
2522
+ this.packet.alloc();
2523
+ const codecId = CODEC_TO_CODEC_ID[this.codec];
2524
+ assert(codecId !== void 0);
2525
+ let codec = null;
2526
+ if (this.codec === "vp9" && this.config.alpha === "keep") {
2527
+ codec = NodeAv4.Codec.findEncoderByName(LIBVPX_VP9) ?? NodeAv4.Codec.findEncoder(codecId);
2528
+ } else if (this.config.hardwareAcceleration === "prefer-software") {
2529
+ codec = NodeAv4.Codec.findEncoder(codecId);
2530
+ } else {
2531
+ codec = getHardwareEncoderCodec(codecId) ?? NodeAv4.Codec.findEncoder(codecId);
2532
+ }
2533
+ if (!codec) {
2534
+ throw new Error(`Unable to obtain libav codec for '${this.codec}'.`);
2535
+ }
2536
+ this.avCodec = codec;
2537
+ await this.createCodecContext();
2538
+ }
2539
+ async createCodecContext() {
2540
+ assert(this.codecContext === null);
2541
+ const codecContext = new NodeAv4.CodecContext();
2542
+ codecContext.allocContext3(this.avCodec);
2543
+ let pixelFormat = NodeAv4.AV_PIX_FMT_YUV420P;
2544
+ if (this.avCodec.pixelFormats) {
2545
+ if (!this.avCodec.pixelFormats.includes(NodeAv4.AV_PIX_FMT_YUV420P)) {
2546
+ pixelFormat = this.avCodec.pixelFormats[0];
2547
+ }
2548
+ if (this.config.alpha === "keep" && this.avCodec.pixelFormats.includes(NodeAv4.AV_PIX_FMT_YUVA420P)) {
2549
+ pixelFormat = NodeAv4.AV_PIX_FMT_YUVA420P;
2550
+ }
2551
+ }
2552
+ const pixelAspectRatio = simplifyRational({
2553
+ num: (this.config.displayWidth ?? this.config.width) * this.config.height,
2554
+ den: (this.config.displayHeight ?? this.config.height) * this.config.width
2555
+ });
2556
+ codecContext.width = this.config.width;
2557
+ codecContext.height = this.config.height;
2558
+ codecContext.pixelFormat = pixelFormat;
2559
+ codecContext.timeBase = new NodeAv4.Rational(1, 1e6);
2560
+ codecContext.gopSize = 60;
2561
+ codecContext.framerate = new NodeAv4.Rational(Math.round(this.config.framerate ?? 0) || 30, 1);
2562
+ codecContext.bitRate = BigInt(
2563
+ this.config.bitrate ?? import_mediabunny3.QUALITY_MEDIUM._toVideoBitrate(this.codec, this.config.width, this.config.height)
2564
+ );
2565
+ codecContext.sampleAspectRatio = new NodeAv4.Rational(pixelAspectRatio.num, pixelAspectRatio.den);
2566
+ if (this.config.bitrateMode === "constant") {
2567
+ codecContext.rcMinRate = codecContext.bitRate;
2568
+ codecContext.rcMaxRate = codecContext.bitRate;
2569
+ }
2570
+ const isRealtime = this.config.latencyMode === "realtime";
2571
+ if (this.avCodec.name === "libx264") {
2572
+ if (isRealtime) {
2573
+ codecContext.setOption("tune", "zerolatency");
2574
+ codecContext.setOption("preset", "ultrafast");
2575
+ }
2576
+ } else if (this.avCodec.name === "libx265") {
2577
+ codecContext.setOption("x265-params", "log-level=error");
2578
+ if (isRealtime) {
2579
+ codecContext.setOption("tune", "zerolatency");
2580
+ codecContext.setOption("preset", "ultrafast");
2581
+ }
2582
+ } else if (this.avCodec.name === "libvpx") {
2583
+ if (isRealtime) {
2584
+ codecContext.setOption("deadline", "realtime");
2585
+ codecContext.setOption("cpu-used", "8");
2586
+ } else {
2587
+ codecContext.setOption("cpu-used", "8");
2588
+ }
2589
+ } else if (this.avCodec.name === "libvpx-vp9") {
2590
+ codecContext.setOption("deadline", "realtime");
2591
+ if (isRealtime) {
2592
+ codecContext.setOption("cpu-used", "8");
2593
+ } else {
2594
+ codecContext.setOption("cpu-used", "5");
2595
+ }
2596
+ } else if (this.avCodec.name === "libsvtav1") {
2597
+ process.env["SVT_LOG"] = "1";
2598
+ if (isRealtime) {
2599
+ codecContext.setOption("preset", "12");
2600
+ }
2601
+ }
2602
+ const ret = await codecContext.open2();
2603
+ NodeAv4.FFmpegError.throwIfError(ret, "Open codec context");
2604
+ this.codecContext = codecContext;
2605
+ }
2606
+ async encode(videoSample, options) {
2607
+ if (this.codecContext === null) {
2608
+ await this.createCodecContext();
2609
+ assert(this.codecContext);
2610
+ }
2611
+ if (videoSample._data instanceof AvFrameVideoSampleResource) {
2612
+ this.frame.ref(videoSample._data.frame);
2613
+ } else {
2614
+ if (videoSample.format === null) {
2615
+ throw new Error("Cannot encode foreign VideoSample with unknown (null) format.");
2616
+ }
2617
+ this.lastBuffer = await copyVideoSampleToAvFrame(videoSample, this.frame, this.lastBuffer);
2618
+ }
2619
+ let frameToEncode = this.frame;
2620
+ const requiresScaler = this.codecContext.pixelFormat !== this.frame.format || this.codecContext.width !== this.frame.width || this.codecContext.height !== this.frame.height;
2621
+ if (requiresScaler) {
2622
+ if (!this.scaler) {
2623
+ this.scaler = new NodeAv4.SoftwareScaleContext();
2624
+ }
2625
+ const key = `${this.frame.width}x${this.frame.height}:${this.frame.format}`;
2626
+ const needsConfigure = key !== this.lastScalerKey;
2627
+ if (needsConfigure) {
2628
+ this.scaler.getContext(
2629
+ this.frame.width,
2630
+ this.frame.height,
2631
+ this.frame.format,
2632
+ this.codecContext.width,
2633
+ this.codecContext.height,
2634
+ this.codecContext.pixelFormat,
2635
+ NodeAv4.SWS_FAST_BILINEAR
2636
+ );
2637
+ this.lastScalerKey = key;
2638
+ const ret2 = this.scaler.initContext();
2639
+ NodeAv4.FFmpegError.throwIfError(ret2, "initContext");
2640
+ }
2641
+ if (!this.dstFrame) {
2642
+ this.dstFrame = new NodeAv4.Frame();
2643
+ this.dstFrame.alloc();
2644
+ this.dstFrame.width = this.codecContext.width;
2645
+ this.dstFrame.height = this.codecContext.height;
2646
+ this.dstFrame.format = this.codecContext.pixelFormat;
2647
+ this.dstFrame.allocBuffer();
2648
+ }
2649
+ await this.scaler.scaleFrame(this.dstFrame, this.frame);
2650
+ this.dstFrame.copyProps(this.frame);
2651
+ frameToEncode = this.dstFrame;
2652
+ }
2653
+ frameToEncode.pts = BigInt(videoSample.microsecondTimestamp);
2654
+ frameToEncode.duration = BigInt(videoSample.microsecondDuration);
2655
+ frameToEncode.timeBase = new NodeAv4.Rational(1, 1e6);
2656
+ frameToEncode.pictType = options?.keyFrame ? NodeAv4.AV_PICTURE_TYPE_I : NodeAv4.AV_PICTURE_TYPE_NONE;
2657
+ frameToEncode.keyFrame = options?.keyFrame ? 1 : 0;
2658
+ const preciseTimingIndex = binarySearchLessOrEqual(
2659
+ this.preciseTimings,
2660
+ videoSample.microsecondTimestamp,
2661
+ (x) => x.microsecondTimestamp
2662
+ );
2663
+ const existingEntry = preciseTimingIndex !== -1 ? this.preciseTimings[preciseTimingIndex] : null;
2664
+ if (existingEntry && existingEntry.microsecondTimestamp === videoSample.microsecondTimestamp) {
2665
+ if (existingEntry.timestamp !== videoSample.timestamp) {
2666
+ existingEntry.timestampIsValid = false;
2667
+ }
2668
+ if (existingEntry.duration !== videoSample.duration) {
2669
+ existingEntry.durationIsValid = false;
2670
+ }
2671
+ } else {
2672
+ this.preciseTimings.splice(preciseTimingIndex + 1, 0, {
2673
+ microsecondTimestamp: videoSample.microsecondTimestamp,
2674
+ timestamp: videoSample.timestamp,
2675
+ duration: videoSample.duration,
2676
+ timestampIsValid: true,
2677
+ durationIsValid: true
2678
+ });
2679
+ if (this.preciseTimings.length > 128) {
2680
+ this.preciseTimings.shift();
2681
+ }
2682
+ }
2683
+ const ret = await this.codecContext.sendFrame(frameToEncode);
2684
+ NodeAv4.FFmpegError.throwIfError(ret, "Send frame");
2685
+ while (true) {
2686
+ const receiveRet = await this.codecContext.receivePacket(this.packet);
2687
+ if (receiveRet === NodeAv4.AVERROR_EAGAIN || receiveRet === NodeAv4.AVERROR_EOF) {
2688
+ break;
2689
+ }
2690
+ this.receivePacket(receiveRet);
2691
+ }
2692
+ }
2693
+ receivePacket(ret) {
2694
+ assert(this.codecContext);
2695
+ NodeAv4.FFmpegError.throwIfError(ret, "Receive packet");
2696
+ if (!this.packet.data) {
2697
+ return;
2698
+ }
2699
+ let packetData = toUint8Array(this.packet.data);
2700
+ let timestamp = Number(this.packet.pts) / 1e6;
2701
+ let duration = Number(this.packet.duration) / 1e6;
2702
+ const preciseTimingIndex = binarySearchLessOrEqual(
2703
+ this.preciseTimings,
2704
+ Number(this.packet.pts),
2705
+ (x) => x.microsecondTimestamp
2706
+ );
2707
+ const entry = preciseTimingIndex !== -1 ? this.preciseTimings[preciseTimingIndex] : null;
2708
+ if (entry && entry.microsecondTimestamp === Number(this.packet.pts)) {
2709
+ if (entry.timestampIsValid) {
2710
+ timestamp = entry.timestamp;
2711
+ }
2712
+ if (entry.durationIsValid) {
2713
+ duration = entry.duration;
2714
+ }
2715
+ }
2716
+ const metadata = {};
2717
+ let decoderConfigCodecString = null;
2718
+ let decoderConfigDescription = null;
2719
+ if (this.codec === "avc" || this.codec === "hevc") {
2720
+ let expectsAnnexB = false;
2721
+ if (this.codec === "avc") {
2722
+ expectsAnnexB = this.config.avc?.format === "annexb";
2723
+ } else {
2724
+ expectsAnnexB = this.config.hevc?.format === "annexb";
2725
+ }
2726
+ if (!this.packetEmitted) {
2727
+ let serializedRecord;
2728
+ if (this.codec === "avc") {
2729
+ const record = extractAvcDecoderConfigurationRecord(this.packet.data);
2730
+ if (!record) {
2731
+ throw new Error("Invalid AVC data, could not extract decoder configuration record.");
2732
+ }
2733
+ serializedRecord = serializeAvcDecoderConfigurationRecord(record);
2734
+ } else {
2735
+ const record = extractHevcDecoderConfigurationRecord(this.packet.data);
2736
+ if (!record) {
2737
+ throw new Error("Invalid HEVC data, could not extract decoder configuration record.");
2738
+ }
2739
+ serializedRecord = serializeHevcDecoderConfigurationRecord(record);
2740
+ }
2741
+ decoderConfigCodecString = extractVideoCodecString({
2742
+ width: this.config.width,
2743
+ height: this.config.height,
2744
+ codec: this.codec,
2745
+ codecDescription: serializedRecord,
2746
+ colorSpace: null,
2747
+ avcType: 1,
2748
+ avcCodecInfo: null,
2749
+ hevcCodecInfo: null,
2750
+ vp9CodecInfo: null,
2751
+ av1CodecInfo: null
2752
+ });
2753
+ if (!expectsAnnexB) {
2754
+ decoderConfigDescription = serializedRecord;
2755
+ }
2756
+ }
2757
+ if (!expectsAnnexB) {
2758
+ const NAL_UNIT_LENGTH_SIZE = 4;
2759
+ const nalUnits = [];
2760
+ for (const loc of iterateNalUnitsInAnnexB(packetData)) {
2761
+ if (this.codec === "avc") {
2762
+ const naluType = extractNalUnitTypeForAvc(packetData[loc.offset]);
2763
+ if (naluType !== 7 /* SPS */ && naluType !== 8 /* PPS */ && naluType !== 13 /* SPS_EXT */) {
2764
+ nalUnits.push(loc);
2765
+ }
2766
+ } else {
2767
+ const naluType = extractNalUnitTypeForHevc(packetData[loc.offset]);
2768
+ if (naluType !== 33 /* SPS_NUT */ && naluType !== 34 /* PPS_NUT */ && naluType !== 32 /* VPS_NUT */) {
2769
+ nalUnits.push(loc);
2770
+ }
2771
+ }
2772
+ }
2773
+ let totalSize = 0;
2774
+ for (const nalUnit of nalUnits) {
2775
+ totalSize += NAL_UNIT_LENGTH_SIZE + nalUnit.length;
2776
+ }
2777
+ const lengthPrefixedData = new Uint8Array(totalSize);
2778
+ const dataView = new DataView(lengthPrefixedData.buffer);
2779
+ let offset = 0;
2780
+ for (const nalUnit of nalUnits) {
2781
+ const length = nalUnit.length;
2782
+ dataView.setUint32(offset, length, false);
2783
+ offset += 4;
2784
+ lengthPrefixedData.set(
2785
+ packetData.subarray(nalUnit.offset, nalUnit.offset + nalUnit.length),
2786
+ offset
2787
+ );
2788
+ offset += nalUnit.length;
2789
+ }
2790
+ packetData = lengthPrefixedData;
2791
+ }
2792
+ } else if (this.codec === "vp8") {
2793
+ if (!this.packetEmitted) {
2794
+ decoderConfigCodecString = extractVideoCodecString({
2795
+ width: this.config.width,
2796
+ height: this.config.height,
2797
+ codec: "vp8",
2798
+ codecDescription: null,
2799
+ colorSpace: null,
2800
+ avcType: null,
2801
+ avcCodecInfo: null,
2802
+ hevcCodecInfo: null,
2803
+ vp9CodecInfo: null,
2804
+ av1CodecInfo: null
2805
+ });
2806
+ }
2807
+ } else if (this.codec === "vp9") {
2808
+ if (!this.packetEmitted) {
2809
+ const vp9CodecInfo = extractVp9CodecInfoFromPacket(packetData);
2810
+ decoderConfigCodecString = extractVideoCodecString({
2811
+ width: this.config.width,
2812
+ height: this.config.height,
2813
+ codec: "vp9",
2814
+ codecDescription: null,
2815
+ colorSpace: null,
2816
+ avcType: null,
2817
+ avcCodecInfo: null,
2818
+ hevcCodecInfo: null,
2819
+ vp9CodecInfo,
2820
+ av1CodecInfo: null
2821
+ });
2822
+ }
2823
+ } else if (this.codec === "av1") {
2824
+ if (!this.packetEmitted) {
2825
+ const av1CodecInfo = extractAv1CodecInfoFromPacket(packetData);
2826
+ decoderConfigCodecString = extractVideoCodecString({
2827
+ width: this.config.width,
2828
+ height: this.config.height,
2829
+ codec: "av1",
2830
+ codecDescription: null,
2831
+ colorSpace: null,
2832
+ avcType: null,
2833
+ avcCodecInfo: null,
2834
+ hevcCodecInfo: null,
2835
+ vp9CodecInfo: null,
2836
+ av1CodecInfo
2837
+ });
2838
+ }
2839
+ } else {
2840
+ throw new Error("Unreachable.");
2841
+ }
2842
+ const sideData = {};
2843
+ const matroskaBlockAdditional = this.packet.getSideData(NodeAv4.AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL);
2844
+ if (matroskaBlockAdditional) {
2845
+ sideData.alpha = toUint8Array(matroskaBlockAdditional).subarray(8);
2846
+ }
2847
+ const packet = new import_mediabunny3.EncodedPacket(
2848
+ packetData,
2849
+ this.packet.isKeyframe ? "key" : "delta",
2850
+ timestamp,
2851
+ duration,
2852
+ void 0,
2853
+ void 0,
2854
+ sideData
2855
+ );
2856
+ if (decoderConfigCodecString !== null) {
2857
+ metadata.decoderConfig = {
2858
+ codec: decoderConfigCodecString,
2859
+ codedWidth: this.codecContext.width,
2860
+ codedHeight: this.codecContext.height,
2861
+ displayAspectWidth: this.config.displayWidth ?? this.codecContext.width,
2862
+ displayAspectHeight: this.config.displayHeight ?? this.codecContext.height,
2863
+ description: decoderConfigDescription ?? void 0,
2864
+ colorSpace: {
2865
+ primaries: unmapColorPrimaries(this.codecContext.colorPrimaries),
2866
+ matrix: unmapMatrixCoefficients(this.codecContext.colorSpace),
2867
+ transfer: unmapTransferCharacteristics(this.codecContext.colorTrc),
2868
+ fullRange: this.codecContext.colorRange === NodeAv4.AVCOL_RANGE_JPEG ? true : this.codecContext.colorRange === NodeAv4.AVCOL_RANGE_MPEG ? false : void 0
2869
+ }
2870
+ };
2871
+ }
2872
+ this.packetEmitted = true;
2873
+ this.onPacket(packet, metadata);
2874
+ }
2875
+ async flush() {
2876
+ if (this.codecContext) {
2877
+ const ret = await this.codecContext.sendFrame(null);
2878
+ NodeAv4.FFmpegError.throwIfError(ret, "Send frame");
2879
+ while (true) {
2880
+ const receiveRet = await this.codecContext.receivePacket(this.packet);
2881
+ if (receiveRet === NodeAv4.AVERROR_EAGAIN || receiveRet === NodeAv4.AVERROR_EOF) {
2882
+ break;
2883
+ }
2884
+ this.receivePacket(receiveRet);
2885
+ }
2886
+ this.codecContext.freeContext();
2887
+ this.codecContext = null;
2888
+ }
2889
+ this.packetEmitted = false;
2890
+ }
2891
+ close() {
2892
+ this.codecContext?.freeContext();
2893
+ this.frame.free();
2894
+ this.packet.free();
2895
+ this.scaler?.freeContext();
2896
+ this.dstFrame?.free();
2897
+ }
2898
+ };
2899
+
2900
+ // packages/server/src/audio-decoder.ts
2901
+ var import_mediabunny5 = __require("mediabunny");
2902
+ var NodeAv6 = __toESM(__require("node-av"));
2903
+
2904
+ // packages/server/src/audio-sample.ts
2905
+ var import_mediabunny4 = __require("mediabunny");
2906
+ var NodeAv5 = __toESM(__require("node-av"));
2907
+ var AvFrameAudioSampleResource = class extends import_mediabunny4.AudioSampleResource {
2908
+ /**
2909
+ * The NodeAV [`Frame`](https://seydx.github.io/node-av/api/lib/classes/Frame.html) instance backing this resource.
2910
+ * Access throws if the resource has already been closed.
2911
+ */
2912
+ get frame() {
2913
+ if (!this._frame) {
2914
+ throw new Error("AvFrameAudioSampleResource has been closed.");
2915
+ }
2916
+ return this._frame;
2917
+ }
2918
+ constructor(frame) {
2919
+ super();
2920
+ if (frame.getMediaType() !== NodeAv5.AVMEDIA_TYPE_AUDIO) {
2921
+ throw new Error("AvFrameAudioSampleResource must be initialized with an audio frame.");
2922
+ }
2923
+ this._frame = frame;
2924
+ }
2925
+ getFormat() {
2926
+ const result = toAudioSampleFormat(this.frame.format);
2927
+ if (result === null) {
2928
+ const name = NodeAv5.avGetSampleFmtName(this.frame.format);
2929
+ throw new TypeError(`Unsupported audio sample format: ${name} (${this.frame.format})`);
2930
+ }
2931
+ return result;
2932
+ }
2933
+ getSampleRate() {
2934
+ return this.frame.sampleRate;
2935
+ }
2936
+ getNumberOfChannels() {
2937
+ return this.frame.channels;
2938
+ }
2939
+ getNumberOfFrames() {
2940
+ return this.frame.nbSamples;
2941
+ }
2942
+ getTimestamp() {
2943
+ return Number(this.frame.pts) / this.frame.timeBase.den;
2944
+ }
2945
+ close() {
2946
+ this.frame.free();
2947
+ this._frame = null;
2948
+ }
2949
+ getDataPlane(planeIndex) {
2950
+ assert(this.frame.data && planeIndex < this.frame.data.length);
2951
+ return toUint8Array(this.frame.data[planeIndex]);
2952
+ }
2953
+ };
2954
+ var copyAudioSampleToAvFrame = (sample, frame) => {
2955
+ frame.format = fromAudioSampleFormat(sample.format);
2956
+ frame.nbSamples = sample.numberOfFrames;
2957
+ frame.sampleRate = sample.sampleRate;
2958
+ frame.channelLayout = getChannelLayout(sample.numberOfChannels);
2959
+ frame.allocBuffer();
2960
+ assert(frame.data);
2961
+ for (let i = 0; i < frame.data.length; i++) {
2962
+ sample.copyTo(frame.data[i], { planeIndex: i });
2963
+ }
2964
+ };
2965
+
2966
+ // packages/server/src/audio-decoder.ts
2967
+ var NodeAvAudioDecoder = class extends import_mediabunny5.CustomAudioDecoder {
2968
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2969
+ static supports(codec, config) {
2970
+ return codec === "aac" || codec === "opus" || codec === "mp3" || codec === "vorbis" || codec === "flac" || codec === "ac3" || codec === "eac3";
2971
+ }
2972
+ async init() {
2973
+ this.frame = new NodeAv6.Frame();
2974
+ this.frame.alloc();
2975
+ this.packet = new NodeAv6.Packet();
2976
+ this.packet.alloc();
2977
+ const codecId = CODEC_TO_CODEC_ID[this.codec];
2978
+ assert(codecId !== void 0);
2979
+ const codec = NodeAv6.Codec.findDecoder(codecId);
2980
+ if (codec === null) {
2981
+ throw new Error(`Unable to obtain libav codec for '${this.codec}'.`);
2982
+ }
2983
+ const codecContext = new NodeAv6.CodecContext();
2984
+ codecContext.allocContext3(codec);
2985
+ codecContext.sampleRate = this.config.sampleRate;
2986
+ codecContext.channelLayout = getChannelLayout(this.config.numberOfChannels);
2987
+ codecContext.timeBase = new NodeAv6.Rational(1, this.config.sampleRate);
2988
+ codecContext.codecType = NodeAv6.AVMEDIA_TYPE_AUDIO;
2989
+ codecContext.codecId = codecId;
2990
+ codecContext.extraData = this.config.description ? Buffer.from(toUint8Array(this.config.description)) : null;
2991
+ const ret = await codecContext.open2();
2992
+ NodeAv6.FFmpegError.throwIfError(ret, "Open codec context");
2993
+ this.codecContext = codecContext;
2994
+ }
2995
+ async decode(packet) {
2996
+ this.packet.isKeyframe = packet.type === "key";
2997
+ this.packet.data = Buffer.from(packet.data);
2998
+ this.packet.timeBase = { num: 1, den: this.config.sampleRate };
2999
+ this.packet.pts = BigInt(Math.round(packet.timestamp * this.config.sampleRate));
3000
+ this.packet.dts = NodeAv6.AV_NOPTS_VALUE;
3001
+ this.packet.duration = BigInt(Math.round(packet.duration * this.config.sampleRate));
3002
+ const ret = await this.codecContext.sendPacket(this.packet);
3003
+ NodeAv6.FFmpegError.throwIfError(ret, "Send packet");
3004
+ while (true) {
3005
+ const receiveRet = await this.codecContext.receiveFrame(this.frame);
3006
+ if (receiveRet === NodeAv6.AVERROR_EAGAIN || receiveRet === NodeAv6.AVERROR_EOF) {
3007
+ break;
3008
+ }
3009
+ this.receiveFrame(receiveRet);
3010
+ }
3011
+ }
3012
+ receiveFrame(ret) {
3013
+ NodeAv6.FFmpegError.throwIfError(ret, "Receive frame");
3014
+ const clone = this.frame.clone();
3015
+ if (!clone) {
3016
+ throw new Error("Allocation failure during frame clone.");
3017
+ }
3018
+ clone.timeBase = new NodeAv6.Rational(1, this.config.sampleRate);
3019
+ this.onSample(new import_mediabunny5.AudioSample(new AvFrameAudioSampleResource(clone)));
3020
+ }
3021
+ async flush() {
3022
+ const ret = await this.codecContext.sendPacket(null);
3023
+ NodeAv6.FFmpegError.throwIfError(ret, "Flush decoder");
3024
+ while (true) {
3025
+ const receiveRet = await this.codecContext.receiveFrame(this.frame);
3026
+ if (receiveRet === NodeAv6.AVERROR_EAGAIN || receiveRet === NodeAv6.AVERROR_EOF) {
3027
+ break;
3028
+ }
3029
+ this.receiveFrame(receiveRet);
3030
+ }
3031
+ this.codecContext.flushBuffers();
3032
+ }
3033
+ close() {
3034
+ this.codecContext.freeContext();
3035
+ this.frame.free();
3036
+ this.packet.free();
3037
+ }
3038
+ };
3039
+
3040
+ // packages/server/src/audio-encoder.ts
3041
+ var import_mediabunny6 = __require("mediabunny");
3042
+ var NodeAv7 = __toESM(__require("node-av"));
3043
+ var AAC_SAMPLE_RATES = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350];
3044
+ var OPUS_SAMPLE_RATES = [8e3, 12e3, 16e3, 24e3, 48e3];
3045
+ var MP3_SAMPLE_RATES = [8e3, 11025, 12e3, 16e3, 22050, 24e3, 32e3, 44100, 48e3];
3046
+ var AC3_SAMPLE_RATES = [32e3, 44100, 48e3];
3047
+ var FRAME_SIZE_FALLBACK = 1024;
3048
+ var NodeAvAudioEncoder = class extends import_mediabunny6.CustomAudioEncoder {
3049
+ constructor() {
3050
+ super(...arguments);
3051
+ this.codecContext = null;
3052
+ this.firstExpectedTimestamp = null;
3053
+ this.outputTimestampOffset = 0;
3054
+ this.resampler = null;
3055
+ this.inputParametersKey = null;
3056
+ this.resamplerInputSampleRate = null;
3057
+ this.nextResamplerPts = null;
3058
+ this.dstFrame = null;
3059
+ this.packetEmitted = false;
3060
+ this.adtsHeaderTemplate = null;
3061
+ }
3062
+ static supports(codec, config) {
3063
+ const { numberOfChannels, sampleRate } = config;
3064
+ return codec === "aac" && numberOfChannels >= 1 && numberOfChannels <= 48 && AAC_SAMPLE_RATES.includes(sampleRate) || codec === "opus" && numberOfChannels >= 1 && numberOfChannels <= 255 && OPUS_SAMPLE_RATES.includes(sampleRate) || codec === "mp3" && numberOfChannels >= 1 && numberOfChannels <= 2 && MP3_SAMPLE_RATES.includes(sampleRate) || codec === "vorbis" && numberOfChannels >= 1 && numberOfChannels <= 255 && sampleRate <= 2e5 || codec === "flac" && numberOfChannels >= 1 && numberOfChannels <= 8 && sampleRate <= 655350 || codec === "ac3" && numberOfChannels >= 1 && numberOfChannels <= 6 && AC3_SAMPLE_RATES.includes(sampleRate) || codec === "eac3" && numberOfChannels >= 1 && numberOfChannels <= 16 && AC3_SAMPLE_RATES.includes(sampleRate);
3065
+ }
3066
+ async init() {
3067
+ this.frame = new NodeAv7.Frame();
3068
+ this.frame.alloc();
3069
+ this.packet = new NodeAv7.Packet();
3070
+ this.packet.alloc();
3071
+ const codecId = CODEC_TO_CODEC_ID[this.codec];
3072
+ assert(codecId !== void 0);
3073
+ const codec = NodeAv7.Codec.findEncoder(codecId);
3074
+ if (!codec) {
3075
+ throw new Error(`Unable to obtain libav codec for '${this.codec}'.`);
3076
+ }
3077
+ this.avCodec = codec;
3078
+ await this.createCodecContext();
3079
+ }
3080
+ async createCodecContext() {
3081
+ assert(this.codecContext === null);
3082
+ const codecContext = new NodeAv7.CodecContext();
3083
+ codecContext.allocContext3(this.avCodec);
3084
+ let sampleFormat = NodeAv7.AV_SAMPLE_FMT_FLTP;
3085
+ if (this.avCodec.sampleFormats && !this.avCodec.sampleFormats.includes(NodeAv7.AV_SAMPLE_FMT_FLTP)) {
3086
+ sampleFormat = this.avCodec.sampleFormats[0];
3087
+ }
3088
+ codecContext.sampleRate = this.config.sampleRate;
3089
+ codecContext.channelLayout = getChannelLayout(this.config.numberOfChannels);
3090
+ codecContext.codecType = NodeAv7.AVMEDIA_TYPE_AUDIO;
3091
+ codecContext.codecId = CODEC_TO_CODEC_ID[this.codec];
3092
+ codecContext.sampleFormat = sampleFormat;
3093
+ codecContext.timeBase = new NodeAv7.Rational(1, this.config.sampleRate);
3094
+ codecContext.bitRate = BigInt(this.config.bitrate ?? import_mediabunny6.QUALITY_MEDIUM._toAudioBitrate(this.codec) ?? 0);
3095
+ if (this.config.bitrateMode === "constant") {
3096
+ codecContext.rcMinRate = codecContext.bitRate;
3097
+ codecContext.rcMaxRate = codecContext.bitRate;
3098
+ }
3099
+ const ret = await codecContext.open2();
3100
+ NodeAv7.FFmpegError.throwIfError(ret, "Open codec context");
3101
+ this.codecContext = codecContext;
3102
+ }
3103
+ async encode(audioSample) {
3104
+ if (this.codecContext === null) {
3105
+ await this.createCodecContext();
3106
+ assert(this.codecContext);
3107
+ }
3108
+ this.firstExpectedTimestamp ??= audioSample.timestamp;
3109
+ if (audioSample._data instanceof AvFrameAudioSampleResource) {
3110
+ this.frame.ref(audioSample._data.frame);
3111
+ } else {
3112
+ copyAudioSampleToAvFrame(audioSample, this.frame);
3113
+ }
3114
+ this.frame.pts = BigInt(Math.round(audioSample.timestamp * this.config.sampleRate));
3115
+ this.frame.duration = BigInt(Math.round(audioSample.duration * this.config.sampleRate));
3116
+ this.frame.timeBase = new NodeAv7.Rational(1, this.config.sampleRate);
3117
+ const key = `${this.frame.sampleRate}:${this.frame.channels}:${this.frame.format}`;
3118
+ if (this.inputParametersKey !== null && this.inputParametersKey !== key) {
3119
+ throw new Error(
3120
+ "Input audio parameters changed. For this audio encoder, you cannot change the input audio parameters over time."
3121
+ );
3122
+ }
3123
+ this.inputParametersKey = key;
3124
+ const requiresResampler = this.codecContext.frameSize > 0 || this.codecContext.sampleFormat !== this.frame.format || this.codecContext.sampleRate !== this.frame.sampleRate || this.codecContext.channels !== this.frame.channels;
3125
+ if (requiresResampler) {
3126
+ if (!this.resampler) {
3127
+ this.resampler = new NodeAv7.SoftwareResampleContext();
3128
+ this.resamplerInputSampleRate = this.frame.sampleRate;
3129
+ const outLayout = getChannelLayout(this.codecContext.channels);
3130
+ const inLayout = getChannelLayout(this.frame.channels);
3131
+ const ret = this.resampler.allocSetOpts2(
3132
+ outLayout,
3133
+ this.codecContext.sampleFormat,
3134
+ this.codecContext.sampleRate,
3135
+ inLayout,
3136
+ this.frame.format,
3137
+ this.frame.sampleRate
3138
+ );
3139
+ NodeAv7.FFmpegError.throwIfError(ret, "allocSetOpts2");
3140
+ const ret2 = this.resampler.init();
3141
+ NodeAv7.FFmpegError.throwIfError(ret2, "init");
3142
+ this.dstFrame = new NodeAv7.Frame();
3143
+ this.dstFrame.alloc();
3144
+ this.dstFrame.channelLayout = outLayout;
3145
+ this.dstFrame.sampleRate = this.codecContext.sampleRate;
3146
+ this.dstFrame.format = this.codecContext.sampleFormat;
3147
+ this.dstFrame.nbSamples = this.codecContext.frameSize || FRAME_SIZE_FALLBACK;
3148
+ this.dstFrame.duration = BigInt(this.dstFrame.nbSamples);
3149
+ this.dstFrame.allocBuffer();
3150
+ this.nextResamplerPts = this.frame.pts;
3151
+ }
3152
+ const inputBuffers = this.frame.data;
3153
+ if (!inputBuffers) {
3154
+ throw new DOMException("Frame has no data", "EncodingError");
3155
+ }
3156
+ await this.resampler.convert(null, 0, inputBuffers, this.frame.nbSamples);
3157
+ await this.pullResampledFrames();
3158
+ } else {
3159
+ await this.sendFrameAndReceivePackets(this.frame);
3160
+ }
3161
+ }
3162
+ async pullResampledFrames() {
3163
+ assert(this.codecContext);
3164
+ assert(this.resampler);
3165
+ assert(this.dstFrame);
3166
+ assert(this.nextResamplerPts !== null);
3167
+ const frameSize = this.codecContext.frameSize || FRAME_SIZE_FALLBACK;
3168
+ while (true) {
3169
+ const available = this.resampler.getOutSamples(0);
3170
+ if (available < frameSize) {
3171
+ break;
3172
+ }
3173
+ await this.resampler.convert(this.dstFrame.data, frameSize, null, 0);
3174
+ this.dstFrame.pts = this.nextResamplerPts;
3175
+ await this.sendFrameAndReceivePackets(this.dstFrame);
3176
+ this.nextResamplerPts += BigInt(frameSize);
3177
+ }
3178
+ }
3179
+ async sendFrameAndReceivePackets(frame) {
3180
+ assert(this.codecContext);
3181
+ const ret = await this.codecContext.sendFrame(frame);
3182
+ NodeAv7.FFmpegError.throwIfError(ret, "Send frame");
3183
+ while (true) {
3184
+ const receiveRet = await this.codecContext.receivePacket(this.packet);
3185
+ if (receiveRet === NodeAv7.AVERROR_EAGAIN || receiveRet === NodeAv7.AVERROR_EOF) {
3186
+ break;
3187
+ }
3188
+ this.receivePacket(receiveRet);
3189
+ }
3190
+ }
3191
+ receivePacket(ret) {
3192
+ assert(this.codecContext);
3193
+ assert(this.firstExpectedTimestamp !== null);
3194
+ NodeAv7.FFmpegError.throwIfError(ret, "Receive packet");
3195
+ if (!this.packet.data) {
3196
+ return;
3197
+ }
3198
+ let timestamp = Number(this.packet.pts) / this.codecContext.sampleRate;
3199
+ const duration = Number(this.packet.duration) / this.codecContext.sampleRate;
3200
+ let data = this.packet.data;
3201
+ let metadata;
3202
+ if (this.packetEmitted) {
3203
+ metadata = {};
3204
+ } else {
3205
+ this.outputTimestampOffset = Math.max(this.firstExpectedTimestamp - timestamp, 0);
3206
+ const codecString = this.config.codec;
3207
+ let description = this.codecContext.extraData ? toUint8Array(this.codecContext.extraData) : void 0;
3208
+ if (this.codec === "aac") {
3209
+ if (!description) {
3210
+ throw new Error("Extradata expected for AAC.");
3211
+ }
3212
+ const isAdts = this.config.aac?.format === "adts";
3213
+ if (isAdts) {
3214
+ const parsedConfig = parseAacAudioSpecificConfig(description);
3215
+ this.adtsHeaderTemplate = buildAdtsHeaderTemplate(parsedConfig);
3216
+ description = void 0;
3217
+ }
3218
+ } else if (this.codec === "opus") {
3219
+ if (!description) {
3220
+ throw new Error("Extradata expected for Opus.");
3221
+ }
3222
+ } else if (this.codec === "vorbis") {
3223
+ if (!description) {
3224
+ throw new Error("Extradata expected for Vorbis.");
3225
+ }
3226
+ } else if (this.codec === "flac") {
3227
+ if (!description) {
3228
+ throw new Error("Extradata expected for FLAC.");
3229
+ }
3230
+ description = new Uint8Array([
3231
+ 102,
3232
+ 76,
3233
+ 97,
3234
+ 67,
3235
+ // 'fLaC'
3236
+ 128,
3237
+ 0,
3238
+ 0,
3239
+ description.byteLength,
3240
+ ...description
3241
+ ]);
3242
+ }
3243
+ metadata = {
3244
+ decoderConfig: {
3245
+ codec: codecString,
3246
+ sampleRate: this.codecContext.sampleRate,
3247
+ numberOfChannels: this.codecContext.channels,
3248
+ description
3249
+ }
3250
+ };
3251
+ }
3252
+ if (this.adtsHeaderTemplate) {
3253
+ const frameLength = data.byteLength + this.adtsHeaderTemplate.header.byteLength;
3254
+ this.adtsHeaderTemplate.bitstream.pos = 30;
3255
+ this.adtsHeaderTemplate.bitstream.writeBits(13, frameLength);
3256
+ const final = new Uint8Array(this.adtsHeaderTemplate.header.byteLength + data.byteLength);
3257
+ final.set(this.adtsHeaderTemplate.header, 0);
3258
+ final.set(data, this.adtsHeaderTemplate.header.byteLength);
3259
+ data = final;
3260
+ }
3261
+ timestamp += this.outputTimestampOffset;
3262
+ const packet = new import_mediabunny6.EncodedPacket(
3263
+ data,
3264
+ "key",
3265
+ timestamp,
3266
+ duration
3267
+ );
3268
+ this.packetEmitted = true;
3269
+ this.onPacket(packet, metadata);
3270
+ }
3271
+ async flush() {
3272
+ if (!this.codecContext) {
3273
+ return;
3274
+ }
3275
+ outer:
3276
+ if (this.resampler) {
3277
+ assert(this.resamplerInputSampleRate !== null);
3278
+ const currentOutSamples = this.resampler.getOutSamples(0);
3279
+ if (currentOutSamples === 0) {
3280
+ break outer;
3281
+ }
3282
+ const frameSize = this.codecContext.frameSize || FRAME_SIZE_FALLBACK;
3283
+ assert(currentOutSamples < frameSize);
3284
+ const inputSamplesNeeded = Math.ceil(
3285
+ (frameSize - currentOutSamples) / this.codecContext.sampleRate * this.resamplerInputSampleRate
3286
+ );
3287
+ this.resampler.injectSilence(inputSamplesNeeded);
3288
+ await this.pullResampledFrames();
3289
+ }
3290
+ await this.sendFrameAndReceivePackets(null);
3291
+ this.codecContext.freeContext();
3292
+ this.codecContext = null;
3293
+ this.packetEmitted = false;
3294
+ this.firstExpectedTimestamp = null;
3295
+ this.outputTimestampOffset = 0;
3296
+ this.adtsHeaderTemplate = null;
3297
+ this.resampler?.free();
3298
+ this.resampler = null;
3299
+ this.inputParametersKey = null;
3300
+ this.resamplerInputSampleRate = null;
3301
+ this.nextResamplerPts = null;
3302
+ this.dstFrame?.free();
3303
+ this.dstFrame = null;
3304
+ }
3305
+ close() {
3306
+ this.codecContext?.freeContext();
3307
+ this.frame.free();
3308
+ this.packet.free();
3309
+ this.dstFrame?.free();
3310
+ this.resampler?.free();
3311
+ }
3312
+ };
3313
+
3314
+ // packages/server/src/index.ts
3315
+ var SERVER_LOADED_SYMBOL = Symbol.for("@mediabunny/server loaded");
3316
+ if (globalThis[SERVER_LOADED_SYMBOL]) {
3317
+ console.error(
3318
+ "[WARNING]\n@mediabunny/server was loaded twice. This will likely cause the package not to work correctly. Check if multiple dependencies are importing different versions of @mediabunny/server, or if something is being bundled incorrectly."
3319
+ );
3320
+ }
3321
+ globalThis[SERVER_LOADED_SYMBOL] = true;
3322
+ var registered = false;
3323
+ var registerMediabunnyServer = () => {
3324
+ if (registered) {
3325
+ return;
3326
+ }
3327
+ registered = true;
3328
+ NodeAv8.Log.setLevel(NodeAv8.AV_LOG_ERROR);
3329
+ (0, import_mediabunny7.registerDecoder)(NodeAvVideoDecoder);
3330
+ (0, import_mediabunny7.registerEncoder)(NodeAvVideoEncoder);
3331
+ (0, import_mediabunny7.registerDecoder)(NodeAvAudioDecoder);
3332
+ (0, import_mediabunny7.registerEncoder)(NodeAvAudioEncoder);
3333
+ (0, import_mediabunny7.registerVideoSampleTransformer)(transformVideoSample);
3334
+ };
3335
+ var toAvFrame = async (sample, frame) => {
3336
+ if (sample instanceof import_mediabunny7.VideoSample) {
3337
+ if (sample._data instanceof AvFrameVideoSampleResource) {
3338
+ frame.ref(sample._data.frame);
3339
+ } else {
3340
+ if (sample.format === null) {
3341
+ throw new Error("Cannot convert foreign VideoSample with unknown (null) format.");
3342
+ }
3343
+ await copyVideoSampleToAvFrame(sample, frame, null);
3344
+ }
3345
+ frame.pts = BigInt(sample.microsecondTimestamp);
3346
+ frame.duration = BigInt(sample.microsecondDuration);
3347
+ frame.timeBase = new NodeAv8.Rational(1, 1e6);
3348
+ } else {
3349
+ if (sample._data instanceof AvFrameAudioSampleResource) {
3350
+ frame.ref(sample._data.frame);
3351
+ } else {
3352
+ copyAudioSampleToAvFrame(sample, frame);
3353
+ }
3354
+ frame.timeBase = new NodeAv8.Rational(1, sample.sampleRate);
3355
+ frame.pts = BigInt(Math.round(sample.timestamp * sample.sampleRate));
3356
+ frame.duration = BigInt(sample.numberOfFrames);
3357
+ }
3358
+ };
3359
+ return __toCommonJS(index_exports);
3360
+ })();
3361
+ if (typeof module === "object" && typeof module.exports === "object") Object.assign(module.exports, MediabunnyServer)