mediabunny 1.56.2 → 1.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles/mediabunny.cjs +698 -195
- package/dist/bundles/mediabunny.min.cjs +13 -13
- package/dist/bundles/mediabunny.min.mjs +13 -13
- package/dist/bundles/mediabunny.mjs +698 -195
- package/dist/bundles/mediabunny.node.cjs +698 -195
- package/dist/mediabunny.d.ts +212 -56
- package/dist/modules/src/conversion.d.ts +19 -6
- package/dist/modules/src/conversion.d.ts.map +1 -1
- package/dist/modules/src/conversion.js +40 -6
- package/dist/modules/src/encode.d.ts +63 -9
- package/dist/modules/src/encode.d.ts.map +1 -1
- package/dist/modules/src/encode.js +8 -2
- package/dist/modules/src/hls/hls-demuxer.js +2 -2
- package/dist/modules/src/hls/hls-muxer.d.ts.map +1 -1
- package/dist/modules/src/hls/hls-muxer.js +5 -3
- package/dist/modules/src/hls/hls-segmented-input.d.ts.map +1 -1
- package/dist/modules/src/hls/hls-segmented-input.js +3 -2
- package/dist/modules/src/id3.d.ts.map +1 -1
- package/dist/modules/src/id3.js +1 -1
- package/dist/modules/src/index.d.ts +1 -1
- package/dist/modules/src/index.d.ts.map +1 -1
- package/dist/modules/src/input-track.d.ts +21 -5
- package/dist/modules/src/input-track.d.ts.map +1 -1
- package/dist/modules/src/input-track.js +26 -6
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts +2 -0
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.js +26 -39
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts +6 -2
- package/dist/modules/src/isobmff/isobmff-demuxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-demuxer.js +44 -30
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts +3 -0
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.js +52 -0
- package/dist/modules/src/isobmff/isobmff-reader.js +1 -1
- package/dist/modules/src/matroska/ebml.d.ts +2 -0
- package/dist/modules/src/matroska/ebml.d.ts.map +1 -1
- package/dist/modules/src/matroska/ebml.js +2 -0
- package/dist/modules/src/matroska/matroska-demuxer.d.ts +2 -0
- package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-demuxer.js +40 -3
- package/dist/modules/src/matroska/matroska-muxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-muxer.js +49 -9
- package/dist/modules/src/media-sink.d.ts +10 -5
- package/dist/modules/src/media-sink.d.ts.map +1 -1
- package/dist/modules/src/media-sink.js +15 -4
- package/dist/modules/src/media-source.d.ts.map +1 -1
- package/dist/modules/src/media-source.js +62 -41
- package/dist/modules/src/misc.d.ts +70 -3
- package/dist/modules/src/misc.d.ts.map +1 -1
- package/dist/modules/src/misc.js +239 -0
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.d.ts.map +1 -1
- package/dist/modules/src/mpeg-ts/mpeg-ts-demuxer.js +3 -3
- package/dist/modules/src/output-format.d.ts +16 -11
- package/dist/modules/src/output-format.d.ts.map +1 -1
- package/dist/modules/src/output-format.js +18 -11
- package/dist/modules/src/output.d.ts +23 -2
- package/dist/modules/src/output.d.ts.map +1 -1
- package/dist/modules/src/output.js +21 -5
- package/dist/modules/src/sample.d.ts +48 -23
- package/dist/modules/src/sample.d.ts.map +1 -1
- package/dist/modules/src/sample.js +72 -16
- package/dist/modules/src/segmented-input.js +2 -2
- package/dist/modules/src/source.d.ts.map +1 -1
- package/dist/modules/src/source.js +34 -17
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/dist/modules/src/wave/riff-writer.d.ts.map +1 -1
- package/dist/modules/src/wave/riff-writer.js +2 -1
- package/package.json +1 -1
- package/src/conversion.ts +68 -12
- package/src/encode.ts +71 -10
- package/src/hls/hls-demuxer.ts +3 -3
- package/src/hls/hls-muxer.ts +5 -3
- package/src/hls/hls-segmented-input.ts +3 -2
- package/src/id3.ts +1 -0
- package/src/index.ts +1 -0
- package/src/input-track.ts +37 -7
- package/src/isobmff/isobmff-boxes.ts +36 -45
- package/src/isobmff/isobmff-demuxer.ts +51 -38
- package/src/isobmff/isobmff-muxer.ts +66 -0
- package/src/isobmff/isobmff-reader.ts +1 -1
- package/src/matroska/ebml.ts +2 -0
- package/src/matroska/matroska-demuxer.ts +47 -2
- package/src/matroska/matroska-muxer.ts +56 -8
- package/src/media-sink.ts +22 -6
- package/src/media-source.ts +60 -44
- package/src/misc.ts +285 -1
- package/src/mpeg-ts/mpeg-ts-demuxer.ts +4 -3
- package/src/output-format.ts +20 -13
- package/src/output.ts +49 -6
- package/src/sample.ts +125 -35
- package/src/segmented-input.ts +2 -2
- package/src/source.ts +43 -22
- package/src/wave/riff-writer.ts +2 -1
|
@@ -245,6 +245,8 @@ var Mediabunny = (() => {
|
|
|
245
245
|
throw new Error("Assertion failed.");
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
+
var DEG_TO_RAD = Math.PI / 180;
|
|
249
|
+
var RAD_TO_DEG = 180 / Math.PI;
|
|
248
250
|
var normalizeRotation = (rotation) => {
|
|
249
251
|
const mappedRotation = (rotation % 360 + 360) % 360;
|
|
250
252
|
if (mappedRotation === 0 || mappedRotation === 90 || mappedRotation === 180 || mappedRotation === 270) {
|
|
@@ -253,6 +255,86 @@ var Mediabunny = (() => {
|
|
|
253
255
|
throw new Error(`Invalid rotation ${rotation}.`);
|
|
254
256
|
}
|
|
255
257
|
};
|
|
258
|
+
var IDENTITY_MATRIX = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
|
259
|
+
var centeredTransformationMatrix = (linear, width, height) => {
|
|
260
|
+
const [a, b, , c, d] = linear;
|
|
261
|
+
const transformedWidth = Math.abs(a) * width + Math.abs(c) * height;
|
|
262
|
+
const transformedHeight = Math.abs(b) * width + Math.abs(d) * height;
|
|
263
|
+
return multiplyMatrices(
|
|
264
|
+
multiplyMatrices(
|
|
265
|
+
translationMatrix(-width / 2, -height / 2),
|
|
266
|
+
linear
|
|
267
|
+
),
|
|
268
|
+
translationMatrix(transformedWidth / 2, transformedHeight / 2)
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
var extractRotationFromMatrix = (matrix) => {
|
|
272
|
+
const [a, b] = matrix;
|
|
273
|
+
const radians = Math.atan2(b, matrixIsFlipped(matrix) ? -a : a);
|
|
274
|
+
return normalizeRotation(roundToMultiple(radians * RAD_TO_DEG, 90));
|
|
275
|
+
};
|
|
276
|
+
var matrixIsFlipped = (matrix) => {
|
|
277
|
+
const [a, b, , c, d] = matrix;
|
|
278
|
+
const det = a * d - b * c;
|
|
279
|
+
return det < 0;
|
|
280
|
+
};
|
|
281
|
+
var rotationMatrix = (rotationInDegrees) => {
|
|
282
|
+
const theta = rotationInDegrees * DEG_TO_RAD;
|
|
283
|
+
const cosTheta = Math.round(Math.cos(theta));
|
|
284
|
+
const sinTheta = Math.round(Math.sin(theta));
|
|
285
|
+
return [
|
|
286
|
+
cosTheta,
|
|
287
|
+
sinTheta,
|
|
288
|
+
0,
|
|
289
|
+
-sinTheta,
|
|
290
|
+
cosTheta,
|
|
291
|
+
0,
|
|
292
|
+
0,
|
|
293
|
+
0,
|
|
294
|
+
1
|
|
295
|
+
];
|
|
296
|
+
};
|
|
297
|
+
var translationMatrix = (x, y) => {
|
|
298
|
+
return [
|
|
299
|
+
1,
|
|
300
|
+
0,
|
|
301
|
+
0,
|
|
302
|
+
0,
|
|
303
|
+
1,
|
|
304
|
+
0,
|
|
305
|
+
x,
|
|
306
|
+
y,
|
|
307
|
+
1
|
|
308
|
+
];
|
|
309
|
+
};
|
|
310
|
+
var scaleMatrix = (x, y) => {
|
|
311
|
+
return [
|
|
312
|
+
x,
|
|
313
|
+
0,
|
|
314
|
+
0,
|
|
315
|
+
0,
|
|
316
|
+
y,
|
|
317
|
+
0,
|
|
318
|
+
0,
|
|
319
|
+
0,
|
|
320
|
+
1
|
|
321
|
+
];
|
|
322
|
+
};
|
|
323
|
+
var multiplyMatrices = (a, b) => {
|
|
324
|
+
const result = new Array(9);
|
|
325
|
+
for (let i = 0; i < 3; i++) {
|
|
326
|
+
for (let j = 0; j < 3; j++) {
|
|
327
|
+
result[3 * i + j] = a[3 * i] * b[j] + a[3 * i + 1] * b[3 + j] + a[3 * i + 2] * b[6 + j];
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return result;
|
|
331
|
+
};
|
|
332
|
+
var composeRotationAndFlip = (rotation1, flip1, rotation2, flip2) => {
|
|
333
|
+
return {
|
|
334
|
+
rotation: normalizeRotation(rotation1 + (flip1 ? -rotation2 : rotation2)),
|
|
335
|
+
flip: flip1 !== flip2
|
|
336
|
+
};
|
|
337
|
+
};
|
|
256
338
|
var last = (arr) => {
|
|
257
339
|
return arr && arr[arr.length - 1];
|
|
258
340
|
};
|
|
@@ -312,6 +394,139 @@ var Mediabunny = (() => {
|
|
|
312
394
|
return new DataView(source);
|
|
313
395
|
}
|
|
314
396
|
};
|
|
397
|
+
var TextEncoder = typeof globalThis.TextEncoder !== "undefined" ? globalThis.TextEncoder : class TextEncoder2 {
|
|
398
|
+
constructor() {
|
|
399
|
+
this.encoding = "utf-8";
|
|
400
|
+
}
|
|
401
|
+
encode(input = "") {
|
|
402
|
+
const bytes2 = new Uint8Array(3 * input.length);
|
|
403
|
+
let n = 0;
|
|
404
|
+
for (let i = 0; i < input.length; i++) {
|
|
405
|
+
let c = input.charCodeAt(i);
|
|
406
|
+
if (c < 128) {
|
|
407
|
+
bytes2[n++] = c;
|
|
408
|
+
} else if (c < 2048) {
|
|
409
|
+
bytes2[n++] = 192 | c >> 6;
|
|
410
|
+
bytes2[n++] = 128 | c & 63;
|
|
411
|
+
} else if (c < 55296 || c > 57343) {
|
|
412
|
+
bytes2[n++] = 224 | c >> 12;
|
|
413
|
+
bytes2[n++] = 128 | c >> 6 & 63;
|
|
414
|
+
bytes2[n++] = 128 | c & 63;
|
|
415
|
+
} else {
|
|
416
|
+
const next = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
|
|
417
|
+
if (c < 56320 && next >= 56320 && next <= 57343) {
|
|
418
|
+
c = 65536 + (c - 55296 << 10) + (next - 56320);
|
|
419
|
+
i++;
|
|
420
|
+
bytes2[n++] = 240 | c >> 18;
|
|
421
|
+
bytes2[n++] = 128 | c >> 12 & 63;
|
|
422
|
+
bytes2[n++] = 128 | c >> 6 & 63;
|
|
423
|
+
bytes2[n++] = 128 | c & 63;
|
|
424
|
+
} else {
|
|
425
|
+
bytes2[n++] = 239;
|
|
426
|
+
bytes2[n++] = 191;
|
|
427
|
+
bytes2[n++] = 189;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return bytes2.slice(0, n);
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
var TextDecoder = typeof globalThis.TextDecoder !== "undefined" ? globalThis.TextDecoder : class TextDecoder2 {
|
|
435
|
+
constructor(label = "utf-8") {
|
|
436
|
+
const normalized = label.trim().toLowerCase();
|
|
437
|
+
if (normalized === "utf-8" || normalized === "utf8" || normalized === "unicode-1-1-utf-8") {
|
|
438
|
+
this.encoding = "utf-8";
|
|
439
|
+
} else if (normalized === "utf-16le" || normalized === "utf-16") {
|
|
440
|
+
this.encoding = "utf-16le";
|
|
441
|
+
} else if (normalized === "utf-16be") {
|
|
442
|
+
this.encoding = "utf-16be";
|
|
443
|
+
} else {
|
|
444
|
+
throw new RangeError(`The encoding label provided ('${label}') is invalid.`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
decode(input) {
|
|
448
|
+
const bytes2 = input ? toUint8Array(input) : new Uint8Array(0);
|
|
449
|
+
const units = [];
|
|
450
|
+
if (this.encoding === "utf-8") {
|
|
451
|
+
let i = bytes2.length >= 3 && bytes2[0] === 239 && bytes2[1] === 187 && bytes2[2] === 191 ? 3 : 0;
|
|
452
|
+
while (i < bytes2.length) {
|
|
453
|
+
const lead = bytes2[i];
|
|
454
|
+
if (lead < 128) {
|
|
455
|
+
units.push(lead);
|
|
456
|
+
i++;
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
let continuationCount;
|
|
460
|
+
let codePoint;
|
|
461
|
+
if (lead >= 194 && lead < 224) {
|
|
462
|
+
continuationCount = 1;
|
|
463
|
+
codePoint = lead & 31;
|
|
464
|
+
} else if (lead >= 224 && lead < 240) {
|
|
465
|
+
continuationCount = 2;
|
|
466
|
+
codePoint = lead & 15;
|
|
467
|
+
} else if (lead >= 240 && lead < 245) {
|
|
468
|
+
continuationCount = 3;
|
|
469
|
+
codePoint = lead & 7;
|
|
470
|
+
} else {
|
|
471
|
+
units.push(65533);
|
|
472
|
+
i++;
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
let lowerBound = lead === 224 ? 160 : lead === 240 ? 144 : 128;
|
|
476
|
+
let upperBound = lead === 237 ? 159 : lead === 244 ? 143 : 191;
|
|
477
|
+
let j = 1;
|
|
478
|
+
for (; j <= continuationCount; j++) {
|
|
479
|
+
const byte = i + j < bytes2.length ? bytes2[i + j] : 0;
|
|
480
|
+
if (byte < lowerBound || byte > upperBound) {
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
codePoint = codePoint << 6 | byte & 63;
|
|
484
|
+
lowerBound = 128;
|
|
485
|
+
upperBound = 191;
|
|
486
|
+
}
|
|
487
|
+
i += j;
|
|
488
|
+
if (j <= continuationCount) {
|
|
489
|
+
units.push(65533);
|
|
490
|
+
} else if (codePoint >= 65536) {
|
|
491
|
+
codePoint -= 65536;
|
|
492
|
+
units.push(55296 | codePoint >> 10, 56320 | codePoint & 1023);
|
|
493
|
+
} else {
|
|
494
|
+
units.push(codePoint);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
} else {
|
|
498
|
+
const littleEndian = this.encoding === "utf-16le";
|
|
499
|
+
const bomLow = littleEndian ? 255 : 254;
|
|
500
|
+
const bomHigh = littleEndian ? 254 : 255;
|
|
501
|
+
let i = bytes2.length >= 2 && bytes2[0] === bomLow && bytes2[1] === bomHigh ? 2 : 0;
|
|
502
|
+
while (i + 1 < bytes2.length) {
|
|
503
|
+
const unit = littleEndian ? bytes2[i] | bytes2[i + 1] << 8 : bytes2[i] << 8 | bytes2[i + 1];
|
|
504
|
+
i += 2;
|
|
505
|
+
if (unit >= 55296 && unit <= 56319) {
|
|
506
|
+
const next = i + 1 < bytes2.length ? littleEndian ? bytes2[i] | bytes2[i + 1] << 8 : bytes2[i] << 8 | bytes2[i + 1] : -1;
|
|
507
|
+
if (next >= 56320 && next <= 57343) {
|
|
508
|
+
units.push(unit, next);
|
|
509
|
+
i += 2;
|
|
510
|
+
} else {
|
|
511
|
+
units.push(65533);
|
|
512
|
+
}
|
|
513
|
+
} else if (unit >= 56320 && unit <= 57343) {
|
|
514
|
+
units.push(65533);
|
|
515
|
+
} else {
|
|
516
|
+
units.push(unit);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
if (i < bytes2.length) {
|
|
520
|
+
units.push(65533);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
let result = "";
|
|
524
|
+
for (let i = 0; i < units.length; i += 8192) {
|
|
525
|
+
result += String.fromCharCode(...units.slice(i, i + 8192));
|
|
526
|
+
}
|
|
527
|
+
return result;
|
|
528
|
+
}
|
|
529
|
+
};
|
|
315
530
|
var textDecoder = /* @__PURE__ */ new TextDecoder();
|
|
316
531
|
var textEncoder = /* @__PURE__ */ new TextEncoder();
|
|
317
532
|
var isIso88591Compatible = (text) => {
|
|
@@ -6258,6 +6473,7 @@ var Mediabunny = (() => {
|
|
|
6258
6473
|
this.metadataPromise = null;
|
|
6259
6474
|
this.movieTimescale = -1;
|
|
6260
6475
|
this.movieDurationInTimescale = -1;
|
|
6476
|
+
this.movieMatrix = IDENTITY_MATRIX;
|
|
6261
6477
|
this.isQuickTime = false;
|
|
6262
6478
|
this.metadataTags = {};
|
|
6263
6479
|
this.currentMetadataKeys = null;
|
|
@@ -6376,6 +6592,7 @@ var Mediabunny = (() => {
|
|
|
6376
6592
|
await initDemuxer.readMetadata();
|
|
6377
6593
|
this.movieTimescale = initDemuxer.movieTimescale;
|
|
6378
6594
|
this.movieDurationInTimescale = initDemuxer.movieDurationInTimescale;
|
|
6595
|
+
this.movieMatrix = initDemuxer.movieMatrix;
|
|
6379
6596
|
this.metadataTags = initDemuxer.metadataTags;
|
|
6380
6597
|
this.isFragmented = true;
|
|
6381
6598
|
this.fragmentTrackDefaults = initDemuxer.fragmentTrackDefaults;
|
|
@@ -6389,7 +6606,7 @@ var Mediabunny = (() => {
|
|
|
6389
6606
|
timescale: foreignTrack.timescale,
|
|
6390
6607
|
durationInMediaTimescale: foreignTrack.durationInMediaTimescale,
|
|
6391
6608
|
durationInMovieTimescale: foreignTrack.durationInMovieTimescale,
|
|
6392
|
-
|
|
6609
|
+
matrix: foreignTrack.matrix,
|
|
6393
6610
|
internalCodecId: foreignTrack.internalCodecId,
|
|
6394
6611
|
name: foreignTrack.name,
|
|
6395
6612
|
languageCode: foreignTrack.languageCode,
|
|
@@ -6403,6 +6620,8 @@ var Mediabunny = (() => {
|
|
|
6403
6620
|
encryptionInfo: foreignTrack.encryptionInfo,
|
|
6404
6621
|
encryptionAuxInfo: null,
|
|
6405
6622
|
frmaCodecString: null,
|
|
6623
|
+
maxBitrate: foreignTrack.maxBitrate,
|
|
6624
|
+
avgBitrate: foreignTrack.avgBitrate,
|
|
6406
6625
|
info: foreignTrack.info
|
|
6407
6626
|
};
|
|
6408
6627
|
if (foreignTrack.trackBacking) {
|
|
@@ -6638,6 +6857,8 @@ var Mediabunny = (() => {
|
|
|
6638
6857
|
this.movieTimescale = readU32Be(slice);
|
|
6639
6858
|
this.movieDurationInTimescale = readU32Be(slice);
|
|
6640
6859
|
}
|
|
6860
|
+
slice.skip(4 + 2 + 2 + 2 * 4);
|
|
6861
|
+
this.movieMatrix = readMatrix(slice);
|
|
6641
6862
|
}
|
|
6642
6863
|
;
|
|
6643
6864
|
break;
|
|
@@ -6655,7 +6876,7 @@ var Mediabunny = (() => {
|
|
|
6655
6876
|
timescale: -1,
|
|
6656
6877
|
durationInMovieTimescale: -1,
|
|
6657
6878
|
durationInMediaTimescale: -1,
|
|
6658
|
-
|
|
6879
|
+
matrix: IDENTITY_MATRIX,
|
|
6659
6880
|
internalCodecId: null,
|
|
6660
6881
|
name: null,
|
|
6661
6882
|
languageCode: UNDETERMINED_LANGUAGE,
|
|
@@ -6668,7 +6889,9 @@ var Mediabunny = (() => {
|
|
|
6668
6889
|
editListOffset: 0,
|
|
6669
6890
|
encryptionInfo: null,
|
|
6670
6891
|
encryptionAuxInfo: null,
|
|
6671
|
-
frmaCodecString: null
|
|
6892
|
+
frmaCodecString: null,
|
|
6893
|
+
maxBitrate: null,
|
|
6894
|
+
avgBitrate: null
|
|
6672
6895
|
};
|
|
6673
6896
|
this.currentTrack = track;
|
|
6674
6897
|
this.readContiguousBoxes(slice.slice(contentStartPos, boxInfo.contentSize));
|
|
@@ -6711,20 +6934,8 @@ var Mediabunny = (() => {
|
|
|
6711
6934
|
throw new Error(`Incorrect track header version ${version}.`);
|
|
6712
6935
|
}
|
|
6713
6936
|
slice.skip(2 * 4 + 2 + 2 + 2 + 2);
|
|
6714
|
-
const
|
|
6715
|
-
|
|
6716
|
-
readFixed_16_16(slice),
|
|
6717
|
-
readFixed_2_30(slice),
|
|
6718
|
-
readFixed_16_16(slice),
|
|
6719
|
-
readFixed_16_16(slice),
|
|
6720
|
-
readFixed_2_30(slice),
|
|
6721
|
-
readFixed_16_16(slice),
|
|
6722
|
-
readFixed_16_16(slice),
|
|
6723
|
-
readFixed_2_30(slice)
|
|
6724
|
-
];
|
|
6725
|
-
const rotation = normalizeRotation(roundToMultiple(extractRotationFromMatrix(matrix), 90));
|
|
6726
|
-
assert(rotation === 0 || rotation === 90 || rotation === 180 || rotation === 270);
|
|
6727
|
-
track.rotation = rotation;
|
|
6937
|
+
const trackMatrix = readMatrix(slice);
|
|
6938
|
+
track.matrix = multiplyMatrices(trackMatrix, this.movieMatrix);
|
|
6728
6939
|
}
|
|
6729
6940
|
;
|
|
6730
6941
|
break;
|
|
@@ -7280,6 +7491,20 @@ var Mediabunny = (() => {
|
|
|
7280
7491
|
}
|
|
7281
7492
|
;
|
|
7282
7493
|
break;
|
|
7494
|
+
case "btrt":
|
|
7495
|
+
{
|
|
7496
|
+
const track = this.currentTrack;
|
|
7497
|
+
if (!track) {
|
|
7498
|
+
break;
|
|
7499
|
+
}
|
|
7500
|
+
slice.skip(4);
|
|
7501
|
+
const maxBitrate = readU32Be(slice);
|
|
7502
|
+
const avgBitrate = readU32Be(slice);
|
|
7503
|
+
track.maxBitrate = maxBitrate > 0 ? maxBitrate : null;
|
|
7504
|
+
track.avgBitrate = avgBitrate > 0 ? avgBitrate : null;
|
|
7505
|
+
}
|
|
7506
|
+
;
|
|
7507
|
+
break;
|
|
7283
7508
|
case "wave":
|
|
7284
7509
|
{
|
|
7285
7510
|
this.readContiguousBoxes(slice.slice(contentStartPos, boxInfo.contentSize));
|
|
@@ -8498,10 +8723,10 @@ var Mediabunny = (() => {
|
|
|
8498
8723
|
return 1n;
|
|
8499
8724
|
}
|
|
8500
8725
|
getBitrate() {
|
|
8501
|
-
return
|
|
8726
|
+
return this.internalTrack.maxBitrate;
|
|
8502
8727
|
}
|
|
8503
8728
|
getAverageBitrate() {
|
|
8504
|
-
return
|
|
8729
|
+
return this.internalTrack.avgBitrate;
|
|
8505
8730
|
}
|
|
8506
8731
|
async getDurationFromMetadata() {
|
|
8507
8732
|
const track = this.internalTrack;
|
|
@@ -8894,8 +9119,8 @@ var Mediabunny = (() => {
|
|
|
8894
9119
|
getSquarePixelHeight() {
|
|
8895
9120
|
return this.internalTrack.info.squarePixelHeight;
|
|
8896
9121
|
}
|
|
8897
|
-
|
|
8898
|
-
return this.internalTrack.
|
|
9122
|
+
getTransformationMatrix() {
|
|
9123
|
+
return [...this.internalTrack.matrix];
|
|
8899
9124
|
}
|
|
8900
9125
|
async getColorSpace() {
|
|
8901
9126
|
const decoderConfig = await this.getDecoderConfig();
|
|
@@ -9134,13 +9359,18 @@ var Mediabunny = (() => {
|
|
|
9134
9359
|
entry.presentationTimestamp += timestamp;
|
|
9135
9360
|
}
|
|
9136
9361
|
};
|
|
9137
|
-
var
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9362
|
+
var readMatrix = (slice) => {
|
|
9363
|
+
return [
|
|
9364
|
+
readFixed_16_16(slice),
|
|
9365
|
+
readFixed_16_16(slice),
|
|
9366
|
+
readFixed_2_30(slice),
|
|
9367
|
+
readFixed_16_16(slice),
|
|
9368
|
+
readFixed_16_16(slice),
|
|
9369
|
+
readFixed_2_30(slice),
|
|
9370
|
+
readFixed_16_16(slice),
|
|
9371
|
+
readFixed_16_16(slice),
|
|
9372
|
+
readFixed_2_30(slice)
|
|
9373
|
+
];
|
|
9144
9374
|
};
|
|
9145
9375
|
var sampleTableIsEmpty = (sampleTable) => {
|
|
9146
9376
|
return sampleTable.sampleSizes.length === 0;
|
|
@@ -10617,6 +10847,8 @@ var Mediabunny = (() => {
|
|
|
10617
10847
|
displayUnit: null,
|
|
10618
10848
|
squarePixelWidth: -1,
|
|
10619
10849
|
squarePixelHeight: -1,
|
|
10850
|
+
horizontalScale: 1,
|
|
10851
|
+
verticalScale: 1,
|
|
10620
10852
|
rotation: 0,
|
|
10621
10853
|
codec: null,
|
|
10622
10854
|
codecDescription: null,
|
|
@@ -10846,6 +11078,32 @@ var Mediabunny = (() => {
|
|
|
10846
11078
|
}
|
|
10847
11079
|
;
|
|
10848
11080
|
break;
|
|
11081
|
+
// Yaw and pitch rotate the frame in 3D space about the vertical and horizontal axis respectively. When
|
|
11082
|
+
// snapped to multiples of 90 degrees, that amounts to scaling each axis by the cosine, which models flips.
|
|
11083
|
+
case 30323 /* ProjectionPoseYaw */:
|
|
11084
|
+
{
|
|
11085
|
+
if (this.currentTrack?.info?.type !== "video") break;
|
|
11086
|
+
const yaw = readFloat(slice, size);
|
|
11087
|
+
try {
|
|
11088
|
+
const normalized = normalizeRotation(yaw);
|
|
11089
|
+
this.currentTrack.info.horizontalScale = Math.round(Math.cos(normalized * DEG_TO_RAD));
|
|
11090
|
+
} catch {
|
|
11091
|
+
}
|
|
11092
|
+
}
|
|
11093
|
+
;
|
|
11094
|
+
break;
|
|
11095
|
+
case 30324 /* ProjectionPosePitch */:
|
|
11096
|
+
{
|
|
11097
|
+
if (this.currentTrack?.info?.type !== "video") break;
|
|
11098
|
+
const pitch = readFloat(slice, size);
|
|
11099
|
+
try {
|
|
11100
|
+
const normalized = normalizeRotation(pitch);
|
|
11101
|
+
this.currentTrack.info.verticalScale = Math.round(Math.cos(normalized * DEG_TO_RAD));
|
|
11102
|
+
} catch {
|
|
11103
|
+
}
|
|
11104
|
+
}
|
|
11105
|
+
;
|
|
11106
|
+
break;
|
|
10849
11107
|
case 30325 /* ProjectionPoseRoll */:
|
|
10850
11108
|
{
|
|
10851
11109
|
if (this.currentTrack?.info?.type !== "video") break;
|
|
@@ -11822,8 +12080,13 @@ var Mediabunny = (() => {
|
|
|
11822
12080
|
getSquarePixelHeight() {
|
|
11823
12081
|
return this.internalTrack.info.squarePixelHeight;
|
|
11824
12082
|
}
|
|
11825
|
-
|
|
11826
|
-
|
|
12083
|
+
getTransformationMatrix() {
|
|
12084
|
+
const info = this.internalTrack.info;
|
|
12085
|
+
const linear = multiplyMatrices(
|
|
12086
|
+
scaleMatrix(info.horizontalScale, info.verticalScale),
|
|
12087
|
+
rotationMatrix(info.rotation)
|
|
12088
|
+
);
|
|
12089
|
+
return centeredTransformationMatrix(linear, info.width, info.height);
|
|
11827
12090
|
}
|
|
11828
12091
|
async getColorSpace() {
|
|
11829
12092
|
const decoderConfig = await this.getDecoderConfig();
|
|
@@ -15801,8 +16064,8 @@ var Mediabunny = (() => {
|
|
|
15801
16064
|
getSquarePixelHeight() {
|
|
15802
16065
|
return this.elementaryStream.info.squarePixelHeight;
|
|
15803
16066
|
}
|
|
15804
|
-
|
|
15805
|
-
return
|
|
16067
|
+
getTransformationMatrix() {
|
|
16068
|
+
return [...IDENTITY_MATRIX];
|
|
15806
16069
|
}
|
|
15807
16070
|
async getColorSpace() {
|
|
15808
16071
|
return this.elementaryStream.info.colorSpace;
|
|
@@ -16855,8 +17118,8 @@ var Mediabunny = (() => {
|
|
|
16855
17118
|
getSquarePixelHeight() {
|
|
16856
17119
|
return this.delegate(() => this.firstInputTrack._backing.getSquarePixelHeight());
|
|
16857
17120
|
}
|
|
16858
|
-
|
|
16859
|
-
return this.delegate(() => this.firstInputTrack._backing.
|
|
17121
|
+
getTransformationMatrix() {
|
|
17122
|
+
return this.delegate(() => this.firstInputTrack._backing.getTransformationMatrix());
|
|
16860
17123
|
}
|
|
16861
17124
|
async getColorSpace() {
|
|
16862
17125
|
return this.delegate(() => this.firstInputTrack._backing.getColorSpace());
|
|
@@ -17752,6 +18015,8 @@ var Mediabunny = (() => {
|
|
|
17752
18015
|
);
|
|
17753
18016
|
}
|
|
17754
18017
|
super();
|
|
18018
|
+
/** @internal */
|
|
18019
|
+
this._readers = /* @__PURE__ */ new Set();
|
|
17755
18020
|
this._options = options;
|
|
17756
18021
|
this._orchestrator = new ReadOrchestrator({
|
|
17757
18022
|
maxCacheSize: options.maxCacheSize ?? 8 * 2 ** 20,
|
|
@@ -17796,6 +18061,9 @@ var Mediabunny = (() => {
|
|
|
17796
18061
|
let data = this._options.read(worker.currentPos, originalTargetPos);
|
|
17797
18062
|
if (isThenable(data)) data = await data;
|
|
17798
18063
|
if (worker.aborted) {
|
|
18064
|
+
if (data instanceof ReadableStream) {
|
|
18065
|
+
await data.cancel();
|
|
18066
|
+
}
|
|
17799
18067
|
break;
|
|
17800
18068
|
}
|
|
17801
18069
|
if (data instanceof Uint8Array) {
|
|
@@ -17809,25 +18077,33 @@ var Mediabunny = (() => {
|
|
|
17809
18077
|
this._orchestrator.supplyWorkerData(worker, data);
|
|
17810
18078
|
} else if (data instanceof ReadableStream) {
|
|
17811
18079
|
const reader = data.getReader();
|
|
17812
|
-
|
|
17813
|
-
|
|
17814
|
-
|
|
17815
|
-
|
|
17816
|
-
|
|
17817
|
-
|
|
18080
|
+
this._readers.add(reader);
|
|
18081
|
+
try {
|
|
18082
|
+
while (worker.currentPos < originalTargetPos && !worker.aborted) {
|
|
18083
|
+
const { done, value } = await reader.read();
|
|
18084
|
+
if (done) {
|
|
18085
|
+
if (worker.currentPos < originalTargetPos) {
|
|
18086
|
+
throw new Error(
|
|
18087
|
+
`ReadableStream returned by options.read ended before supplying enough data. Requested ${originalTargetPos - originalCurrentPos} bytes, but got ${worker.currentPos - originalCurrentPos}`
|
|
18088
|
+
);
|
|
18089
|
+
}
|
|
18090
|
+
break;
|
|
18091
|
+
}
|
|
18092
|
+
if (!(value instanceof Uint8Array)) {
|
|
18093
|
+
throw new TypeError(
|
|
18094
|
+
"ReadableStream returned by options.read must yield Uint8Array chunks."
|
|
17818
18095
|
);
|
|
17819
18096
|
}
|
|
17820
|
-
|
|
17821
|
-
|
|
17822
|
-
|
|
17823
|
-
|
|
17824
|
-
|
|
17825
|
-
|
|
17826
|
-
break;
|
|
18097
|
+
if (worker.aborted) {
|
|
18098
|
+
break;
|
|
18099
|
+
}
|
|
18100
|
+
const data2 = toUint8Array(value);
|
|
18101
|
+
this._dispatchRead(worker.currentPos, worker.currentPos + data2.length);
|
|
18102
|
+
this._orchestrator.supplyWorkerData(worker, data2);
|
|
17827
18103
|
}
|
|
17828
|
-
|
|
17829
|
-
this.
|
|
17830
|
-
|
|
18104
|
+
} finally {
|
|
18105
|
+
this._readers.delete(reader);
|
|
18106
|
+
reader.releaseLock();
|
|
17831
18107
|
}
|
|
17832
18108
|
} else {
|
|
17833
18109
|
throw new TypeError("options.read must return or resolve to a Uint8Array or a ReadableStream.");
|
|
@@ -17838,6 +18114,11 @@ var Mediabunny = (() => {
|
|
|
17838
18114
|
/** @internal */
|
|
17839
18115
|
_dispose() {
|
|
17840
18116
|
this._orchestrator.dispose();
|
|
18117
|
+
for (const reader of this._readers) {
|
|
18118
|
+
void reader.cancel().catch(() => {
|
|
18119
|
+
});
|
|
18120
|
+
}
|
|
18121
|
+
this._readers.clear();
|
|
17841
18122
|
this._options.dispose?.();
|
|
17842
18123
|
}
|
|
17843
18124
|
};
|
|
@@ -18871,10 +19152,11 @@ var Mediabunny = (() => {
|
|
|
18871
19152
|
throw new Error(`Unsupported IV format '${ivString}'.`);
|
|
18872
19153
|
}
|
|
18873
19154
|
let hex = ivString.slice(2);
|
|
18874
|
-
hex = hex.padStart(
|
|
19155
|
+
hex = hex.padStart(2 * AES_128_BLOCK_SIZE, "0");
|
|
19156
|
+
hex = hex.slice(-2 * AES_128_BLOCK_SIZE);
|
|
18875
19157
|
iv = new Uint8Array(AES_128_BLOCK_SIZE);
|
|
18876
19158
|
for (let i2 = 0; i2 < AES_128_BLOCK_SIZE; i2++) {
|
|
18877
|
-
const startIndex =
|
|
19159
|
+
const startIndex = 2 * i2;
|
|
18878
19160
|
iv[i2] = parseInt(hex.slice(startIndex, startIndex + 2), 16);
|
|
18879
19161
|
}
|
|
18880
19162
|
}
|
|
@@ -19780,8 +20062,8 @@ var Mediabunny = (() => {
|
|
|
19780
20062
|
}
|
|
19781
20063
|
return this.internalTrack.info.height;
|
|
19782
20064
|
}
|
|
19783
|
-
|
|
19784
|
-
return this.delegate(() => this.backingVideoTrack.
|
|
20065
|
+
getTransformationMatrix() {
|
|
20066
|
+
return this.delegate(() => this.backingVideoTrack.getTransformationMatrix());
|
|
19785
20067
|
}
|
|
19786
20068
|
async getColorSpace() {
|
|
19787
20069
|
await this.hydrate();
|
|
@@ -20581,6 +20863,9 @@ var Mediabunny = (() => {
|
|
|
20581
20863
|
if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20582
20864
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20583
20865
|
}
|
|
20866
|
+
if (init.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
20867
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
20868
|
+
}
|
|
20584
20869
|
if (!Number.isFinite(init.timestamp)) {
|
|
20585
20870
|
throw new TypeError("init.timestamp must be a number.");
|
|
20586
20871
|
}
|
|
@@ -20619,6 +20904,7 @@ var Mediabunny = (() => {
|
|
|
20619
20904
|
}
|
|
20620
20905
|
this.format = init.format;
|
|
20621
20906
|
this.rotation = init.rotation ?? 0;
|
|
20907
|
+
this.flip = init.flip ?? false;
|
|
20622
20908
|
this.timestamp = init.timestamp;
|
|
20623
20909
|
this.duration = init.duration ?? 0;
|
|
20624
20910
|
const layout = init.layout ?? createDefaultPlaneLayout(init.format, init.codedWidth, init.codedHeight);
|
|
@@ -20660,6 +20946,9 @@ var Mediabunny = (() => {
|
|
|
20660
20946
|
if (init?.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20661
20947
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20662
20948
|
}
|
|
20949
|
+
if (init?.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
20950
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
20951
|
+
}
|
|
20663
20952
|
if (init?.timestamp !== void 0 && !Number.isFinite(init?.timestamp)) {
|
|
20664
20953
|
throw new TypeError("init.timestamp, when provided, must be a number.");
|
|
20665
20954
|
}
|
|
@@ -20679,6 +20968,7 @@ var Mediabunny = (() => {
|
|
|
20679
20968
|
height: data.visibleRect?.height ?? data.codedHeight
|
|
20680
20969
|
};
|
|
20681
20970
|
this.rotation = init?.rotation ?? 0;
|
|
20971
|
+
this.flip = init?.flip ?? false;
|
|
20682
20972
|
this.squarePixelWidth = data.displayWidth;
|
|
20683
20973
|
this.squarePixelHeight = data.displayHeight;
|
|
20684
20974
|
this.timestamp = init?.timestamp ?? data.timestamp / 1e6;
|
|
@@ -20691,6 +20981,9 @@ var Mediabunny = (() => {
|
|
|
20691
20981
|
if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20692
20982
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20693
20983
|
}
|
|
20984
|
+
if (init.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
20985
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
20986
|
+
}
|
|
20694
20987
|
if (!Number.isFinite(init.timestamp)) {
|
|
20695
20988
|
throw new TypeError("init.timestamp must be a number.");
|
|
20696
20989
|
}
|
|
@@ -20752,6 +21045,7 @@ var Mediabunny = (() => {
|
|
|
20752
21045
|
this.squarePixelWidth = visibleRect.width;
|
|
20753
21046
|
this.squarePixelHeight = visibleRect.height;
|
|
20754
21047
|
this.rotation = init.rotation ?? 0;
|
|
21048
|
+
this.flip = init.flip ?? false;
|
|
20755
21049
|
this.timestamp = init.timestamp;
|
|
20756
21050
|
this.duration = init.duration ?? 0;
|
|
20757
21051
|
this.colorSpace = new VideoSampleColorSpace({
|
|
@@ -20767,6 +21061,9 @@ var Mediabunny = (() => {
|
|
|
20767
21061
|
if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20768
21062
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20769
21063
|
}
|
|
21064
|
+
if (init.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
21065
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
21066
|
+
}
|
|
20770
21067
|
if (!Number.isFinite(init.timestamp)) {
|
|
20771
21068
|
throw new TypeError("init.timestamp must be a number.");
|
|
20772
21069
|
}
|
|
@@ -20800,6 +21097,7 @@ var Mediabunny = (() => {
|
|
|
20800
21097
|
throw new TypeError("getSquarePixelHeight() must return a positive integer.");
|
|
20801
21098
|
}
|
|
20802
21099
|
this.rotation = init.rotation ?? 0;
|
|
21100
|
+
this.flip = init.flip ?? false;
|
|
20803
21101
|
this.timestamp = init.timestamp;
|
|
20804
21102
|
this.duration = init.duration ?? 0;
|
|
20805
21103
|
this.colorSpace = data.getColorSpace();
|
|
@@ -20823,11 +21121,11 @@ var Mediabunny = (() => {
|
|
|
20823
21121
|
get codedHeight() {
|
|
20824
21122
|
return this.visibleRect.height;
|
|
20825
21123
|
}
|
|
20826
|
-
/** The display width of the frame in pixels, after aspect ratio adjustment and
|
|
21124
|
+
/** The display width of the frame in pixels, after aspect ratio adjustment, rotation and flip. */
|
|
20827
21125
|
get displayWidth() {
|
|
20828
21126
|
return this.rotation % 180 === 0 ? this.squarePixelWidth : this.squarePixelHeight;
|
|
20829
21127
|
}
|
|
20830
|
-
/** The display height of the frame in pixels, after aspect ratio adjustment and
|
|
21128
|
+
/** The display height of the frame in pixels, after aspect ratio adjustment, rotation and flip. */
|
|
20831
21129
|
get displayHeight() {
|
|
20832
21130
|
return this.rotation % 180 === 0 ? this.squarePixelHeight : this.squarePixelWidth;
|
|
20833
21131
|
}
|
|
@@ -20857,6 +21155,7 @@ var Mediabunny = (() => {
|
|
|
20857
21155
|
timestamp: this.timestamp,
|
|
20858
21156
|
duration: this.duration,
|
|
20859
21157
|
rotation: this.rotation,
|
|
21158
|
+
flip: this.flip,
|
|
20860
21159
|
encodeOptions: this.encodeOptions
|
|
20861
21160
|
});
|
|
20862
21161
|
} else if (isVideoFrame(this._data)) {
|
|
@@ -20864,6 +21163,7 @@ var Mediabunny = (() => {
|
|
|
20864
21163
|
timestamp: this.timestamp,
|
|
20865
21164
|
duration: this.duration,
|
|
20866
21165
|
rotation: this.rotation,
|
|
21166
|
+
flip: this.flip,
|
|
20867
21167
|
encodeOptions: this.encodeOptions
|
|
20868
21168
|
});
|
|
20869
21169
|
} else if (this._data instanceof Uint8Array) {
|
|
@@ -20877,6 +21177,7 @@ var Mediabunny = (() => {
|
|
|
20877
21177
|
duration: this.duration,
|
|
20878
21178
|
colorSpace: this.colorSpace,
|
|
20879
21179
|
rotation: this.rotation,
|
|
21180
|
+
flip: this.flip,
|
|
20880
21181
|
visibleRect: this.visibleRect,
|
|
20881
21182
|
displayWidth: this.displayWidth,
|
|
20882
21183
|
displayHeight: this.displayHeight,
|
|
@@ -20893,6 +21194,7 @@ var Mediabunny = (() => {
|
|
|
20893
21194
|
duration: this.duration,
|
|
20894
21195
|
colorSpace: this.colorSpace,
|
|
20895
21196
|
rotation: this.rotation,
|
|
21197
|
+
flip: this.flip,
|
|
20896
21198
|
visibleRect: this.visibleRect,
|
|
20897
21199
|
displayWidth: this.displayWidth,
|
|
20898
21200
|
displayHeight: this.displayHeight,
|
|
@@ -20965,7 +21267,8 @@ var Mediabunny = (() => {
|
|
|
20965
21267
|
{
|
|
20966
21268
|
timestamp: this.timestamp,
|
|
20967
21269
|
duration: this.duration,
|
|
20968
|
-
rotation: this.rotation
|
|
21270
|
+
rotation: this.rotation,
|
|
21271
|
+
flip: this.flip
|
|
20969
21272
|
},
|
|
20970
21273
|
options.colorSpace ?? "srgb"
|
|
20971
21274
|
));
|
|
@@ -21221,12 +21524,15 @@ var Mediabunny = (() => {
|
|
|
21221
21524
|
if (this._closed) {
|
|
21222
21525
|
throw new Error("VideoSample is closed.");
|
|
21223
21526
|
}
|
|
21224
|
-
({ sx, sy, sWidth, sHeight } = this.
|
|
21527
|
+
({ sx, sy, sWidth, sHeight } = this._unmapSourceRegion(sx, sy, sWidth, sHeight, this.rotation, this.flip));
|
|
21225
21528
|
const source = this.toCanvasImageSource();
|
|
21226
21529
|
context.save();
|
|
21227
21530
|
const centerX = dx + dWidth / 2;
|
|
21228
21531
|
const centerY = dy + dHeight / 2;
|
|
21229
21532
|
context.translate(centerX, centerY);
|
|
21533
|
+
if (this.flip) {
|
|
21534
|
+
context.scale(-1, 1);
|
|
21535
|
+
}
|
|
21230
21536
|
context.rotate(this.rotation * Math.PI / 180);
|
|
21231
21537
|
const aspectRatioChange = this.rotation % 180 === 0 ? 1 : dWidth / dHeight;
|
|
21232
21538
|
context.scale(1 / aspectRatioChange, aspectRatioChange);
|
|
@@ -21259,12 +21565,16 @@ var Mediabunny = (() => {
|
|
|
21259
21565
|
if (options.rotation !== void 0 && ![0, 90, 180, 270].includes(options.rotation)) {
|
|
21260
21566
|
throw new TypeError("options.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
21261
21567
|
}
|
|
21568
|
+
if (options.flip !== void 0 && typeof options.flip !== "boolean") {
|
|
21569
|
+
throw new TypeError("options.flip, when provided, must be a boolean.");
|
|
21570
|
+
}
|
|
21262
21571
|
if (options.crop !== void 0) {
|
|
21263
21572
|
validateCropRectangle(options.crop, "options.");
|
|
21264
21573
|
}
|
|
21265
21574
|
const canvasWidth = context.canvas.width;
|
|
21266
21575
|
const canvasHeight = context.canvas.height;
|
|
21267
21576
|
const rotation = options.rotation ?? this.rotation;
|
|
21577
|
+
const flip = options.flip ?? this.flip;
|
|
21268
21578
|
const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [this.squarePixelWidth, this.squarePixelHeight] : [this.squarePixelHeight, this.squarePixelWidth];
|
|
21269
21579
|
let finalCrop = options.crop;
|
|
21270
21580
|
if (finalCrop) {
|
|
@@ -21274,12 +21584,13 @@ var Mediabunny = (() => {
|
|
|
21274
21584
|
let dy;
|
|
21275
21585
|
let newWidth;
|
|
21276
21586
|
let newHeight;
|
|
21277
|
-
const { sx, sy, sWidth, sHeight } = this.
|
|
21587
|
+
const { sx, sy, sWidth, sHeight } = this._unmapSourceRegion(
|
|
21278
21588
|
options.crop?.left ?? 0,
|
|
21279
21589
|
options.crop?.top ?? 0,
|
|
21280
21590
|
options.crop?.width ?? rotatedWidth,
|
|
21281
21591
|
options.crop?.height ?? rotatedHeight,
|
|
21282
|
-
rotation
|
|
21592
|
+
rotation,
|
|
21593
|
+
flip
|
|
21283
21594
|
);
|
|
21284
21595
|
if (options.fit === "fill") {
|
|
21285
21596
|
dx = 0;
|
|
@@ -21297,6 +21608,9 @@ var Mediabunny = (() => {
|
|
|
21297
21608
|
context.save();
|
|
21298
21609
|
const aspectRatioChange = rotation % 180 === 0 ? 1 : newWidth / newHeight;
|
|
21299
21610
|
context.translate(canvasWidth / 2, canvasHeight / 2);
|
|
21611
|
+
if (flip) {
|
|
21612
|
+
context.scale(-1, 1);
|
|
21613
|
+
}
|
|
21300
21614
|
context.rotate(rotation * Math.PI / 180);
|
|
21301
21615
|
context.scale(1 / aspectRatioChange, aspectRatioChange);
|
|
21302
21616
|
context.translate(-canvasWidth / 2, -canvasHeight / 2);
|
|
@@ -21304,7 +21618,11 @@ var Mediabunny = (() => {
|
|
|
21304
21618
|
context.restore();
|
|
21305
21619
|
}
|
|
21306
21620
|
/** @internal */
|
|
21307
|
-
|
|
21621
|
+
_unmapSourceRegion(sx, sy, sWidth, sHeight, rotation, flip) {
|
|
21622
|
+
if (flip) {
|
|
21623
|
+
const rotatedWidth = rotation % 180 === 0 ? this.squarePixelWidth : this.squarePixelHeight;
|
|
21624
|
+
sx = rotatedWidth - sx - sWidth;
|
|
21625
|
+
}
|
|
21308
21626
|
if (rotation === 90) {
|
|
21309
21627
|
[sx, sy, sWidth, sHeight] = [
|
|
21310
21628
|
sy,
|
|
@@ -21356,6 +21674,7 @@ var Mediabunny = (() => {
|
|
|
21356
21674
|
this.drawWithFit(context, {
|
|
21357
21675
|
fit: options.fit,
|
|
21358
21676
|
rotation: options.rotation,
|
|
21677
|
+
flip: options.flip,
|
|
21359
21678
|
crop: options.crop
|
|
21360
21679
|
});
|
|
21361
21680
|
context.globalCompositeOperation = "copy";
|
|
@@ -21403,8 +21722,8 @@ var Mediabunny = (() => {
|
|
|
21403
21722
|
}
|
|
21404
21723
|
}
|
|
21405
21724
|
/**
|
|
21406
|
-
* Transform this video sample to a new video sample given the options. Can be used to resize, rotate, and
|
|
21407
|
-
* the sample.
|
|
21725
|
+
* Transform this video sample to a new video sample given the options. Can be used to resize, rotate, flip, and
|
|
21726
|
+
* crop the sample.
|
|
21408
21727
|
*
|
|
21409
21728
|
* In non-browser environments, this method will not work by default. To make it work, register a custom
|
|
21410
21729
|
* transformer function via {@link registerVideoSampleTransformer}.
|
|
@@ -21433,13 +21752,21 @@ var Mediabunny = (() => {
|
|
|
21433
21752
|
if (options.rotate !== void 0 && ![0, 90, 180, 270].includes(options.rotate)) {
|
|
21434
21753
|
throw new TypeError("options.rotate, when provided, must be 0, 90, 180 or 270.");
|
|
21435
21754
|
}
|
|
21755
|
+
if (options.flip !== void 0 && typeof options.flip !== "boolean") {
|
|
21756
|
+
throw new TypeError("options.flip, when provided, must be a boolean.");
|
|
21757
|
+
}
|
|
21436
21758
|
if (options.crop !== void 0) {
|
|
21437
21759
|
validateCropRectangle(options.crop, "options.");
|
|
21438
21760
|
}
|
|
21439
21761
|
if (options.alpha !== void 0 && !["keep", "discard"].includes(options.alpha)) {
|
|
21440
21762
|
throw new TypeError("options.alpha, when provided, must be 'keep' or 'discard'.");
|
|
21441
21763
|
}
|
|
21442
|
-
const rotation
|
|
21764
|
+
const { rotation, flip } = composeRotationAndFlip(
|
|
21765
|
+
this.rotation,
|
|
21766
|
+
this.flip,
|
|
21767
|
+
options.rotate ?? 0,
|
|
21768
|
+
options.flip ?? false
|
|
21769
|
+
);
|
|
21443
21770
|
const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [this.squarePixelWidth, this.squarePixelHeight] : [this.squarePixelHeight, this.squarePixelWidth];
|
|
21444
21771
|
let finalCrop = options.crop;
|
|
21445
21772
|
if (finalCrop) {
|
|
@@ -21470,6 +21797,7 @@ var Mediabunny = (() => {
|
|
|
21470
21797
|
height: targetHeight,
|
|
21471
21798
|
fit: options.fit ?? "fill",
|
|
21472
21799
|
rotation,
|
|
21800
|
+
flip,
|
|
21473
21801
|
crop: finalCrop ?? {
|
|
21474
21802
|
left: 0,
|
|
21475
21803
|
top: 0,
|
|
@@ -21489,6 +21817,7 @@ var Mediabunny = (() => {
|
|
|
21489
21817
|
this._drawWithFitAndMipmapping(canvas, context, {
|
|
21490
21818
|
fit: description.fit,
|
|
21491
21819
|
rotation: description.rotation,
|
|
21820
|
+
flip: description.flip,
|
|
21492
21821
|
crop: description.crop,
|
|
21493
21822
|
targetIsFresh: isNew,
|
|
21494
21823
|
fillBlack: description.alpha === "discard"
|
|
@@ -21496,8 +21825,9 @@ var Mediabunny = (() => {
|
|
|
21496
21825
|
return new _VideoSample(canvas, {
|
|
21497
21826
|
timestamp: this.timestamp,
|
|
21498
21827
|
duration: this.duration,
|
|
21499
|
-
rotation
|
|
21500
|
-
|
|
21828
|
+
// Any previous rotation and flip are now baked in
|
|
21829
|
+
rotation: 0,
|
|
21830
|
+
flip: false
|
|
21501
21831
|
});
|
|
21502
21832
|
}
|
|
21503
21833
|
/** Sets the rotation metadata of this video sample. */
|
|
@@ -21507,6 +21837,13 @@ var Mediabunny = (() => {
|
|
|
21507
21837
|
}
|
|
21508
21838
|
this.rotation = newRotation;
|
|
21509
21839
|
}
|
|
21840
|
+
/** Sets the flip metadata of this video sample. */
|
|
21841
|
+
setFlip(newFlip) {
|
|
21842
|
+
if (typeof newFlip !== "boolean") {
|
|
21843
|
+
throw new TypeError("newFlip must be a boolean.");
|
|
21844
|
+
}
|
|
21845
|
+
this.flip = newFlip;
|
|
21846
|
+
}
|
|
21510
21847
|
/** Sets the presentation timestamp of this video sample, in seconds. */
|
|
21511
21848
|
setTimestamp(newTimestamp) {
|
|
21512
21849
|
if (!Number.isFinite(newTimestamp)) {
|
|
@@ -22702,6 +23039,9 @@ var Mediabunny = (() => {
|
|
|
22702
23039
|
if (config.transform.rotate !== void 0 && ![0, 90, 180, 270].includes(config.transform.rotate)) {
|
|
22703
23040
|
throw new TypeError("config.transform.rotate, when provided, must be 0, 90, 180 or 270.");
|
|
22704
23041
|
}
|
|
23042
|
+
if (config.transform.flip !== void 0 && typeof config.transform.flip !== "boolean") {
|
|
23043
|
+
throw new TypeError("config.transform.flip, when provided, must be a boolean.");
|
|
23044
|
+
}
|
|
22705
23045
|
if (config.transform.crop !== void 0) {
|
|
22706
23046
|
validateCropRectangle(config.transform.crop, "config.transform.");
|
|
22707
23047
|
}
|
|
@@ -23133,6 +23473,7 @@ var Mediabunny = (() => {
|
|
|
23133
23473
|
quality,
|
|
23134
23474
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
23135
23475
|
bitrate,
|
|
23476
|
+
frameRate,
|
|
23136
23477
|
...restOptions
|
|
23137
23478
|
} = options;
|
|
23138
23479
|
if (!VIDEO_CODECS.includes(codec)) {
|
|
@@ -23153,6 +23494,9 @@ var Mediabunny = (() => {
|
|
|
23153
23494
|
if (bitrate !== void 0 && !(bitrate instanceof Quality) && (!Number.isInteger(bitrate) || bitrate <= 0)) {
|
|
23154
23495
|
throw new TypeError("bitrate must be a positive integer or a quality.");
|
|
23155
23496
|
}
|
|
23497
|
+
if (frameRate !== void 0 && (!Number.isFinite(frameRate) || frameRate <= 0)) {
|
|
23498
|
+
throw new TypeError("frameRate, when provided, must be a finite positive number.");
|
|
23499
|
+
}
|
|
23156
23500
|
validateVideoEncodingAdditionalOptions(codec, restOptions);
|
|
23157
23501
|
const resolvedQuality = resolveQuality(quality, bitrate) ?? new Quality("medium");
|
|
23158
23502
|
let candidates;
|
|
@@ -23162,7 +23506,7 @@ var Mediabunny = (() => {
|
|
|
23162
23506
|
width,
|
|
23163
23507
|
height,
|
|
23164
23508
|
quality: resolvedQuality,
|
|
23165
|
-
framerate:
|
|
23509
|
+
framerate: frameRate,
|
|
23166
23510
|
...restOptions,
|
|
23167
23511
|
alpha: "discard"
|
|
23168
23512
|
// Since we handle alpha ourselves
|
|
@@ -24086,11 +24430,12 @@ var Mediabunny = (() => {
|
|
|
24086
24430
|
return decodedSampleQueueSize === 0 ? 40 : 8;
|
|
24087
24431
|
};
|
|
24088
24432
|
var VideoDecoderWrapper = class extends DecoderWrapper {
|
|
24089
|
-
constructor(onSample, onError, codec, decoderConfig, rotation, timeResolution) {
|
|
24433
|
+
constructor(onSample, onError, codec, decoderConfig, rotation, flip, timeResolution) {
|
|
24090
24434
|
super(onSample, onError);
|
|
24091
24435
|
this.codec = codec;
|
|
24092
24436
|
this.decoderConfig = decoderConfig;
|
|
24093
24437
|
this.rotation = rotation;
|
|
24438
|
+
this.flip = flip;
|
|
24094
24439
|
this.timeResolution = timeResolution;
|
|
24095
24440
|
this.decoder = null;
|
|
24096
24441
|
this.customDecoder = null;
|
|
@@ -24375,6 +24720,7 @@ var Mediabunny = (() => {
|
|
|
24375
24720
|
sample.setTimestamp(Math.round(sample.timestamp * this.timeResolution) / this.timeResolution);
|
|
24376
24721
|
sample.setDuration(Math.round(sample.duration * this.timeResolution) / this.timeResolution);
|
|
24377
24722
|
sample.setRotation(this.rotation);
|
|
24723
|
+
sample.setFlip(this.flip);
|
|
24378
24724
|
this.onSample(sample);
|
|
24379
24725
|
}
|
|
24380
24726
|
async mergeAlpha(color, alpha) {
|
|
@@ -24709,6 +25055,7 @@ var Mediabunny = (() => {
|
|
|
24709
25055
|
}
|
|
24710
25056
|
const codec = await this._track.getCodec();
|
|
24711
25057
|
const rotation = await this._track.getRotation();
|
|
25058
|
+
const flip = await this._track.getFlip();
|
|
24712
25059
|
let decoderConfig = await this._track.getDecoderConfig();
|
|
24713
25060
|
const timeResolution = await this._track.getTimeResolution();
|
|
24714
25061
|
assert(codec && decoderConfig);
|
|
@@ -24717,7 +25064,7 @@ var Mediabunny = (() => {
|
|
|
24717
25064
|
hardwareAcceleration: this._decoderOptions.hardwareAcceleration,
|
|
24718
25065
|
optimizeForLatency: this._decoderOptions.optimizeForLatency
|
|
24719
25066
|
};
|
|
24720
|
-
return new VideoDecoderWrapper(onSample, onError, codec, decoderConfig, rotation, timeResolution);
|
|
25067
|
+
return new VideoDecoderWrapper(onSample, onError, codec, decoderConfig, rotation, flip, timeResolution);
|
|
24721
25068
|
}
|
|
24722
25069
|
/** @internal */
|
|
24723
25070
|
_createPacketSink() {
|
|
@@ -24771,6 +25118,8 @@ var Mediabunny = (() => {
|
|
|
24771
25118
|
/** @internal */
|
|
24772
25119
|
this._rotation = 0;
|
|
24773
25120
|
/** @internal */
|
|
25121
|
+
this._flip = false;
|
|
25122
|
+
/** @internal */
|
|
24774
25123
|
this._initPromise = null;
|
|
24775
25124
|
/** @internal */
|
|
24776
25125
|
this._nextCanvasIndex = 0;
|
|
@@ -24800,6 +25149,9 @@ var Mediabunny = (() => {
|
|
|
24800
25149
|
if (options.rotation !== void 0 && ![0, 90, 180, 270].includes(options.rotation)) {
|
|
24801
25150
|
throw new TypeError("options.rotation, when provided, must be 0, 90, 180 or 270.");
|
|
24802
25151
|
}
|
|
25152
|
+
if (options.flip !== void 0 && typeof options.flip !== "boolean") {
|
|
25153
|
+
throw new TypeError("options.flip, when provided, must be a boolean.");
|
|
25154
|
+
}
|
|
24803
25155
|
if (options.crop !== void 0) {
|
|
24804
25156
|
validateCropRectangle(options.crop, "options.");
|
|
24805
25157
|
}
|
|
@@ -24822,6 +25174,7 @@ var Mediabunny = (() => {
|
|
|
24822
25174
|
const options = this._options;
|
|
24823
25175
|
const videoTrack = this._videoTrack;
|
|
24824
25176
|
const rotation = options.rotation ?? await videoTrack.getRotation();
|
|
25177
|
+
const flip = options.flip ?? await videoTrack.getFlip();
|
|
24825
25178
|
const squarePixelWidth = await videoTrack.getSquarePixelWidth();
|
|
24826
25179
|
const squarePixelHeight = await videoTrack.getSquarePixelHeight();
|
|
24827
25180
|
const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [squarePixelWidth, squarePixelHeight] : [squarePixelHeight, squarePixelWidth];
|
|
@@ -24844,6 +25197,7 @@ var Mediabunny = (() => {
|
|
|
24844
25197
|
this._width = width;
|
|
24845
25198
|
this._height = height;
|
|
24846
25199
|
this._rotation = rotation;
|
|
25200
|
+
this._flip = flip;
|
|
24847
25201
|
this._crop = crop;
|
|
24848
25202
|
})();
|
|
24849
25203
|
}
|
|
@@ -24877,6 +25231,7 @@ var Mediabunny = (() => {
|
|
|
24877
25231
|
sample._drawWithFitAndMipmapping(canvas, context, {
|
|
24878
25232
|
fit: this._fit,
|
|
24879
25233
|
rotation: this._rotation,
|
|
25234
|
+
flip: this._flip,
|
|
24880
25235
|
crop: this._crop,
|
|
24881
25236
|
targetIsFresh: canvasIsNew,
|
|
24882
25237
|
fillBlack: !this._alpha && isFirefox()
|
|
@@ -25742,16 +26097,38 @@ var Mediabunny = (() => {
|
|
|
25742
26097
|
get codedHeight() {
|
|
25743
26098
|
return requireSync(this._backing.getCodedHeight(), "codedHeight", "getCodedHeight");
|
|
25744
26099
|
}
|
|
25745
|
-
/**
|
|
26100
|
+
/**
|
|
26101
|
+
* Returns the row-major 3x3 affine transformation matrix that is used to transform the raw video frames before they
|
|
26102
|
+
* are displayed. The raw frames are assumed to be placed with their top-left corner at the origin (0,0).
|
|
26103
|
+
*
|
|
26104
|
+
* Usually, this matrix models a rotation and a flip. Depending on the file, it may also contain a translation
|
|
26105
|
+
* component. When displaying video, you should typically ignore the translation component and display the center of
|
|
26106
|
+
* the transformed frame in the center of the viewport.
|
|
26107
|
+
*/
|
|
26108
|
+
async getTransformationMatrix() {
|
|
26109
|
+
return this._backing.getTransformationMatrix();
|
|
26110
|
+
}
|
|
26111
|
+
/**
|
|
26112
|
+
* Returns the angle in degrees by which the track's frames should be rotated (clockwise). The rotation is
|
|
26113
|
+
* applied before flipping.
|
|
26114
|
+
*/
|
|
25746
26115
|
async getRotation() {
|
|
25747
|
-
return this._backing.
|
|
26116
|
+
return extractRotationFromMatrix(await this._backing.getTransformationMatrix());
|
|
25748
26117
|
}
|
|
25749
26118
|
/**
|
|
25750
26119
|
* The angle in degrees by which the track's frames should be rotated (clockwise).
|
|
25751
26120
|
* @deprecated Use {@link InputVideoTrack.getRotation} instead.
|
|
25752
26121
|
*/
|
|
25753
26122
|
get rotation() {
|
|
25754
|
-
return
|
|
26123
|
+
return extractRotationFromMatrix(
|
|
26124
|
+
requireSync(this._backing.getTransformationMatrix(), "rotation", "getRotation")
|
|
26125
|
+
);
|
|
26126
|
+
}
|
|
26127
|
+
/**
|
|
26128
|
+
* Returns whether the track's frames should be flipped horizontally (about the vertical axis), after rotation.
|
|
26129
|
+
*/
|
|
26130
|
+
async getFlip() {
|
|
26131
|
+
return matrixIsFlipped(await this._backing.getTransformationMatrix());
|
|
25755
26132
|
}
|
|
25756
26133
|
/**
|
|
25757
26134
|
* Returns the width of the track's frames in square pixels, adjusted for pixel aspect ratio but before rotation.
|
|
@@ -25821,7 +26198,9 @@ var Mediabunny = (() => {
|
|
|
25821
26198
|
return metadata;
|
|
25822
26199
|
}
|
|
25823
26200
|
}
|
|
25824
|
-
const rotation =
|
|
26201
|
+
const rotation = extractRotationFromMatrix(
|
|
26202
|
+
requireSync(this._backing.getTransformationMatrix(), "displayWidth", "getDisplayWidth")
|
|
26203
|
+
);
|
|
25825
26204
|
const value = rotation % 180 === 0 ? this._backing.getSquarePixelWidth() : this._backing.getSquarePixelHeight();
|
|
25826
26205
|
return requireSync(value, "displayWidth", "getDisplayWidth");
|
|
25827
26206
|
}
|
|
@@ -25846,7 +26225,9 @@ var Mediabunny = (() => {
|
|
|
25846
26225
|
return metadata;
|
|
25847
26226
|
}
|
|
25848
26227
|
}
|
|
25849
|
-
const rotation =
|
|
26228
|
+
const rotation = extractRotationFromMatrix(
|
|
26229
|
+
requireSync(this._backing.getTransformationMatrix(), "displayHeight", "getDisplayHeight")
|
|
26230
|
+
);
|
|
25850
26231
|
const value = rotation % 180 === 0 ? this._backing.getSquarePixelHeight() : this._backing.getSquarePixelWidth();
|
|
25851
26232
|
return requireSync(value, "displayHeight", "getDisplayHeight");
|
|
25852
26233
|
}
|
|
@@ -28617,23 +28998,6 @@ var Mediabunny = (() => {
|
|
|
28617
28998
|
if (nullTerminated) bytes2.push(0);
|
|
28618
28999
|
return bytes2;
|
|
28619
29000
|
};
|
|
28620
|
-
var rotationMatrix = (rotationInDegrees) => {
|
|
28621
|
-
const theta = rotationInDegrees * (Math.PI / 180);
|
|
28622
|
-
const cosTheta = Math.round(Math.cos(theta));
|
|
28623
|
-
const sinTheta = Math.round(Math.sin(theta));
|
|
28624
|
-
return [
|
|
28625
|
-
cosTheta,
|
|
28626
|
-
sinTheta,
|
|
28627
|
-
0,
|
|
28628
|
-
-sinTheta,
|
|
28629
|
-
cosTheta,
|
|
28630
|
-
0,
|
|
28631
|
-
0,
|
|
28632
|
-
0,
|
|
28633
|
-
1
|
|
28634
|
-
];
|
|
28635
|
-
};
|
|
28636
|
-
var IDENTITY_MATRIX = /* @__PURE__ */ rotationMatrix(0);
|
|
28637
29001
|
var matrixToBytes = (matrix) => {
|
|
28638
29002
|
return [
|
|
28639
29003
|
fixed_16_16(matrix[0]),
|
|
@@ -28793,26 +29157,6 @@ var Mediabunny = (() => {
|
|
|
28793
29157
|
// Next track ID
|
|
28794
29158
|
]);
|
|
28795
29159
|
};
|
|
28796
|
-
var presentationSpan = (trackData) => {
|
|
28797
|
-
if (trackData.samples.length === 0) {
|
|
28798
|
-
return 0;
|
|
28799
|
-
}
|
|
28800
|
-
let minTimestamp = Infinity;
|
|
28801
|
-
let maxEndTimestamp = -Infinity;
|
|
28802
|
-
for (let i = 0; i < trackData.samples.length; i++) {
|
|
28803
|
-
const sample = trackData.samples[i];
|
|
28804
|
-
if (sample.timestamp < minTimestamp) {
|
|
28805
|
-
minTimestamp = sample.timestamp;
|
|
28806
|
-
}
|
|
28807
|
-
if (sample.timestamp + sample.duration > maxEndTimestamp) {
|
|
28808
|
-
maxEndTimestamp = sample.timestamp + sample.duration;
|
|
28809
|
-
}
|
|
28810
|
-
}
|
|
28811
|
-
if (minTimestamp === Infinity) {
|
|
28812
|
-
return 0;
|
|
28813
|
-
}
|
|
28814
|
-
return maxEndTimestamp - minTimestamp;
|
|
28815
|
-
};
|
|
28816
29160
|
var trak = (trackData, creationTime) => {
|
|
28817
29161
|
const trackMetadata = getTrackMetadata(trackData);
|
|
28818
29162
|
const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset !== 0;
|
|
@@ -28836,9 +29180,15 @@ var Mediabunny = (() => {
|
|
|
28836
29180
|
const needsU64 = !isU32(creationTime) || !isU32(durationInGlobalTimescale);
|
|
28837
29181
|
const u32OrU64 = needsU64 ? u64 : u32;
|
|
28838
29182
|
let matrix;
|
|
28839
|
-
if (trackData.type === "video") {
|
|
28840
|
-
|
|
28841
|
-
|
|
29183
|
+
if (trackData.type === "video" && trackData.track.metadata.transformationMatrix) {
|
|
29184
|
+
matrix = trackData.track.metadata.transformationMatrix;
|
|
29185
|
+
} else if (trackData.type === "video") {
|
|
29186
|
+
const { rotation, flip } = trackData.track.metadata;
|
|
29187
|
+
const linear = multiplyMatrices(
|
|
29188
|
+
rotationMatrix(rotation ?? 0),
|
|
29189
|
+
scaleMatrix(flip ? -1 : 1, 1)
|
|
29190
|
+
);
|
|
29191
|
+
matrix = centeredTransformationMatrix(linear, trackData.info.width, trackData.info.height);
|
|
28842
29192
|
} else {
|
|
28843
29193
|
matrix = IDENTITY_MATRIX;
|
|
28844
29194
|
}
|
|
@@ -29097,8 +29447,22 @@ var Mediabunny = (() => {
|
|
|
29097
29447
|
], [
|
|
29098
29448
|
VIDEO_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec]?.(trackData) ?? null,
|
|
29099
29449
|
pasp(trackData),
|
|
29100
|
-
colorSpaceIsEmpty(trackData.info.decoderConfig.colorSpace) ? null : colr(trackData)
|
|
29450
|
+
colorSpaceIsEmpty(trackData.info.decoderConfig.colorSpace) ? null : colr(trackData),
|
|
29451
|
+
btrt(trackData)
|
|
29101
29452
|
]);
|
|
29453
|
+
var btrt = (trackData) => {
|
|
29454
|
+
if (trackData.avgBitrate === 0 && trackData.maxBitrate === 0) {
|
|
29455
|
+
return null;
|
|
29456
|
+
}
|
|
29457
|
+
return box("btrt", [
|
|
29458
|
+
u32(0),
|
|
29459
|
+
// Decoding buffer size (unknown)
|
|
29460
|
+
u32(trackData.maxBitrate),
|
|
29461
|
+
// Max bitrate
|
|
29462
|
+
u32(trackData.avgBitrate)
|
|
29463
|
+
// Average bitrate
|
|
29464
|
+
]);
|
|
29465
|
+
};
|
|
29102
29466
|
var pasp = (trackData) => {
|
|
29103
29467
|
if (trackData.info.pixelAspectRatio.num === trackData.info.pixelAspectRatio.den) {
|
|
29104
29468
|
return null;
|
|
@@ -29252,7 +29616,8 @@ var Mediabunny = (() => {
|
|
|
29252
29616
|
];
|
|
29253
29617
|
}
|
|
29254
29618
|
return box(compressionType, contents, [
|
|
29255
|
-
audioCodecToConfigurationBox(trackData.track.source._codec, trackData.muxer.isQuickTime)?.(trackData) ?? null
|
|
29619
|
+
audioCodecToConfigurationBox(trackData.track.source._codec, trackData.muxer.isQuickTime)?.(trackData) ?? null,
|
|
29620
|
+
btrt(trackData)
|
|
29256
29621
|
]);
|
|
29257
29622
|
};
|
|
29258
29623
|
var esds = (trackData) => {
|
|
@@ -29286,9 +29651,9 @@ var Mediabunny = (() => {
|
|
|
29286
29651
|
// stream type(6bits)=5 audio, flags(2bits)=1
|
|
29287
29652
|
...u24(0),
|
|
29288
29653
|
// 24bit buffer size
|
|
29289
|
-
...u32(
|
|
29654
|
+
...u32(trackData.maxBitrate),
|
|
29290
29655
|
// max bitrate
|
|
29291
|
-
...u32(
|
|
29656
|
+
...u32(trackData.avgBitrate)
|
|
29292
29657
|
// avg bitrate
|
|
29293
29658
|
];
|
|
29294
29659
|
if (trackData.info.decoderConfig.description) {
|
|
@@ -29476,7 +29841,8 @@ var Mediabunny = (() => {
|
|
|
29476
29841
|
u16(1)
|
|
29477
29842
|
// Data reference index
|
|
29478
29843
|
], [
|
|
29479
|
-
SUBTITLE_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData)
|
|
29844
|
+
SUBTITLE_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData),
|
|
29845
|
+
btrt(trackData)
|
|
29480
29846
|
]);
|
|
29481
29847
|
var vttC = (trackData) => box("vttC", [
|
|
29482
29848
|
...textEncoder.encode(trackData.info.config.description)
|
|
@@ -30911,6 +31277,26 @@ var Mediabunny = (() => {
|
|
|
30911
31277
|
const value = timeInSeconds * timescale;
|
|
30912
31278
|
return round ? Math.round(value) : value;
|
|
30913
31279
|
};
|
|
31280
|
+
var presentationSpan = (trackData) => {
|
|
31281
|
+
if (trackData.samples.length === 0) {
|
|
31282
|
+
return 0;
|
|
31283
|
+
}
|
|
31284
|
+
let minTimestamp = Infinity;
|
|
31285
|
+
let maxEndTimestamp = -Infinity;
|
|
31286
|
+
for (let i = 0; i < trackData.samples.length; i++) {
|
|
31287
|
+
const sample = trackData.samples[i];
|
|
31288
|
+
if (sample.timestamp < minTimestamp) {
|
|
31289
|
+
minTimestamp = sample.timestamp;
|
|
31290
|
+
}
|
|
31291
|
+
if (sample.timestamp + sample.duration > maxEndTimestamp) {
|
|
31292
|
+
maxEndTimestamp = sample.timestamp + sample.duration;
|
|
31293
|
+
}
|
|
31294
|
+
}
|
|
31295
|
+
if (minTimestamp === Infinity) {
|
|
31296
|
+
return 0;
|
|
31297
|
+
}
|
|
31298
|
+
return maxEndTimestamp - minTimestamp;
|
|
31299
|
+
};
|
|
30914
31300
|
var IsobmffMuxer2 = class extends Muxer {
|
|
30915
31301
|
constructor(output, format) {
|
|
30916
31302
|
super(output);
|
|
@@ -31124,7 +31510,9 @@ var Mediabunny = (() => {
|
|
|
31124
31510
|
finalizedChunks: [],
|
|
31125
31511
|
currentChunk: null,
|
|
31126
31512
|
compactlyCodedChunkTable: [],
|
|
31127
|
-
closed: false
|
|
31513
|
+
closed: false,
|
|
31514
|
+
avgBitrate: track.source._nominalBitrate ?? track.metadata.averageBitrate ?? 0,
|
|
31515
|
+
maxBitrate: track.source._nominalBitrate ?? track.metadata.bitrate ?? 0
|
|
31128
31516
|
};
|
|
31129
31517
|
this.trackDatas.push(newTrackData);
|
|
31130
31518
|
this.trackDatas.sort((a, b) => a.track.id - b.track.id);
|
|
@@ -31198,7 +31586,9 @@ var Mediabunny = (() => {
|
|
|
31198
31586
|
finalizedChunks: [],
|
|
31199
31587
|
currentChunk: null,
|
|
31200
31588
|
compactlyCodedChunkTable: [],
|
|
31201
|
-
closed: false
|
|
31589
|
+
closed: false,
|
|
31590
|
+
avgBitrate: track.source._nominalBitrate ?? track.metadata.averageBitrate ?? 0,
|
|
31591
|
+
maxBitrate: track.source._nominalBitrate ?? track.metadata.bitrate ?? 0
|
|
31202
31592
|
};
|
|
31203
31593
|
this.trackDatas.push(newTrackData);
|
|
31204
31594
|
this.trackDatas.sort((a, b) => a.track.id - b.track.id);
|
|
@@ -31236,6 +31626,8 @@ var Mediabunny = (() => {
|
|
|
31236
31626
|
currentChunk: null,
|
|
31237
31627
|
compactlyCodedChunkTable: [],
|
|
31238
31628
|
closed: false,
|
|
31629
|
+
avgBitrate: track.source._nominalBitrate ?? track.metadata.averageBitrate ?? 0,
|
|
31630
|
+
maxBitrate: track.source._nominalBitrate ?? track.metadata.bitrate ?? 0,
|
|
31239
31631
|
lastCueEndTimestamp: null,
|
|
31240
31632
|
cueQueue: [],
|
|
31241
31633
|
nextSourceId: 0,
|
|
@@ -31901,6 +32293,29 @@ var Mediabunny = (() => {
|
|
|
31901
32293
|
} else {
|
|
31902
32294
|
for (const trackData of this.trackDatas) {
|
|
31903
32295
|
await this.finalizeCurrentChunk(trackData);
|
|
32296
|
+
const span = presentationSpan(trackData);
|
|
32297
|
+
if (span > 0) {
|
|
32298
|
+
let totalBytes = 0;
|
|
32299
|
+
for (const sample of trackData.samples) {
|
|
32300
|
+
totalBytes += sample.size;
|
|
32301
|
+
}
|
|
32302
|
+
trackData.avgBitrate = Math.round(8 * totalBytes / span);
|
|
32303
|
+
} else {
|
|
32304
|
+
trackData.avgBitrate = 0;
|
|
32305
|
+
}
|
|
32306
|
+
let windowStart = 0;
|
|
32307
|
+
let windowBytes = 0;
|
|
32308
|
+
let maxWindowBytes = 0;
|
|
32309
|
+
for (let i = 0; i < trackData.samples.length; i++) {
|
|
32310
|
+
const sample = trackData.samples[i];
|
|
32311
|
+
windowBytes += sample.size;
|
|
32312
|
+
while (sample.decodeTimestamp - trackData.samples[windowStart].decodeTimestamp >= 1) {
|
|
32313
|
+
windowBytes -= trackData.samples[windowStart].size;
|
|
32314
|
+
windowStart++;
|
|
32315
|
+
}
|
|
32316
|
+
maxWindowBytes = Math.max(maxWindowBytes, windowBytes);
|
|
32317
|
+
}
|
|
32318
|
+
trackData.maxBitrate = 8 * maxWindowBytes;
|
|
31904
32319
|
if (trackData.startTimestampOffset !== null) {
|
|
31905
32320
|
for (let i = 0; i < trackData.samples.length; i++) {
|
|
31906
32321
|
const sample = trackData.samples[i];
|
|
@@ -32199,14 +32614,34 @@ var Mediabunny = (() => {
|
|
|
32199
32614
|
}
|
|
32200
32615
|
}
|
|
32201
32616
|
videoSpecificTrackInfo(trackData) {
|
|
32202
|
-
const { frameRate,
|
|
32617
|
+
const { frameRate, transformationMatrix } = trackData.track.metadata;
|
|
32203
32618
|
const elements = [
|
|
32204
32619
|
frameRate ? {
|
|
32205
32620
|
id: 2352003 /* DefaultDuration */,
|
|
32206
32621
|
data: 1e9 / frameRate
|
|
32207
32622
|
} : null
|
|
32208
32623
|
];
|
|
32209
|
-
|
|
32624
|
+
let rotation;
|
|
32625
|
+
let horizontalScale;
|
|
32626
|
+
let verticalScale;
|
|
32627
|
+
if (transformationMatrix) {
|
|
32628
|
+
rotation = extractRotationFromMatrix(transformationMatrix);
|
|
32629
|
+
const unrotated = multiplyMatrices(rotationMatrix(-rotation), transformationMatrix);
|
|
32630
|
+
horizontalScale = Math.sign(unrotated[0]);
|
|
32631
|
+
verticalScale = Math.sign(unrotated[4]);
|
|
32632
|
+
if (verticalScale === -1) {
|
|
32633
|
+
verticalScale = 1;
|
|
32634
|
+
horizontalScale = -horizontalScale;
|
|
32635
|
+
rotation = normalizeRotation(rotation + 180);
|
|
32636
|
+
}
|
|
32637
|
+
} else {
|
|
32638
|
+
rotation = trackData.track.metadata.rotation ?? 0;
|
|
32639
|
+
horizontalScale = trackData.track.metadata.flip ? -1 : 1;
|
|
32640
|
+
verticalScale = 1;
|
|
32641
|
+
}
|
|
32642
|
+
const roll = rotation ? normalizeRotation(horizontalScale === -1 ? rotation : -rotation) : 0;
|
|
32643
|
+
const yaw = Math.round(Math.acos(horizontalScale) * RAD_TO_DEG);
|
|
32644
|
+
const pitch = Math.round(Math.acos(verticalScale) * RAD_TO_DEG);
|
|
32210
32645
|
const hasNonSquarePixelAspectRatio = !!trackData.info.aspectRatio && trackData.info.aspectRatio.num * trackData.info.height !== trackData.info.aspectRatio.den * trackData.info.width;
|
|
32211
32646
|
const colorSpace = trackData.info.decoderConfig.colorSpace;
|
|
32212
32647
|
const videoElement = { id: 224 /* Video */, data: [
|
|
@@ -32238,7 +32673,7 @@ var Mediabunny = (() => {
|
|
|
32238
32673
|
}
|
|
32239
32674
|
]
|
|
32240
32675
|
},
|
|
32241
|
-
|
|
32676
|
+
roll || yaw || pitch ? {
|
|
32242
32677
|
id: 30320 /* Projection */,
|
|
32243
32678
|
data: [
|
|
32244
32679
|
{
|
|
@@ -32246,11 +32681,19 @@ var Mediabunny = (() => {
|
|
|
32246
32681
|
data: 0
|
|
32247
32682
|
// rectangular
|
|
32248
32683
|
},
|
|
32249
|
-
{
|
|
32684
|
+
yaw ? {
|
|
32685
|
+
id: 30323 /* ProjectionPoseYaw */,
|
|
32686
|
+
data: new EBMLFloat32(yaw)
|
|
32687
|
+
} : null,
|
|
32688
|
+
pitch ? {
|
|
32689
|
+
id: 30324 /* ProjectionPosePitch */,
|
|
32690
|
+
data: new EBMLFloat32(pitch)
|
|
32691
|
+
} : null,
|
|
32692
|
+
roll ? {
|
|
32250
32693
|
id: 30325 /* ProjectionPoseRoll */,
|
|
32251
|
-
data: new EBMLFloat32((
|
|
32694
|
+
data: new EBMLFloat32((roll + 180) % 360 - 180)
|
|
32252
32695
|
// [0, 270] -> [-180, 90]
|
|
32253
|
-
}
|
|
32696
|
+
} : null
|
|
32254
32697
|
]
|
|
32255
32698
|
} : null
|
|
32256
32699
|
] };
|
|
@@ -34213,7 +34656,7 @@ ${cue.notes ?? ""}`;
|
|
|
34213
34656
|
this.writer.write(this.helper);
|
|
34214
34657
|
}
|
|
34215
34658
|
writeAscii(text) {
|
|
34216
|
-
this.writer.write(
|
|
34659
|
+
this.writer.write(textEncoder.encode(text));
|
|
34217
34660
|
}
|
|
34218
34661
|
};
|
|
34219
34662
|
|
|
@@ -34697,6 +35140,11 @@ ${cue.notes ?? ""}`;
|
|
|
34697
35140
|
this._closingPromise = null;
|
|
34698
35141
|
/** @internal */
|
|
34699
35142
|
this._closed = false;
|
|
35143
|
+
/**
|
|
35144
|
+
* Set when the encoder is configured with a bitrate.
|
|
35145
|
+
* @internal
|
|
35146
|
+
*/
|
|
35147
|
+
this._nominalBitrate = null;
|
|
34700
35148
|
}
|
|
34701
35149
|
/** @internal */
|
|
34702
35150
|
_ensureValidAdd() {
|
|
@@ -34873,7 +35321,7 @@ ${cue.notes ?? ""}`;
|
|
|
34873
35321
|
this.codedWidth = videoSample.codedWidth;
|
|
34874
35322
|
this.codedHeight = videoSample.codedHeight;
|
|
34875
35323
|
}
|
|
34876
|
-
const hasTransformConfig = config.transform?.width !== void 0 || config.transform?.height !== void 0 || config.transform?.rotate !== void 0 || config.transform?.crop !== void 0 || config.transform?.force === true;
|
|
35324
|
+
const hasTransformConfig = config.transform?.width !== void 0 || config.transform?.height !== void 0 || config.transform?.rotate !== void 0 || config.transform?.flip !== void 0 || config.transform?.crop !== void 0 || config.transform?.force === true;
|
|
34877
35325
|
const needsTransform = hasTransformConfig || isSizeChange && sizeChangeBehavior !== "passThrough";
|
|
34878
35326
|
if (needsTransform) {
|
|
34879
35327
|
let targetWidth = config.transform?.width;
|
|
@@ -34893,6 +35341,7 @@ ${cue.notes ?? ""}`;
|
|
|
34893
35341
|
roundDimensionsTo: 2,
|
|
34894
35342
|
crop: config.transform?.crop,
|
|
34895
35343
|
rotate: config.transform?.rotate,
|
|
35344
|
+
flip: config.transform?.flip,
|
|
34896
35345
|
fit: appliedFit,
|
|
34897
35346
|
alpha: config.alpha
|
|
34898
35347
|
});
|
|
@@ -35187,6 +35636,8 @@ ${cue.notes ?? ""}`;
|
|
|
35187
35636
|
this.encodingConfig.codec,
|
|
35188
35637
|
selected.quantizer
|
|
35189
35638
|
);
|
|
35639
|
+
} else {
|
|
35640
|
+
this.source._nominalBitrate = encoderConfig.bitrate ?? null;
|
|
35190
35641
|
}
|
|
35191
35642
|
if (MatchingCustomEncoder) {
|
|
35192
35643
|
this.customEncoder = new MatchingCustomEncoder();
|
|
@@ -35857,39 +36308,42 @@ ${cue.notes ?? ""}`;
|
|
|
35857
36308
|
}
|
|
35858
36309
|
/** @internal */
|
|
35859
36310
|
async _flushAndClose(forceClose) {
|
|
35860
|
-
|
|
35861
|
-
this._abortController
|
|
35862
|
-
|
|
35863
|
-
|
|
35864
|
-
|
|
35865
|
-
|
|
35866
|
-
|
|
35867
|
-
|
|
35868
|
-
|
|
35869
|
-
this._videoElement
|
|
35870
|
-
|
|
35871
|
-
|
|
35872
|
-
|
|
35873
|
-
|
|
35874
|
-
|
|
35875
|
-
|
|
35876
|
-
|
|
35877
|
-
|
|
35878
|
-
|
|
35879
|
-
|
|
35880
|
-
|
|
35881
|
-
const
|
|
35882
|
-
|
|
35883
|
-
|
|
35884
|
-
|
|
35885
|
-
|
|
35886
|
-
|
|
35887
|
-
|
|
35888
|
-
|
|
35889
|
-
|
|
35890
|
-
|
|
36311
|
+
try {
|
|
36312
|
+
if (this._abortController) {
|
|
36313
|
+
this._abortController.abort();
|
|
36314
|
+
this._abortController = null;
|
|
36315
|
+
}
|
|
36316
|
+
if (this._timerHandle) {
|
|
36317
|
+
clearIntervalUnthrottled(this._timerHandle);
|
|
36318
|
+
}
|
|
36319
|
+
this._lastVideoFrame?.close();
|
|
36320
|
+
if (this._videoElement) {
|
|
36321
|
+
this._videoElement.srcObject = null;
|
|
36322
|
+
this._videoElement.remove();
|
|
36323
|
+
this._videoElement = null;
|
|
36324
|
+
}
|
|
36325
|
+
if (this._workerTrackId !== null) {
|
|
36326
|
+
assert(this._workerListener);
|
|
36327
|
+
sendMessageToMediaStreamTrackProcessorWorker({
|
|
36328
|
+
type: "stopTrack",
|
|
36329
|
+
trackId: this._workerTrackId
|
|
36330
|
+
});
|
|
36331
|
+
await new Promise((resolve) => {
|
|
36332
|
+
const listener = (event) => {
|
|
36333
|
+
const message = event.data;
|
|
36334
|
+
if (message.type === "trackStopped" && message.trackId === this._workerTrackId) {
|
|
36335
|
+
assert(this._workerListener);
|
|
36336
|
+
mediaStreamTrackProcessorWorker.removeEventListener("message", this._workerListener);
|
|
36337
|
+
mediaStreamTrackProcessorWorker.removeEventListener("message", listener);
|
|
36338
|
+
resolve();
|
|
36339
|
+
}
|
|
36340
|
+
};
|
|
36341
|
+
mediaStreamTrackProcessorWorker.addEventListener("message", listener);
|
|
36342
|
+
});
|
|
36343
|
+
}
|
|
36344
|
+
} finally {
|
|
36345
|
+
await this._encoder.flushAndClose(forceClose);
|
|
35891
36346
|
}
|
|
35892
|
-
await this._encoder.flushAndClose(forceClose);
|
|
35893
36347
|
}
|
|
35894
36348
|
};
|
|
35895
36349
|
var AudioSource = class extends MediaSource {
|
|
@@ -36192,6 +36646,7 @@ ${cue.notes ?? ""}`;
|
|
|
36192
36646
|
quality
|
|
36193
36647
|
});
|
|
36194
36648
|
this.encodingConfig.onEncoderConfig?.(encoderConfig);
|
|
36649
|
+
this.source._nominalBitrate = encoderConfig.bitrate ?? null;
|
|
36195
36650
|
const MatchingCustomEncoder = customAudioEncoders.find((x) => x.supports(
|
|
36196
36651
|
this.encodingConfig.codec,
|
|
36197
36652
|
encoderConfig
|
|
@@ -36636,16 +37091,19 @@ ${cue.notes ?? ""}`;
|
|
|
36636
37091
|
}
|
|
36637
37092
|
/** @internal */
|
|
36638
37093
|
async _flushAndClose(forceClose) {
|
|
36639
|
-
|
|
36640
|
-
this._abortController
|
|
36641
|
-
|
|
36642
|
-
|
|
36643
|
-
|
|
36644
|
-
|
|
36645
|
-
|
|
36646
|
-
|
|
37094
|
+
try {
|
|
37095
|
+
if (this._abortController) {
|
|
37096
|
+
this._abortController.abort();
|
|
37097
|
+
this._abortController = null;
|
|
37098
|
+
}
|
|
37099
|
+
if (this._audioContext) {
|
|
37100
|
+
assert(this._scriptProcessorNode);
|
|
37101
|
+
this._scriptProcessorNode.disconnect();
|
|
37102
|
+
await this._audioContext.suspend();
|
|
37103
|
+
}
|
|
37104
|
+
} finally {
|
|
37105
|
+
await this._encoder.flushAndClose(forceClose);
|
|
36647
37106
|
}
|
|
36648
|
-
await this._encoder.flushAndClose(forceClose);
|
|
36649
37107
|
}
|
|
36650
37108
|
};
|
|
36651
37109
|
var mediaStreamTrackProcessorWorkerCode = () => {
|
|
@@ -37022,13 +37480,13 @@ ${cue.notes ?? ""}`;
|
|
|
37022
37480
|
const codecs = [];
|
|
37023
37481
|
let videoCount = 0;
|
|
37024
37482
|
let audioCount = 0;
|
|
37025
|
-
let
|
|
37483
|
+
let requiresTransformationMetadata = false;
|
|
37026
37484
|
let candidate = null;
|
|
37027
37485
|
let candidateScore = -Infinity;
|
|
37028
37486
|
for (const track of tracks) {
|
|
37029
37487
|
if (track.isVideoTrack()) {
|
|
37030
37488
|
videoCount++;
|
|
37031
|
-
|
|
37489
|
+
requiresTransformationMetadata ||= (track.metadata.rotation ?? 0) !== 0 || !!track.metadata.flip || !!track.metadata.transformationMatrix;
|
|
37032
37490
|
} else if (track.isAudioTrack()) {
|
|
37033
37491
|
audioCount++;
|
|
37034
37492
|
}
|
|
@@ -37047,7 +37505,7 @@ ${cue.notes ?? ""}`;
|
|
|
37047
37505
|
continue;
|
|
37048
37506
|
}
|
|
37049
37507
|
let score = 0;
|
|
37050
|
-
if (
|
|
37508
|
+
if (requiresTransformationMetadata && format.supportsVideoTransformationMetadata) {
|
|
37051
37509
|
score++;
|
|
37052
37510
|
}
|
|
37053
37511
|
if (score > candidateScore) {
|
|
@@ -37975,6 +38433,13 @@ ${cue.notes ?? ""}`;
|
|
|
37975
38433
|
|
|
37976
38434
|
// src/output-format.ts
|
|
37977
38435
|
var OutputFormat = class {
|
|
38436
|
+
/**
|
|
38437
|
+
* Whether this output format supports video rotation metadata.
|
|
38438
|
+
* @deprecated Use {@link OutputFormat.supportsVideoTransformationMetadata} instead.
|
|
38439
|
+
*/
|
|
38440
|
+
get supportsVideoRotationMetadata() {
|
|
38441
|
+
return this.supportsVideoTransformationMetadata;
|
|
38442
|
+
}
|
|
37978
38443
|
/** Returns a list of video codecs that this output format can contain. */
|
|
37979
38444
|
getSupportedVideoCodecs() {
|
|
37980
38445
|
return this.getSupportedCodecs().filter((codec) => VIDEO_CODECS.includes(codec));
|
|
@@ -38040,7 +38505,7 @@ ${cue.notes ?? ""}`;
|
|
|
38040
38505
|
total: { min: 0, max }
|
|
38041
38506
|
};
|
|
38042
38507
|
}
|
|
38043
|
-
get
|
|
38508
|
+
get supportsVideoTransformationMetadata() {
|
|
38044
38509
|
return true;
|
|
38045
38510
|
}
|
|
38046
38511
|
get supportsTimestampedMediaData() {
|
|
@@ -38217,7 +38682,7 @@ ${cue.notes ?? ""}`;
|
|
|
38217
38682
|
...SUBTITLE_CODECS
|
|
38218
38683
|
];
|
|
38219
38684
|
}
|
|
38220
|
-
get
|
|
38685
|
+
get supportsVideoTransformationMetadata() {
|
|
38221
38686
|
return false;
|
|
38222
38687
|
}
|
|
38223
38688
|
get supportsTimestampedMediaData() {
|
|
@@ -38297,7 +38762,7 @@ ${cue.notes ?? ""}`;
|
|
|
38297
38762
|
getSupportedCodecs() {
|
|
38298
38763
|
return ["mp3"];
|
|
38299
38764
|
}
|
|
38300
|
-
get
|
|
38765
|
+
get supportsVideoTransformationMetadata() {
|
|
38301
38766
|
return false;
|
|
38302
38767
|
}
|
|
38303
38768
|
get supportsTimestampedMediaData() {
|
|
@@ -38354,7 +38819,7 @@ ${cue.notes ?? ""}`;
|
|
|
38354
38819
|
)
|
|
38355
38820
|
];
|
|
38356
38821
|
}
|
|
38357
|
-
get
|
|
38822
|
+
get supportsVideoTransformationMetadata() {
|
|
38358
38823
|
return false;
|
|
38359
38824
|
}
|
|
38360
38825
|
get supportsTimestampedMediaData() {
|
|
@@ -38407,7 +38872,7 @@ ${cue.notes ?? ""}`;
|
|
|
38407
38872
|
...AUDIO_CODECS.filter((codec) => ["vorbis", "opus"].includes(codec))
|
|
38408
38873
|
];
|
|
38409
38874
|
}
|
|
38410
|
-
get
|
|
38875
|
+
get supportsVideoTransformationMetadata() {
|
|
38411
38876
|
return false;
|
|
38412
38877
|
}
|
|
38413
38878
|
get supportsTimestampedMediaData() {
|
|
@@ -38454,7 +38919,7 @@ ${cue.notes ?? ""}`;
|
|
|
38454
38919
|
getSupportedCodecs() {
|
|
38455
38920
|
return ["aac"];
|
|
38456
38921
|
}
|
|
38457
|
-
get
|
|
38922
|
+
get supportsVideoTransformationMetadata() {
|
|
38458
38923
|
return false;
|
|
38459
38924
|
}
|
|
38460
38925
|
get supportsTimestampedMediaData() {
|
|
@@ -38501,7 +38966,7 @@ ${cue.notes ?? ""}`;
|
|
|
38501
38966
|
getSupportedCodecs() {
|
|
38502
38967
|
return ["flac"];
|
|
38503
38968
|
}
|
|
38504
|
-
get
|
|
38969
|
+
get supportsVideoTransformationMetadata() {
|
|
38505
38970
|
return false;
|
|
38506
38971
|
}
|
|
38507
38972
|
get supportsTimestampedMediaData() {
|
|
@@ -38554,7 +39019,7 @@ ${cue.notes ?? ""}`;
|
|
|
38554
39019
|
...AUDIO_CODECS.filter((codec) => ["aac", "mp3", "ac3", "eac3", "dts"].includes(codec))
|
|
38555
39020
|
];
|
|
38556
39021
|
}
|
|
38557
|
-
get
|
|
39022
|
+
get supportsVideoTransformationMetadata() {
|
|
38558
39023
|
return false;
|
|
38559
39024
|
}
|
|
38560
39025
|
get supportsTimestampedMediaData() {
|
|
@@ -38650,8 +39115,8 @@ ${cue.notes ?? ""}`;
|
|
|
38650
39115
|
total: { min: 0, max: Infinity }
|
|
38651
39116
|
};
|
|
38652
39117
|
}
|
|
38653
|
-
get
|
|
38654
|
-
return toArray(this._options.segmentFormat).some((format) => format.
|
|
39118
|
+
get supportsVideoTransformationMetadata() {
|
|
39119
|
+
return toArray(this._options.segmentFormat).some((format) => format.supportsVideoTransformationMetadata);
|
|
38655
39120
|
}
|
|
38656
39121
|
get supportsTimestampedMediaData() {
|
|
38657
39122
|
return true;
|
|
@@ -38784,6 +39249,12 @@ ${cue.notes ?? ""}`;
|
|
|
38784
39249
|
if (metadata.maximumPacketCount !== void 0 && (!Number.isInteger(metadata.maximumPacketCount) || metadata.maximumPacketCount < 0)) {
|
|
38785
39250
|
throw new TypeError("metadata.maximumPacketCount, when provided, must be a non-negative integer.");
|
|
38786
39251
|
}
|
|
39252
|
+
if (metadata.bitrate !== void 0 && (!Number.isFinite(metadata.bitrate) || metadata.bitrate < 0)) {
|
|
39253
|
+
throw new TypeError("metadata.bitrate, when provided, must be a non-negative number.");
|
|
39254
|
+
}
|
|
39255
|
+
if (metadata.averageBitrate !== void 0 && (!Number.isFinite(metadata.averageBitrate) || metadata.averageBitrate < 0)) {
|
|
39256
|
+
throw new TypeError("metadata.averageBitrate, when provided, must be a non-negative number.");
|
|
39257
|
+
}
|
|
38787
39258
|
if (metadata.group !== void 0 && !(metadata.group instanceof OutputTrackGroup) && (!Array.isArray(metadata.group) || metadata.group.some((group) => !(group instanceof OutputTrackGroup)))) {
|
|
38788
39259
|
throw new TypeError(
|
|
38789
39260
|
"metadata.group, when provided, must be an OutputTrackGroup instance or an array of OutputTrackGroup instances."
|
|
@@ -38983,8 +39454,11 @@ ${cue.notes ?? ""}`;
|
|
|
38983
39454
|
if (metadata.rotation !== void 0 && ![0, 90, 180, 270].includes(metadata.rotation)) {
|
|
38984
39455
|
throw new TypeError(`Invalid video rotation: ${metadata.rotation}. Has to be 0, 90, 180 or 270.`);
|
|
38985
39456
|
}
|
|
38986
|
-
if (
|
|
38987
|
-
throw new
|
|
39457
|
+
if (metadata.flip !== void 0 && typeof metadata.flip !== "boolean") {
|
|
39458
|
+
throw new TypeError("metadata.flip, when provided, must be a boolean.");
|
|
39459
|
+
}
|
|
39460
|
+
if (metadata.transformationMatrix !== void 0 && (!Array.isArray(metadata.transformationMatrix) || metadata.transformationMatrix.length !== 9 || !metadata.transformationMatrix.every((x) => Number.isFinite(x)))) {
|
|
39461
|
+
throw new TypeError("metadata.transformationMatrix, when provided, must be an array of 9 finite numbers.");
|
|
38988
39462
|
}
|
|
38989
39463
|
if (metadata.frameRate !== void 0 && (!Number.isFinite(metadata.frameRate) || metadata.frameRate <= 0)) {
|
|
38990
39464
|
throw new TypeError(
|
|
@@ -39210,9 +39684,8 @@ ${cue.notes ?? ""}`;
|
|
|
39210
39684
|
* @returns A promise that resolves once all internal resources have been released.
|
|
39211
39685
|
*/
|
|
39212
39686
|
async cancel() {
|
|
39213
|
-
if (this.
|
|
39214
|
-
|
|
39215
|
-
return this._cancelPromise;
|
|
39687
|
+
if (this.state === "canceled") {
|
|
39688
|
+
return this._cancelPromise ?? void 0;
|
|
39216
39689
|
} else if (this.state === "finalizing" || this.state === "finalized") {
|
|
39217
39690
|
if (this.state === "finalized") {
|
|
39218
39691
|
Logging._warn("Output has already been finalized.");
|
|
@@ -39265,6 +39738,9 @@ ${cue.notes ?? ""}`;
|
|
|
39265
39738
|
await this._onFinalize();
|
|
39266
39739
|
}
|
|
39267
39740
|
this.state = "finalized";
|
|
39741
|
+
} catch (error) {
|
|
39742
|
+
this.state = "canceled";
|
|
39743
|
+
throw error;
|
|
39268
39744
|
} finally {
|
|
39269
39745
|
await Promise.all([...this._unfinalizedTargets].map((target) => target._close().catch(() => {
|
|
39270
39746
|
})));
|
|
@@ -39318,6 +39794,12 @@ ${cue.notes ?? ""}`;
|
|
|
39318
39794
|
if (videoOptions?.rotate !== void 0 && ![0, 90, 180, 270].includes(videoOptions.rotate)) {
|
|
39319
39795
|
throw new TypeError("options.video.rotate, when provided, must be 0, 90, 180 or 270.");
|
|
39320
39796
|
}
|
|
39797
|
+
if (videoOptions?.flip !== void 0 && typeof videoOptions.flip !== "boolean") {
|
|
39798
|
+
throw new TypeError("options.video.flip, when provided, must be a boolean.");
|
|
39799
|
+
}
|
|
39800
|
+
if (videoOptions?.allowTransformationMetadata !== void 0 && typeof videoOptions.allowTransformationMetadata !== "boolean") {
|
|
39801
|
+
throw new TypeError("options.video.allowTransformationMetadata, when provided, must be a boolean.");
|
|
39802
|
+
}
|
|
39321
39803
|
if (videoOptions?.allowRotationMetadata !== void 0 && typeof videoOptions.allowRotationMetadata !== "boolean") {
|
|
39322
39804
|
throw new TypeError("options.video.allowRotationMetadata, when provided, must be a boolean.");
|
|
39323
39805
|
}
|
|
@@ -39987,9 +40469,17 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
39987
40469
|
}
|
|
39988
40470
|
let videoSource;
|
|
39989
40471
|
const innateRotation = await track.getRotation();
|
|
39990
|
-
const
|
|
40472
|
+
const innateFlip = await track.getFlip();
|
|
40473
|
+
const { rotation: totalRotation, flip: totalFlip } = composeRotationAndFlip(
|
|
40474
|
+
innateRotation,
|
|
40475
|
+
innateFlip,
|
|
40476
|
+
trackOptions.rotate ?? 0,
|
|
40477
|
+
trackOptions.flip ?? false
|
|
40478
|
+
);
|
|
39991
40479
|
let outputTrackRotation = totalRotation;
|
|
39992
|
-
|
|
40480
|
+
let outputTrackFlip = totalFlip;
|
|
40481
|
+
let outputTrackMatrix = trackOptions.rotate || trackOptions.flip ? null : await track.getTransformationMatrix();
|
|
40482
|
+
const canUseRotationMetadata = this.output.format.supportsVideoTransformationMetadata && (trackOptions.allowTransformationMetadata ?? trackOptions.allowRotationMetadata ?? true);
|
|
39993
40483
|
const squarePixelWidth = await track.getSquarePixelWidth();
|
|
39994
40484
|
const squarePixelHeight = await track.getSquarePixelHeight();
|
|
39995
40485
|
const [rotatedWidth, rotatedHeight] = totalRotation % 180 === 0 ? [squarePixelWidth, squarePixelHeight] : [squarePixelHeight, squarePixelWidth];
|
|
@@ -40013,7 +40503,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40013
40503
|
}
|
|
40014
40504
|
let videoCodecs = this.output.format.getSupportedVideoCodecs();
|
|
40015
40505
|
const alpha = trackOptions.alpha ?? "discard";
|
|
40016
|
-
let needsTranscode = !this._copyMode || !!trackOptions.forceTranscode || !!trackOptions.frameRate || trackOptions.keyFrameInterval !== void 0 || trackOptions.process !== void 0 || trackOptions.quality !== void 0 || trackOptions.bitrate !== void 0 || !videoCodecs.includes(sourceCodec) || trackOptions.codec && trackOptions.codec !== sourceCodec || width !== originalWidth || height !== originalHeight || totalRotation !== 0 && !canUseRotationMetadata || !!crop;
|
|
40506
|
+
let needsTranscode = !this._copyMode || !!trackOptions.forceTranscode || !!trackOptions.frameRate || trackOptions.keyFrameInterval !== void 0 || trackOptions.process !== void 0 || trackOptions.quality !== void 0 || trackOptions.bitrate !== void 0 || !videoCodecs.includes(sourceCodec) || trackOptions.codec && trackOptions.codec !== sourceCodec || width !== originalWidth || height !== originalHeight || totalRotation !== 0 && !canUseRotationMetadata || totalFlip && !canUseRotationMetadata || !!crop;
|
|
40017
40507
|
let copyStartPacket = null;
|
|
40018
40508
|
if (!needsTranscode) {
|
|
40019
40509
|
const sink = new EncodedPacketSink(track);
|
|
@@ -40167,7 +40657,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40167
40657
|
transform: {}
|
|
40168
40658
|
};
|
|
40169
40659
|
assert(encodingConfig.transform);
|
|
40170
|
-
let needsRerender = width !== originalWidth || height !== originalHeight || totalRotation !== 0 && (!canUseRotationMetadata || trackOptions.process !== void 0) || !!crop || squarePixelWidth !== await track.getCodedWidth() || squarePixelHeight !== await track.getCodedHeight();
|
|
40660
|
+
let needsRerender = width !== originalWidth || height !== originalHeight || totalRotation !== 0 && (!canUseRotationMetadata || trackOptions.process !== void 0) || totalFlip && (!canUseRotationMetadata || trackOptions.process !== void 0) || !!crop || squarePixelWidth !== await track.getCodedWidth() || squarePixelHeight !== await track.getCodedHeight();
|
|
40171
40661
|
if (!needsRerender) {
|
|
40172
40662
|
var _stack = [];
|
|
40173
40663
|
try {
|
|
@@ -40212,10 +40702,13 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40212
40702
|
}
|
|
40213
40703
|
if (needsRerender) {
|
|
40214
40704
|
outputTrackRotation = 0;
|
|
40705
|
+
outputTrackFlip = false;
|
|
40706
|
+
outputTrackMatrix = null;
|
|
40215
40707
|
encodingConfig.transform.width = width;
|
|
40216
40708
|
encodingConfig.transform.height = height;
|
|
40217
40709
|
encodingConfig.transform.fit = trackOptions.fit ?? "fill";
|
|
40218
|
-
encodingConfig.transform.rotate =
|
|
40710
|
+
encodingConfig.transform.rotate = trackOptions.rotate;
|
|
40711
|
+
encodingConfig.transform.flip = trackOptions.flip;
|
|
40219
40712
|
encodingConfig.transform.crop = crop;
|
|
40220
40713
|
encodingConfig.transform.alpha = alpha;
|
|
40221
40714
|
}
|
|
@@ -40267,6 +40760,8 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40267
40760
|
const videoTrackLanguageCode = await track.getLanguageCode();
|
|
40268
40761
|
const trackName = await track.getName();
|
|
40269
40762
|
const trackDisposition = await track.getDisposition();
|
|
40763
|
+
const bitrate = needsTranscode ? null : await track.getBitrate();
|
|
40764
|
+
const averageBitrate = needsTranscode ? null : await track.getAverageBitrate();
|
|
40270
40765
|
this.output.addVideoTrack(videoSource, {
|
|
40271
40766
|
frameRate: trackOptions.frameRate,
|
|
40272
40767
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
@@ -40274,7 +40769,11 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40274
40769
|
name: trackName ?? void 0,
|
|
40275
40770
|
disposition: trackDisposition,
|
|
40276
40771
|
rotation: outputTrackRotation,
|
|
40277
|
-
|
|
40772
|
+
flip: outputTrackFlip,
|
|
40773
|
+
transformationMatrix: outputTrackMatrix ?? void 0,
|
|
40774
|
+
group: ownGroup ?? trackOptions.group,
|
|
40775
|
+
bitrate: bitrate ?? void 0,
|
|
40776
|
+
averageBitrate: averageBitrate ?? void 0
|
|
40278
40777
|
});
|
|
40279
40778
|
this.utilizedTracks.push(track);
|
|
40280
40779
|
this._outputTrackIds.push(outputTrackId);
|
|
@@ -40558,12 +41057,16 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40558
41057
|
const audioTrackLanguageCode = await track.getLanguageCode();
|
|
40559
41058
|
const trackName = await track.getName();
|
|
40560
41059
|
const trackDisposition = await track.getDisposition();
|
|
41060
|
+
const bitrate = needsTranscode ? null : await track.getBitrate();
|
|
41061
|
+
const averageBitrate = needsTranscode ? null : await track.getAverageBitrate();
|
|
40561
41062
|
this.output.addAudioTrack(audioSource, {
|
|
40562
41063
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
40563
41064
|
languageCode: isIso639Dash2LanguageCode(audioTrackLanguageCode) ? audioTrackLanguageCode : void 0,
|
|
40564
41065
|
name: trackName ?? void 0,
|
|
40565
41066
|
disposition: trackDisposition,
|
|
40566
|
-
group: ownGroup ?? trackOptions.group
|
|
41067
|
+
group: ownGroup ?? trackOptions.group,
|
|
41068
|
+
bitrate: bitrate ?? void 0,
|
|
41069
|
+
averageBitrate: averageBitrate ?? void 0
|
|
40567
41070
|
});
|
|
40568
41071
|
this.utilizedTracks.push(track);
|
|
40569
41072
|
this._outputTrackIds.push(outputTrackId);
|