mediabunny 1.56.3 → 1.58.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 +551 -182
- package/dist/bundles/mediabunny.min.cjs +13 -13
- package/dist/bundles/mediabunny.min.mjs +13 -13
- package/dist/bundles/mediabunny.mjs +551 -182
- package/dist/bundles/mediabunny.node.cjs +551 -182
- package/dist/mediabunny.d.ts +221 -56
- package/dist/modules/src/conversion.d.ts +28 -6
- package/dist/modules/src/conversion.d.ts.map +1 -1
- package/dist/modules/src/conversion.js +69 -8
- 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/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/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 +44 -1
- package/dist/modules/src/misc.d.ts.map +1 -1
- package/dist/modules/src/misc.js +79 -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 +6 -4
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/conversion.ts +111 -14
- 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/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/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 +123 -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 +6 -4
|
@@ -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
|
};
|
|
@@ -6391,6 +6473,7 @@ var Mediabunny = (() => {
|
|
|
6391
6473
|
this.metadataPromise = null;
|
|
6392
6474
|
this.movieTimescale = -1;
|
|
6393
6475
|
this.movieDurationInTimescale = -1;
|
|
6476
|
+
this.movieMatrix = IDENTITY_MATRIX;
|
|
6394
6477
|
this.isQuickTime = false;
|
|
6395
6478
|
this.metadataTags = {};
|
|
6396
6479
|
this.currentMetadataKeys = null;
|
|
@@ -6509,6 +6592,7 @@ var Mediabunny = (() => {
|
|
|
6509
6592
|
await initDemuxer.readMetadata();
|
|
6510
6593
|
this.movieTimescale = initDemuxer.movieTimescale;
|
|
6511
6594
|
this.movieDurationInTimescale = initDemuxer.movieDurationInTimescale;
|
|
6595
|
+
this.movieMatrix = initDemuxer.movieMatrix;
|
|
6512
6596
|
this.metadataTags = initDemuxer.metadataTags;
|
|
6513
6597
|
this.isFragmented = true;
|
|
6514
6598
|
this.fragmentTrackDefaults = initDemuxer.fragmentTrackDefaults;
|
|
@@ -6522,7 +6606,7 @@ var Mediabunny = (() => {
|
|
|
6522
6606
|
timescale: foreignTrack.timescale,
|
|
6523
6607
|
durationInMediaTimescale: foreignTrack.durationInMediaTimescale,
|
|
6524
6608
|
durationInMovieTimescale: foreignTrack.durationInMovieTimescale,
|
|
6525
|
-
|
|
6609
|
+
matrix: foreignTrack.matrix,
|
|
6526
6610
|
internalCodecId: foreignTrack.internalCodecId,
|
|
6527
6611
|
name: foreignTrack.name,
|
|
6528
6612
|
languageCode: foreignTrack.languageCode,
|
|
@@ -6536,6 +6620,8 @@ var Mediabunny = (() => {
|
|
|
6536
6620
|
encryptionInfo: foreignTrack.encryptionInfo,
|
|
6537
6621
|
encryptionAuxInfo: null,
|
|
6538
6622
|
frmaCodecString: null,
|
|
6623
|
+
maxBitrate: foreignTrack.maxBitrate,
|
|
6624
|
+
avgBitrate: foreignTrack.avgBitrate,
|
|
6539
6625
|
info: foreignTrack.info
|
|
6540
6626
|
};
|
|
6541
6627
|
if (foreignTrack.trackBacking) {
|
|
@@ -6771,6 +6857,8 @@ var Mediabunny = (() => {
|
|
|
6771
6857
|
this.movieTimescale = readU32Be(slice);
|
|
6772
6858
|
this.movieDurationInTimescale = readU32Be(slice);
|
|
6773
6859
|
}
|
|
6860
|
+
slice.skip(4 + 2 + 2 + 2 * 4);
|
|
6861
|
+
this.movieMatrix = readMatrix(slice);
|
|
6774
6862
|
}
|
|
6775
6863
|
;
|
|
6776
6864
|
break;
|
|
@@ -6788,7 +6876,7 @@ var Mediabunny = (() => {
|
|
|
6788
6876
|
timescale: -1,
|
|
6789
6877
|
durationInMovieTimescale: -1,
|
|
6790
6878
|
durationInMediaTimescale: -1,
|
|
6791
|
-
|
|
6879
|
+
matrix: IDENTITY_MATRIX,
|
|
6792
6880
|
internalCodecId: null,
|
|
6793
6881
|
name: null,
|
|
6794
6882
|
languageCode: UNDETERMINED_LANGUAGE,
|
|
@@ -6801,7 +6889,9 @@ var Mediabunny = (() => {
|
|
|
6801
6889
|
editListOffset: 0,
|
|
6802
6890
|
encryptionInfo: null,
|
|
6803
6891
|
encryptionAuxInfo: null,
|
|
6804
|
-
frmaCodecString: null
|
|
6892
|
+
frmaCodecString: null,
|
|
6893
|
+
maxBitrate: null,
|
|
6894
|
+
avgBitrate: null
|
|
6805
6895
|
};
|
|
6806
6896
|
this.currentTrack = track;
|
|
6807
6897
|
this.readContiguousBoxes(slice.slice(contentStartPos, boxInfo.contentSize));
|
|
@@ -6844,20 +6934,8 @@ var Mediabunny = (() => {
|
|
|
6844
6934
|
throw new Error(`Incorrect track header version ${version}.`);
|
|
6845
6935
|
}
|
|
6846
6936
|
slice.skip(2 * 4 + 2 + 2 + 2 + 2);
|
|
6847
|
-
const
|
|
6848
|
-
|
|
6849
|
-
readFixed_16_16(slice),
|
|
6850
|
-
readFixed_2_30(slice),
|
|
6851
|
-
readFixed_16_16(slice),
|
|
6852
|
-
readFixed_16_16(slice),
|
|
6853
|
-
readFixed_2_30(slice),
|
|
6854
|
-
readFixed_16_16(slice),
|
|
6855
|
-
readFixed_16_16(slice),
|
|
6856
|
-
readFixed_2_30(slice)
|
|
6857
|
-
];
|
|
6858
|
-
const rotation = normalizeRotation(roundToMultiple(extractRotationFromMatrix(matrix), 90));
|
|
6859
|
-
assert(rotation === 0 || rotation === 90 || rotation === 180 || rotation === 270);
|
|
6860
|
-
track.rotation = rotation;
|
|
6937
|
+
const trackMatrix = readMatrix(slice);
|
|
6938
|
+
track.matrix = multiplyMatrices(trackMatrix, this.movieMatrix);
|
|
6861
6939
|
}
|
|
6862
6940
|
;
|
|
6863
6941
|
break;
|
|
@@ -7413,6 +7491,20 @@ var Mediabunny = (() => {
|
|
|
7413
7491
|
}
|
|
7414
7492
|
;
|
|
7415
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;
|
|
7416
7508
|
case "wave":
|
|
7417
7509
|
{
|
|
7418
7510
|
this.readContiguousBoxes(slice.slice(contentStartPos, boxInfo.contentSize));
|
|
@@ -8631,10 +8723,10 @@ var Mediabunny = (() => {
|
|
|
8631
8723
|
return 1n;
|
|
8632
8724
|
}
|
|
8633
8725
|
getBitrate() {
|
|
8634
|
-
return
|
|
8726
|
+
return this.internalTrack.maxBitrate;
|
|
8635
8727
|
}
|
|
8636
8728
|
getAverageBitrate() {
|
|
8637
|
-
return
|
|
8729
|
+
return this.internalTrack.avgBitrate;
|
|
8638
8730
|
}
|
|
8639
8731
|
async getDurationFromMetadata() {
|
|
8640
8732
|
const track = this.internalTrack;
|
|
@@ -9027,8 +9119,8 @@ var Mediabunny = (() => {
|
|
|
9027
9119
|
getSquarePixelHeight() {
|
|
9028
9120
|
return this.internalTrack.info.squarePixelHeight;
|
|
9029
9121
|
}
|
|
9030
|
-
|
|
9031
|
-
return this.internalTrack.
|
|
9122
|
+
getTransformationMatrix() {
|
|
9123
|
+
return [...this.internalTrack.matrix];
|
|
9032
9124
|
}
|
|
9033
9125
|
async getColorSpace() {
|
|
9034
9126
|
const decoderConfig = await this.getDecoderConfig();
|
|
@@ -9267,13 +9359,18 @@ var Mediabunny = (() => {
|
|
|
9267
9359
|
entry.presentationTimestamp += timestamp;
|
|
9268
9360
|
}
|
|
9269
9361
|
};
|
|
9270
|
-
var
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
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
|
+
];
|
|
9277
9374
|
};
|
|
9278
9375
|
var sampleTableIsEmpty = (sampleTable) => {
|
|
9279
9376
|
return sampleTable.sampleSizes.length === 0;
|
|
@@ -10750,6 +10847,8 @@ var Mediabunny = (() => {
|
|
|
10750
10847
|
displayUnit: null,
|
|
10751
10848
|
squarePixelWidth: -1,
|
|
10752
10849
|
squarePixelHeight: -1,
|
|
10850
|
+
horizontalScale: 1,
|
|
10851
|
+
verticalScale: 1,
|
|
10753
10852
|
rotation: 0,
|
|
10754
10853
|
codec: null,
|
|
10755
10854
|
codecDescription: null,
|
|
@@ -10979,6 +11078,32 @@ var Mediabunny = (() => {
|
|
|
10979
11078
|
}
|
|
10980
11079
|
;
|
|
10981
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;
|
|
10982
11107
|
case 30325 /* ProjectionPoseRoll */:
|
|
10983
11108
|
{
|
|
10984
11109
|
if (this.currentTrack?.info?.type !== "video") break;
|
|
@@ -11955,8 +12080,13 @@ var Mediabunny = (() => {
|
|
|
11955
12080
|
getSquarePixelHeight() {
|
|
11956
12081
|
return this.internalTrack.info.squarePixelHeight;
|
|
11957
12082
|
}
|
|
11958
|
-
|
|
11959
|
-
|
|
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);
|
|
11960
12090
|
}
|
|
11961
12091
|
async getColorSpace() {
|
|
11962
12092
|
const decoderConfig = await this.getDecoderConfig();
|
|
@@ -15934,8 +16064,8 @@ var Mediabunny = (() => {
|
|
|
15934
16064
|
getSquarePixelHeight() {
|
|
15935
16065
|
return this.elementaryStream.info.squarePixelHeight;
|
|
15936
16066
|
}
|
|
15937
|
-
|
|
15938
|
-
return
|
|
16067
|
+
getTransformationMatrix() {
|
|
16068
|
+
return [...IDENTITY_MATRIX];
|
|
15939
16069
|
}
|
|
15940
16070
|
async getColorSpace() {
|
|
15941
16071
|
return this.elementaryStream.info.colorSpace;
|
|
@@ -16988,8 +17118,8 @@ var Mediabunny = (() => {
|
|
|
16988
17118
|
getSquarePixelHeight() {
|
|
16989
17119
|
return this.delegate(() => this.firstInputTrack._backing.getSquarePixelHeight());
|
|
16990
17120
|
}
|
|
16991
|
-
|
|
16992
|
-
return this.delegate(() => this.firstInputTrack._backing.
|
|
17121
|
+
getTransformationMatrix() {
|
|
17122
|
+
return this.delegate(() => this.firstInputTrack._backing.getTransformationMatrix());
|
|
16993
17123
|
}
|
|
16994
17124
|
async getColorSpace() {
|
|
16995
17125
|
return this.delegate(() => this.firstInputTrack._backing.getColorSpace());
|
|
@@ -17579,7 +17709,7 @@ var Mediabunny = (() => {
|
|
|
17579
17709
|
this.rootPath = response.url;
|
|
17580
17710
|
}
|
|
17581
17711
|
outer:
|
|
17582
|
-
if (this._orchestrator.fileSize === null && (response.status === 206 || response.type === "basic"
|
|
17712
|
+
if (this._orchestrator.fileSize === null && !response.headers.has("Content-Encoding") && (response.status === 206 || response.type === "basic")) {
|
|
17583
17713
|
const contentRange = response.headers.get("Content-Range");
|
|
17584
17714
|
if (contentRange) {
|
|
17585
17715
|
const match = /\/(\d+)/.exec(contentRange);
|
|
@@ -19022,10 +19152,11 @@ var Mediabunny = (() => {
|
|
|
19022
19152
|
throw new Error(`Unsupported IV format '${ivString}'.`);
|
|
19023
19153
|
}
|
|
19024
19154
|
let hex = ivString.slice(2);
|
|
19025
|
-
hex = hex.padStart(
|
|
19155
|
+
hex = hex.padStart(2 * AES_128_BLOCK_SIZE, "0");
|
|
19156
|
+
hex = hex.slice(-2 * AES_128_BLOCK_SIZE);
|
|
19026
19157
|
iv = new Uint8Array(AES_128_BLOCK_SIZE);
|
|
19027
19158
|
for (let i2 = 0; i2 < AES_128_BLOCK_SIZE; i2++) {
|
|
19028
|
-
const startIndex =
|
|
19159
|
+
const startIndex = 2 * i2;
|
|
19029
19160
|
iv[i2] = parseInt(hex.slice(startIndex, startIndex + 2), 16);
|
|
19030
19161
|
}
|
|
19031
19162
|
}
|
|
@@ -19931,8 +20062,8 @@ var Mediabunny = (() => {
|
|
|
19931
20062
|
}
|
|
19932
20063
|
return this.internalTrack.info.height;
|
|
19933
20064
|
}
|
|
19934
|
-
|
|
19935
|
-
return this.delegate(() => this.backingVideoTrack.
|
|
20065
|
+
getTransformationMatrix() {
|
|
20066
|
+
return this.delegate(() => this.backingVideoTrack.getTransformationMatrix());
|
|
19936
20067
|
}
|
|
19937
20068
|
async getColorSpace() {
|
|
19938
20069
|
await this.hydrate();
|
|
@@ -20732,6 +20863,9 @@ var Mediabunny = (() => {
|
|
|
20732
20863
|
if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20733
20864
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20734
20865
|
}
|
|
20866
|
+
if (init.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
20867
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
20868
|
+
}
|
|
20735
20869
|
if (!Number.isFinite(init.timestamp)) {
|
|
20736
20870
|
throw new TypeError("init.timestamp must be a number.");
|
|
20737
20871
|
}
|
|
@@ -20770,6 +20904,7 @@ var Mediabunny = (() => {
|
|
|
20770
20904
|
}
|
|
20771
20905
|
this.format = init.format;
|
|
20772
20906
|
this.rotation = init.rotation ?? 0;
|
|
20907
|
+
this.flip = init.flip ?? false;
|
|
20773
20908
|
this.timestamp = init.timestamp;
|
|
20774
20909
|
this.duration = init.duration ?? 0;
|
|
20775
20910
|
const layout = init.layout ?? createDefaultPlaneLayout(init.format, init.codedWidth, init.codedHeight);
|
|
@@ -20811,6 +20946,9 @@ var Mediabunny = (() => {
|
|
|
20811
20946
|
if (init?.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20812
20947
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20813
20948
|
}
|
|
20949
|
+
if (init?.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
20950
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
20951
|
+
}
|
|
20814
20952
|
if (init?.timestamp !== void 0 && !Number.isFinite(init?.timestamp)) {
|
|
20815
20953
|
throw new TypeError("init.timestamp, when provided, must be a number.");
|
|
20816
20954
|
}
|
|
@@ -20830,6 +20968,7 @@ var Mediabunny = (() => {
|
|
|
20830
20968
|
height: data.visibleRect?.height ?? data.codedHeight
|
|
20831
20969
|
};
|
|
20832
20970
|
this.rotation = init?.rotation ?? 0;
|
|
20971
|
+
this.flip = init?.flip ?? false;
|
|
20833
20972
|
this.squarePixelWidth = data.displayWidth;
|
|
20834
20973
|
this.squarePixelHeight = data.displayHeight;
|
|
20835
20974
|
this.timestamp = init?.timestamp ?? data.timestamp / 1e6;
|
|
@@ -20842,6 +20981,9 @@ var Mediabunny = (() => {
|
|
|
20842
20981
|
if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20843
20982
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20844
20983
|
}
|
|
20984
|
+
if (init.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
20985
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
20986
|
+
}
|
|
20845
20987
|
if (!Number.isFinite(init.timestamp)) {
|
|
20846
20988
|
throw new TypeError("init.timestamp must be a number.");
|
|
20847
20989
|
}
|
|
@@ -20903,6 +21045,7 @@ var Mediabunny = (() => {
|
|
|
20903
21045
|
this.squarePixelWidth = visibleRect.width;
|
|
20904
21046
|
this.squarePixelHeight = visibleRect.height;
|
|
20905
21047
|
this.rotation = init.rotation ?? 0;
|
|
21048
|
+
this.flip = init.flip ?? false;
|
|
20906
21049
|
this.timestamp = init.timestamp;
|
|
20907
21050
|
this.duration = init.duration ?? 0;
|
|
20908
21051
|
this.colorSpace = new VideoSampleColorSpace({
|
|
@@ -20918,6 +21061,9 @@ var Mediabunny = (() => {
|
|
|
20918
21061
|
if (init.rotation !== void 0 && ![0, 90, 180, 270].includes(init.rotation)) {
|
|
20919
21062
|
throw new TypeError("init.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
20920
21063
|
}
|
|
21064
|
+
if (init.flip !== void 0 && typeof init.flip !== "boolean") {
|
|
21065
|
+
throw new TypeError("init.flip, when provided, must be a boolean.");
|
|
21066
|
+
}
|
|
20921
21067
|
if (!Number.isFinite(init.timestamp)) {
|
|
20922
21068
|
throw new TypeError("init.timestamp must be a number.");
|
|
20923
21069
|
}
|
|
@@ -20951,6 +21097,7 @@ var Mediabunny = (() => {
|
|
|
20951
21097
|
throw new TypeError("getSquarePixelHeight() must return a positive integer.");
|
|
20952
21098
|
}
|
|
20953
21099
|
this.rotation = init.rotation ?? 0;
|
|
21100
|
+
this.flip = init.flip ?? false;
|
|
20954
21101
|
this.timestamp = init.timestamp;
|
|
20955
21102
|
this.duration = init.duration ?? 0;
|
|
20956
21103
|
this.colorSpace = data.getColorSpace();
|
|
@@ -20974,11 +21121,11 @@ var Mediabunny = (() => {
|
|
|
20974
21121
|
get codedHeight() {
|
|
20975
21122
|
return this.visibleRect.height;
|
|
20976
21123
|
}
|
|
20977
|
-
/** 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. */
|
|
20978
21125
|
get displayWidth() {
|
|
20979
21126
|
return this.rotation % 180 === 0 ? this.squarePixelWidth : this.squarePixelHeight;
|
|
20980
21127
|
}
|
|
20981
|
-
/** 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. */
|
|
20982
21129
|
get displayHeight() {
|
|
20983
21130
|
return this.rotation % 180 === 0 ? this.squarePixelHeight : this.squarePixelWidth;
|
|
20984
21131
|
}
|
|
@@ -21008,6 +21155,7 @@ var Mediabunny = (() => {
|
|
|
21008
21155
|
timestamp: this.timestamp,
|
|
21009
21156
|
duration: this.duration,
|
|
21010
21157
|
rotation: this.rotation,
|
|
21158
|
+
flip: this.flip,
|
|
21011
21159
|
encodeOptions: this.encodeOptions
|
|
21012
21160
|
});
|
|
21013
21161
|
} else if (isVideoFrame(this._data)) {
|
|
@@ -21015,6 +21163,7 @@ var Mediabunny = (() => {
|
|
|
21015
21163
|
timestamp: this.timestamp,
|
|
21016
21164
|
duration: this.duration,
|
|
21017
21165
|
rotation: this.rotation,
|
|
21166
|
+
flip: this.flip,
|
|
21018
21167
|
encodeOptions: this.encodeOptions
|
|
21019
21168
|
});
|
|
21020
21169
|
} else if (this._data instanceof Uint8Array) {
|
|
@@ -21028,6 +21177,7 @@ var Mediabunny = (() => {
|
|
|
21028
21177
|
duration: this.duration,
|
|
21029
21178
|
colorSpace: this.colorSpace,
|
|
21030
21179
|
rotation: this.rotation,
|
|
21180
|
+
flip: this.flip,
|
|
21031
21181
|
visibleRect: this.visibleRect,
|
|
21032
21182
|
displayWidth: this.displayWidth,
|
|
21033
21183
|
displayHeight: this.displayHeight,
|
|
@@ -21044,6 +21194,7 @@ var Mediabunny = (() => {
|
|
|
21044
21194
|
duration: this.duration,
|
|
21045
21195
|
colorSpace: this.colorSpace,
|
|
21046
21196
|
rotation: this.rotation,
|
|
21197
|
+
flip: this.flip,
|
|
21047
21198
|
visibleRect: this.visibleRect,
|
|
21048
21199
|
displayWidth: this.displayWidth,
|
|
21049
21200
|
displayHeight: this.displayHeight,
|
|
@@ -21116,7 +21267,8 @@ var Mediabunny = (() => {
|
|
|
21116
21267
|
{
|
|
21117
21268
|
timestamp: this.timestamp,
|
|
21118
21269
|
duration: this.duration,
|
|
21119
|
-
rotation: this.rotation
|
|
21270
|
+
rotation: this.rotation,
|
|
21271
|
+
flip: this.flip
|
|
21120
21272
|
},
|
|
21121
21273
|
options.colorSpace ?? "srgb"
|
|
21122
21274
|
));
|
|
@@ -21372,12 +21524,15 @@ var Mediabunny = (() => {
|
|
|
21372
21524
|
if (this._closed) {
|
|
21373
21525
|
throw new Error("VideoSample is closed.");
|
|
21374
21526
|
}
|
|
21375
|
-
({ sx, sy, sWidth, sHeight } = this.
|
|
21527
|
+
({ sx, sy, sWidth, sHeight } = this._unmapSourceRegion(sx, sy, sWidth, sHeight, this.rotation, this.flip));
|
|
21376
21528
|
const source = this.toCanvasImageSource();
|
|
21377
21529
|
context.save();
|
|
21378
21530
|
const centerX = dx + dWidth / 2;
|
|
21379
21531
|
const centerY = dy + dHeight / 2;
|
|
21380
21532
|
context.translate(centerX, centerY);
|
|
21533
|
+
if (this.flip) {
|
|
21534
|
+
context.scale(-1, 1);
|
|
21535
|
+
}
|
|
21381
21536
|
context.rotate(this.rotation * Math.PI / 180);
|
|
21382
21537
|
const aspectRatioChange = this.rotation % 180 === 0 ? 1 : dWidth / dHeight;
|
|
21383
21538
|
context.scale(1 / aspectRatioChange, aspectRatioChange);
|
|
@@ -21410,12 +21565,16 @@ var Mediabunny = (() => {
|
|
|
21410
21565
|
if (options.rotation !== void 0 && ![0, 90, 180, 270].includes(options.rotation)) {
|
|
21411
21566
|
throw new TypeError("options.rotation, when provided, must be 0, 90, 180, or 270.");
|
|
21412
21567
|
}
|
|
21568
|
+
if (options.flip !== void 0 && typeof options.flip !== "boolean") {
|
|
21569
|
+
throw new TypeError("options.flip, when provided, must be a boolean.");
|
|
21570
|
+
}
|
|
21413
21571
|
if (options.crop !== void 0) {
|
|
21414
21572
|
validateCropRectangle(options.crop, "options.");
|
|
21415
21573
|
}
|
|
21416
21574
|
const canvasWidth = context.canvas.width;
|
|
21417
21575
|
const canvasHeight = context.canvas.height;
|
|
21418
21576
|
const rotation = options.rotation ?? this.rotation;
|
|
21577
|
+
const flip = options.flip ?? this.flip;
|
|
21419
21578
|
const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [this.squarePixelWidth, this.squarePixelHeight] : [this.squarePixelHeight, this.squarePixelWidth];
|
|
21420
21579
|
let finalCrop = options.crop;
|
|
21421
21580
|
if (finalCrop) {
|
|
@@ -21425,12 +21584,13 @@ var Mediabunny = (() => {
|
|
|
21425
21584
|
let dy;
|
|
21426
21585
|
let newWidth;
|
|
21427
21586
|
let newHeight;
|
|
21428
|
-
const { sx, sy, sWidth, sHeight } = this.
|
|
21587
|
+
const { sx, sy, sWidth, sHeight } = this._unmapSourceRegion(
|
|
21429
21588
|
options.crop?.left ?? 0,
|
|
21430
21589
|
options.crop?.top ?? 0,
|
|
21431
21590
|
options.crop?.width ?? rotatedWidth,
|
|
21432
21591
|
options.crop?.height ?? rotatedHeight,
|
|
21433
|
-
rotation
|
|
21592
|
+
rotation,
|
|
21593
|
+
flip
|
|
21434
21594
|
);
|
|
21435
21595
|
if (options.fit === "fill") {
|
|
21436
21596
|
dx = 0;
|
|
@@ -21448,6 +21608,9 @@ var Mediabunny = (() => {
|
|
|
21448
21608
|
context.save();
|
|
21449
21609
|
const aspectRatioChange = rotation % 180 === 0 ? 1 : newWidth / newHeight;
|
|
21450
21610
|
context.translate(canvasWidth / 2, canvasHeight / 2);
|
|
21611
|
+
if (flip) {
|
|
21612
|
+
context.scale(-1, 1);
|
|
21613
|
+
}
|
|
21451
21614
|
context.rotate(rotation * Math.PI / 180);
|
|
21452
21615
|
context.scale(1 / aspectRatioChange, aspectRatioChange);
|
|
21453
21616
|
context.translate(-canvasWidth / 2, -canvasHeight / 2);
|
|
@@ -21455,7 +21618,11 @@ var Mediabunny = (() => {
|
|
|
21455
21618
|
context.restore();
|
|
21456
21619
|
}
|
|
21457
21620
|
/** @internal */
|
|
21458
|
-
|
|
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
|
+
}
|
|
21459
21626
|
if (rotation === 90) {
|
|
21460
21627
|
[sx, sy, sWidth, sHeight] = [
|
|
21461
21628
|
sy,
|
|
@@ -21507,6 +21674,7 @@ var Mediabunny = (() => {
|
|
|
21507
21674
|
this.drawWithFit(context, {
|
|
21508
21675
|
fit: options.fit,
|
|
21509
21676
|
rotation: options.rotation,
|
|
21677
|
+
flip: options.flip,
|
|
21510
21678
|
crop: options.crop
|
|
21511
21679
|
});
|
|
21512
21680
|
context.globalCompositeOperation = "copy";
|
|
@@ -21554,8 +21722,8 @@ var Mediabunny = (() => {
|
|
|
21554
21722
|
}
|
|
21555
21723
|
}
|
|
21556
21724
|
/**
|
|
21557
|
-
* Transform this video sample to a new video sample given the options. Can be used to resize, rotate, and
|
|
21558
|
-
* 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.
|
|
21559
21727
|
*
|
|
21560
21728
|
* In non-browser environments, this method will not work by default. To make it work, register a custom
|
|
21561
21729
|
* transformer function via {@link registerVideoSampleTransformer}.
|
|
@@ -21584,13 +21752,21 @@ var Mediabunny = (() => {
|
|
|
21584
21752
|
if (options.rotate !== void 0 && ![0, 90, 180, 270].includes(options.rotate)) {
|
|
21585
21753
|
throw new TypeError("options.rotate, when provided, must be 0, 90, 180 or 270.");
|
|
21586
21754
|
}
|
|
21755
|
+
if (options.flip !== void 0 && typeof options.flip !== "boolean") {
|
|
21756
|
+
throw new TypeError("options.flip, when provided, must be a boolean.");
|
|
21757
|
+
}
|
|
21587
21758
|
if (options.crop !== void 0) {
|
|
21588
21759
|
validateCropRectangle(options.crop, "options.");
|
|
21589
21760
|
}
|
|
21590
21761
|
if (options.alpha !== void 0 && !["keep", "discard"].includes(options.alpha)) {
|
|
21591
21762
|
throw new TypeError("options.alpha, when provided, must be 'keep' or 'discard'.");
|
|
21592
21763
|
}
|
|
21593
|
-
const rotation
|
|
21764
|
+
const { rotation, flip } = composeRotationAndFlip(
|
|
21765
|
+
this.rotation,
|
|
21766
|
+
this.flip,
|
|
21767
|
+
options.rotate ?? 0,
|
|
21768
|
+
options.flip ?? false
|
|
21769
|
+
);
|
|
21594
21770
|
const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [this.squarePixelWidth, this.squarePixelHeight] : [this.squarePixelHeight, this.squarePixelWidth];
|
|
21595
21771
|
let finalCrop = options.crop;
|
|
21596
21772
|
if (finalCrop) {
|
|
@@ -21621,6 +21797,7 @@ var Mediabunny = (() => {
|
|
|
21621
21797
|
height: targetHeight,
|
|
21622
21798
|
fit: options.fit ?? "fill",
|
|
21623
21799
|
rotation,
|
|
21800
|
+
flip,
|
|
21624
21801
|
crop: finalCrop ?? {
|
|
21625
21802
|
left: 0,
|
|
21626
21803
|
top: 0,
|
|
@@ -21640,6 +21817,7 @@ var Mediabunny = (() => {
|
|
|
21640
21817
|
this._drawWithFitAndMipmapping(canvas, context, {
|
|
21641
21818
|
fit: description.fit,
|
|
21642
21819
|
rotation: description.rotation,
|
|
21820
|
+
flip: description.flip,
|
|
21643
21821
|
crop: description.crop,
|
|
21644
21822
|
targetIsFresh: isNew,
|
|
21645
21823
|
fillBlack: description.alpha === "discard"
|
|
@@ -21647,8 +21825,9 @@ var Mediabunny = (() => {
|
|
|
21647
21825
|
return new _VideoSample(canvas, {
|
|
21648
21826
|
timestamp: this.timestamp,
|
|
21649
21827
|
duration: this.duration,
|
|
21650
|
-
rotation
|
|
21651
|
-
|
|
21828
|
+
// Any previous rotation and flip are now baked in
|
|
21829
|
+
rotation: 0,
|
|
21830
|
+
flip: false
|
|
21652
21831
|
});
|
|
21653
21832
|
}
|
|
21654
21833
|
/** Sets the rotation metadata of this video sample. */
|
|
@@ -21658,6 +21837,13 @@ var Mediabunny = (() => {
|
|
|
21658
21837
|
}
|
|
21659
21838
|
this.rotation = newRotation;
|
|
21660
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
|
+
}
|
|
21661
21847
|
/** Sets the presentation timestamp of this video sample, in seconds. */
|
|
21662
21848
|
setTimestamp(newTimestamp) {
|
|
21663
21849
|
if (!Number.isFinite(newTimestamp)) {
|
|
@@ -22853,6 +23039,9 @@ var Mediabunny = (() => {
|
|
|
22853
23039
|
if (config.transform.rotate !== void 0 && ![0, 90, 180, 270].includes(config.transform.rotate)) {
|
|
22854
23040
|
throw new TypeError("config.transform.rotate, when provided, must be 0, 90, 180 or 270.");
|
|
22855
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
|
+
}
|
|
22856
23045
|
if (config.transform.crop !== void 0) {
|
|
22857
23046
|
validateCropRectangle(config.transform.crop, "config.transform.");
|
|
22858
23047
|
}
|
|
@@ -23284,6 +23473,7 @@ var Mediabunny = (() => {
|
|
|
23284
23473
|
quality,
|
|
23285
23474
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
23286
23475
|
bitrate,
|
|
23476
|
+
frameRate,
|
|
23287
23477
|
...restOptions
|
|
23288
23478
|
} = options;
|
|
23289
23479
|
if (!VIDEO_CODECS.includes(codec)) {
|
|
@@ -23304,6 +23494,9 @@ var Mediabunny = (() => {
|
|
|
23304
23494
|
if (bitrate !== void 0 && !(bitrate instanceof Quality) && (!Number.isInteger(bitrate) || bitrate <= 0)) {
|
|
23305
23495
|
throw new TypeError("bitrate must be a positive integer or a quality.");
|
|
23306
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
|
+
}
|
|
23307
23500
|
validateVideoEncodingAdditionalOptions(codec, restOptions);
|
|
23308
23501
|
const resolvedQuality = resolveQuality(quality, bitrate) ?? new Quality("medium");
|
|
23309
23502
|
let candidates;
|
|
@@ -23313,7 +23506,7 @@ var Mediabunny = (() => {
|
|
|
23313
23506
|
width,
|
|
23314
23507
|
height,
|
|
23315
23508
|
quality: resolvedQuality,
|
|
23316
|
-
framerate:
|
|
23509
|
+
framerate: frameRate,
|
|
23317
23510
|
...restOptions,
|
|
23318
23511
|
alpha: "discard"
|
|
23319
23512
|
// Since we handle alpha ourselves
|
|
@@ -24237,11 +24430,12 @@ var Mediabunny = (() => {
|
|
|
24237
24430
|
return decodedSampleQueueSize === 0 ? 40 : 8;
|
|
24238
24431
|
};
|
|
24239
24432
|
var VideoDecoderWrapper = class extends DecoderWrapper {
|
|
24240
|
-
constructor(onSample, onError, codec, decoderConfig, rotation, timeResolution) {
|
|
24433
|
+
constructor(onSample, onError, codec, decoderConfig, rotation, flip, timeResolution) {
|
|
24241
24434
|
super(onSample, onError);
|
|
24242
24435
|
this.codec = codec;
|
|
24243
24436
|
this.decoderConfig = decoderConfig;
|
|
24244
24437
|
this.rotation = rotation;
|
|
24438
|
+
this.flip = flip;
|
|
24245
24439
|
this.timeResolution = timeResolution;
|
|
24246
24440
|
this.decoder = null;
|
|
24247
24441
|
this.customDecoder = null;
|
|
@@ -24526,6 +24720,7 @@ var Mediabunny = (() => {
|
|
|
24526
24720
|
sample.setTimestamp(Math.round(sample.timestamp * this.timeResolution) / this.timeResolution);
|
|
24527
24721
|
sample.setDuration(Math.round(sample.duration * this.timeResolution) / this.timeResolution);
|
|
24528
24722
|
sample.setRotation(this.rotation);
|
|
24723
|
+
sample.setFlip(this.flip);
|
|
24529
24724
|
this.onSample(sample);
|
|
24530
24725
|
}
|
|
24531
24726
|
async mergeAlpha(color, alpha) {
|
|
@@ -24860,6 +25055,7 @@ var Mediabunny = (() => {
|
|
|
24860
25055
|
}
|
|
24861
25056
|
const codec = await this._track.getCodec();
|
|
24862
25057
|
const rotation = await this._track.getRotation();
|
|
25058
|
+
const flip = await this._track.getFlip();
|
|
24863
25059
|
let decoderConfig = await this._track.getDecoderConfig();
|
|
24864
25060
|
const timeResolution = await this._track.getTimeResolution();
|
|
24865
25061
|
assert(codec && decoderConfig);
|
|
@@ -24868,7 +25064,7 @@ var Mediabunny = (() => {
|
|
|
24868
25064
|
hardwareAcceleration: this._decoderOptions.hardwareAcceleration,
|
|
24869
25065
|
optimizeForLatency: this._decoderOptions.optimizeForLatency
|
|
24870
25066
|
};
|
|
24871
|
-
return new VideoDecoderWrapper(onSample, onError, codec, decoderConfig, rotation, timeResolution);
|
|
25067
|
+
return new VideoDecoderWrapper(onSample, onError, codec, decoderConfig, rotation, flip, timeResolution);
|
|
24872
25068
|
}
|
|
24873
25069
|
/** @internal */
|
|
24874
25070
|
_createPacketSink() {
|
|
@@ -24922,6 +25118,8 @@ var Mediabunny = (() => {
|
|
|
24922
25118
|
/** @internal */
|
|
24923
25119
|
this._rotation = 0;
|
|
24924
25120
|
/** @internal */
|
|
25121
|
+
this._flip = false;
|
|
25122
|
+
/** @internal */
|
|
24925
25123
|
this._initPromise = null;
|
|
24926
25124
|
/** @internal */
|
|
24927
25125
|
this._nextCanvasIndex = 0;
|
|
@@ -24951,6 +25149,9 @@ var Mediabunny = (() => {
|
|
|
24951
25149
|
if (options.rotation !== void 0 && ![0, 90, 180, 270].includes(options.rotation)) {
|
|
24952
25150
|
throw new TypeError("options.rotation, when provided, must be 0, 90, 180 or 270.");
|
|
24953
25151
|
}
|
|
25152
|
+
if (options.flip !== void 0 && typeof options.flip !== "boolean") {
|
|
25153
|
+
throw new TypeError("options.flip, when provided, must be a boolean.");
|
|
25154
|
+
}
|
|
24954
25155
|
if (options.crop !== void 0) {
|
|
24955
25156
|
validateCropRectangle(options.crop, "options.");
|
|
24956
25157
|
}
|
|
@@ -24973,6 +25174,7 @@ var Mediabunny = (() => {
|
|
|
24973
25174
|
const options = this._options;
|
|
24974
25175
|
const videoTrack = this._videoTrack;
|
|
24975
25176
|
const rotation = options.rotation ?? await videoTrack.getRotation();
|
|
25177
|
+
const flip = options.flip ?? await videoTrack.getFlip();
|
|
24976
25178
|
const squarePixelWidth = await videoTrack.getSquarePixelWidth();
|
|
24977
25179
|
const squarePixelHeight = await videoTrack.getSquarePixelHeight();
|
|
24978
25180
|
const [rotatedWidth, rotatedHeight] = rotation % 180 === 0 ? [squarePixelWidth, squarePixelHeight] : [squarePixelHeight, squarePixelWidth];
|
|
@@ -24995,6 +25197,7 @@ var Mediabunny = (() => {
|
|
|
24995
25197
|
this._width = width;
|
|
24996
25198
|
this._height = height;
|
|
24997
25199
|
this._rotation = rotation;
|
|
25200
|
+
this._flip = flip;
|
|
24998
25201
|
this._crop = crop;
|
|
24999
25202
|
})();
|
|
25000
25203
|
}
|
|
@@ -25028,6 +25231,7 @@ var Mediabunny = (() => {
|
|
|
25028
25231
|
sample._drawWithFitAndMipmapping(canvas, context, {
|
|
25029
25232
|
fit: this._fit,
|
|
25030
25233
|
rotation: this._rotation,
|
|
25234
|
+
flip: this._flip,
|
|
25031
25235
|
crop: this._crop,
|
|
25032
25236
|
targetIsFresh: canvasIsNew,
|
|
25033
25237
|
fillBlack: !this._alpha && isFirefox()
|
|
@@ -25893,16 +26097,38 @@ var Mediabunny = (() => {
|
|
|
25893
26097
|
get codedHeight() {
|
|
25894
26098
|
return requireSync(this._backing.getCodedHeight(), "codedHeight", "getCodedHeight");
|
|
25895
26099
|
}
|
|
25896
|
-
/**
|
|
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
|
+
*/
|
|
25897
26115
|
async getRotation() {
|
|
25898
|
-
return this._backing.
|
|
26116
|
+
return extractRotationFromMatrix(await this._backing.getTransformationMatrix());
|
|
25899
26117
|
}
|
|
25900
26118
|
/**
|
|
25901
26119
|
* The angle in degrees by which the track's frames should be rotated (clockwise).
|
|
25902
26120
|
* @deprecated Use {@link InputVideoTrack.getRotation} instead.
|
|
25903
26121
|
*/
|
|
25904
26122
|
get rotation() {
|
|
25905
|
-
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());
|
|
25906
26132
|
}
|
|
25907
26133
|
/**
|
|
25908
26134
|
* Returns the width of the track's frames in square pixels, adjusted for pixel aspect ratio but before rotation.
|
|
@@ -25972,7 +26198,9 @@ var Mediabunny = (() => {
|
|
|
25972
26198
|
return metadata;
|
|
25973
26199
|
}
|
|
25974
26200
|
}
|
|
25975
|
-
const rotation =
|
|
26201
|
+
const rotation = extractRotationFromMatrix(
|
|
26202
|
+
requireSync(this._backing.getTransformationMatrix(), "displayWidth", "getDisplayWidth")
|
|
26203
|
+
);
|
|
25976
26204
|
const value = rotation % 180 === 0 ? this._backing.getSquarePixelWidth() : this._backing.getSquarePixelHeight();
|
|
25977
26205
|
return requireSync(value, "displayWidth", "getDisplayWidth");
|
|
25978
26206
|
}
|
|
@@ -25997,7 +26225,9 @@ var Mediabunny = (() => {
|
|
|
25997
26225
|
return metadata;
|
|
25998
26226
|
}
|
|
25999
26227
|
}
|
|
26000
|
-
const rotation =
|
|
26228
|
+
const rotation = extractRotationFromMatrix(
|
|
26229
|
+
requireSync(this._backing.getTransformationMatrix(), "displayHeight", "getDisplayHeight")
|
|
26230
|
+
);
|
|
26001
26231
|
const value = rotation % 180 === 0 ? this._backing.getSquarePixelHeight() : this._backing.getSquarePixelWidth();
|
|
26002
26232
|
return requireSync(value, "displayHeight", "getDisplayHeight");
|
|
26003
26233
|
}
|
|
@@ -28768,23 +28998,6 @@ var Mediabunny = (() => {
|
|
|
28768
28998
|
if (nullTerminated) bytes2.push(0);
|
|
28769
28999
|
return bytes2;
|
|
28770
29000
|
};
|
|
28771
|
-
var rotationMatrix = (rotationInDegrees) => {
|
|
28772
|
-
const theta = rotationInDegrees * (Math.PI / 180);
|
|
28773
|
-
const cosTheta = Math.round(Math.cos(theta));
|
|
28774
|
-
const sinTheta = Math.round(Math.sin(theta));
|
|
28775
|
-
return [
|
|
28776
|
-
cosTheta,
|
|
28777
|
-
sinTheta,
|
|
28778
|
-
0,
|
|
28779
|
-
-sinTheta,
|
|
28780
|
-
cosTheta,
|
|
28781
|
-
0,
|
|
28782
|
-
0,
|
|
28783
|
-
0,
|
|
28784
|
-
1
|
|
28785
|
-
];
|
|
28786
|
-
};
|
|
28787
|
-
var IDENTITY_MATRIX = /* @__PURE__ */ rotationMatrix(0);
|
|
28788
29001
|
var matrixToBytes = (matrix) => {
|
|
28789
29002
|
return [
|
|
28790
29003
|
fixed_16_16(matrix[0]),
|
|
@@ -28944,26 +29157,6 @@ var Mediabunny = (() => {
|
|
|
28944
29157
|
// Next track ID
|
|
28945
29158
|
]);
|
|
28946
29159
|
};
|
|
28947
|
-
var presentationSpan = (trackData) => {
|
|
28948
|
-
if (trackData.samples.length === 0) {
|
|
28949
|
-
return 0;
|
|
28950
|
-
}
|
|
28951
|
-
let minTimestamp = Infinity;
|
|
28952
|
-
let maxEndTimestamp = -Infinity;
|
|
28953
|
-
for (let i = 0; i < trackData.samples.length; i++) {
|
|
28954
|
-
const sample = trackData.samples[i];
|
|
28955
|
-
if (sample.timestamp < minTimestamp) {
|
|
28956
|
-
minTimestamp = sample.timestamp;
|
|
28957
|
-
}
|
|
28958
|
-
if (sample.timestamp + sample.duration > maxEndTimestamp) {
|
|
28959
|
-
maxEndTimestamp = sample.timestamp + sample.duration;
|
|
28960
|
-
}
|
|
28961
|
-
}
|
|
28962
|
-
if (minTimestamp === Infinity) {
|
|
28963
|
-
return 0;
|
|
28964
|
-
}
|
|
28965
|
-
return maxEndTimestamp - minTimestamp;
|
|
28966
|
-
};
|
|
28967
29160
|
var trak = (trackData, creationTime) => {
|
|
28968
29161
|
const trackMetadata = getTrackMetadata(trackData);
|
|
28969
29162
|
const needsEditList = trackData.startTimestampOffset !== null && trackData.startTimestampOffset !== 0;
|
|
@@ -28987,9 +29180,15 @@ var Mediabunny = (() => {
|
|
|
28987
29180
|
const needsU64 = !isU32(creationTime) || !isU32(durationInGlobalTimescale);
|
|
28988
29181
|
const u32OrU64 = needsU64 ? u64 : u32;
|
|
28989
29182
|
let matrix;
|
|
28990
|
-
if (trackData.type === "video") {
|
|
28991
|
-
|
|
28992
|
-
|
|
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);
|
|
28993
29192
|
} else {
|
|
28994
29193
|
matrix = IDENTITY_MATRIX;
|
|
28995
29194
|
}
|
|
@@ -29248,8 +29447,22 @@ var Mediabunny = (() => {
|
|
|
29248
29447
|
], [
|
|
29249
29448
|
VIDEO_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec]?.(trackData) ?? null,
|
|
29250
29449
|
pasp(trackData),
|
|
29251
|
-
colorSpaceIsEmpty(trackData.info.decoderConfig.colorSpace) ? null : colr(trackData)
|
|
29450
|
+
colorSpaceIsEmpty(trackData.info.decoderConfig.colorSpace) ? null : colr(trackData),
|
|
29451
|
+
btrt(trackData)
|
|
29252
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
|
+
};
|
|
29253
29466
|
var pasp = (trackData) => {
|
|
29254
29467
|
if (trackData.info.pixelAspectRatio.num === trackData.info.pixelAspectRatio.den) {
|
|
29255
29468
|
return null;
|
|
@@ -29403,7 +29616,8 @@ var Mediabunny = (() => {
|
|
|
29403
29616
|
];
|
|
29404
29617
|
}
|
|
29405
29618
|
return box(compressionType, contents, [
|
|
29406
|
-
audioCodecToConfigurationBox(trackData.track.source._codec, trackData.muxer.isQuickTime)?.(trackData) ?? null
|
|
29619
|
+
audioCodecToConfigurationBox(trackData.track.source._codec, trackData.muxer.isQuickTime)?.(trackData) ?? null,
|
|
29620
|
+
btrt(trackData)
|
|
29407
29621
|
]);
|
|
29408
29622
|
};
|
|
29409
29623
|
var esds = (trackData) => {
|
|
@@ -29437,9 +29651,9 @@ var Mediabunny = (() => {
|
|
|
29437
29651
|
// stream type(6bits)=5 audio, flags(2bits)=1
|
|
29438
29652
|
...u24(0),
|
|
29439
29653
|
// 24bit buffer size
|
|
29440
|
-
...u32(
|
|
29654
|
+
...u32(trackData.maxBitrate),
|
|
29441
29655
|
// max bitrate
|
|
29442
|
-
...u32(
|
|
29656
|
+
...u32(trackData.avgBitrate)
|
|
29443
29657
|
// avg bitrate
|
|
29444
29658
|
];
|
|
29445
29659
|
if (trackData.info.decoderConfig.description) {
|
|
@@ -29627,7 +29841,8 @@ var Mediabunny = (() => {
|
|
|
29627
29841
|
u16(1)
|
|
29628
29842
|
// Data reference index
|
|
29629
29843
|
], [
|
|
29630
|
-
SUBTITLE_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData)
|
|
29844
|
+
SUBTITLE_CODEC_TO_CONFIGURATION_BOX[trackData.track.source._codec](trackData),
|
|
29845
|
+
btrt(trackData)
|
|
29631
29846
|
]);
|
|
29632
29847
|
var vttC = (trackData) => box("vttC", [
|
|
29633
29848
|
...textEncoder.encode(trackData.info.config.description)
|
|
@@ -31062,6 +31277,26 @@ var Mediabunny = (() => {
|
|
|
31062
31277
|
const value = timeInSeconds * timescale;
|
|
31063
31278
|
return round ? Math.round(value) : value;
|
|
31064
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
|
+
};
|
|
31065
31300
|
var IsobmffMuxer2 = class extends Muxer {
|
|
31066
31301
|
constructor(output, format) {
|
|
31067
31302
|
super(output);
|
|
@@ -31275,7 +31510,9 @@ var Mediabunny = (() => {
|
|
|
31275
31510
|
finalizedChunks: [],
|
|
31276
31511
|
currentChunk: null,
|
|
31277
31512
|
compactlyCodedChunkTable: [],
|
|
31278
|
-
closed: false
|
|
31513
|
+
closed: false,
|
|
31514
|
+
avgBitrate: track.source._nominalBitrate ?? track.metadata.averageBitrate ?? 0,
|
|
31515
|
+
maxBitrate: track.source._nominalBitrate ?? track.metadata.bitrate ?? 0
|
|
31279
31516
|
};
|
|
31280
31517
|
this.trackDatas.push(newTrackData);
|
|
31281
31518
|
this.trackDatas.sort((a, b) => a.track.id - b.track.id);
|
|
@@ -31349,7 +31586,9 @@ var Mediabunny = (() => {
|
|
|
31349
31586
|
finalizedChunks: [],
|
|
31350
31587
|
currentChunk: null,
|
|
31351
31588
|
compactlyCodedChunkTable: [],
|
|
31352
|
-
closed: false
|
|
31589
|
+
closed: false,
|
|
31590
|
+
avgBitrate: track.source._nominalBitrate ?? track.metadata.averageBitrate ?? 0,
|
|
31591
|
+
maxBitrate: track.source._nominalBitrate ?? track.metadata.bitrate ?? 0
|
|
31353
31592
|
};
|
|
31354
31593
|
this.trackDatas.push(newTrackData);
|
|
31355
31594
|
this.trackDatas.sort((a, b) => a.track.id - b.track.id);
|
|
@@ -31387,6 +31626,8 @@ var Mediabunny = (() => {
|
|
|
31387
31626
|
currentChunk: null,
|
|
31388
31627
|
compactlyCodedChunkTable: [],
|
|
31389
31628
|
closed: false,
|
|
31629
|
+
avgBitrate: track.source._nominalBitrate ?? track.metadata.averageBitrate ?? 0,
|
|
31630
|
+
maxBitrate: track.source._nominalBitrate ?? track.metadata.bitrate ?? 0,
|
|
31390
31631
|
lastCueEndTimestamp: null,
|
|
31391
31632
|
cueQueue: [],
|
|
31392
31633
|
nextSourceId: 0,
|
|
@@ -32052,6 +32293,29 @@ var Mediabunny = (() => {
|
|
|
32052
32293
|
} else {
|
|
32053
32294
|
for (const trackData of this.trackDatas) {
|
|
32054
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;
|
|
32055
32319
|
if (trackData.startTimestampOffset !== null) {
|
|
32056
32320
|
for (let i = 0; i < trackData.samples.length; i++) {
|
|
32057
32321
|
const sample = trackData.samples[i];
|
|
@@ -32350,14 +32614,34 @@ var Mediabunny = (() => {
|
|
|
32350
32614
|
}
|
|
32351
32615
|
}
|
|
32352
32616
|
videoSpecificTrackInfo(trackData) {
|
|
32353
|
-
const { frameRate,
|
|
32617
|
+
const { frameRate, transformationMatrix } = trackData.track.metadata;
|
|
32354
32618
|
const elements = [
|
|
32355
32619
|
frameRate ? {
|
|
32356
32620
|
id: 2352003 /* DefaultDuration */,
|
|
32357
32621
|
data: 1e9 / frameRate
|
|
32358
32622
|
} : null
|
|
32359
32623
|
];
|
|
32360
|
-
|
|
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);
|
|
32361
32645
|
const hasNonSquarePixelAspectRatio = !!trackData.info.aspectRatio && trackData.info.aspectRatio.num * trackData.info.height !== trackData.info.aspectRatio.den * trackData.info.width;
|
|
32362
32646
|
const colorSpace = trackData.info.decoderConfig.colorSpace;
|
|
32363
32647
|
const videoElement = { id: 224 /* Video */, data: [
|
|
@@ -32389,7 +32673,7 @@ var Mediabunny = (() => {
|
|
|
32389
32673
|
}
|
|
32390
32674
|
]
|
|
32391
32675
|
},
|
|
32392
|
-
|
|
32676
|
+
roll || yaw || pitch ? {
|
|
32393
32677
|
id: 30320 /* Projection */,
|
|
32394
32678
|
data: [
|
|
32395
32679
|
{
|
|
@@ -32397,11 +32681,19 @@ var Mediabunny = (() => {
|
|
|
32397
32681
|
data: 0
|
|
32398
32682
|
// rectangular
|
|
32399
32683
|
},
|
|
32400
|
-
{
|
|
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 ? {
|
|
32401
32693
|
id: 30325 /* ProjectionPoseRoll */,
|
|
32402
|
-
data: new EBMLFloat32((
|
|
32694
|
+
data: new EBMLFloat32((roll + 180) % 360 - 180)
|
|
32403
32695
|
// [0, 270] -> [-180, 90]
|
|
32404
|
-
}
|
|
32696
|
+
} : null
|
|
32405
32697
|
]
|
|
32406
32698
|
} : null
|
|
32407
32699
|
] };
|
|
@@ -34848,6 +35140,11 @@ ${cue.notes ?? ""}`;
|
|
|
34848
35140
|
this._closingPromise = null;
|
|
34849
35141
|
/** @internal */
|
|
34850
35142
|
this._closed = false;
|
|
35143
|
+
/**
|
|
35144
|
+
* Set when the encoder is configured with a bitrate.
|
|
35145
|
+
* @internal
|
|
35146
|
+
*/
|
|
35147
|
+
this._nominalBitrate = null;
|
|
34851
35148
|
}
|
|
34852
35149
|
/** @internal */
|
|
34853
35150
|
_ensureValidAdd() {
|
|
@@ -35024,7 +35321,7 @@ ${cue.notes ?? ""}`;
|
|
|
35024
35321
|
this.codedWidth = videoSample.codedWidth;
|
|
35025
35322
|
this.codedHeight = videoSample.codedHeight;
|
|
35026
35323
|
}
|
|
35027
|
-
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;
|
|
35028
35325
|
const needsTransform = hasTransformConfig || isSizeChange && sizeChangeBehavior !== "passThrough";
|
|
35029
35326
|
if (needsTransform) {
|
|
35030
35327
|
let targetWidth = config.transform?.width;
|
|
@@ -35044,6 +35341,7 @@ ${cue.notes ?? ""}`;
|
|
|
35044
35341
|
roundDimensionsTo: 2,
|
|
35045
35342
|
crop: config.transform?.crop,
|
|
35046
35343
|
rotate: config.transform?.rotate,
|
|
35344
|
+
flip: config.transform?.flip,
|
|
35047
35345
|
fit: appliedFit,
|
|
35048
35346
|
alpha: config.alpha
|
|
35049
35347
|
});
|
|
@@ -35338,6 +35636,8 @@ ${cue.notes ?? ""}`;
|
|
|
35338
35636
|
this.encodingConfig.codec,
|
|
35339
35637
|
selected.quantizer
|
|
35340
35638
|
);
|
|
35639
|
+
} else {
|
|
35640
|
+
this.source._nominalBitrate = encoderConfig.bitrate ?? null;
|
|
35341
35641
|
}
|
|
35342
35642
|
if (MatchingCustomEncoder) {
|
|
35343
35643
|
this.customEncoder = new MatchingCustomEncoder();
|
|
@@ -36008,39 +36308,42 @@ ${cue.notes ?? ""}`;
|
|
|
36008
36308
|
}
|
|
36009
36309
|
/** @internal */
|
|
36010
36310
|
async _flushAndClose(forceClose) {
|
|
36011
|
-
|
|
36012
|
-
this._abortController
|
|
36013
|
-
|
|
36014
|
-
|
|
36015
|
-
|
|
36016
|
-
|
|
36017
|
-
|
|
36018
|
-
|
|
36019
|
-
|
|
36020
|
-
this._videoElement
|
|
36021
|
-
|
|
36022
|
-
|
|
36023
|
-
|
|
36024
|
-
|
|
36025
|
-
|
|
36026
|
-
|
|
36027
|
-
|
|
36028
|
-
|
|
36029
|
-
|
|
36030
|
-
|
|
36031
|
-
|
|
36032
|
-
const
|
|
36033
|
-
|
|
36034
|
-
|
|
36035
|
-
|
|
36036
|
-
|
|
36037
|
-
|
|
36038
|
-
|
|
36039
|
-
|
|
36040
|
-
|
|
36041
|
-
|
|
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);
|
|
36042
36346
|
}
|
|
36043
|
-
await this._encoder.flushAndClose(forceClose);
|
|
36044
36347
|
}
|
|
36045
36348
|
};
|
|
36046
36349
|
var AudioSource = class extends MediaSource {
|
|
@@ -36343,6 +36646,7 @@ ${cue.notes ?? ""}`;
|
|
|
36343
36646
|
quality
|
|
36344
36647
|
});
|
|
36345
36648
|
this.encodingConfig.onEncoderConfig?.(encoderConfig);
|
|
36649
|
+
this.source._nominalBitrate = encoderConfig.bitrate ?? null;
|
|
36346
36650
|
const MatchingCustomEncoder = customAudioEncoders.find((x) => x.supports(
|
|
36347
36651
|
this.encodingConfig.codec,
|
|
36348
36652
|
encoderConfig
|
|
@@ -36787,16 +37091,19 @@ ${cue.notes ?? ""}`;
|
|
|
36787
37091
|
}
|
|
36788
37092
|
/** @internal */
|
|
36789
37093
|
async _flushAndClose(forceClose) {
|
|
36790
|
-
|
|
36791
|
-
this._abortController
|
|
36792
|
-
|
|
36793
|
-
|
|
36794
|
-
|
|
36795
|
-
|
|
36796
|
-
|
|
36797
|
-
|
|
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);
|
|
36798
37106
|
}
|
|
36799
|
-
await this._encoder.flushAndClose(forceClose);
|
|
36800
37107
|
}
|
|
36801
37108
|
};
|
|
36802
37109
|
var mediaStreamTrackProcessorWorkerCode = () => {
|
|
@@ -37173,13 +37480,13 @@ ${cue.notes ?? ""}`;
|
|
|
37173
37480
|
const codecs = [];
|
|
37174
37481
|
let videoCount = 0;
|
|
37175
37482
|
let audioCount = 0;
|
|
37176
|
-
let
|
|
37483
|
+
let requiresTransformationMetadata = false;
|
|
37177
37484
|
let candidate = null;
|
|
37178
37485
|
let candidateScore = -Infinity;
|
|
37179
37486
|
for (const track of tracks) {
|
|
37180
37487
|
if (track.isVideoTrack()) {
|
|
37181
37488
|
videoCount++;
|
|
37182
|
-
|
|
37489
|
+
requiresTransformationMetadata ||= (track.metadata.rotation ?? 0) !== 0 || !!track.metadata.flip || !!track.metadata.transformationMatrix;
|
|
37183
37490
|
} else if (track.isAudioTrack()) {
|
|
37184
37491
|
audioCount++;
|
|
37185
37492
|
}
|
|
@@ -37198,7 +37505,7 @@ ${cue.notes ?? ""}`;
|
|
|
37198
37505
|
continue;
|
|
37199
37506
|
}
|
|
37200
37507
|
let score = 0;
|
|
37201
|
-
if (
|
|
37508
|
+
if (requiresTransformationMetadata && format.supportsVideoTransformationMetadata) {
|
|
37202
37509
|
score++;
|
|
37203
37510
|
}
|
|
37204
37511
|
if (score > candidateScore) {
|
|
@@ -38126,6 +38433,13 @@ ${cue.notes ?? ""}`;
|
|
|
38126
38433
|
|
|
38127
38434
|
// src/output-format.ts
|
|
38128
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
|
+
}
|
|
38129
38443
|
/** Returns a list of video codecs that this output format can contain. */
|
|
38130
38444
|
getSupportedVideoCodecs() {
|
|
38131
38445
|
return this.getSupportedCodecs().filter((codec) => VIDEO_CODECS.includes(codec));
|
|
@@ -38191,7 +38505,7 @@ ${cue.notes ?? ""}`;
|
|
|
38191
38505
|
total: { min: 0, max }
|
|
38192
38506
|
};
|
|
38193
38507
|
}
|
|
38194
|
-
get
|
|
38508
|
+
get supportsVideoTransformationMetadata() {
|
|
38195
38509
|
return true;
|
|
38196
38510
|
}
|
|
38197
38511
|
get supportsTimestampedMediaData() {
|
|
@@ -38368,7 +38682,7 @@ ${cue.notes ?? ""}`;
|
|
|
38368
38682
|
...SUBTITLE_CODECS
|
|
38369
38683
|
];
|
|
38370
38684
|
}
|
|
38371
|
-
get
|
|
38685
|
+
get supportsVideoTransformationMetadata() {
|
|
38372
38686
|
return false;
|
|
38373
38687
|
}
|
|
38374
38688
|
get supportsTimestampedMediaData() {
|
|
@@ -38448,7 +38762,7 @@ ${cue.notes ?? ""}`;
|
|
|
38448
38762
|
getSupportedCodecs() {
|
|
38449
38763
|
return ["mp3"];
|
|
38450
38764
|
}
|
|
38451
|
-
get
|
|
38765
|
+
get supportsVideoTransformationMetadata() {
|
|
38452
38766
|
return false;
|
|
38453
38767
|
}
|
|
38454
38768
|
get supportsTimestampedMediaData() {
|
|
@@ -38505,7 +38819,7 @@ ${cue.notes ?? ""}`;
|
|
|
38505
38819
|
)
|
|
38506
38820
|
];
|
|
38507
38821
|
}
|
|
38508
|
-
get
|
|
38822
|
+
get supportsVideoTransformationMetadata() {
|
|
38509
38823
|
return false;
|
|
38510
38824
|
}
|
|
38511
38825
|
get supportsTimestampedMediaData() {
|
|
@@ -38558,7 +38872,7 @@ ${cue.notes ?? ""}`;
|
|
|
38558
38872
|
...AUDIO_CODECS.filter((codec) => ["vorbis", "opus"].includes(codec))
|
|
38559
38873
|
];
|
|
38560
38874
|
}
|
|
38561
|
-
get
|
|
38875
|
+
get supportsVideoTransformationMetadata() {
|
|
38562
38876
|
return false;
|
|
38563
38877
|
}
|
|
38564
38878
|
get supportsTimestampedMediaData() {
|
|
@@ -38605,7 +38919,7 @@ ${cue.notes ?? ""}`;
|
|
|
38605
38919
|
getSupportedCodecs() {
|
|
38606
38920
|
return ["aac"];
|
|
38607
38921
|
}
|
|
38608
|
-
get
|
|
38922
|
+
get supportsVideoTransformationMetadata() {
|
|
38609
38923
|
return false;
|
|
38610
38924
|
}
|
|
38611
38925
|
get supportsTimestampedMediaData() {
|
|
@@ -38652,7 +38966,7 @@ ${cue.notes ?? ""}`;
|
|
|
38652
38966
|
getSupportedCodecs() {
|
|
38653
38967
|
return ["flac"];
|
|
38654
38968
|
}
|
|
38655
|
-
get
|
|
38969
|
+
get supportsVideoTransformationMetadata() {
|
|
38656
38970
|
return false;
|
|
38657
38971
|
}
|
|
38658
38972
|
get supportsTimestampedMediaData() {
|
|
@@ -38705,7 +39019,7 @@ ${cue.notes ?? ""}`;
|
|
|
38705
39019
|
...AUDIO_CODECS.filter((codec) => ["aac", "mp3", "ac3", "eac3", "dts"].includes(codec))
|
|
38706
39020
|
];
|
|
38707
39021
|
}
|
|
38708
|
-
get
|
|
39022
|
+
get supportsVideoTransformationMetadata() {
|
|
38709
39023
|
return false;
|
|
38710
39024
|
}
|
|
38711
39025
|
get supportsTimestampedMediaData() {
|
|
@@ -38801,8 +39115,8 @@ ${cue.notes ?? ""}`;
|
|
|
38801
39115
|
total: { min: 0, max: Infinity }
|
|
38802
39116
|
};
|
|
38803
39117
|
}
|
|
38804
|
-
get
|
|
38805
|
-
return toArray(this._options.segmentFormat).some((format) => format.
|
|
39118
|
+
get supportsVideoTransformationMetadata() {
|
|
39119
|
+
return toArray(this._options.segmentFormat).some((format) => format.supportsVideoTransformationMetadata);
|
|
38806
39120
|
}
|
|
38807
39121
|
get supportsTimestampedMediaData() {
|
|
38808
39122
|
return true;
|
|
@@ -38935,6 +39249,12 @@ ${cue.notes ?? ""}`;
|
|
|
38935
39249
|
if (metadata.maximumPacketCount !== void 0 && (!Number.isInteger(metadata.maximumPacketCount) || metadata.maximumPacketCount < 0)) {
|
|
38936
39250
|
throw new TypeError("metadata.maximumPacketCount, when provided, must be a non-negative integer.");
|
|
38937
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
|
+
}
|
|
38938
39258
|
if (metadata.group !== void 0 && !(metadata.group instanceof OutputTrackGroup) && (!Array.isArray(metadata.group) || metadata.group.some((group) => !(group instanceof OutputTrackGroup)))) {
|
|
38939
39259
|
throw new TypeError(
|
|
38940
39260
|
"metadata.group, when provided, must be an OutputTrackGroup instance or an array of OutputTrackGroup instances."
|
|
@@ -39134,8 +39454,11 @@ ${cue.notes ?? ""}`;
|
|
|
39134
39454
|
if (metadata.rotation !== void 0 && ![0, 90, 180, 270].includes(metadata.rotation)) {
|
|
39135
39455
|
throw new TypeError(`Invalid video rotation: ${metadata.rotation}. Has to be 0, 90, 180 or 270.`);
|
|
39136
39456
|
}
|
|
39137
|
-
if (
|
|
39138
|
-
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.");
|
|
39139
39462
|
}
|
|
39140
39463
|
if (metadata.frameRate !== void 0 && (!Number.isFinite(metadata.frameRate) || metadata.frameRate <= 0)) {
|
|
39141
39464
|
throw new TypeError(
|
|
@@ -39361,9 +39684,8 @@ ${cue.notes ?? ""}`;
|
|
|
39361
39684
|
* @returns A promise that resolves once all internal resources have been released.
|
|
39362
39685
|
*/
|
|
39363
39686
|
async cancel() {
|
|
39364
|
-
if (this.
|
|
39365
|
-
|
|
39366
|
-
return this._cancelPromise;
|
|
39687
|
+
if (this.state === "canceled") {
|
|
39688
|
+
return this._cancelPromise ?? void 0;
|
|
39367
39689
|
} else if (this.state === "finalizing" || this.state === "finalized") {
|
|
39368
39690
|
if (this.state === "finalized") {
|
|
39369
39691
|
Logging._warn("Output has already been finalized.");
|
|
@@ -39416,6 +39738,9 @@ ${cue.notes ?? ""}`;
|
|
|
39416
39738
|
await this._onFinalize();
|
|
39417
39739
|
}
|
|
39418
39740
|
this.state = "finalized";
|
|
39741
|
+
} catch (error) {
|
|
39742
|
+
this.state = "canceled";
|
|
39743
|
+
throw error;
|
|
39419
39744
|
} finally {
|
|
39420
39745
|
await Promise.all([...this._unfinalizedTargets].map((target) => target._close().catch(() => {
|
|
39421
39746
|
})));
|
|
@@ -39469,6 +39794,12 @@ ${cue.notes ?? ""}`;
|
|
|
39469
39794
|
if (videoOptions?.rotate !== void 0 && ![0, 90, 180, 270].includes(videoOptions.rotate)) {
|
|
39470
39795
|
throw new TypeError("options.video.rotate, when provided, must be 0, 90, 180 or 270.");
|
|
39471
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
|
+
}
|
|
39472
39803
|
if (videoOptions?.allowRotationMetadata !== void 0 && typeof videoOptions.allowRotationMetadata !== "boolean") {
|
|
39473
39804
|
throw new TypeError("options.video.allowRotationMetadata, when provided, must be a boolean.");
|
|
39474
39805
|
}
|
|
@@ -39653,6 +39984,9 @@ ${cue.notes ?? ""}`;
|
|
|
39653
39984
|
"options.copy.boundaryPolicy, when provided, must be 'expand' or 'shrink'."
|
|
39654
39985
|
);
|
|
39655
39986
|
}
|
|
39987
|
+
if (options.copy.boundaryTolerance !== void 0 && (!isNumber(options.copy.boundaryTolerance) || options.copy.boundaryTolerance < 0)) {
|
|
39988
|
+
throw new TypeError("options.copy.boundaryTolerance, when provided, must be a non-negative number.");
|
|
39989
|
+
}
|
|
39656
39990
|
}
|
|
39657
39991
|
const composable = options.composable ?? false;
|
|
39658
39992
|
if (!composable) {
|
|
@@ -39714,6 +40048,7 @@ ${cue.notes ?? ""}`;
|
|
|
39714
40048
|
this._copyMode = options.copy === false ? false : options.copy?.mode ?? "preferred";
|
|
39715
40049
|
this._copyTimestampShiftTolerance = options.copy === false ? 0 : options.copy?.shiftTolerance ?? 0;
|
|
39716
40050
|
this._copyBoundaryPolicy = options.copy === false ? "expand" : options.copy?.boundaryPolicy ?? "expand";
|
|
40051
|
+
this._copyBoundaryTolerance = options.copy === false ? Infinity : options.copy?.boundaryTolerance ?? Infinity;
|
|
39717
40052
|
this._composable = composable;
|
|
39718
40053
|
this.input = options.input;
|
|
39719
40054
|
this.output = options.output;
|
|
@@ -40138,9 +40473,17 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40138
40473
|
}
|
|
40139
40474
|
let videoSource;
|
|
40140
40475
|
const innateRotation = await track.getRotation();
|
|
40141
|
-
const
|
|
40476
|
+
const innateFlip = await track.getFlip();
|
|
40477
|
+
const { rotation: totalRotation, flip: totalFlip } = composeRotationAndFlip(
|
|
40478
|
+
innateRotation,
|
|
40479
|
+
innateFlip,
|
|
40480
|
+
trackOptions.rotate ?? 0,
|
|
40481
|
+
trackOptions.flip ?? false
|
|
40482
|
+
);
|
|
40142
40483
|
let outputTrackRotation = totalRotation;
|
|
40143
|
-
|
|
40484
|
+
let outputTrackFlip = totalFlip;
|
|
40485
|
+
let outputTrackMatrix = trackOptions.rotate || trackOptions.flip ? null : await track.getTransformationMatrix();
|
|
40486
|
+
const canUseRotationMetadata = this.output.format.supportsVideoTransformationMetadata && (trackOptions.allowTransformationMetadata ?? trackOptions.allowRotationMetadata ?? true);
|
|
40144
40487
|
const squarePixelWidth = await track.getSquarePixelWidth();
|
|
40145
40488
|
const squarePixelHeight = await track.getSquarePixelHeight();
|
|
40146
40489
|
const [rotatedWidth, rotatedHeight] = totalRotation % 180 === 0 ? [squarePixelWidth, squarePixelHeight] : [squarePixelHeight, squarePixelWidth];
|
|
@@ -40164,7 +40507,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40164
40507
|
}
|
|
40165
40508
|
let videoCodecs = this.output.format.getSupportedVideoCodecs();
|
|
40166
40509
|
const alpha = trackOptions.alpha ?? "discard";
|
|
40167
|
-
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;
|
|
40510
|
+
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;
|
|
40168
40511
|
let copyStartPacket = null;
|
|
40169
40512
|
if (!needsTranscode) {
|
|
40170
40513
|
const sink = new EncodedPacketSink(track);
|
|
@@ -40175,7 +40518,10 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40175
40518
|
copyStartPacket = startPacket;
|
|
40176
40519
|
if (startPacket) {
|
|
40177
40520
|
const effectiveStartTimestamp = this._copyBoundaryPolicy === "shrink" ? Math.max(startPacket.timestamp, this._startTimestamp) : startPacket.timestamp;
|
|
40178
|
-
|
|
40521
|
+
const boundaryDeviation = this._copyBoundaryPolicy === "shrink" ? effectiveStartTimestamp - this._startTimestamp : Math.max(this._startTimestamp - effectiveStartTimestamp, 0);
|
|
40522
|
+
if (boundaryDeviation > this._copyBoundaryTolerance) {
|
|
40523
|
+
needsTranscode = true;
|
|
40524
|
+
} else if (!this.output.format.supportsTimestampedMediaData) {
|
|
40179
40525
|
if (this._timestampOffsetAdjusted) {
|
|
40180
40526
|
const isValid = effectiveStartTimestamp + this._timestampOffset === 0;
|
|
40181
40527
|
if (!isValid) {
|
|
@@ -40226,6 +40572,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40226
40572
|
const sink = new EncodedPacketSink(track);
|
|
40227
40573
|
const decoderConfig = await track.getDecoderConfig();
|
|
40228
40574
|
const meta = { decoderConfig: decoderConfig ?? void 0 };
|
|
40575
|
+
let maxTimestamp = null;
|
|
40229
40576
|
if (copyStartPacket) for await (const packet of sink.packets(
|
|
40230
40577
|
copyStartPacket,
|
|
40231
40578
|
void 0,
|
|
@@ -40266,10 +40613,16 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40266
40613
|
}
|
|
40267
40614
|
packetStartTimestamp += this._timestampOffset;
|
|
40268
40615
|
packetEndTimestamp += this._timestampOffset;
|
|
40616
|
+
let packetType = packet.type;
|
|
40617
|
+
if (packetType === "key" && maxTimestamp !== null && packetStartTimestamp < maxTimestamp) {
|
|
40618
|
+
packetType = "delta";
|
|
40619
|
+
}
|
|
40620
|
+
maxTimestamp = Math.max(maxTimestamp ?? -Infinity, packetStartTimestamp);
|
|
40269
40621
|
const modifiedPacket = packet.clone({
|
|
40270
40622
|
timestamp: packetStartTimestamp,
|
|
40271
40623
|
duration: packetEndTimestamp - packetStartTimestamp,
|
|
40272
|
-
sideData: alpha === "discard" ? {} : packet.sideData
|
|
40624
|
+
sideData: alpha === "discard" ? {} : packet.sideData,
|
|
40625
|
+
type: packetType
|
|
40273
40626
|
});
|
|
40274
40627
|
this._reportProgress(outputTrackId, modifiedPacket.timestamp + modifiedPacket.duration);
|
|
40275
40628
|
await source.add(modifiedPacket, meta);
|
|
@@ -40318,7 +40671,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40318
40671
|
transform: {}
|
|
40319
40672
|
};
|
|
40320
40673
|
assert(encodingConfig.transform);
|
|
40321
|
-
let needsRerender = width !== originalWidth || height !== originalHeight || totalRotation !== 0 && (!canUseRotationMetadata || trackOptions.process !== void 0) || !!crop || squarePixelWidth !== await track.getCodedWidth() || squarePixelHeight !== await track.getCodedHeight();
|
|
40674
|
+
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();
|
|
40322
40675
|
if (!needsRerender) {
|
|
40323
40676
|
var _stack = [];
|
|
40324
40677
|
try {
|
|
@@ -40363,10 +40716,13 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40363
40716
|
}
|
|
40364
40717
|
if (needsRerender) {
|
|
40365
40718
|
outputTrackRotation = 0;
|
|
40719
|
+
outputTrackFlip = false;
|
|
40720
|
+
outputTrackMatrix = null;
|
|
40366
40721
|
encodingConfig.transform.width = width;
|
|
40367
40722
|
encodingConfig.transform.height = height;
|
|
40368
40723
|
encodingConfig.transform.fit = trackOptions.fit ?? "fill";
|
|
40369
|
-
encodingConfig.transform.rotate =
|
|
40724
|
+
encodingConfig.transform.rotate = trackOptions.rotate;
|
|
40725
|
+
encodingConfig.transform.flip = trackOptions.flip;
|
|
40370
40726
|
encodingConfig.transform.crop = crop;
|
|
40371
40727
|
encodingConfig.transform.alpha = alpha;
|
|
40372
40728
|
}
|
|
@@ -40418,6 +40774,8 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40418
40774
|
const videoTrackLanguageCode = await track.getLanguageCode();
|
|
40419
40775
|
const trackName = await track.getName();
|
|
40420
40776
|
const trackDisposition = await track.getDisposition();
|
|
40777
|
+
const bitrate = needsTranscode ? null : await track.getBitrate();
|
|
40778
|
+
const averageBitrate = needsTranscode ? null : await track.getAverageBitrate();
|
|
40421
40779
|
this.output.addVideoTrack(videoSource, {
|
|
40422
40780
|
frameRate: trackOptions.frameRate,
|
|
40423
40781
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
@@ -40425,7 +40783,11 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40425
40783
|
name: trackName ?? void 0,
|
|
40426
40784
|
disposition: trackDisposition,
|
|
40427
40785
|
rotation: outputTrackRotation,
|
|
40428
|
-
|
|
40786
|
+
flip: outputTrackFlip,
|
|
40787
|
+
transformationMatrix: outputTrackMatrix ?? void 0,
|
|
40788
|
+
group: ownGroup ?? trackOptions.group,
|
|
40789
|
+
bitrate: bitrate ?? void 0,
|
|
40790
|
+
averageBitrate: averageBitrate ?? void 0
|
|
40429
40791
|
});
|
|
40430
40792
|
this.utilizedTracks.push(track);
|
|
40431
40793
|
this._outputTrackIds.push(outputTrackId);
|
|
@@ -40467,7 +40829,10 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40467
40829
|
}
|
|
40468
40830
|
copyStartPacket = startPacket;
|
|
40469
40831
|
if (startPacket) {
|
|
40470
|
-
|
|
40832
|
+
const boundaryDeviation = this._copyBoundaryPolicy === "shrink" ? Math.max(startPacket.timestamp - this._startTimestamp, 0) : Math.max(this._startTimestamp - startPacket.timestamp, 0);
|
|
40833
|
+
if (boundaryDeviation > this._copyBoundaryTolerance) {
|
|
40834
|
+
needsTranscode = true;
|
|
40835
|
+
} else if (!this.output.format.supportsTimestampedMediaData) {
|
|
40471
40836
|
if (this._timestampOffsetAdjusted) {
|
|
40472
40837
|
const isValid = startPacket.timestamp + this._timestampOffset === 0;
|
|
40473
40838
|
if (!isValid) {
|
|
@@ -40709,12 +41074,16 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
|
|
|
40709
41074
|
const audioTrackLanguageCode = await track.getLanguageCode();
|
|
40710
41075
|
const trackName = await track.getName();
|
|
40711
41076
|
const trackDisposition = await track.getDisposition();
|
|
41077
|
+
const bitrate = needsTranscode ? null : await track.getBitrate();
|
|
41078
|
+
const averageBitrate = needsTranscode ? null : await track.getAverageBitrate();
|
|
40712
41079
|
this.output.addAudioTrack(audioSource, {
|
|
40713
41080
|
// TODO: This condition can be removed when all demuxers properly homogenize to BCP47 in v2
|
|
40714
41081
|
languageCode: isIso639Dash2LanguageCode(audioTrackLanguageCode) ? audioTrackLanguageCode : void 0,
|
|
40715
41082
|
name: trackName ?? void 0,
|
|
40716
41083
|
disposition: trackDisposition,
|
|
40717
|
-
group: ownGroup ?? trackOptions.group
|
|
41084
|
+
group: ownGroup ?? trackOptions.group,
|
|
41085
|
+
bitrate: bitrate ?? void 0,
|
|
41086
|
+
averageBitrate: averageBitrate ?? void 0
|
|
40718
41087
|
});
|
|
40719
41088
|
this.utilizedTracks.push(track);
|
|
40720
41089
|
this._outputTrackIds.push(outputTrackId);
|