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");
{
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));
+ }
}
}
CPPUNIT_TEST(testFreeForm);
CPPUNIT_TEST(testUpdateStco);
CPPUNIT_TEST(testSaveExisingWhenIlstIsLast);
+ CPPUNIT_TEST(test64BitAtom);
CPPUNIT_TEST_SUITE_END();
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);