mediabunny 1.15.2 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/bundles/mediabunny.cjs +253 -42
- package/dist/bundles/mediabunny.min.cjs +4 -4
- package/dist/bundles/mediabunny.min.mjs +4 -4
- package/dist/bundles/mediabunny.mjs +253 -42
- package/dist/mediabunny.d.ts +21 -1
- package/dist/modules/src/codec-data.d.ts.map +1 -1
- package/dist/modules/src/codec-data.js +2 -2
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts +3 -1
- package/dist/modules/src/isobmff/isobmff-boxes.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-boxes.js +4 -2
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts +4 -1
- package/dist/modules/src/isobmff/isobmff-muxer.d.ts.map +1 -1
- package/dist/modules/src/isobmff/isobmff-muxer.js +100 -12
- package/dist/modules/src/matroska/ebml.d.ts +9 -1
- package/dist/modules/src/matroska/ebml.d.ts.map +1 -1
- package/dist/modules/src/matroska/ebml.js +8 -0
- package/dist/modules/src/matroska/matroska-demuxer.d.ts +30 -2
- package/dist/modules/src/matroska/matroska-demuxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-demuxer.js +180 -14
- package/dist/modules/src/matroska/matroska-muxer.d.ts.map +1 -1
- package/dist/modules/src/matroska/matroska-muxer.js +2 -4
- package/dist/modules/src/muxer.js +3 -3
- package/dist/modules/src/ogg/ogg-demuxer.js +1 -1
- package/dist/modules/src/output-format.d.ts +6 -1
- package/dist/modules/src/output-format.d.ts.map +1 -1
- package/dist/modules/src/output-format.js +3 -2
- package/dist/modules/src/output.d.ts +15 -0
- package/dist/modules/src/output.d.ts.map +1 -1
- package/dist/modules/src/output.js +4 -0
- package/dist/modules/src/reader.d.ts.map +1 -1
- package/dist/modules/src/reader.js +4 -4
- package/dist/modules/src/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/codec-data.ts +2 -1
- package/src/isobmff/isobmff-boxes.ts +5 -5
- package/src/isobmff/isobmff-muxer.ts +123 -14
- package/src/matroska/ebml.ts +8 -0
- package/src/matroska/matroska-demuxer.ts +194 -15
- package/src/matroska/matroska-muxer.ts +2 -4
- package/src/muxer.ts +3 -3
- package/src/ogg/ogg-demuxer.ts +1 -1
- package/src/output-format.ts +13 -3
- package/src/output.ts +21 -0
- package/src/reader.ts +5 -4
package/README.md
CHANGED
|
@@ -39,6 +39,10 @@ Mediabunny is a JavaScript library for reading, writing, and converting media fi
|
|
|
39
39
|
<a href="https://www.reactvideoeditor.com/" target="_blank">
|
|
40
40
|
<img src="./docs/public/sponsors/rve.svg" width="40" height="40" alt="React Video Editor">
|
|
41
41
|
</a>
|
|
42
|
+
|
|
43
|
+
<a href="https://www.mux.com/" target="_blank">
|
|
44
|
+
<img src="./docs/public/sponsors/mux.jpg" width="40" height="40" alt="Mux">
|
|
45
|
+
</a>
|
|
42
46
|
</div>
|
|
43
47
|
|
|
44
48
|
[Sponsor Mediabunny's development](https://github.com/sponsors/Vanilagy)
|
|
@@ -1610,7 +1610,7 @@ var Mediabunny = (() => {
|
|
|
1610
1610
|
}
|
|
1611
1611
|
if (timestampInSeconds < timestampInfo.maxTimestampBeforeLastKeyFrame) {
|
|
1612
1612
|
throw new Error(
|
|
1613
|
-
`Timestamps cannot be smaller than the highest timestamp of the previous
|
|
1613
|
+
`Timestamps cannot be smaller than the highest timestamp of the previous GOP (a GOP begins with a key frame and ends right before the next key frame). Got ${timestampInSeconds}s, but highest timestamp is ${timestampInfo.maxTimestampBeforeLastKeyFrame}s.`
|
|
1614
1614
|
);
|
|
1615
1615
|
}
|
|
1616
1616
|
timestampInfo.maxTimestamp = Math.max(timestampInfo.maxTimestamp, timestampInSeconds);
|
|
@@ -1812,7 +1812,7 @@ var Mediabunny = (() => {
|
|
|
1812
1812
|
} else if (lengthSize === 2) {
|
|
1813
1813
|
nalUnitLength = dataView.getUint16(offset, false);
|
|
1814
1814
|
} else if (lengthSize === 3) {
|
|
1815
|
-
nalUnitLength = (dataView
|
|
1815
|
+
nalUnitLength = getUint24(dataView, offset, false);
|
|
1816
1816
|
} else if (lengthSize === 4) {
|
|
1817
1817
|
nalUnitLength = dataView.getUint32(offset, false);
|
|
1818
1818
|
} else {
|
|
@@ -3077,10 +3077,11 @@ var Mediabunny = (() => {
|
|
|
3077
3077
|
]);
|
|
3078
3078
|
};
|
|
3079
3079
|
var mdat = (reserveLargeSize) => ({ type: "mdat", largeSize: reserveLargeSize });
|
|
3080
|
-
var
|
|
3080
|
+
var free = (size) => ({ type: "free", size });
|
|
3081
|
+
var moov = (muxer) => box("moov", void 0, [
|
|
3081
3082
|
mvhd(muxer.creationTime, muxer.trackDatas),
|
|
3082
3083
|
...muxer.trackDatas.map((x) => trak(x, muxer.creationTime)),
|
|
3083
|
-
|
|
3084
|
+
muxer.isFragmented ? mvex(muxer.trackDatas) : null,
|
|
3084
3085
|
udta(muxer)
|
|
3085
3086
|
]);
|
|
3086
3087
|
var mvhd = (creationTime, trackDatas) => {
|
|
@@ -4883,9 +4884,9 @@ var Mediabunny = (() => {
|
|
|
4883
4884
|
return value;
|
|
4884
4885
|
};
|
|
4885
4886
|
var readU24Be = (slice) => {
|
|
4886
|
-
const
|
|
4887
|
-
|
|
4888
|
-
return
|
|
4887
|
+
const value = getUint24(slice.view, slice.bufferPos, false);
|
|
4888
|
+
slice.bufferPos += 3;
|
|
4889
|
+
return value;
|
|
4889
4890
|
};
|
|
4890
4891
|
var readI16Be = (slice) => {
|
|
4891
4892
|
const value = slice.view.getInt16(slice.bufferPos, false);
|
|
@@ -5054,6 +5055,7 @@ var Mediabunny = (() => {
|
|
|
5054
5055
|
this.auxWriter = this.auxTarget._createWriter();
|
|
5055
5056
|
this.auxBoxWriter = new IsobmffBoxWriter(this.auxWriter);
|
|
5056
5057
|
this.mdat = null;
|
|
5058
|
+
this.ftypSize = null;
|
|
5057
5059
|
this.trackDatas = [];
|
|
5058
5060
|
this.allTracksKnown = promiseWithResolvers();
|
|
5059
5061
|
this.creationTime = Math.floor(Date.now() / 1e3) + TIMESTAMP_OFFSET;
|
|
@@ -5090,8 +5092,16 @@ var Mediabunny = (() => {
|
|
|
5090
5092
|
this.format._options.onFtyp(data, start);
|
|
5091
5093
|
}
|
|
5092
5094
|
}
|
|
5095
|
+
this.ftypSize = this.writer.getPos();
|
|
5093
5096
|
if (this.fastStart === "in-memory") {
|
|
5094
|
-
|
|
5097
|
+
} else if (this.fastStart === "reserve") {
|
|
5098
|
+
for (const track of this.output._tracks) {
|
|
5099
|
+
if (track.metadata.maximumPacketCount === void 0) {
|
|
5100
|
+
throw new Error(
|
|
5101
|
+
"All tracks must specify maximumPacketCount in their metadata when using fastStart: 'reserve'."
|
|
5102
|
+
);
|
|
5103
|
+
}
|
|
5104
|
+
}
|
|
5095
5105
|
} else if (this.isFragmented) {
|
|
5096
5106
|
} else {
|
|
5097
5107
|
if (this.format._options.onMdat) {
|
|
@@ -5548,6 +5558,8 @@ var Mediabunny = (() => {
|
|
|
5548
5558
|
if (this.isFragmented) {
|
|
5549
5559
|
trackData.sampleQueue.push(sample);
|
|
5550
5560
|
await this.interleaveSamples();
|
|
5561
|
+
} else if (this.fastStart === "reserve") {
|
|
5562
|
+
await this.registerSampleFastStartReserve(trackData, sample);
|
|
5551
5563
|
} else {
|
|
5552
5564
|
await this.addSampleToTrack(trackData, sample);
|
|
5553
5565
|
}
|
|
@@ -5555,6 +5567,15 @@ var Mediabunny = (() => {
|
|
|
5555
5567
|
async addSampleToTrack(trackData, sample) {
|
|
5556
5568
|
if (!this.isFragmented) {
|
|
5557
5569
|
trackData.samples.push(sample);
|
|
5570
|
+
if (this.fastStart === "reserve") {
|
|
5571
|
+
const maximumPacketCount = trackData.track.metadata.maximumPacketCount;
|
|
5572
|
+
assert(maximumPacketCount !== void 0);
|
|
5573
|
+
if (trackData.samples.length > maximumPacketCount) {
|
|
5574
|
+
throw new Error(
|
|
5575
|
+
`Track #${trackData.track.id} has already reached the maximum packet count (${maximumPacketCount}). Either add less packets or increase the maximum packet count.`
|
|
5576
|
+
);
|
|
5577
|
+
}
|
|
5578
|
+
}
|
|
5558
5579
|
}
|
|
5559
5580
|
let beginNewChunk = false;
|
|
5560
5581
|
if (!trackData.currentChunk) {
|
|
@@ -5631,10 +5652,8 @@ var Mediabunny = (() => {
|
|
|
5631
5652
|
}
|
|
5632
5653
|
async interleaveSamples(isFinalCall = false) {
|
|
5633
5654
|
assert(this.isFragmented);
|
|
5634
|
-
if (!isFinalCall) {
|
|
5635
|
-
|
|
5636
|
-
return;
|
|
5637
|
-
}
|
|
5655
|
+
if (!isFinalCall && !this.allTracksAreKnown()) {
|
|
5656
|
+
return;
|
|
5638
5657
|
}
|
|
5639
5658
|
outer:
|
|
5640
5659
|
while (true) {
|
|
@@ -5663,7 +5682,7 @@ var Mediabunny = (() => {
|
|
|
5663
5682
|
if (this.format._options.onMoov) {
|
|
5664
5683
|
this.writer.startTrackingWrites();
|
|
5665
5684
|
}
|
|
5666
|
-
const movieBox = moov(this
|
|
5685
|
+
const movieBox = moov(this);
|
|
5667
5686
|
this.boxWriter.writeBox(movieBox);
|
|
5668
5687
|
if (this.format._options.onMoov) {
|
|
5669
5688
|
const { data, start } = this.writer.stopTrackingWrites();
|
|
@@ -5727,6 +5746,46 @@ var Mediabunny = (() => {
|
|
|
5727
5746
|
await this.writer.flush();
|
|
5728
5747
|
}
|
|
5729
5748
|
}
|
|
5749
|
+
async registerSampleFastStartReserve(trackData, sample) {
|
|
5750
|
+
if (this.allTracksAreKnown()) {
|
|
5751
|
+
if (!this.mdat) {
|
|
5752
|
+
const moovBox = moov(this);
|
|
5753
|
+
const moovSize = this.boxWriter.measureBox(moovBox);
|
|
5754
|
+
const reservedSize = moovSize + this.computeSampleTableSizeUpperBound() + 4096;
|
|
5755
|
+
assert(this.ftypSize !== null);
|
|
5756
|
+
this.writer.seek(this.ftypSize + reservedSize);
|
|
5757
|
+
if (this.format._options.onMdat) {
|
|
5758
|
+
this.writer.startTrackingWrites();
|
|
5759
|
+
}
|
|
5760
|
+
this.mdat = mdat(true);
|
|
5761
|
+
this.boxWriter.writeBox(this.mdat);
|
|
5762
|
+
for (const trackData2 of this.trackDatas) {
|
|
5763
|
+
for (const sample2 of trackData2.sampleQueue) {
|
|
5764
|
+
await this.addSampleToTrack(trackData2, sample2);
|
|
5765
|
+
}
|
|
5766
|
+
trackData2.sampleQueue.length = 0;
|
|
5767
|
+
}
|
|
5768
|
+
}
|
|
5769
|
+
await this.addSampleToTrack(trackData, sample);
|
|
5770
|
+
} else {
|
|
5771
|
+
trackData.sampleQueue.push(sample);
|
|
5772
|
+
}
|
|
5773
|
+
}
|
|
5774
|
+
computeSampleTableSizeUpperBound() {
|
|
5775
|
+
assert(this.fastStart === "reserve");
|
|
5776
|
+
let upperBound = 0;
|
|
5777
|
+
for (const trackData of this.trackDatas) {
|
|
5778
|
+
const n = trackData.track.metadata.maximumPacketCount;
|
|
5779
|
+
assert(n !== void 0);
|
|
5780
|
+
upperBound += (4 + 4) * Math.ceil(2 / 3 * n);
|
|
5781
|
+
upperBound += 4 * n;
|
|
5782
|
+
upperBound += (4 + 4) * Math.ceil(2 / 3 * n);
|
|
5783
|
+
upperBound += (4 + 4 + 4) * Math.ceil(2 / 3 * n);
|
|
5784
|
+
upperBound += 4 * n;
|
|
5785
|
+
upperBound += 8 * n;
|
|
5786
|
+
}
|
|
5787
|
+
return upperBound;
|
|
5788
|
+
}
|
|
5730
5789
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
5731
5790
|
async onTrackClose(track) {
|
|
5732
5791
|
const release = await this.mutex.acquire();
|
|
@@ -5766,7 +5825,7 @@ var Mediabunny = (() => {
|
|
|
5766
5825
|
}
|
|
5767
5826
|
}
|
|
5768
5827
|
if (this.fastStart === "in-memory") {
|
|
5769
|
-
|
|
5828
|
+
this.mdat = mdat(false);
|
|
5770
5829
|
let mdatSize;
|
|
5771
5830
|
for (let i = 0; i < 2; i++) {
|
|
5772
5831
|
const movieBox2 = moov(this);
|
|
@@ -5828,11 +5887,22 @@ var Mediabunny = (() => {
|
|
|
5828
5887
|
const { data, start } = this.writer.stopTrackingWrites();
|
|
5829
5888
|
this.format._options.onMdat(data, start);
|
|
5830
5889
|
}
|
|
5831
|
-
if (this.format._options.onMoov) {
|
|
5832
|
-
this.writer.startTrackingWrites();
|
|
5833
|
-
}
|
|
5834
5890
|
const movieBox = moov(this);
|
|
5835
|
-
this.
|
|
5891
|
+
if (this.fastStart === "reserve") {
|
|
5892
|
+
assert(this.ftypSize !== null);
|
|
5893
|
+
this.writer.seek(this.ftypSize);
|
|
5894
|
+
if (this.format._options.onMoov) {
|
|
5895
|
+
this.writer.startTrackingWrites();
|
|
5896
|
+
}
|
|
5897
|
+
this.boxWriter.writeBox(movieBox);
|
|
5898
|
+
const remainingSpace = this.boxWriter.offsets.get(this.mdat) - this.writer.getPos();
|
|
5899
|
+
this.boxWriter.writeBox(free(remainingSpace));
|
|
5900
|
+
} else {
|
|
5901
|
+
if (this.format._options.onMoov) {
|
|
5902
|
+
this.writer.startTrackingWrites();
|
|
5903
|
+
}
|
|
5904
|
+
this.boxWriter.writeBox(movieBox);
|
|
5905
|
+
}
|
|
5836
5906
|
if (this.format._options.onMoov) {
|
|
5837
5907
|
const { data, start } = this.writer.stopTrackingWrites();
|
|
5838
5908
|
this.format._options.onMoov(data, start);
|
|
@@ -6897,10 +6967,8 @@ ${cue.notes ?? ""}`;
|
|
|
6897
6967
|
}
|
|
6898
6968
|
}
|
|
6899
6969
|
async interleaveChunks(isFinalCall = false) {
|
|
6900
|
-
if (!isFinalCall) {
|
|
6901
|
-
|
|
6902
|
-
return;
|
|
6903
|
-
}
|
|
6970
|
+
if (!isFinalCall && !this.allTracksAreKnown()) {
|
|
6971
|
+
return;
|
|
6904
6972
|
}
|
|
6905
6973
|
outer:
|
|
6906
6974
|
while (true) {
|
|
@@ -12410,8 +12478,10 @@ ${cue.notes ?? ""}`;
|
|
|
12410
12478
|
if (!options || typeof options !== "object") {
|
|
12411
12479
|
throw new TypeError("options must be an object.");
|
|
12412
12480
|
}
|
|
12413
|
-
if (options.fastStart !== void 0 && ![false, "in-memory", "fragmented"].includes(options.fastStart)) {
|
|
12414
|
-
throw new TypeError(
|
|
12481
|
+
if (options.fastStart !== void 0 && ![false, "in-memory", "reserve", "fragmented"].includes(options.fastStart)) {
|
|
12482
|
+
throw new TypeError(
|
|
12483
|
+
"options.fastStart, when provided, must be false, 'in-memory', 'reserve', or 'fragmented'."
|
|
12484
|
+
);
|
|
12415
12485
|
}
|
|
12416
12486
|
if (options.minimumFragmentDuration !== void 0 && (!Number.isFinite(options.minimumFragmentDuration) || options.minimumFragmentDuration < 0)) {
|
|
12417
12487
|
throw new TypeError("options.minimumFragmentDuration, when provided, must be a non-negative number.");
|
|
@@ -14381,6 +14451,9 @@ ${cue.notes ?? ""}`;
|
|
|
14381
14451
|
if (metadata.name !== void 0 && typeof metadata.name !== "string") {
|
|
14382
14452
|
throw new TypeError("metadata.name, when provided, must be a string.");
|
|
14383
14453
|
}
|
|
14454
|
+
if (metadata.maximumPacketCount !== void 0 && (!Number.isInteger(metadata.maximumPacketCount) || metadata.maximumPacketCount < 0)) {
|
|
14455
|
+
throw new TypeError("metadata.maximumPacketCount, when provided, must be a non-negative integer.");
|
|
14456
|
+
}
|
|
14384
14457
|
};
|
|
14385
14458
|
var Output = class {
|
|
14386
14459
|
/**
|
|
@@ -18232,6 +18305,7 @@ ${cue.notes ?? ""}`;
|
|
|
18232
18305
|
this.currentCluster = null;
|
|
18233
18306
|
this.currentBlock = null;
|
|
18234
18307
|
this.currentCueTime = null;
|
|
18308
|
+
this.currentDecodingInstruction = null;
|
|
18235
18309
|
this.currentTagTargetIsMovie = true;
|
|
18236
18310
|
this.currentSimpleTagName = null;
|
|
18237
18311
|
this.currentAttachedFile = null;
|
|
@@ -18494,6 +18568,7 @@ ${cue.notes ?? ""}`;
|
|
|
18494
18568
|
let dataSlice = this.reader.requestSlice(dataStartPos, size);
|
|
18495
18569
|
if (dataSlice instanceof Promise) dataSlice = await dataSlice;
|
|
18496
18570
|
const cluster = {
|
|
18571
|
+
segment,
|
|
18497
18572
|
elementStartPos,
|
|
18498
18573
|
elementEndPos: dataStartPos + size,
|
|
18499
18574
|
dataStartPos,
|
|
@@ -18506,8 +18581,8 @@ ${cue.notes ?? ""}`;
|
|
|
18506
18581
|
if (dataSlice) {
|
|
18507
18582
|
this.readContiguousElements(dataSlice);
|
|
18508
18583
|
}
|
|
18509
|
-
for (const [
|
|
18510
|
-
const track =
|
|
18584
|
+
for (const [, trackData] of cluster.trackData) {
|
|
18585
|
+
const track = trackData.track;
|
|
18511
18586
|
assert(trackData.blocks.length > 0);
|
|
18512
18587
|
let blockReferencesExist = false;
|
|
18513
18588
|
let hasLacedBlocks = false;
|
|
@@ -18531,7 +18606,7 @@ ${cue.notes ?? ""}`;
|
|
|
18531
18606
|
const nextEntry = trackData.presentationTimestamps[i + 1];
|
|
18532
18607
|
currentBlock.duration = nextEntry.timestamp - currentBlock.timestamp;
|
|
18533
18608
|
} else if (currentBlock.duration === 0) {
|
|
18534
|
-
if (track
|
|
18609
|
+
if (track.defaultDuration != null) {
|
|
18535
18610
|
if (currentBlock.lacing === 0 /* None */) {
|
|
18536
18611
|
currentBlock.duration = track.defaultDuration;
|
|
18537
18612
|
} else {
|
|
@@ -18547,12 +18622,10 @@ ${cue.notes ?? ""}`;
|
|
|
18547
18622
|
const lastBlock = trackData.blocks[last(trackData.presentationTimestamps).blockIndex];
|
|
18548
18623
|
trackData.startTimestamp = firstBlock.timestamp;
|
|
18549
18624
|
trackData.endTimestamp = lastBlock.timestamp + lastBlock.duration;
|
|
18550
|
-
|
|
18551
|
-
|
|
18552
|
-
|
|
18553
|
-
|
|
18554
|
-
insertSorted(track.clustersWithKeyFrame, cluster, (x) => x.elementStartPos);
|
|
18555
|
-
}
|
|
18625
|
+
insertSorted(track.clusters, cluster, (x) => x.elementStartPos);
|
|
18626
|
+
const hasKeyFrame = trackData.firstKeyFrameTimestamp !== null;
|
|
18627
|
+
if (hasKeyFrame) {
|
|
18628
|
+
insertSorted(track.clustersWithKeyFrame, cluster, (x) => x.elementStartPos);
|
|
18556
18629
|
}
|
|
18557
18630
|
}
|
|
18558
18631
|
insertSorted(segment.clusters, cluster, (x) => x.elementStartPos);
|
|
@@ -18562,7 +18635,12 @@ ${cue.notes ?? ""}`;
|
|
|
18562
18635
|
getTrackDataInCluster(cluster, trackNumber) {
|
|
18563
18636
|
let trackData = cluster.trackData.get(trackNumber);
|
|
18564
18637
|
if (!trackData) {
|
|
18638
|
+
const track = cluster.segment.tracks.find((x) => x.id === trackNumber);
|
|
18639
|
+
if (!track) {
|
|
18640
|
+
return null;
|
|
18641
|
+
}
|
|
18565
18642
|
trackData = {
|
|
18643
|
+
track,
|
|
18566
18644
|
startTimestamp: 0,
|
|
18567
18645
|
endTimestamp: 0,
|
|
18568
18646
|
firstKeyFrameTimestamp: null,
|
|
@@ -18579,6 +18657,10 @@ ${cue.notes ?? ""}`;
|
|
|
18579
18657
|
if (originalBlock.lacing === 0 /* None */) {
|
|
18580
18658
|
continue;
|
|
18581
18659
|
}
|
|
18660
|
+
if (!originalBlock.decoded) {
|
|
18661
|
+
originalBlock.data = this.decodeBlockData(track, originalBlock.data);
|
|
18662
|
+
originalBlock.decoded = true;
|
|
18663
|
+
}
|
|
18582
18664
|
const slice = FileSlice.tempFromBytes(originalBlock.data);
|
|
18583
18665
|
const frameSizes = [];
|
|
18584
18666
|
const frameCount = readU8(slice) + 1;
|
|
@@ -18643,7 +18725,7 @@ ${cue.notes ?? ""}`;
|
|
|
18643
18725
|
for (let i = 0; i < frameCount; i++) {
|
|
18644
18726
|
const frameSize = frameSizes[i];
|
|
18645
18727
|
const frameData = readBytes(slice, frameSize);
|
|
18646
|
-
const blockDuration = originalBlock.duration || frameCount * (track
|
|
18728
|
+
const blockDuration = originalBlock.duration || frameCount * (track.defaultDuration ?? 0);
|
|
18647
18729
|
const frameTimestamp = originalBlock.timestamp + blockDuration * i / frameCount;
|
|
18648
18730
|
const frameDuration = blockDuration / frameCount;
|
|
18649
18731
|
blocks.splice(blockIndex + i, 0, {
|
|
@@ -18652,7 +18734,8 @@ ${cue.notes ?? ""}`;
|
|
|
18652
18734
|
isKeyFrame: originalBlock.isKeyFrame,
|
|
18653
18735
|
referencedTimestamps: originalBlock.referencedTimestamps,
|
|
18654
18736
|
data: frameData,
|
|
18655
|
-
lacing: 0 /* None
|
|
18737
|
+
lacing: 0 /* None */,
|
|
18738
|
+
decoded: true
|
|
18656
18739
|
});
|
|
18657
18740
|
}
|
|
18658
18741
|
blockIndex += frameCount;
|
|
@@ -18776,9 +18859,16 @@ ${cue.notes ?? ""}`;
|
|
|
18776
18859
|
defaultDuration: null,
|
|
18777
18860
|
name: null,
|
|
18778
18861
|
languageCode: UNDETERMINED_LANGUAGE,
|
|
18862
|
+
decodingInstructions: [],
|
|
18779
18863
|
info: null
|
|
18780
18864
|
};
|
|
18781
18865
|
this.readContiguousElements(slice.slice(dataStartPos, size));
|
|
18866
|
+
if (this.currentTrack.decodingInstructions.some((instruction) => {
|
|
18867
|
+
return instruction.data?.type !== "decompress" || instruction.data.algorithm !== 3 /* HeaderStripping */;
|
|
18868
|
+
})) {
|
|
18869
|
+
console.warn(`Track #${this.currentTrack.id} has an unsupported content encoding; dropping.`);
|
|
18870
|
+
this.currentTrack = null;
|
|
18871
|
+
}
|
|
18782
18872
|
if (this.currentTrack && this.currentTrack.id !== -1 && this.currentTrack.codecId && this.currentTrack.info) {
|
|
18783
18873
|
const slashIndex = this.currentTrack.codecId.indexOf("/");
|
|
18784
18874
|
const codecIdWithoutSuffix = slashIndex === -1 ? this.currentTrack.codecId : this.currentTrack.codecId.slice(0, slashIndex);
|
|
@@ -19129,11 +19219,14 @@ ${cue.notes ?? ""}`;
|
|
|
19129
19219
|
if (!this.currentCluster) break;
|
|
19130
19220
|
const trackNumber = readVarInt(slice);
|
|
19131
19221
|
if (trackNumber === null) break;
|
|
19222
|
+
const trackData = this.getTrackDataInCluster(this.currentCluster, trackNumber);
|
|
19223
|
+
if (!trackData) break;
|
|
19132
19224
|
const relativeTimestamp = readI16Be(slice);
|
|
19133
19225
|
const flags = readU8(slice);
|
|
19134
19226
|
const isKeyFrame = !!(flags & 128);
|
|
19135
19227
|
const lacing = flags >> 1 & 3;
|
|
19136
|
-
const
|
|
19228
|
+
const blockData = readBytes(slice, size - (slice.filePos - dataStartPos));
|
|
19229
|
+
const hasDecodingInstructions = trackData.track.decodingInstructions.length > 0;
|
|
19137
19230
|
trackData.blocks.push({
|
|
19138
19231
|
timestamp: relativeTimestamp,
|
|
19139
19232
|
// We'll add the cluster's timestamp to this later
|
|
@@ -19141,8 +19234,9 @@ ${cue.notes ?? ""}`;
|
|
|
19141
19234
|
// Will set later
|
|
19142
19235
|
isKeyFrame,
|
|
19143
19236
|
referencedTimestamps: [],
|
|
19144
|
-
data:
|
|
19145
|
-
lacing
|
|
19237
|
+
data: blockData,
|
|
19238
|
+
lacing,
|
|
19239
|
+
decoded: !hasDecodingInstructions
|
|
19146
19240
|
});
|
|
19147
19241
|
}
|
|
19148
19242
|
;
|
|
@@ -19165,10 +19259,13 @@ ${cue.notes ?? ""}`;
|
|
|
19165
19259
|
if (!this.currentCluster) break;
|
|
19166
19260
|
const trackNumber = readVarInt(slice);
|
|
19167
19261
|
if (trackNumber === null) break;
|
|
19262
|
+
const trackData = this.getTrackDataInCluster(this.currentCluster, trackNumber);
|
|
19263
|
+
if (!trackData) break;
|
|
19168
19264
|
const relativeTimestamp = readI16Be(slice);
|
|
19169
19265
|
const flags = readU8(slice);
|
|
19170
19266
|
const lacing = flags >> 1 & 3;
|
|
19171
|
-
const
|
|
19267
|
+
const blockData = readBytes(slice, size - (slice.filePos - dataStartPos));
|
|
19268
|
+
const hasDecodingInstructions = trackData.track.decodingInstructions.length > 0;
|
|
19172
19269
|
this.currentBlock = {
|
|
19173
19270
|
timestamp: relativeTimestamp,
|
|
19174
19271
|
// We'll add the cluster's timestamp to this later
|
|
@@ -19176,8 +19273,9 @@ ${cue.notes ?? ""}`;
|
|
|
19176
19273
|
// Will set later
|
|
19177
19274
|
isKeyFrame: true,
|
|
19178
19275
|
referencedTimestamps: [],
|
|
19179
|
-
data:
|
|
19180
|
-
lacing
|
|
19276
|
+
data: blockData,
|
|
19277
|
+
lacing,
|
|
19278
|
+
decoded: !hasDecodingInstructions
|
|
19181
19279
|
};
|
|
19182
19280
|
trackData.blocks.push(this.currentBlock);
|
|
19183
19281
|
}
|
|
@@ -19322,10 +19420,119 @@ ${cue.notes ?? ""}`;
|
|
|
19322
19420
|
}
|
|
19323
19421
|
;
|
|
19324
19422
|
break;
|
|
19423
|
+
case 28032 /* ContentEncodings */:
|
|
19424
|
+
{
|
|
19425
|
+
if (!this.currentTrack) break;
|
|
19426
|
+
this.readContiguousElements(slice.slice(dataStartPos, size));
|
|
19427
|
+
this.currentTrack.decodingInstructions.sort((a, b) => b.order - a.order);
|
|
19428
|
+
}
|
|
19429
|
+
;
|
|
19430
|
+
break;
|
|
19431
|
+
case 25152 /* ContentEncoding */:
|
|
19432
|
+
{
|
|
19433
|
+
this.currentDecodingInstruction = {
|
|
19434
|
+
order: 0,
|
|
19435
|
+
scope: 1 /* Block */,
|
|
19436
|
+
data: null
|
|
19437
|
+
};
|
|
19438
|
+
this.readContiguousElements(slice.slice(dataStartPos, size));
|
|
19439
|
+
if (this.currentDecodingInstruction.data) {
|
|
19440
|
+
this.currentTrack.decodingInstructions.push(this.currentDecodingInstruction);
|
|
19441
|
+
}
|
|
19442
|
+
this.currentDecodingInstruction = null;
|
|
19443
|
+
}
|
|
19444
|
+
;
|
|
19445
|
+
break;
|
|
19446
|
+
case 20529 /* ContentEncodingOrder */:
|
|
19447
|
+
{
|
|
19448
|
+
if (!this.currentDecodingInstruction) break;
|
|
19449
|
+
this.currentDecodingInstruction.order = readUnsignedInt(slice, size);
|
|
19450
|
+
}
|
|
19451
|
+
;
|
|
19452
|
+
break;
|
|
19453
|
+
case 20530 /* ContentEncodingScope */:
|
|
19454
|
+
{
|
|
19455
|
+
if (!this.currentDecodingInstruction) break;
|
|
19456
|
+
this.currentDecodingInstruction.scope = readUnsignedInt(slice, size);
|
|
19457
|
+
}
|
|
19458
|
+
;
|
|
19459
|
+
break;
|
|
19460
|
+
case 20532 /* ContentCompression */:
|
|
19461
|
+
{
|
|
19462
|
+
if (!this.currentDecodingInstruction) break;
|
|
19463
|
+
this.currentDecodingInstruction.data = {
|
|
19464
|
+
type: "decompress",
|
|
19465
|
+
algorithm: 0 /* Zlib */,
|
|
19466
|
+
settings: null
|
|
19467
|
+
};
|
|
19468
|
+
this.readContiguousElements(slice.slice(dataStartPos, size));
|
|
19469
|
+
}
|
|
19470
|
+
;
|
|
19471
|
+
break;
|
|
19472
|
+
case 16980 /* ContentCompAlgo */:
|
|
19473
|
+
{
|
|
19474
|
+
if (this.currentDecodingInstruction?.data?.type !== "decompress") break;
|
|
19475
|
+
this.currentDecodingInstruction.data.algorithm = readUnsignedInt(slice, size);
|
|
19476
|
+
}
|
|
19477
|
+
;
|
|
19478
|
+
break;
|
|
19479
|
+
case 16981 /* ContentCompSettings */:
|
|
19480
|
+
{
|
|
19481
|
+
if (this.currentDecodingInstruction?.data?.type !== "decompress") break;
|
|
19482
|
+
this.currentDecodingInstruction.data.settings = readBytes(slice, size);
|
|
19483
|
+
}
|
|
19484
|
+
;
|
|
19485
|
+
break;
|
|
19486
|
+
case 20533 /* ContentEncryption */:
|
|
19487
|
+
{
|
|
19488
|
+
if (!this.currentDecodingInstruction) break;
|
|
19489
|
+
this.currentDecodingInstruction.data = {
|
|
19490
|
+
type: "decrypt"
|
|
19491
|
+
};
|
|
19492
|
+
}
|
|
19493
|
+
;
|
|
19494
|
+
break;
|
|
19325
19495
|
}
|
|
19326
19496
|
slice.filePos = dataStartPos + size;
|
|
19327
19497
|
return true;
|
|
19328
19498
|
}
|
|
19499
|
+
decodeBlockData(track, rawData) {
|
|
19500
|
+
assert(track.decodingInstructions.length > 0);
|
|
19501
|
+
let currentData = rawData;
|
|
19502
|
+
for (const instruction of track.decodingInstructions) {
|
|
19503
|
+
assert(instruction.data);
|
|
19504
|
+
switch (instruction.data.type) {
|
|
19505
|
+
case "decompress":
|
|
19506
|
+
{
|
|
19507
|
+
switch (instruction.data.algorithm) {
|
|
19508
|
+
case 3 /* HeaderStripping */:
|
|
19509
|
+
{
|
|
19510
|
+
if (instruction.data.settings && instruction.data.settings.length > 0) {
|
|
19511
|
+
const prefix = instruction.data.settings;
|
|
19512
|
+
const newData = new Uint8Array(prefix.length + currentData.length);
|
|
19513
|
+
newData.set(prefix, 0);
|
|
19514
|
+
newData.set(currentData, prefix.length);
|
|
19515
|
+
currentData = newData;
|
|
19516
|
+
}
|
|
19517
|
+
}
|
|
19518
|
+
;
|
|
19519
|
+
break;
|
|
19520
|
+
default:
|
|
19521
|
+
{
|
|
19522
|
+
}
|
|
19523
|
+
;
|
|
19524
|
+
}
|
|
19525
|
+
}
|
|
19526
|
+
;
|
|
19527
|
+
break;
|
|
19528
|
+
default:
|
|
19529
|
+
{
|
|
19530
|
+
}
|
|
19531
|
+
;
|
|
19532
|
+
}
|
|
19533
|
+
}
|
|
19534
|
+
return currentData;
|
|
19535
|
+
}
|
|
19329
19536
|
processTagValue(name, value) {
|
|
19330
19537
|
if (!this.currentSegment?.metadataTags) return;
|
|
19331
19538
|
const metadataTags = this.currentSegment.metadataTags;
|
|
@@ -19626,6 +19833,10 @@ ${cue.notes ?? ""}`;
|
|
|
19626
19833
|
const trackData = cluster.trackData.get(this.internalTrack.id);
|
|
19627
19834
|
const block = trackData.blocks[blockIndex];
|
|
19628
19835
|
assert(block);
|
|
19836
|
+
if (!block.decoded) {
|
|
19837
|
+
block.data = this.internalTrack.demuxer.decodeBlockData(this.internalTrack, block.data);
|
|
19838
|
+
block.decoded = true;
|
|
19839
|
+
}
|
|
19629
19840
|
const data = options.metadataOnly ? PLACEHOLDER_DATA : block.data;
|
|
19630
19841
|
const timestamp = block.timestamp / this.internalTrack.segment.timestampFactor;
|
|
19631
19842
|
const duration = block.duration / this.internalTrack.segment.timestampFactor;
|
|
@@ -20297,7 +20508,7 @@ ${cue.notes ?? ""}`;
|
|
|
20297
20508
|
const description = new Uint8Array(
|
|
20298
20509
|
1 + lacingValues.length + firstPacket.data.length + secondPacket.data.length + thirdPacket.data.length
|
|
20299
20510
|
);
|
|
20300
|
-
description[0] =
|
|
20511
|
+
description[0] = 2;
|
|
20301
20512
|
description.set(
|
|
20302
20513
|
lacingValues,
|
|
20303
20514
|
1
|