mediabunny 1.0.5 → 1.1.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 +147 -46
- package/dist/bundles/mediabunny.min.cjs +4 -4
- package/dist/bundles/mediabunny.min.mjs +3 -3
- package/dist/bundles/mediabunny.mjs +147 -46
- package/dist/mediabunny.d.ts +15 -0
- package/dist/modules/input-format.d.ts.map +1 -1
- package/dist/modules/input-format.js +5 -3
- package/dist/modules/isobmff/isobmff-demuxer.d.ts +2 -0
- package/dist/modules/isobmff/isobmff-demuxer.d.ts.map +1 -1
- package/dist/modules/isobmff/isobmff-demuxer.js +63 -28
- package/dist/modules/matroska/matroska-demuxer.d.ts.map +1 -1
- package/dist/modules/matroska/matroska-demuxer.js +7 -11
- package/dist/modules/media-sink.d.ts.map +1 -1
- package/dist/modules/media-sink.js +1 -0
- package/dist/modules/mp3/mp3-misc.d.ts.map +1 -1
- package/dist/modules/mp3/mp3-misc.js +3 -0
- package/dist/modules/mp3/mp3-reader.js +1 -1
- package/dist/modules/sample.d.ts +15 -0
- package/dist/modules/sample.d.ts.map +1 -1
- package/dist/modules/sample.js +70 -10
- package/package.json +1 -1
- package/src/input-format.ts +5 -3
- package/src/isobmff/isobmff-demuxer.ts +83 -30
- package/src/matroska/matroska-demuxer.ts +7 -12
- package/src/media-sink.ts +1 -0
- package/src/mp3/mp3-misc.ts +4 -0
- package/src/mp3/mp3-reader.ts +1 -1
- package/src/sample.ts +111 -2
|
@@ -6224,6 +6224,9 @@ ${cue.notes ?? ""}`;
|
|
|
6224
6224
|
return null;
|
|
6225
6225
|
}
|
|
6226
6226
|
reader.pos += 1;
|
|
6227
|
+
if (firstByte !== 255) {
|
|
6228
|
+
return null;
|
|
6229
|
+
}
|
|
6227
6230
|
if ((secondByte & 224) !== 224) {
|
|
6228
6231
|
return null;
|
|
6229
6232
|
}
|
|
@@ -7366,18 +7369,52 @@ ${cue.notes ?? ""}`;
|
|
|
7366
7369
|
});
|
|
7367
7370
|
}
|
|
7368
7371
|
}
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7372
|
+
draw(context, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) {
|
|
7373
|
+
let sx = 0;
|
|
7374
|
+
let sy = 0;
|
|
7375
|
+
let sWidth = this.displayWidth;
|
|
7376
|
+
let sHeight = this.displayHeight;
|
|
7377
|
+
let dx = 0;
|
|
7378
|
+
let dy = 0;
|
|
7379
|
+
let dWidth = this.displayWidth;
|
|
7380
|
+
let dHeight = this.displayHeight;
|
|
7381
|
+
if (arg5 !== void 0) {
|
|
7382
|
+
sx = arg1;
|
|
7383
|
+
sy = arg2;
|
|
7384
|
+
sWidth = arg3;
|
|
7385
|
+
sHeight = arg4;
|
|
7386
|
+
dx = arg5;
|
|
7387
|
+
dy = arg6;
|
|
7388
|
+
if (arg7 !== void 0) {
|
|
7389
|
+
dWidth = arg7;
|
|
7390
|
+
dHeight = arg8;
|
|
7391
|
+
} else {
|
|
7392
|
+
dWidth = sWidth;
|
|
7393
|
+
dHeight = sHeight;
|
|
7394
|
+
}
|
|
7395
|
+
} else {
|
|
7396
|
+
dx = arg1;
|
|
7397
|
+
dy = arg2;
|
|
7398
|
+
if (arg3 !== void 0) {
|
|
7399
|
+
dWidth = arg3;
|
|
7400
|
+
dHeight = arg4;
|
|
7401
|
+
}
|
|
7402
|
+
}
|
|
7378
7403
|
if (!(typeof CanvasRenderingContext2D !== "undefined" && context instanceof CanvasRenderingContext2D || typeof OffscreenCanvasRenderingContext2D !== "undefined" && context instanceof OffscreenCanvasRenderingContext2D)) {
|
|
7379
7404
|
throw new TypeError("context must be a CanvasRenderingContext2D or OffscreenCanvasRenderingContext2D.");
|
|
7380
7405
|
}
|
|
7406
|
+
if (!Number.isFinite(sx)) {
|
|
7407
|
+
throw new TypeError("sx must be a number.");
|
|
7408
|
+
}
|
|
7409
|
+
if (!Number.isFinite(sy)) {
|
|
7410
|
+
throw new TypeError("sy must be a number.");
|
|
7411
|
+
}
|
|
7412
|
+
if (!Number.isFinite(sWidth) || sWidth < 0) {
|
|
7413
|
+
throw new TypeError("sWidth must be a non-negative number.");
|
|
7414
|
+
}
|
|
7415
|
+
if (!Number.isFinite(sHeight) || sHeight < 0) {
|
|
7416
|
+
throw new TypeError("sHeight must be a non-negative number.");
|
|
7417
|
+
}
|
|
7381
7418
|
if (!Number.isFinite(dx)) {
|
|
7382
7419
|
throw new TypeError("dx must be a number.");
|
|
7383
7420
|
}
|
|
@@ -7393,6 +7430,26 @@ ${cue.notes ?? ""}`;
|
|
|
7393
7430
|
if (this._closed) {
|
|
7394
7431
|
throw new Error("VideoSample is closed.");
|
|
7395
7432
|
}
|
|
7433
|
+
if (this.rotation === 90) {
|
|
7434
|
+
[sx, sy, sWidth, sHeight] = [
|
|
7435
|
+
sy,
|
|
7436
|
+
this.codedHeight - sx - sWidth,
|
|
7437
|
+
sHeight,
|
|
7438
|
+
sWidth
|
|
7439
|
+
];
|
|
7440
|
+
} else if (this.rotation === 180) {
|
|
7441
|
+
[sx, sy] = [
|
|
7442
|
+
this.codedWidth - sx - sWidth,
|
|
7443
|
+
this.codedHeight - sy - sHeight
|
|
7444
|
+
];
|
|
7445
|
+
} else if (this.rotation === 270) {
|
|
7446
|
+
[sx, sy, sWidth, sHeight] = [
|
|
7447
|
+
this.codedWidth - sy - sHeight,
|
|
7448
|
+
sx,
|
|
7449
|
+
sHeight,
|
|
7450
|
+
sWidth
|
|
7451
|
+
];
|
|
7452
|
+
}
|
|
7396
7453
|
const source = this.toCanvasImageSource();
|
|
7397
7454
|
context.save();
|
|
7398
7455
|
const centerX = dx + dWidth / 2;
|
|
@@ -7403,6 +7460,10 @@ ${cue.notes ?? ""}`;
|
|
|
7403
7460
|
context.scale(1 / aspectRatioChange, aspectRatioChange);
|
|
7404
7461
|
context.drawImage(
|
|
7405
7462
|
source,
|
|
7463
|
+
sx,
|
|
7464
|
+
sy,
|
|
7465
|
+
sWidth,
|
|
7466
|
+
sHeight,
|
|
7406
7467
|
-dWidth / 2,
|
|
7407
7468
|
-dHeight / 2,
|
|
7408
7469
|
dWidth,
|
|
@@ -8367,6 +8428,7 @@ ${cue.notes ?? ""}`;
|
|
|
8367
8428
|
finalizeAndEmitSample(sample) {
|
|
8368
8429
|
sample.setTimestamp(Math.round(sample.timestamp * this.timeResolution) / this.timeResolution);
|
|
8369
8430
|
sample.setDuration(Math.round(sample.duration * this.timeResolution) / this.timeResolution);
|
|
8431
|
+
sample.setRotation(this.rotation);
|
|
8370
8432
|
this.onSample(sample);
|
|
8371
8433
|
}
|
|
8372
8434
|
getDecodeQueueSize() {
|
|
@@ -11823,6 +11885,7 @@ ${cue.notes ?? ""}`;
|
|
|
11823
11885
|
fragmentLookupTable: null,
|
|
11824
11886
|
currentFragmentState: null,
|
|
11825
11887
|
fragments: [],
|
|
11888
|
+
fragmentsWithKeyFrame: [],
|
|
11826
11889
|
editListPreviousSegmentDurations: 0,
|
|
11827
11890
|
editListOffset: 0
|
|
11828
11891
|
};
|
|
@@ -11911,7 +11974,8 @@ ${cue.notes ?? ""}`;
|
|
|
11911
11974
|
continue;
|
|
11912
11975
|
}
|
|
11913
11976
|
if (mediaRate !== 1) {
|
|
11914
|
-
|
|
11977
|
+
console.warn("Unsupported edit list entry: media rate must be 1.");
|
|
11978
|
+
break;
|
|
11915
11979
|
}
|
|
11916
11980
|
track.editListPreviousSegmentDurations = previousSegmentDurations;
|
|
11917
11981
|
track.editListOffset = mediaTime;
|
|
@@ -12099,7 +12163,8 @@ ${cue.notes ?? ""}`;
|
|
|
12099
12163
|
} else if (sampleSize === 16) {
|
|
12100
12164
|
track.info.codec = "pcm-s16be";
|
|
12101
12165
|
} else {
|
|
12102
|
-
|
|
12166
|
+
console.warn(`Unsupported sample size ${sampleSize} for codec 'twos'.`);
|
|
12167
|
+
track.info.codec = null;
|
|
12103
12168
|
}
|
|
12104
12169
|
} else if (lowercaseBoxName === "sowt") {
|
|
12105
12170
|
if (sampleSize === 8) {
|
|
@@ -12107,7 +12172,8 @@ ${cue.notes ?? ""}`;
|
|
|
12107
12172
|
} else if (sampleSize === 16) {
|
|
12108
12173
|
track.info.codec = "pcm-s16";
|
|
12109
12174
|
} else {
|
|
12110
|
-
|
|
12175
|
+
console.warn(`Unsupported sample size ${sampleSize} for codec 'sowt'.`);
|
|
12176
|
+
track.info.codec = null;
|
|
12111
12177
|
}
|
|
12112
12178
|
} else if (lowercaseBoxName === "raw ") {
|
|
12113
12179
|
track.info.codec = "pcm-u8";
|
|
@@ -12327,7 +12393,8 @@ ${cue.notes ?? ""}`;
|
|
|
12327
12393
|
} else if (pcmSampleSize === 32) {
|
|
12328
12394
|
track.info.codec = "pcm-s32";
|
|
12329
12395
|
} else {
|
|
12330
|
-
|
|
12396
|
+
console.warn(`Invalid ipcm sample size ${pcmSampleSize}.`);
|
|
12397
|
+
track.info.codec = null;
|
|
12331
12398
|
}
|
|
12332
12399
|
} else {
|
|
12333
12400
|
if (pcmSampleSize === 16) {
|
|
@@ -12337,7 +12404,8 @@ ${cue.notes ?? ""}`;
|
|
|
12337
12404
|
} else if (pcmSampleSize === 32) {
|
|
12338
12405
|
track.info.codec = "pcm-s32be";
|
|
12339
12406
|
} else {
|
|
12340
|
-
|
|
12407
|
+
console.warn(`Invalid ipcm sample size ${pcmSampleSize}.`);
|
|
12408
|
+
track.info.codec = null;
|
|
12341
12409
|
}
|
|
12342
12410
|
}
|
|
12343
12411
|
} else if (track.info.codec === "pcm-f32be") {
|
|
@@ -12347,7 +12415,8 @@ ${cue.notes ?? ""}`;
|
|
|
12347
12415
|
} else if (pcmSampleSize === 64) {
|
|
12348
12416
|
track.info.codec = "pcm-f64";
|
|
12349
12417
|
} else {
|
|
12350
|
-
|
|
12418
|
+
console.warn(`Invalid fpcm sample size ${pcmSampleSize}.`);
|
|
12419
|
+
track.info.codec = null;
|
|
12351
12420
|
}
|
|
12352
12421
|
} else {
|
|
12353
12422
|
if (pcmSampleSize === 32) {
|
|
@@ -12355,7 +12424,8 @@ ${cue.notes ?? ""}`;
|
|
|
12355
12424
|
} else if (pcmSampleSize === 64) {
|
|
12356
12425
|
track.info.codec = "pcm-f64be";
|
|
12357
12426
|
} else {
|
|
12358
|
-
|
|
12427
|
+
console.warn(`Invalid fpcm sample size ${pcmSampleSize}.`);
|
|
12428
|
+
track.info.codec = null;
|
|
12359
12429
|
}
|
|
12360
12430
|
}
|
|
12361
12431
|
}
|
|
@@ -12505,9 +12575,24 @@ ${cue.notes ?? ""}`;
|
|
|
12505
12575
|
break;
|
|
12506
12576
|
case "stz2":
|
|
12507
12577
|
{
|
|
12508
|
-
|
|
12578
|
+
const track = this.currentTrack;
|
|
12579
|
+
assert(track);
|
|
12580
|
+
if (!track.sampleTable) {
|
|
12581
|
+
break;
|
|
12582
|
+
}
|
|
12583
|
+
this.metadataReader.pos += 4;
|
|
12584
|
+
this.metadataReader.pos += 3;
|
|
12585
|
+
const fieldSize = this.metadataReader.readU8();
|
|
12586
|
+
const sampleCount = this.metadataReader.readU32();
|
|
12587
|
+
const bytes2 = this.metadataReader.readBytes(Math.ceil(sampleCount * fieldSize / 8));
|
|
12588
|
+
const bitstream = new Bitstream(bytes2);
|
|
12589
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
12590
|
+
const sampleSize = bitstream.readBits(fieldSize);
|
|
12591
|
+
track.sampleTable.sampleSizes.push(sampleSize);
|
|
12592
|
+
}
|
|
12509
12593
|
}
|
|
12510
12594
|
;
|
|
12595
|
+
break;
|
|
12511
12596
|
case "stss":
|
|
12512
12597
|
{
|
|
12513
12598
|
const track = this.currentTrack;
|
|
@@ -12705,6 +12790,15 @@ ${cue.notes ?? ""}`;
|
|
|
12705
12790
|
(x) => x.moofOffset
|
|
12706
12791
|
);
|
|
12707
12792
|
this.currentTrack.fragments.splice(insertionIndex + 1, 0, this.currentFragment);
|
|
12793
|
+
const hasKeyFrame = trackData.firstKeyFrameTimestamp !== null;
|
|
12794
|
+
if (hasKeyFrame) {
|
|
12795
|
+
const insertionIndex2 = binarySearchLessOrEqual(
|
|
12796
|
+
this.currentTrack.fragmentsWithKeyFrame,
|
|
12797
|
+
this.currentFragment.moofOffset,
|
|
12798
|
+
(x) => x.moofOffset
|
|
12799
|
+
);
|
|
12800
|
+
this.currentTrack.fragmentsWithKeyFrame.splice(insertionIndex2 + 1, 0, this.currentFragment);
|
|
12801
|
+
}
|
|
12708
12802
|
const { currentFragmentState } = this.currentTrack;
|
|
12709
12803
|
assert(currentFragmentState);
|
|
12710
12804
|
if (currentFragmentState.startTimestamp !== null) {
|
|
@@ -12791,7 +12885,8 @@ ${cue.notes ?? ""}`;
|
|
|
12791
12885
|
assert(this.currentFragment);
|
|
12792
12886
|
assert(track.currentFragmentState);
|
|
12793
12887
|
if (this.currentFragment.trackData.has(track.id)) {
|
|
12794
|
-
|
|
12888
|
+
console.warn("Can't have two trun boxes for the same track in one fragment. Ignoring...");
|
|
12889
|
+
break;
|
|
12795
12890
|
}
|
|
12796
12891
|
const version = this.metadataReader.readU8();
|
|
12797
12892
|
const flags = this.metadataReader.readU24();
|
|
@@ -12819,6 +12914,7 @@ ${cue.notes ?? ""}`;
|
|
|
12819
12914
|
const trackData = {
|
|
12820
12915
|
startTimestamp: 0,
|
|
12821
12916
|
endTimestamp: 0,
|
|
12917
|
+
firstKeyFrameTimestamp: null,
|
|
12822
12918
|
samples: [],
|
|
12823
12919
|
presentationTimestamps: [],
|
|
12824
12920
|
startTimestampIsFinal: false
|
|
@@ -12869,11 +12965,16 @@ ${cue.notes ?? ""}`;
|
|
|
12869
12965
|
currentTimestamp += sampleDuration;
|
|
12870
12966
|
}
|
|
12871
12967
|
trackData.presentationTimestamps = trackData.samples.map((x, i) => ({ presentationTimestamp: x.presentationTimestamp, sampleIndex: i })).sort((a, b) => a.presentationTimestamp - b.presentationTimestamp);
|
|
12872
|
-
for (let i = 0; i < trackData.presentationTimestamps.length
|
|
12873
|
-
const
|
|
12874
|
-
const
|
|
12875
|
-
|
|
12876
|
-
|
|
12968
|
+
for (let i = 0; i < trackData.presentationTimestamps.length; i++) {
|
|
12969
|
+
const currentEntry = trackData.presentationTimestamps[i];
|
|
12970
|
+
const currentSample = trackData.samples[currentEntry.sampleIndex];
|
|
12971
|
+
if (trackData.firstKeyFrameTimestamp === null && currentSample.isKeyFrame) {
|
|
12972
|
+
trackData.firstKeyFrameTimestamp = currentSample.presentationTimestamp;
|
|
12973
|
+
}
|
|
12974
|
+
if (i < trackData.presentationTimestamps.length - 1) {
|
|
12975
|
+
const nextEntry = trackData.presentationTimestamps[i + 1];
|
|
12976
|
+
currentSample.duration = nextEntry.presentationTimestamp - currentEntry.presentationTimestamp;
|
|
12977
|
+
}
|
|
12877
12978
|
}
|
|
12878
12979
|
const firstSample = trackData.samples[trackData.presentationTimestamps[0].sampleIndex];
|
|
12879
12980
|
const lastSample = trackData.samples[last(trackData.presentationTimestamps).sampleIndex];
|
|
@@ -13072,7 +13173,7 @@ ${cue.notes ?? ""}`;
|
|
|
13072
13173
|
while (currentFragment.nextFragment) {
|
|
13073
13174
|
currentFragment = currentFragment.nextFragment;
|
|
13074
13175
|
const trackData2 = currentFragment.trackData.get(this.internalTrack.id);
|
|
13075
|
-
if (trackData2) {
|
|
13176
|
+
if (trackData2 && trackData2.firstKeyFrameTimestamp !== null) {
|
|
13076
13177
|
const fragmentIndex2 = binarySearchExact(
|
|
13077
13178
|
this.internalTrack.fragments,
|
|
13078
13179
|
currentFragment.moofOffset,
|
|
@@ -13080,9 +13181,7 @@ ${cue.notes ?? ""}`;
|
|
|
13080
13181
|
);
|
|
13081
13182
|
assert(fragmentIndex2 !== -1);
|
|
13082
13183
|
const keyFrameIndex = trackData2.samples.findIndex((x) => x.isKeyFrame);
|
|
13083
|
-
|
|
13084
|
-
throw new Error("Not supported: Fragment does not contain key sample.");
|
|
13085
|
-
}
|
|
13184
|
+
assert(keyFrameIndex !== -1);
|
|
13086
13185
|
return {
|
|
13087
13186
|
fragmentIndex: fragmentIndex2,
|
|
13088
13187
|
sampleIndex: keyFrameIndex,
|
|
@@ -13195,24 +13294,29 @@ ${cue.notes ?? ""}`;
|
|
|
13195
13294
|
return { fragmentIndex, sampleIndex, correctSampleFound };
|
|
13196
13295
|
}
|
|
13197
13296
|
findKeySampleInFragmentsForTimestamp(timestampInTimescale) {
|
|
13198
|
-
const
|
|
13297
|
+
const indexInKeyFrameFragments = binarySearchLessOrEqual(
|
|
13199
13298
|
// This array is technically not sorted by start timestamp, but for any reasonable file, it basically is.
|
|
13200
|
-
this.internalTrack.
|
|
13299
|
+
this.internalTrack.fragmentsWithKeyFrame,
|
|
13201
13300
|
timestampInTimescale,
|
|
13202
13301
|
(x) => x.trackData.get(this.internalTrack.id).startTimestamp
|
|
13203
13302
|
);
|
|
13303
|
+
let fragmentIndex = -1;
|
|
13204
13304
|
let sampleIndex = -1;
|
|
13205
13305
|
let correctSampleFound = false;
|
|
13206
|
-
if (
|
|
13207
|
-
const fragment = this.internalTrack.
|
|
13306
|
+
if (indexInKeyFrameFragments !== -1) {
|
|
13307
|
+
const fragment = this.internalTrack.fragmentsWithKeyFrame[indexInKeyFrameFragments];
|
|
13308
|
+
fragmentIndex = binarySearchExact(
|
|
13309
|
+
this.internalTrack.fragments,
|
|
13310
|
+
fragment.moofOffset,
|
|
13311
|
+
(x) => x.moofOffset
|
|
13312
|
+
);
|
|
13313
|
+
assert(fragmentIndex !== -1);
|
|
13208
13314
|
const trackData = fragment.trackData.get(this.internalTrack.id);
|
|
13209
13315
|
const index = findLastIndex(trackData.presentationTimestamps, (x) => {
|
|
13210
13316
|
const sample = trackData.samples[x.sampleIndex];
|
|
13211
13317
|
return sample.isKeyFrame && x.presentationTimestamp <= timestampInTimescale;
|
|
13212
13318
|
});
|
|
13213
|
-
|
|
13214
|
-
throw new Error("Not supported: Fragment does not begin with a key sample.");
|
|
13215
|
-
}
|
|
13319
|
+
assert(index !== -1);
|
|
13216
13320
|
const entry = trackData.presentationTimestamps[index];
|
|
13217
13321
|
sampleIndex = entry.sampleIndex;
|
|
13218
13322
|
correctSampleFound = timestampInTimescale < trackData.endTimestamp;
|
|
@@ -13735,20 +13839,15 @@ ${cue.notes ?? ""}`;
|
|
|
13735
13839
|
trackData.blocks = sortBlocksByReferences(trackData.blocks);
|
|
13736
13840
|
}
|
|
13737
13841
|
trackData.presentationTimestamps = trackData.blocks.map((block, i) => ({ timestamp: block.timestamp, blockIndex: i })).sort((a, b) => a.timestamp - b.timestamp);
|
|
13738
|
-
let hasKeyFrame = false;
|
|
13739
13842
|
for (let i = 0; i < trackData.presentationTimestamps.length; i++) {
|
|
13740
|
-
const
|
|
13741
|
-
const
|
|
13742
|
-
if (
|
|
13743
|
-
|
|
13744
|
-
if (trackData.firstKeyFrameTimestamp === null && block.isKeyFrame) {
|
|
13745
|
-
trackData.firstKeyFrameTimestamp = block.timestamp;
|
|
13746
|
-
}
|
|
13843
|
+
const currentEntry = trackData.presentationTimestamps[i];
|
|
13844
|
+
const currentBlock = trackData.blocks[currentEntry.blockIndex];
|
|
13845
|
+
if (trackData.firstKeyFrameTimestamp === null && currentBlock.isKeyFrame) {
|
|
13846
|
+
trackData.firstKeyFrameTimestamp = currentBlock.timestamp;
|
|
13747
13847
|
}
|
|
13748
13848
|
if (i < trackData.presentationTimestamps.length - 1) {
|
|
13749
13849
|
const nextEntry = trackData.presentationTimestamps[i + 1];
|
|
13750
|
-
|
|
13751
|
-
block.duration = nextBlock.timestamp - block.timestamp;
|
|
13850
|
+
currentBlock.duration = nextEntry.timestamp - currentBlock.timestamp;
|
|
13752
13851
|
}
|
|
13753
13852
|
}
|
|
13754
13853
|
const firstBlock = trackData.blocks[trackData.presentationTimestamps[0].blockIndex];
|
|
@@ -13763,6 +13862,7 @@ ${cue.notes ?? ""}`;
|
|
|
13763
13862
|
(x) => x.elementStartPos
|
|
13764
13863
|
);
|
|
13765
13864
|
track.clusters.splice(insertionIndex2 + 1, 0, cluster);
|
|
13865
|
+
const hasKeyFrame = trackData.firstKeyFrameTimestamp !== null;
|
|
13766
13866
|
if (hasKeyFrame) {
|
|
13767
13867
|
const insertionIndex3 = binarySearchLessOrEqual(
|
|
13768
13868
|
track.clustersWithKeyFrame,
|
|
@@ -14801,7 +14901,7 @@ ${cue.notes ?? ""}`;
|
|
|
14801
14901
|
readNextFrameHeader(until) {
|
|
14802
14902
|
assert(this.fileSize);
|
|
14803
14903
|
until ??= this.fileSize;
|
|
14804
|
-
while (this.pos
|
|
14904
|
+
while (this.pos <= until - FRAME_HEADER_SIZE) {
|
|
14805
14905
|
const word = this.readU32();
|
|
14806
14906
|
this.pos -= 4;
|
|
14807
14907
|
const header = readFrameHeader(word, this);
|
|
@@ -15843,7 +15943,8 @@ ${cue.notes ?? ""}`;
|
|
|
15843
15943
|
return true;
|
|
15844
15944
|
}
|
|
15845
15945
|
mp3Reader.pos = firstHeader.startPos + firstHeader.totalSize;
|
|
15846
|
-
|
|
15946
|
+
await mp3Reader.reader.loadRange(mp3Reader.pos, mp3Reader.pos + FRAME_HEADER_SIZE);
|
|
15947
|
+
const secondHeader = mp3Reader.readNextFrameHeader(mp3Reader.pos + FRAME_HEADER_SIZE);
|
|
15847
15948
|
if (!secondHeader) {
|
|
15848
15949
|
return false;
|
|
15849
15950
|
}
|