mediabunny 1.2.0 → 1.3.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 +324 -127
- package/dist/bundles/mediabunny.min.cjs +4 -4
- package/dist/bundles/mediabunny.min.mjs +4 -4
- package/dist/bundles/mediabunny.mjs +324 -127
- package/dist/mediabunny.d.ts +26 -2
- package/dist/modules/codec-data.d.ts +9 -0
- package/dist/modules/codec-data.d.ts.map +1 -1
- package/dist/modules/codec-data.js +278 -145
- package/dist/modules/codec.js +2 -2
- package/dist/modules/conversion.js +8 -8
- package/dist/modules/index.js +14 -14
- package/dist/modules/input-format.js +11 -11
- package/dist/modules/input-track.d.ts +16 -3
- package/dist/modules/input-track.d.ts.map +1 -1
- package/dist/modules/input-track.js +34 -5
- package/dist/modules/input.js +4 -4
- package/dist/modules/isobmff/isobmff-boxes.js +5 -5
- package/dist/modules/isobmff/isobmff-demuxer.js +9 -9
- package/dist/modules/isobmff/isobmff-muxer.js +10 -10
- package/dist/modules/matroska/matroska-demuxer.js +9 -9
- package/dist/modules/matroska/matroska-muxer.d.ts.map +1 -1
- package/dist/modules/matroska/matroska-muxer.js +9 -11
- package/dist/modules/media-sink.d.ts +11 -0
- package/dist/modules/media-sink.d.ts.map +1 -1
- package/dist/modules/media-sink.js +70 -17
- package/dist/modules/media-source.js +7 -7
- package/dist/modules/misc.d.ts +1 -1
- package/dist/modules/misc.d.ts.map +1 -1
- package/dist/modules/misc.js +4 -1
- package/dist/modules/mp3/mp3-demuxer.js +6 -6
- package/dist/modules/mp3/mp3-muxer.js +4 -4
- package/dist/modules/mp3/mp3-reader.js +2 -2
- package/dist/modules/mp3/mp3-writer.js +1 -1
- package/dist/modules/muxer.js +1 -1
- package/dist/modules/ogg/ogg-demuxer.js +9 -9
- package/dist/modules/ogg/ogg-misc.js +2 -2
- package/dist/modules/ogg/ogg-muxer.js +6 -6
- package/dist/modules/ogg/ogg-reader.js +1 -1
- package/dist/modules/output-format.js +6 -6
- package/dist/modules/output.js +4 -4
- package/dist/modules/packet.js +1 -1
- package/dist/modules/reader.js +1 -1
- package/dist/modules/sample.js +1 -1
- package/dist/modules/source.js +1 -1
- package/dist/modules/target.js +1 -1
- package/dist/modules/wave/wave-demuxer.js +6 -6
- package/dist/modules/wave/wave-muxer.js +5 -5
- package/dist/modules/writer.js +1 -1
- package/package.json +2 -2
- package/src/codec-data.ts +317 -155
- package/src/conversion.ts +1 -1
- package/src/input-track.ts +42 -3
- package/src/matroska/matroska-muxer.ts +1 -2
- package/src/media-sink.ts +88 -10
- package/src/misc.ts +6 -2
|
@@ -159,6 +159,9 @@ var Mediabunny = (() => {
|
|
|
159
159
|
return bit;
|
|
160
160
|
}
|
|
161
161
|
readBits(n) {
|
|
162
|
+
if (n === 1) {
|
|
163
|
+
return this.readBit();
|
|
164
|
+
}
|
|
162
165
|
let result = 0;
|
|
163
166
|
for (let i = 0; i < n; i++) {
|
|
164
167
|
result <<= 1;
|
|
@@ -189,7 +192,7 @@ var Mediabunny = (() => {
|
|
|
189
192
|
};
|
|
190
193
|
var readExpGolomb = (bitstream) => {
|
|
191
194
|
let leadingZeroBits = 0;
|
|
192
|
-
while (bitstream.
|
|
195
|
+
while (bitstream.readBits(1) === 0 && leadingZeroBits < 32) {
|
|
193
196
|
leadingZeroBits++;
|
|
194
197
|
}
|
|
195
198
|
if (leadingZeroBits >= 32) {
|
|
@@ -1773,6 +1776,31 @@ var Mediabunny = (() => {
|
|
|
1773
1776
|
}
|
|
1774
1777
|
return nalUnits;
|
|
1775
1778
|
};
|
|
1779
|
+
var findNalUnitsInLengthPrefixed = (packetData, lengthSize) => {
|
|
1780
|
+
const nalUnits = [];
|
|
1781
|
+
let offset = 0;
|
|
1782
|
+
const dataView = new DataView(packetData.buffer, packetData.byteOffset, packetData.byteLength);
|
|
1783
|
+
while (offset + lengthSize <= packetData.length) {
|
|
1784
|
+
let nalUnitLength;
|
|
1785
|
+
if (lengthSize === 1) {
|
|
1786
|
+
nalUnitLength = dataView.getUint8(offset);
|
|
1787
|
+
} else if (lengthSize === 2) {
|
|
1788
|
+
nalUnitLength = dataView.getUint16(offset, false);
|
|
1789
|
+
} else if (lengthSize === 3) {
|
|
1790
|
+
nalUnitLength = (dataView.getUint16(offset, false) << 8) + dataView.getUint8(offset + 2);
|
|
1791
|
+
} else if (lengthSize === 4) {
|
|
1792
|
+
nalUnitLength = dataView.getUint32(offset, false);
|
|
1793
|
+
} else {
|
|
1794
|
+
assertNever(lengthSize);
|
|
1795
|
+
assert(false);
|
|
1796
|
+
}
|
|
1797
|
+
offset += lengthSize;
|
|
1798
|
+
const nalUnit = packetData.subarray(offset, offset + nalUnitLength);
|
|
1799
|
+
nalUnits.push(nalUnit);
|
|
1800
|
+
offset += nalUnitLength;
|
|
1801
|
+
}
|
|
1802
|
+
return nalUnits;
|
|
1803
|
+
};
|
|
1776
1804
|
var removeEmulationPreventionBytes = (data) => {
|
|
1777
1805
|
const result = [];
|
|
1778
1806
|
const len = data.length;
|
|
@@ -2348,22 +2376,6 @@ var Mediabunny = (() => {
|
|
|
2348
2376
|
return new Uint8Array(bytes2);
|
|
2349
2377
|
};
|
|
2350
2378
|
var extractVp9CodecInfoFromPacket = (packet) => {
|
|
2351
|
-
const lastByte = packet[packet.length - 1];
|
|
2352
|
-
if (lastByte && (lastByte & 224) === 192) {
|
|
2353
|
-
const bytesPerFrameSize = ((lastByte & 24) >> 3) + 1;
|
|
2354
|
-
const numFrames = (lastByte & 7) + 1;
|
|
2355
|
-
const indexSize = 2 + numFrames * bytesPerFrameSize;
|
|
2356
|
-
if (packet[packet.length - indexSize] !== lastByte) {
|
|
2357
|
-
return null;
|
|
2358
|
-
}
|
|
2359
|
-
let frameSize = 0;
|
|
2360
|
-
const offset = packet.length - indexSize + 1;
|
|
2361
|
-
for (let i = 0; i < bytesPerFrameSize; i++) {
|
|
2362
|
-
if (!packet[offset + i]) return null;
|
|
2363
|
-
frameSize |= packet[offset + i] << 8 * i;
|
|
2364
|
-
}
|
|
2365
|
-
packet = packet.subarray(0, frameSize);
|
|
2366
|
-
}
|
|
2367
2379
|
const bitstream = new Bitstream(packet);
|
|
2368
2380
|
const frameMarker = bitstream.readBits(2);
|
|
2369
2381
|
if (frameMarker !== 2) {
|
|
@@ -2437,13 +2449,12 @@ var Mediabunny = (() => {
|
|
|
2437
2449
|
matrixCoefficients
|
|
2438
2450
|
};
|
|
2439
2451
|
};
|
|
2440
|
-
|
|
2452
|
+
function* iterateAv1PacketObus(packet) {
|
|
2441
2453
|
const bitstream = new Bitstream(packet);
|
|
2442
2454
|
const readLeb128 = () => {
|
|
2443
2455
|
let value = 0;
|
|
2444
2456
|
for (let i = 0; i < 8; i++) {
|
|
2445
2457
|
const byte = bitstream.readAlignedByte();
|
|
2446
|
-
if (byte === void 0) return 0;
|
|
2447
2458
|
value |= (byte & 127) << i * 7;
|
|
2448
2459
|
if (!(byte & 128)) {
|
|
2449
2460
|
break;
|
|
@@ -2458,121 +2469,133 @@ var Mediabunny = (() => {
|
|
|
2458
2469
|
return value;
|
|
2459
2470
|
};
|
|
2460
2471
|
while (bitstream.getBitsLeft() >= 8) {
|
|
2461
|
-
|
|
2462
|
-
const obuType =
|
|
2463
|
-
const obuExtension =
|
|
2464
|
-
const obuHasSizeField =
|
|
2472
|
+
bitstream.skipBits(1);
|
|
2473
|
+
const obuType = bitstream.readBits(4);
|
|
2474
|
+
const obuExtension = bitstream.readBits(1);
|
|
2475
|
+
const obuHasSizeField = bitstream.readBits(1);
|
|
2476
|
+
bitstream.skipBits(1);
|
|
2465
2477
|
if (obuExtension) {
|
|
2466
2478
|
bitstream.skipBits(8);
|
|
2467
2479
|
}
|
|
2468
2480
|
let obuSize;
|
|
2469
2481
|
if (obuHasSizeField) {
|
|
2470
2482
|
const obuSizeValue = readLeb128();
|
|
2471
|
-
if (obuSizeValue === null) return
|
|
2483
|
+
if (obuSizeValue === null) return;
|
|
2472
2484
|
obuSize = obuSizeValue;
|
|
2473
2485
|
} else {
|
|
2474
2486
|
obuSize = Math.floor(bitstream.getBitsLeft() / 8);
|
|
2475
2487
|
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2488
|
+
assert(bitstream.pos % 8 === 0);
|
|
2489
|
+
yield {
|
|
2490
|
+
type: obuType,
|
|
2491
|
+
data: packet.subarray(bitstream.pos / 8, bitstream.pos / 8 + obuSize)
|
|
2492
|
+
};
|
|
2493
|
+
bitstream.skipBits(obuSize * 8);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
var extractAv1CodecInfoFromPacket = (packet) => {
|
|
2497
|
+
for (const { type, data } of iterateAv1PacketObus(packet)) {
|
|
2498
|
+
if (type !== 1) {
|
|
2499
|
+
continue;
|
|
2500
|
+
}
|
|
2501
|
+
const bitstream = new Bitstream(data);
|
|
2502
|
+
const seqProfile = bitstream.readBits(3);
|
|
2503
|
+
const stillPicture = bitstream.readBits(1);
|
|
2504
|
+
const reducedStillPictureHeader = bitstream.readBits(1);
|
|
2505
|
+
let seqLevel = 0;
|
|
2506
|
+
let seqTier = 0;
|
|
2507
|
+
let bufferDelayLengthMinus1 = 0;
|
|
2508
|
+
if (reducedStillPictureHeader) {
|
|
2509
|
+
seqLevel = bitstream.readBits(5);
|
|
2510
|
+
} else {
|
|
2511
|
+
const timingInfoPresentFlag = bitstream.readBits(1);
|
|
2512
|
+
if (timingInfoPresentFlag) {
|
|
2513
|
+
bitstream.skipBits(32);
|
|
2514
|
+
bitstream.skipBits(32);
|
|
2515
|
+
const equalPictureInterval = bitstream.readBits(1);
|
|
2516
|
+
if (equalPictureInterval) {
|
|
2517
|
+
return null;
|
|
2494
2518
|
}
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2519
|
+
}
|
|
2520
|
+
const decoderModelInfoPresentFlag = bitstream.readBits(1);
|
|
2521
|
+
if (decoderModelInfoPresentFlag) {
|
|
2522
|
+
bufferDelayLengthMinus1 = bitstream.readBits(5);
|
|
2523
|
+
bitstream.skipBits(32);
|
|
2524
|
+
bitstream.skipBits(5);
|
|
2525
|
+
bitstream.skipBits(5);
|
|
2526
|
+
}
|
|
2527
|
+
const operatingPointsCntMinus1 = bitstream.readBits(5);
|
|
2528
|
+
for (let i = 0; i <= operatingPointsCntMinus1; i++) {
|
|
2529
|
+
bitstream.skipBits(12);
|
|
2530
|
+
const seqLevelIdx = bitstream.readBits(5);
|
|
2531
|
+
if (i === 0) {
|
|
2532
|
+
seqLevel = seqLevelIdx;
|
|
2501
2533
|
}
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
bitstream.skipBits(12);
|
|
2505
|
-
const seqLevelIdx = bitstream.readBits(5);
|
|
2534
|
+
if (seqLevelIdx > 7) {
|
|
2535
|
+
const seqTierTemp = bitstream.readBits(1);
|
|
2506
2536
|
if (i === 0) {
|
|
2507
|
-
|
|
2508
|
-
}
|
|
2509
|
-
if (seqLevelIdx > 7) {
|
|
2510
|
-
const seqTierTemp = bitstream.readBits(1);
|
|
2511
|
-
if (i === 0) {
|
|
2512
|
-
seqTier = seqTierTemp;
|
|
2513
|
-
}
|
|
2514
|
-
}
|
|
2515
|
-
if (decoderModelInfoPresentFlag) {
|
|
2516
|
-
const decoderModelPresentForThisOp = bitstream.readBits(1);
|
|
2517
|
-
if (decoderModelPresentForThisOp) {
|
|
2518
|
-
const n = bufferDelayLengthMinus1 + 1;
|
|
2519
|
-
bitstream.skipBits(n);
|
|
2520
|
-
bitstream.skipBits(n);
|
|
2521
|
-
bitstream.skipBits(1);
|
|
2522
|
-
}
|
|
2537
|
+
seqTier = seqTierTemp;
|
|
2523
2538
|
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2539
|
+
}
|
|
2540
|
+
if (decoderModelInfoPresentFlag) {
|
|
2541
|
+
const decoderModelPresentForThisOp = bitstream.readBits(1);
|
|
2542
|
+
if (decoderModelPresentForThisOp) {
|
|
2543
|
+
const n = bufferDelayLengthMinus1 + 1;
|
|
2544
|
+
bitstream.skipBits(n);
|
|
2545
|
+
bitstream.skipBits(n);
|
|
2546
|
+
bitstream.skipBits(1);
|
|
2527
2547
|
}
|
|
2528
2548
|
}
|
|
2549
|
+
const initialDisplayDelayPresentFlag = bitstream.readBits(1);
|
|
2550
|
+
if (initialDisplayDelayPresentFlag) {
|
|
2551
|
+
bitstream.skipBits(4);
|
|
2552
|
+
}
|
|
2529
2553
|
}
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2554
|
+
}
|
|
2555
|
+
const highBitdepth = bitstream.readBits(1);
|
|
2556
|
+
let bitDepth = 8;
|
|
2557
|
+
if (seqProfile === 2 && highBitdepth) {
|
|
2558
|
+
const twelveBit = bitstream.readBits(1);
|
|
2559
|
+
bitDepth = twelveBit ? 12 : 10;
|
|
2560
|
+
} else if (seqProfile <= 2) {
|
|
2561
|
+
bitDepth = highBitdepth ? 10 : 8;
|
|
2562
|
+
}
|
|
2563
|
+
let monochrome = 0;
|
|
2564
|
+
if (seqProfile !== 1) {
|
|
2565
|
+
monochrome = bitstream.readBits(1);
|
|
2566
|
+
}
|
|
2567
|
+
let chromaSubsamplingX = 1;
|
|
2568
|
+
let chromaSubsamplingY = 1;
|
|
2569
|
+
let chromaSamplePosition = 0;
|
|
2570
|
+
if (!monochrome) {
|
|
2571
|
+
if (seqProfile === 0) {
|
|
2572
|
+
chromaSubsamplingX = 1;
|
|
2573
|
+
chromaSubsamplingY = 1;
|
|
2574
|
+
} else if (seqProfile === 1) {
|
|
2575
|
+
chromaSubsamplingX = 0;
|
|
2576
|
+
chromaSubsamplingY = 0;
|
|
2577
|
+
} else {
|
|
2578
|
+
if (bitDepth === 12) {
|
|
2579
|
+
chromaSubsamplingX = bitstream.readBits(1);
|
|
2580
|
+
if (chromaSubsamplingX) {
|
|
2581
|
+
chromaSubsamplingY = bitstream.readBits(1);
|
|
2558
2582
|
}
|
|
2559
2583
|
}
|
|
2560
|
-
if (chromaSubsamplingX && chromaSubsamplingY) {
|
|
2561
|
-
chromaSamplePosition = bitstream.readBits(2);
|
|
2562
|
-
}
|
|
2563
2584
|
}
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
tier: seqTier,
|
|
2568
|
-
bitDepth,
|
|
2569
|
-
monochrome,
|
|
2570
|
-
chromaSubsamplingX,
|
|
2571
|
-
chromaSubsamplingY,
|
|
2572
|
-
chromaSamplePosition
|
|
2573
|
-
};
|
|
2585
|
+
if (chromaSubsamplingX && chromaSubsamplingY) {
|
|
2586
|
+
chromaSamplePosition = bitstream.readBits(2);
|
|
2587
|
+
}
|
|
2574
2588
|
}
|
|
2575
|
-
|
|
2589
|
+
return {
|
|
2590
|
+
profile: seqProfile,
|
|
2591
|
+
level: seqLevel,
|
|
2592
|
+
tier: seqTier,
|
|
2593
|
+
bitDepth,
|
|
2594
|
+
monochrome,
|
|
2595
|
+
chromaSubsamplingX,
|
|
2596
|
+
chromaSubsamplingY,
|
|
2597
|
+
chromaSamplePosition
|
|
2598
|
+
};
|
|
2576
2599
|
}
|
|
2577
2600
|
return null;
|
|
2578
2601
|
};
|
|
@@ -2703,6 +2726,105 @@ var Mediabunny = (() => {
|
|
|
2703
2726
|
}
|
|
2704
2727
|
return { modeBlockflags };
|
|
2705
2728
|
};
|
|
2729
|
+
var determineVideoPacketType = async (videoTrack, packet) => {
|
|
2730
|
+
assert(videoTrack.codec);
|
|
2731
|
+
switch (videoTrack.codec) {
|
|
2732
|
+
case "avc":
|
|
2733
|
+
{
|
|
2734
|
+
const decoderConfig = await videoTrack.getDecoderConfig();
|
|
2735
|
+
assert(decoderConfig);
|
|
2736
|
+
let nalUnits;
|
|
2737
|
+
if (decoderConfig.description) {
|
|
2738
|
+
const bytes2 = toUint8Array(decoderConfig.description);
|
|
2739
|
+
const lengthSizeMinusOne = bytes2[4] & 3;
|
|
2740
|
+
const lengthSize = lengthSizeMinusOne + 1;
|
|
2741
|
+
nalUnits = findNalUnitsInLengthPrefixed(packet.data, lengthSize);
|
|
2742
|
+
} else {
|
|
2743
|
+
nalUnits = findNalUnitsInAnnexB(packet.data);
|
|
2744
|
+
}
|
|
2745
|
+
const isKeyframe = nalUnits.some((x) => extractNalUnitTypeForAvc(x) === 5);
|
|
2746
|
+
return isKeyframe ? "key" : "delta";
|
|
2747
|
+
}
|
|
2748
|
+
;
|
|
2749
|
+
case "hevc":
|
|
2750
|
+
{
|
|
2751
|
+
const decoderConfig = await videoTrack.getDecoderConfig();
|
|
2752
|
+
assert(decoderConfig);
|
|
2753
|
+
let nalUnits;
|
|
2754
|
+
if (decoderConfig.description) {
|
|
2755
|
+
const bytes2 = toUint8Array(decoderConfig.description);
|
|
2756
|
+
const lengthSizeMinusOne = bytes2[21] & 3;
|
|
2757
|
+
const lengthSize = lengthSizeMinusOne + 1;
|
|
2758
|
+
nalUnits = findNalUnitsInLengthPrefixed(packet.data, lengthSize);
|
|
2759
|
+
} else {
|
|
2760
|
+
nalUnits = findNalUnitsInAnnexB(packet.data);
|
|
2761
|
+
}
|
|
2762
|
+
const isKeyframe = nalUnits.some((x) => {
|
|
2763
|
+
const type = extractNalUnitTypeForHevc(x);
|
|
2764
|
+
return 16 <= type && type <= 23;
|
|
2765
|
+
});
|
|
2766
|
+
return isKeyframe ? "key" : "delta";
|
|
2767
|
+
}
|
|
2768
|
+
;
|
|
2769
|
+
case "vp8":
|
|
2770
|
+
{
|
|
2771
|
+
const frameType = packet.data[0] & 1;
|
|
2772
|
+
return frameType === 0 ? "key" : "delta";
|
|
2773
|
+
}
|
|
2774
|
+
;
|
|
2775
|
+
case "vp9":
|
|
2776
|
+
{
|
|
2777
|
+
const bitstream = new Bitstream(packet.data);
|
|
2778
|
+
if (bitstream.readBits(2) !== 2) {
|
|
2779
|
+
return null;
|
|
2780
|
+
}
|
|
2781
|
+
;
|
|
2782
|
+
const profileLowBit = bitstream.readBits(1);
|
|
2783
|
+
const profileHighBit = bitstream.readBits(1);
|
|
2784
|
+
const profile = (profileHighBit << 1) + profileLowBit;
|
|
2785
|
+
if (profile === 3) {
|
|
2786
|
+
bitstream.skipBits(1);
|
|
2787
|
+
}
|
|
2788
|
+
const showExistingFrame = bitstream.readBits(1);
|
|
2789
|
+
if (showExistingFrame) {
|
|
2790
|
+
return null;
|
|
2791
|
+
}
|
|
2792
|
+
const frameType = bitstream.readBits(1);
|
|
2793
|
+
return frameType === 0 ? "key" : "delta";
|
|
2794
|
+
}
|
|
2795
|
+
;
|
|
2796
|
+
case "av1":
|
|
2797
|
+
{
|
|
2798
|
+
let reducedStillPictureHeader = false;
|
|
2799
|
+
for (const { type, data } of iterateAv1PacketObus(packet.data)) {
|
|
2800
|
+
if (type === 1) {
|
|
2801
|
+
const bitstream = new Bitstream(data);
|
|
2802
|
+
bitstream.skipBits(4);
|
|
2803
|
+
reducedStillPictureHeader = !!bitstream.readBits(1);
|
|
2804
|
+
} else if (type === 3 || type === 6 || type === 7) {
|
|
2805
|
+
if (reducedStillPictureHeader) {
|
|
2806
|
+
return "key";
|
|
2807
|
+
}
|
|
2808
|
+
const bitstream = new Bitstream(data);
|
|
2809
|
+
const showExistingFrame = bitstream.readBits(1);
|
|
2810
|
+
if (showExistingFrame) {
|
|
2811
|
+
return null;
|
|
2812
|
+
}
|
|
2813
|
+
const frameType = bitstream.readBits(2);
|
|
2814
|
+
return frameType === 0 ? "key" : "delta";
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
return null;
|
|
2818
|
+
}
|
|
2819
|
+
;
|
|
2820
|
+
default:
|
|
2821
|
+
{
|
|
2822
|
+
assertNever(videoTrack.codec);
|
|
2823
|
+
assert(false);
|
|
2824
|
+
}
|
|
2825
|
+
;
|
|
2826
|
+
}
|
|
2827
|
+
};
|
|
2706
2828
|
|
|
2707
2829
|
// src/isobmff/isobmff-boxes.ts
|
|
2708
2830
|
var IsobmffBoxWriter = class {
|
|
@@ -5970,7 +6092,7 @@ ${cue.notes ?? ""}`;
|
|
|
5970
6092
|
if (chunk.type !== "key") return;
|
|
5971
6093
|
if (!trackData.info.decoderConfig.colorSpace || !trackData.info.decoderConfig.colorSpace.matrix) return;
|
|
5972
6094
|
const bitstream = new Bitstream(chunk.data);
|
|
5973
|
-
|
|
6095
|
+
bitstream.skipBits(2);
|
|
5974
6096
|
const profileLowBit = bitstream.readBits(1);
|
|
5975
6097
|
const profileHighBit = bitstream.readBits(1);
|
|
5976
6098
|
const profile = (profileHighBit << 1) + profileLowBit;
|
|
@@ -7933,12 +8055,34 @@ ${cue.notes ?? ""}`;
|
|
|
7933
8055
|
if (options.metadataOnly !== void 0 && typeof options.metadataOnly !== "boolean") {
|
|
7934
8056
|
throw new TypeError("options.metadataOnly, when defined, must be a boolean.");
|
|
7935
8057
|
}
|
|
8058
|
+
if (options.verifyKeyPackets !== void 0 && typeof options.verifyKeyPackets !== "boolean") {
|
|
8059
|
+
throw new TypeError("options.verifyKeyPackets, when defined, must be a boolean.");
|
|
8060
|
+
}
|
|
8061
|
+
if (options.verifyKeyPackets && options.metadataOnly) {
|
|
8062
|
+
throw new TypeError("options.verifyKeyPackets and options.metadataOnly cannot be enabled together.");
|
|
8063
|
+
}
|
|
7936
8064
|
};
|
|
7937
8065
|
var validateTimestamp = (timestamp) => {
|
|
7938
8066
|
if (typeof timestamp !== "number" || Number.isNaN(timestamp)) {
|
|
7939
8067
|
throw new TypeError("timestamp must be a number.");
|
|
7940
8068
|
}
|
|
7941
8069
|
};
|
|
8070
|
+
var maybeFixPacketType = (track, promise, options) => {
|
|
8071
|
+
if (options.verifyKeyPackets) {
|
|
8072
|
+
return promise.then(async (packet) => {
|
|
8073
|
+
if (!packet || packet.type === "delta") {
|
|
8074
|
+
return packet;
|
|
8075
|
+
}
|
|
8076
|
+
const determinedType = await track.determinePacketType(packet);
|
|
8077
|
+
if (determinedType) {
|
|
8078
|
+
packet.type = determinedType;
|
|
8079
|
+
}
|
|
8080
|
+
return packet;
|
|
8081
|
+
});
|
|
8082
|
+
} else {
|
|
8083
|
+
return promise;
|
|
8084
|
+
}
|
|
8085
|
+
};
|
|
7942
8086
|
var EncodedPacketSink = class {
|
|
7943
8087
|
constructor(track) {
|
|
7944
8088
|
if (!(track instanceof InputTrack)) {
|
|
@@ -7952,7 +8096,7 @@ ${cue.notes ?? ""}`;
|
|
|
7952
8096
|
*/
|
|
7953
8097
|
getFirstPacket(options = {}) {
|
|
7954
8098
|
validatePacketRetrievalOptions(options);
|
|
7955
|
-
return this._track._backing.getFirstPacket(options);
|
|
8099
|
+
return maybeFixPacketType(this._track, this._track._backing.getFirstPacket(options), options);
|
|
7956
8100
|
}
|
|
7957
8101
|
/**
|
|
7958
8102
|
* Retrieves the packet corresponding to the given timestamp, in seconds. More specifically, returns the last packet
|
|
@@ -7965,7 +8109,7 @@ ${cue.notes ?? ""}`;
|
|
|
7965
8109
|
getPacket(timestamp, options = {}) {
|
|
7966
8110
|
validateTimestamp(timestamp);
|
|
7967
8111
|
validatePacketRetrievalOptions(options);
|
|
7968
|
-
return this._track._backing.getPacket(timestamp, options);
|
|
8112
|
+
return maybeFixPacketType(this._track, this._track._backing.getPacket(timestamp, options), options);
|
|
7969
8113
|
}
|
|
7970
8114
|
/**
|
|
7971
8115
|
* Retrieves the packet following the given packet (in decode order), or null if the given packet is the
|
|
@@ -7976,7 +8120,7 @@ ${cue.notes ?? ""}`;
|
|
|
7976
8120
|
throw new TypeError("packet must be an EncodedPacket.");
|
|
7977
8121
|
}
|
|
7978
8122
|
validatePacketRetrievalOptions(options);
|
|
7979
|
-
return this._track._backing.getNextPacket(packet, options);
|
|
8123
|
+
return maybeFixPacketType(this._track, this._track._backing.getNextPacket(packet, options), options);
|
|
7980
8124
|
}
|
|
7981
8125
|
/**
|
|
7982
8126
|
* Retrieves the key packet corresponding to the given timestamp, in seconds. More specifically, returns the last
|
|
@@ -7985,23 +8129,49 @@ ${cue.notes ?? ""}`;
|
|
|
7985
8129
|
* last key packet using `getKeyPacket(Infinity)`. The method returns null if the timestamp is before the first
|
|
7986
8130
|
* key packet in the track.
|
|
7987
8131
|
*
|
|
8132
|
+
* To ensure that the returned packet is guaranteed to be a real key frame, enable `options.verifyKeyPackets`.
|
|
8133
|
+
*
|
|
7988
8134
|
* @param timestamp - The timestamp used for retrieval, in seconds.
|
|
7989
8135
|
*/
|
|
7990
|
-
getKeyPacket(timestamp, options = {}) {
|
|
8136
|
+
async getKeyPacket(timestamp, options = {}) {
|
|
7991
8137
|
validateTimestamp(timestamp);
|
|
7992
8138
|
validatePacketRetrievalOptions(options);
|
|
7993
|
-
|
|
8139
|
+
if (!options.verifyKeyPackets) {
|
|
8140
|
+
return this._track._backing.getKeyPacket(timestamp, options);
|
|
8141
|
+
}
|
|
8142
|
+
const packet = await this._track._backing.getKeyPacket(timestamp, options);
|
|
8143
|
+
if (!packet || packet.type === "delta") {
|
|
8144
|
+
return packet;
|
|
8145
|
+
}
|
|
8146
|
+
const determinedType = await this._track.determinePacketType(packet);
|
|
8147
|
+
if (determinedType === "delta") {
|
|
8148
|
+
return this.getKeyPacket(packet.timestamp - 1 / this._track.timeResolution, options);
|
|
8149
|
+
}
|
|
8150
|
+
return packet;
|
|
7994
8151
|
}
|
|
7995
8152
|
/**
|
|
7996
8153
|
* Retrieves the key packet following the given packet (in decode order), or null if the given packet is the last
|
|
7997
8154
|
* key packet.
|
|
8155
|
+
*
|
|
8156
|
+
* To ensure that the returned packet is guaranteed to be a real key frame, enable `options.verifyKeyPackets`.
|
|
7998
8157
|
*/
|
|
7999
|
-
getNextKeyPacket(packet, options = {}) {
|
|
8158
|
+
async getNextKeyPacket(packet, options = {}) {
|
|
8000
8159
|
if (!(packet instanceof EncodedPacket)) {
|
|
8001
8160
|
throw new TypeError("packet must be an EncodedPacket.");
|
|
8002
8161
|
}
|
|
8003
8162
|
validatePacketRetrievalOptions(options);
|
|
8004
|
-
|
|
8163
|
+
if (!options.verifyKeyPackets) {
|
|
8164
|
+
return this._track._backing.getNextKeyPacket(packet, options);
|
|
8165
|
+
}
|
|
8166
|
+
const nextPacket = await this._track._backing.getNextKeyPacket(packet, options);
|
|
8167
|
+
if (!nextPacket || nextPacket.type === "delta") {
|
|
8168
|
+
return nextPacket;
|
|
8169
|
+
}
|
|
8170
|
+
const determinedType = await this._track.determinePacketType(nextPacket);
|
|
8171
|
+
if (determinedType === "delta") {
|
|
8172
|
+
return this.getNextKeyPacket(nextPacket, options);
|
|
8173
|
+
}
|
|
8174
|
+
return nextPacket;
|
|
8005
8175
|
}
|
|
8006
8176
|
/**
|
|
8007
8177
|
* Creates an async iterator that yields the packets in this track in decode order. To enable fast iteration, this
|
|
@@ -8147,7 +8317,7 @@ ${cue.notes ?? ""}`;
|
|
|
8147
8317
|
}
|
|
8148
8318
|
});
|
|
8149
8319
|
const packetSink = this._createPacketSink();
|
|
8150
|
-
const keyPacket = await packetSink.getKeyPacket(startTimestamp) ?? await packetSink.getFirstPacket();
|
|
8320
|
+
const keyPacket = await packetSink.getKeyPacket(startTimestamp, { verifyKeyPackets: true }) ?? await packetSink.getFirstPacket();
|
|
8151
8321
|
if (!keyPacket) {
|
|
8152
8322
|
return;
|
|
8153
8323
|
}
|
|
@@ -8155,7 +8325,7 @@ ${cue.notes ?? ""}`;
|
|
|
8155
8325
|
let endPacket = void 0;
|
|
8156
8326
|
if (endTimestamp < Infinity) {
|
|
8157
8327
|
const packet = await packetSink.getPacket(endTimestamp);
|
|
8158
|
-
const keyPacket2 = !packet ? null : packet.type === "key" && packet.timestamp === endTimestamp ? packet : await packetSink.getNextKeyPacket(packet);
|
|
8328
|
+
const keyPacket2 = !packet ? null : packet.type === "key" && packet.timestamp === endTimestamp ? packet : await packetSink.getNextKeyPacket(packet, { verifyKeyPackets: true });
|
|
8159
8329
|
if (keyPacket2) {
|
|
8160
8330
|
endPacket = keyPacket2;
|
|
8161
8331
|
}
|
|
@@ -8307,7 +8477,7 @@ ${cue.notes ?? ""}`;
|
|
|
8307
8477
|
break;
|
|
8308
8478
|
}
|
|
8309
8479
|
const targetPacket = await packetSink.getPacket(timestamp);
|
|
8310
|
-
const keyPacket = targetPacket && await packetSink.getKeyPacket(timestamp);
|
|
8480
|
+
const keyPacket = targetPacket && await packetSink.getKeyPacket(timestamp, { verifyKeyPackets: true });
|
|
8311
8481
|
if (!keyPacket) {
|
|
8312
8482
|
if (maxSequenceNumber !== -1) {
|
|
8313
8483
|
await decodePackets();
|
|
@@ -9158,7 +9328,10 @@ ${cue.notes ?? ""}`;
|
|
|
9158
9328
|
const colorSpace = await this._backing.getColorSpace();
|
|
9159
9329
|
return colorSpace.primaries === "bt2020" || colorSpace.primaries === "smpte432" || colorSpace.transfer === "pg" || colorSpace.transfer === "hlg" || colorSpace.matrix === "bt2020-ncl";
|
|
9160
9330
|
}
|
|
9161
|
-
/**
|
|
9331
|
+
/**
|
|
9332
|
+
* Returns the decoder configuration for decoding the track's packets using a VideoDecoder. Returns null if the
|
|
9333
|
+
* track's codec is unknown.
|
|
9334
|
+
*/
|
|
9162
9335
|
getDecoderConfig() {
|
|
9163
9336
|
return this._backing.getDecoderConfig();
|
|
9164
9337
|
}
|
|
@@ -9187,6 +9360,18 @@ ${cue.notes ?? ""}`;
|
|
|
9187
9360
|
return false;
|
|
9188
9361
|
}
|
|
9189
9362
|
}
|
|
9363
|
+
async determinePacketType(packet) {
|
|
9364
|
+
if (!(packet instanceof EncodedPacket)) {
|
|
9365
|
+
throw new TypeError("packet must be an EncodedPacket.");
|
|
9366
|
+
}
|
|
9367
|
+
if (packet.isMetadataOnly) {
|
|
9368
|
+
throw new TypeError("packet must not be metadata-only to determine its type.");
|
|
9369
|
+
}
|
|
9370
|
+
if (this.codec === null) {
|
|
9371
|
+
return null;
|
|
9372
|
+
}
|
|
9373
|
+
return determineVideoPacketType(this, packet);
|
|
9374
|
+
}
|
|
9190
9375
|
};
|
|
9191
9376
|
var InputAudioTrack = class extends InputTrack {
|
|
9192
9377
|
/** @internal */
|
|
@@ -9208,7 +9393,10 @@ ${cue.notes ?? ""}`;
|
|
|
9208
9393
|
get sampleRate() {
|
|
9209
9394
|
return this._backing.getSampleRate();
|
|
9210
9395
|
}
|
|
9211
|
-
/**
|
|
9396
|
+
/**
|
|
9397
|
+
* Returns the decoder configuration for decoding the track's packets using an AudioDecoder. Returns null if the
|
|
9398
|
+
* track's codec is unknown.
|
|
9399
|
+
*/
|
|
9212
9400
|
getDecoderConfig() {
|
|
9213
9401
|
return this._backing.getDecoderConfig();
|
|
9214
9402
|
}
|
|
@@ -9241,6 +9429,15 @@ ${cue.notes ?? ""}`;
|
|
|
9241
9429
|
return false;
|
|
9242
9430
|
}
|
|
9243
9431
|
}
|
|
9432
|
+
async determinePacketType(packet) {
|
|
9433
|
+
if (!(packet instanceof EncodedPacket)) {
|
|
9434
|
+
throw new TypeError("packet must be an EncodedPacket.");
|
|
9435
|
+
}
|
|
9436
|
+
if (this.codec === null) {
|
|
9437
|
+
return null;
|
|
9438
|
+
}
|
|
9439
|
+
return "key";
|
|
9440
|
+
}
|
|
9244
9441
|
};
|
|
9245
9442
|
|
|
9246
9443
|
// src/reader.ts
|
|
@@ -16448,7 +16645,7 @@ ${cue.notes ?? ""}`;
|
|
|
16448
16645
|
const decoderConfig = await track.getDecoderConfig();
|
|
16449
16646
|
const meta = { decoderConfig: decoderConfig ?? void 0 };
|
|
16450
16647
|
const endPacket = Number.isFinite(this._endTimestamp) ? await sink.getPacket(this._endTimestamp, { metadataOnly: true }) ?? void 0 : void 0;
|
|
16451
|
-
for await (const packet of sink.packets(void 0, endPacket)) {
|
|
16648
|
+
for await (const packet of sink.packets(void 0, endPacket, { verifyKeyPackets: true })) {
|
|
16452
16649
|
if (this._synchronizer.shouldWait(track.id, packet.timestamp)) {
|
|
16453
16650
|
await this._synchronizer.wait(packet.timestamp);
|
|
16454
16651
|
}
|