Handle size==0 in MP4 atoms

Issue: #3191

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=165925148
This commit is contained in:
olly 2017-08-21 07:26:50 -07:00 committed by Oliver Woodman
parent 85bc8a08db
commit cc5cfd46c0
6 changed files with 43 additions and 13 deletions

View File

@ -16,7 +16,6 @@
package com.google.android.exoplayer2.extractor.mp4;
import android.test.InstrumentationTestCase;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.testutil.ExtractorAsserts;
import com.google.android.exoplayer2.testutil.ExtractorAsserts.ExtractorFactory;
@ -38,11 +37,6 @@ public final class FragmentedMp4ExtractorTest extends InstrumentationTestCase {
"mp4/sample_fragmented_sei.mp4", getInstrumentation());
}
public void testAtomWithZeroSize() throws Exception {
ExtractorAsserts.assertThrows(getExtractorFactory(), "mp4/sample_fragmented_zero_size_atom.mp4",
getInstrumentation(), ParserException.class);
}
private static ExtractorFactory getExtractorFactory() {
return getExtractorFactory(0);
}

View File

@ -39,9 +39,14 @@ import java.util.List;
public static final int LONG_HEADER_SIZE = 16;
/**
* Value for the first 32 bits of atomSize when the atom size is actually a long value.
* Value for the size field in an atom that defines its size in the largesize field.
*/
public static final int LONG_SIZE_PREFIX = 1;
public static final int DEFINES_LARGE_SIZE = 1;
/**
* Value for the size field in an atom that extends to the end of the file.
*/
public static final int EXTENDS_TO_END_SIZE = 0;
public static final int TYPE_ftyp = Util.getIntegerCodeForString("ftyp");
public static final int TYPE_avc1 = Util.getIntegerCodeForString("avc1");

View File

@ -283,12 +283,22 @@ public final class FragmentedMp4Extractor implements Extractor {
atomType = atomHeader.readInt();
}
if (atomSize == Atom.LONG_SIZE_PREFIX) {
// Read the extended atom size.
if (atomSize == Atom.DEFINES_LARGE_SIZE) {
// Read the large size.
int headerBytesRemaining = Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE;
input.readFully(atomHeader.data, Atom.HEADER_SIZE, headerBytesRemaining);
atomHeaderBytesRead += headerBytesRemaining;
atomSize = atomHeader.readUnsignedLongToLong();
} else if (atomSize == Atom.EXTENDS_TO_END_SIZE) {
// The atom extends to the end of the file. Note that if the atom is within a container we can
// work out its size even if the input length is unknown.
long endPosition = input.getLength();
if (endPosition == C.LENGTH_UNSET && !containerAtoms.isEmpty()) {
endPosition = containerAtoms.peek().endPosition;
}
if (endPosition != C.LENGTH_UNSET) {
atomSize = endPosition - input.getPosition() + atomHeaderBytesRead;
}
}
if (atomSize < atomHeaderBytesRead) {

View File

@ -205,12 +205,26 @@ public final class Mp4Extractor implements Extractor, SeekMap {
atomType = atomHeader.readInt();
}
if (atomSize == Atom.LONG_SIZE_PREFIX) {
// Read the extended atom size.
if (atomSize == Atom.DEFINES_LARGE_SIZE) {
// Read the large size.
int headerBytesRemaining = Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE;
input.readFully(atomHeader.data, Atom.HEADER_SIZE, headerBytesRemaining);
atomHeaderBytesRead += headerBytesRemaining;
atomSize = atomHeader.readUnsignedLongToLong();
} else if (atomSize == Atom.EXTENDS_TO_END_SIZE) {
// The atom extends to the end of the file. Note that if the atom is within a container we can
// work out its size even if the input length is unknown.
long endPosition = input.getLength();
if (endPosition == C.LENGTH_UNSET && !containerAtoms.isEmpty()) {
endPosition = containerAtoms.peek().endPosition;
}
if (endPosition != C.LENGTH_UNSET) {
atomSize = endPosition - input.getPosition() + atomHeaderBytesRead;
}
}
if (atomSize < atomHeaderBytesRead) {
throw new ParserException("Atom size less than header length (unsupported).");
}
if (shouldParseContainerAtom(atomType)) {

View File

@ -104,11 +104,18 @@ import java.io.IOException;
input.peekFully(buffer.data, 0, headerSize);
long atomSize = buffer.readUnsignedInt();
int atomType = buffer.readInt();
if (atomSize == Atom.LONG_SIZE_PREFIX) {
if (atomSize == Atom.DEFINES_LARGE_SIZE) {
// Read the large atom size.
headerSize = Atom.LONG_HEADER_SIZE;
input.peekFully(buffer.data, Atom.HEADER_SIZE, Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE);
buffer.setLimit(Atom.LONG_HEADER_SIZE);
atomSize = buffer.readUnsignedLongToLong();
} else if (atomSize == Atom.EXTENDS_TO_END_SIZE) {
// The atom extends to the end of the file.
long endPosition = input.getLength();
if (endPosition != C.LENGTH_UNSET) {
atomSize = endPosition - input.getPosition() + headerSize;
}
}
if (atomSize < headerSize) {