diff --git a/dev/demux.html b/dev/demux.html index 8391087..3bfb4db 100644 --- a/dev/demux.html +++ b/dev/demux.html @@ -22,7 +22,7 @@ for await (const packet of sink.packets()) { console.log(packet); - if (packet.timestamp > 135) break; + //if (packet.timestamp > 135) break; } /* diff --git a/package-lock.json b/package-lock.json index ed9eeb2..f07e527 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediabunny", - "version": "1.9.2", + "version": "1.9.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mediabunny", - "version": "1.9.2", + "version": "1.9.3", "license": "MPL-2.0", "workspaces": [ "packages/*" @@ -5900,9 +5900,9 @@ } }, "node_modules/mediabunny": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.9.1.tgz", - "integrity": "sha512-DghqcYW2s8LsZ9kErFeZdm6308BEABYs8SkY1z3Y7v3LWgPNvBmkXk7Yt+EKcpEGEFjGgDGoTapOjrrrNh7dQA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.9.2.tgz", + "integrity": "sha512-U3RKZVvU2O7vXVtPf6Q+4XNulkV6fdVOVYMm7V2YTr6PqyqrvUl1eUCTtcrmQESgRi9sFZeXkUR8ln5TS48M2g==", "license": "MPL-2.0", "peer": true, "workspaces": [ @@ -9017,7 +9017,7 @@ }, "packages/mp3-encoder": { "name": "@mediabunny/mp3-encoder", - "version": "1.9.2", + "version": "1.9.3", "license": "MPL-2.0", "devDependencies": { "@types/emscripten": "^1.40.1" diff --git a/package.json b/package.json index b49df22..d0541fb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediabunny", "author": "Vanilagy", - "version": "1.9.2", + "version": "1.9.3", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "type": "module", "workspaces": [ diff --git a/packages/mp3-encoder/package.json b/packages/mp3-encoder/package.json index f2de19e..883ca3c 100644 --- a/packages/mp3-encoder/package.json +++ b/packages/mp3-encoder/package.json @@ -1,7 +1,7 @@ { "name": "@mediabunny/mp3-encoder", "author": "Vanilagy", - "version": "1.9.2", + "version": "1.9.3", "description": "MP3 encoder extension for Mediabunny, based on LAME.", "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", "module": "./dist/bundles/mediabunny-mp3-encoder.mjs", diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts index 0f6c7cb..9a88c43 100644 --- a/src/isobmff/isobmff-demuxer.ts +++ b/src/isobmff/isobmff-demuxer.ts @@ -257,6 +257,9 @@ export class IsobmffDemuxer extends Demuxer { ); const startPos = this.metadataReader.pos; const boxInfo = this.metadataReader.readBoxHeader(); + if (!boxInfo) { + break; + } if (boxInfo.name === 'ftyp') { const majorBrand = this.metadataReader.readAscii(4); @@ -298,7 +301,7 @@ export class IsobmffDemuxer extends Demuxer { this.metadataReader.pos = potentialMfraPos; const boxInfo = this.metadataReader.readBoxHeader(); - if (boxInfo.name === 'mfra') { + if (boxInfo && boxInfo.name === 'mfra') { // We found the mfra box, allowing for much better random access. Let's parse it. await this.metadataReader.reader.loadRange( @@ -462,7 +465,7 @@ export class IsobmffDemuxer extends Demuxer { ); const moofBoxInfo = this.metadataReader.readBoxHeader(); - assert(moofBoxInfo.name === 'moof'); + assert(moofBoxInfo?.name === 'moof'); const contentStart = this.metadataReader.pos; await this.metadataReader.reader.loadRange(contentStart, contentStart + moofBoxInfo.contentSize); @@ -508,7 +511,7 @@ export class IsobmffDemuxer extends Demuxer { let nextFragmentIsFirstFragment = this.metadataReader.pos === 0; - while (this.metadataReader.pos < startPos) { + while (this.metadataReader.pos <= startPos - MIN_BOX_HEADER_SIZE) { if (currentFragment?.nextFragment) { currentFragment = currentFragment.nextFragment; this.metadataReader.pos = currentFragment.moofOffset + currentFragment.moofSize; @@ -519,6 +522,9 @@ export class IsobmffDemuxer extends Demuxer { ); const startPos = this.metadataReader.pos; const boxInfo = this.metadataReader.readBoxHeader(); + if (!boxInfo) { + break; + } if (boxInfo.name === 'moof') { const index = binarySearchExact(this.fragments, startPos, x => x.moofOffset); @@ -568,13 +574,21 @@ export class IsobmffDemuxer extends Demuxer { const startIndex = this.metadataReader.pos; while (this.metadataReader.pos - startIndex <= totalSize - MIN_BOX_HEADER_SIZE) { - this.traverseBox(); + const foundBox = this.traverseBox(); + + if (!foundBox) { + break; + } } } traverseBox() { const startPos = this.metadataReader.pos; const boxInfo = this.metadataReader.readBoxHeader(); + if (!boxInfo) { + return false; + } + const boxEndPos = startPos + boxInfo.totalSize; switch (boxInfo.name) { @@ -825,6 +839,10 @@ export class IsobmffDemuxer extends Demuxer { for (let i = 0; i < entries; i++) { const startPos = this.metadataReader.pos; const sampleBoxInfo = this.metadataReader.readBoxHeader(); + if (!sampleBoxInfo) { + break; + } + const lowercaseBoxName = sampleBoxInfo.name.toLowerCase(); if (track.info.type === 'video') { @@ -1904,6 +1922,7 @@ export class IsobmffDemuxer extends Demuxer { } this.metadataReader.pos = boxEndPos; + return true; } } @@ -2324,8 +2343,12 @@ abstract class IsobmffTrackBacking implements InputTrackBacking { /** Looks for a packet in the fragments while trying to load as few fragments as possible to retrieve it. */ private async performFragmentedLookup( + // This function returns the best-matching sample that is currently loaded. Based on this information, we know + // which fragments we need to load to find the actual match. getBestMatch: () => { fragmentIndex: number; sampleIndex: number; correctSampleFound: boolean }, + // The timestamp with which we can search the lookup table searchTimestamp: number, + // The timestamp for which we know the correct sample will not come after it latestTimestamp: number, options: PacketRetrievalOptions, ): Promise { @@ -2397,6 +2420,9 @@ abstract class IsobmffTrackBacking implements InputTrackBacking { await metadataReader.reader.loadRange(metadataReader.pos, metadataReader.pos + MAX_BOX_HEADER_SIZE); const startPos = metadataReader.pos; const boxInfo = metadataReader.readBoxHeader(); + if (!boxInfo) { + break; + } if (boxInfo.name === 'moof') { const index = binarySearchExact(demuxer.fragments, startPos, x => x.moofOffset); diff --git a/src/isobmff/isobmff-reader.ts b/src/isobmff/isobmff-reader.ts index 425059b..bbcd541 100644 --- a/src/isobmff/isobmff-reader.ts +++ b/src/isobmff/isobmff-reader.ts @@ -132,6 +132,11 @@ export class IsobmffReader { headerSize = 16; } - return { name, totalSize, headerSize, contentSize: totalSize - headerSize }; + const contentSize = totalSize - headerSize; + if (contentSize < 0) { + return null; // Hardly a box is it + } + + return { name, totalSize, headerSize, contentSize }; } } diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index bb6f7ae..46632cd 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -760,6 +760,7 @@ export class MatroskaDemuxer extends Demuxer { while (reader.pos - startIndex <= totalSize - MIN_HEADER_SIZE) { const foundElement = this.traverseElement(reader); + if (!foundElement) { break; }