diff --git a/README.md b/README.md index 48c6816..49c4443 100644 --- a/README.md +++ b/README.md @@ -182,3 +182,4 @@ All supported image and video formats can be found in the table below: - http://netpbm.sourceforge.net/doc/#formats - https://www.garykessler.net/library/file_sigs.html - https://github.com/sannies/mp4parser/blob/c869d076e9cd42aba5a3e35d88827610dec6ca15/examples/src/main/java/com/google/code/mp4parser/example/GetHeight.java +- https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html diff --git a/package-lock.json b/package-lock.json index ad31e8e..1cbb3ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "leather", - "version": "2.1.3", + "version": "2.1.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "leather", - "version": "2.1.3", + "version": "2.1.4", "license": "MIT", "devDependencies": { "ava": "^5.2.0", diff --git a/package.json b/package.json index 1f222cd..bf50ea4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leather", - "version": "2.1.3", + "version": "2.1.4", "description": "A pure JS library for extracting image/video attributes such as width, height, size, and mime type", "author": "Sidney Liebrand", "license": "MIT", diff --git a/src/extractors/mp4.js b/src/extractors/mp4.js index ba2fa80..2ae4b51 100644 --- a/src/extractors/mp4.js +++ b/src/extractors/mp4.js @@ -7,53 +7,46 @@ const MIME_TYPES = { export function attributes(input) { const stream = lazystream(input); + const size = stream.size(); const type = stream.skip(4).take(8).toString('hex'); const mime = MIME_TYPES[type] || 'video/mp4'; stream.goto(0); - const result = Object.assign(parse(stream) ?? {}, { - size: stream.size(), - mime, - }); + const result = Object.assign(parse(stream), {size, mime}); stream.close(); return result; } -function parse(stream, lastTkhd, ftypSize = 32) { +function parse(stream, lastTkhd) { while (stream.more()) { - let size = stream.takeUInt32BE(); + const initialSize = stream.takeUInt32BE(); const header = stream.take(4).toString(); - - if (header === 'ftyp') ftypSize = size; + const size = initialSize === 1 ? stream.takeUInt64BE() : initialSize; if (['moov', 'mdia', 'trak'].includes(header)) { - const result = parse(stream, lastTkhd, ftypSize); + const result = parse(stream, lastTkhd); if (result) return result; - } else if (ftypSize === 28 && header === 'mdat') { - size += stream.skip(4).takeUInt32BE() - size; } else if (header === 'tkhd') { - const pos = stream.position(); lastTkhd = stream.take(size - 8); - stream.goto(pos); + stream.rewind(size - 8); } else if (header === 'hdlr') { - const pos = stream.position(); - const hdlr = stream.skip(8).take(4); - - if (hdlr.includes('vide')) { + if (stream.skip(8).take(4).includes('vide')) { return { width: lastTkhd.readUInt32BE(lastTkhd.length - 8) / 65536, height: lastTkhd.readUInt32BE(lastTkhd.length - 4) / 65536, }; } - stream.goto(pos); + stream.rewind(12); } stream.skip(size - 8); } + + return {width: 0, height: 0}; } diff --git a/src/util.js b/src/util.js index 33e0f06..448be24 100644 --- a/src/util.js +++ b/src/util.js @@ -85,6 +85,7 @@ export function lazystream(file) { take(bytes = 1) { if (isBuffer) { const buffer = reader.subarray(position, position + bytes); + position += buffer.length; return buffer; @@ -97,6 +98,7 @@ export function lazystream(file) { bytes, position ); + position += bytesRead; return buffer; @@ -160,6 +162,13 @@ export function lazystream(file) { return methods.take(4).readUInt32LE(); }, + takeUInt64BE() { + const v1 = methods.takeUInt32BE(); + const v2 = methods.takeUInt32BE(); + + return 0x100000000 * v1 + v2; + }, + takeUInt64LE() { const v1 = methods.takeUInt32LE(); const v2 = methods.takeUInt32LE();