Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions lib/src/parsers/mp4.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class BoxHeader {
String type;

BoxHeader(this.size, this.type);

@override
toString() => 'size: ${size}, type: ${type}';
}

final supportedBox = [
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -125,16 +132,15 @@ 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") {
await parseRecurvise(reader, box);
} 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"]
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion test/mp4/mp4_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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');
});
}
Binary file added test/mp4/track_ftypmp42.m4a
Binary file not shown.