diff --git a/lib/src/parsers/mp4.dart b/lib/src/parsers/mp4.dart index fd151cd..d4fe489 100644 --- a/lib/src/parsers/mp4.dart +++ b/lib/src/parsers/mp4.dart @@ -20,6 +20,9 @@ class BoxHeader { String type; BoxHeader(this.size, this.type); + + @override + toString() => 'size: ${size}, type: ${type}'; } final supportedBox = [ @@ -82,9 +85,13 @@ class MP4Parser extends TagParser { if (supportedBox.contains(box.type)) { await processBox(reader, box); - } else { - // We substract 8 to the box size because we already read the data for + } else if (box.type == "ftyp"){ + // read 4 bytes brand name + reader.readSync(4); + // We substract 4 to the box size because we already read the data for // the box header + reader.setPositionSync(reader.positionSync() + box.size - 4); + } else { reader.setPositionSync(reader.positionSync() + box.size - 8); } } @@ -125,7 +132,8 @@ class MP4Parser extends TagParser { final timeScale = getUint32(bytes.sublist(12, 16)); final timeUnit = getUint32(bytes.sublist(16, 20)); - tags.duration = Duration(seconds: timeUnit ~/ timeScale); + double microseconds = (timeUnit / timeScale) * 1000000; + tags.duration = Duration(microseconds: microseconds.toInt()); } else if (box.type == "udta") { await parseRecurvise(reader, box); } else if (box.type == "ilst") { @@ -133,8 +141,6 @@ class MP4Parser extends TagParser { } else if (["trak", "mdia", "minf", "stbl", "stsd"].contains(box.type)) { await parseRecurvise(reader, box); } else if (box.type == "meta") { - reader.readSync(4); - await parseRecurvise(reader, box); } else if (box.type[0] == "©" || ["gnre", "trkn", "disk", "tmpo", "cpil", "too", "covr", "pgap", "gen"] @@ -198,8 +204,7 @@ class MP4Parser extends TagParser { final name = await _readBox(reader); - final nameValue = - String.fromCharCodes(reader.readSync(name.size - 8).sublist(4)); + final nameValue = String.fromCharCodes(reader.readSync(name.size - 8).sublist(4)); final dataBox = await _readBox(reader); final data = reader.readSync(dataBox.size - 8); final finalValue = String.fromCharCodes(data.sublist(8)); @@ -233,6 +238,7 @@ class MP4Parser extends TagParser { // the `meta` box has 4 additional bytes that are not useful. We skip them if ("meta" == box.type) { offset += 4; + reader.readSync(4); } else if (box.type == "stsd") { offset += 8; reader.readSync(8); diff --git a/test/mp4/mp4_test.dart b/test/mp4/mp4_test.dart index 9db889a..b7a8e7b 100644 --- a/test/mp4/mp4_test.dart +++ b/test/mp4/mp4_test.dart @@ -16,7 +16,7 @@ void main() { // expect(result.bitrate, equals(48000)); expect(result.title, equals("Title")); expect(result.trackNumber, equals(1)); - expect(result.duration, equals(Duration(seconds: 1))); + expect(result.duration, equals(Duration(microseconds: 1021333))); expect(result.totalDisc, equals(1)); expect(result.lyrics, equals("Lyrics")); expect(result.trackTotal, equals(10)); @@ -33,4 +33,10 @@ void main() { expect(result.pictures.first.bytes, File("test/data/cover.png").readAsBytesSync()); }); + test("Parse MP4 file with ftypmp42 container without the cover", () async { + final track = File('./test/mp4/track_ftypmp42.m4a'); + final result = await readMetadata(track, getImage: false); + + expect(result.duration, equals(3392), reason: 'Wrong: Audio duration'); + }); } diff --git a/test/mp4/track_ftypmp42.m4a b/test/mp4/track_ftypmp42.m4a new file mode 100644 index 0000000..1633b4d Binary files /dev/null and b/test/mp4/track_ftypmp42.m4a differ