diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp index e030579f..140ed12b 100644 --- a/taglib/mp4/mp4atom.cpp +++ b/taglib/mp4/mp4atom.cpp @@ -85,7 +85,25 @@ MP4::Atom::Atom(File *file) for(int i = 0; i < numContainers; i++) { if(name == containers[i]) { if(name == "meta") { - file->seek(4, File::Current); + long posAfterMeta = file->tell(); + ByteVector nextSize = file->readBlock(8).mid(4, 4); + static const char *const metaChildrenNames[] = { + "hdlr", "ilst", "mhdr", "ctry", "lang" + }; + bool metaIsFullAtom = true; + for(size_t j = 0; + j < sizeof(metaChildrenNames) / sizeof(metaChildrenNames[0]); + ++j) { + if(nextSize == metaChildrenNames[j]) { + // meta is not a full atom (i.e. not followed by version, flags). It + // is followed by the size and type of the first child atom. + metaIsFullAtom = false; + break; + } + } + // Only skip next four bytes, which contain version and flags, if meta + // is a full atom. + file->seek(posAfterMeta + (metaIsFullAtom ? 4 : 0)); } else if(name == "stsd") { file->seek(8, File::Current); diff --git a/tests/data/non-full-meta.m4a b/tests/data/non-full-meta.m4a new file mode 100644 index 00000000..724cc675 Binary files /dev/null and b/tests/data/non-full-meta.m4a differ diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index 31f99287..14b23e1f 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -66,6 +66,7 @@ class TestMP4 : public CppUnit::TestFixture CPPUNIT_TEST(testWithZeroLengthAtom); CPPUNIT_TEST(testEmptyValuesRemoveItems); CPPUNIT_TEST(testRemoveMetadata); + CPPUNIT_TEST(testNonFullMetaAtom); CPPUNIT_TEST_SUITE_END(); public: @@ -686,6 +687,27 @@ public: TEST_FILE_PATH_C("no-tags.m4a"))); } } + + void testNonFullMetaAtom() + { + { + MP4::File f(TEST_FILE_PATH_C("non-full-meta.m4a")); + CPPUNIT_ASSERT(f.isValid()); + CPPUNIT_ASSERT(f.hasMP4Tag()); + + CPPUNIT_ASSERT(f.tag()->contains("covr")); + MP4::CoverArtList l = f.tag()->item("covr").toCoverArtList(); + CPPUNIT_ASSERT_EQUAL((unsigned int)2, l.size()); + CPPUNIT_ASSERT_EQUAL(MP4::CoverArt::PNG, l[0].format()); + CPPUNIT_ASSERT_EQUAL((unsigned int)79, l[0].data().size()); + CPPUNIT_ASSERT_EQUAL(MP4::CoverArt::JPEG, l[1].format()); + CPPUNIT_ASSERT_EQUAL((unsigned int)287, l[1].data().size()); + + PropertyMap properties = f.properties(); + CPPUNIT_ASSERT_EQUAL(StringList("Test Artist!!!!"), properties["ARTIST"]); + CPPUNIT_ASSERT_EQUAL(StringList("FAAC 1.24"), properties["ENCODEDBY"]); + } + } }; CPPUNIT_TEST_SUITE_REGISTRATION(TestMP4);