Partial support for 64-bit atoms

We still can't handle actual 64-bit atoms, but we can handle 32-bit sizes
stored in 64 bits.

CCBUG:198730


git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1001897 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
Lukáš Lalinský 2009-07-24 13:08:51 +00:00
parent 097ae0d785
commit 834d9d6b23
4 changed files with 52 additions and 7 deletions

View File

@ -47,10 +47,17 @@ MP4::Atom::Atom(File *file)
length = header.mid(0, 4).toUInt();
if (length == 1) {
debug("MP4: 64-bit atoms are not supported");
length = 0;
file->seek(0, File::End);
return;
long long longLength = file->readBlock(8).toLongLong();
if (longLength >= 8 && longLength <= 0xFFFFFFFF) {
// The atom has a 64-bit length, but it's actually a 32-bit value
length = (long)longLength;
}
else {
debug("MP4: 64-bit atoms are not supported");
length = 0;
file->seek(0, File::End);
return;
}
}
if (length < 8) {
debug("MP4: Invalid atom size");

View File

@ -314,9 +314,20 @@ MP4::Tag::updateParents(AtomList &path, long delta, int ignore)
{
for(unsigned int i = 0; i < path.size() - ignore; i++) {
d->file->seek(path[i]->offset);
long size = d->file->readBlock(4).toUInt() + delta;
d->file->seek(path[i]->offset);
d->file->writeBlock(ByteVector::fromUInt(size));
long size = d->file->readBlock(4).toUInt();
// 64-bit
if (size == 1) {
d->file->seek(4, File::Current); // Skip name
long long longSize = d->file->readBlock(8).toLongLong();
// Seek the offset of the 64-bit size
d->file->seek(path[i]->offset + 8);
d->file->writeBlock(ByteVector::fromLongLong(longSize + delta));
}
// 32-bit
else {
d->file->seek(path[i]->offset);
d->file->writeBlock(ByteVector::fromUInt(size + delta));
}
}
}

BIN
tests/data/64bit.mp4 Normal file

Binary file not shown.

View File

@ -18,6 +18,7 @@ class TestMP4 : public CppUnit::TestFixture
CPPUNIT_TEST(testFreeForm);
CPPUNIT_TEST(testUpdateStco);
CPPUNIT_TEST(testSaveExisingWhenIlstIsLast);
CPPUNIT_TEST(test64BitAtom);
CPPUNIT_TEST_SUITE_END();
public:
@ -118,6 +119,32 @@ public:
deleteFile(filename);
}
void test64BitAtom()
{
string filename = copyFile("64bit", ".mp4");
MP4::File *f = new MP4::File(filename.c_str());
CPPUNIT_ASSERT_EQUAL(true, f->tag()->itemListMap()["cpil"].toBool());
MP4::Atoms *atoms = new MP4::Atoms(f);
MP4::Atom *moov = atoms->atoms[0];
CPPUNIT_ASSERT_EQUAL(long(77), moov->length);
f->tag()->itemListMap()["pgap"] = 1;
f->save();
f = new MP4::File(filename.c_str());
CPPUNIT_ASSERT_EQUAL(true, f->tag()->itemListMap()["cpil"].toBool());
CPPUNIT_ASSERT_EQUAL(true, f->tag()->itemListMap()["pgap"].toBool());
atoms = new MP4::Atoms(f);
moov = atoms->atoms[0];
// original size + 'pgap' size + padding
CPPUNIT_ASSERT_EQUAL(long(77 + 25 + 974), moov->length);
deleteFile(filename);
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestMP4);