Throw ParserException from parsers when a parse exception occurs.

This commit is contained in:
Oliver Woodman 2015-10-26 15:18:53 +00:00
parent 13aaa5a5db
commit c59fc47565
4 changed files with 56 additions and 34 deletions

View File

@ -22,6 +22,10 @@ import java.io.IOException;
*/
public class ParserException extends IOException {
public ParserException() {
super();
}
public ParserException(String message) {
super(message);
}

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer.extractor.mp4;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.drm.DrmInitData;
import com.google.android.exoplayer.extractor.ChunkIndex;
import com.google.android.exoplayer.extractor.Extractor;
@ -26,7 +27,6 @@ import com.google.android.exoplayer.extractor.SeekMap;
import com.google.android.exoplayer.extractor.TrackOutput;
import com.google.android.exoplayer.extractor.mp4.Atom.ContainerAtom;
import com.google.android.exoplayer.extractor.mp4.Atom.LeafAtom;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.NalUnitUtil;
import com.google.android.exoplayer.util.ParsableByteArray;
@ -234,15 +234,15 @@ public final class FragmentedMp4Extractor implements Extractor {
} else {
// We don't support parsing of leaf atoms that define extended atom sizes, or that have
// lengths greater than Integer.MAX_VALUE.
Assertions.checkState(atomHeaderBytesRead == Atom.HEADER_SIZE);
Assertions.checkState(atomSize <= Integer.MAX_VALUE);
checkState(atomHeaderBytesRead == Atom.HEADER_SIZE);
checkState(atomSize <= Integer.MAX_VALUE);
atomData = new ParsableByteArray((int) atomSize);
System.arraycopy(atomHeader.data, 0, atomData.data, 0, Atom.HEADER_SIZE);
parserState = STATE_READING_ATOM_PAYLOAD;
}
} else {
// We don't support skipping of atoms that have lengths greater than Integer.MAX_VALUE.
Assertions.checkState(atomSize <= Integer.MAX_VALUE);
checkState(atomSize <= Integer.MAX_VALUE);
atomData = null;
parserState = STATE_READING_ATOM_PAYLOAD;
}
@ -265,7 +265,7 @@ public final class FragmentedMp4Extractor implements Extractor {
enterReadingAtomHeaderState();
}
private void onLeafAtomRead(LeafAtom leaf, long inputPosition) {
private void onLeafAtomRead(LeafAtom leaf, long inputPosition) throws ParserException {
if (!containerAtoms.isEmpty()) {
containerAtoms.peek().add(leaf);
} else if (leaf.type == Atom.TYPE_sidx) {
@ -275,7 +275,7 @@ public final class FragmentedMp4Extractor implements Extractor {
}
}
private void onContainerAtomRead(ContainerAtom container) {
private void onContainerAtomRead(ContainerAtom container) throws ParserException {
if (container.type == Atom.TYPE_moov) {
onMoovContainerAtomRead(container);
} else if (container.type == Atom.TYPE_moof) {
@ -285,7 +285,7 @@ public final class FragmentedMp4Extractor implements Extractor {
}
}
private void onMoovContainerAtomRead(ContainerAtom moov) {
private void onMoovContainerAtomRead(ContainerAtom moov) throws ParserException {
List<Atom.LeafAtom> moovChildren = moov.leafChildren;
int moovChildrenSize = moovChildren.size();
@ -308,16 +308,28 @@ public final class FragmentedMp4Extractor implements Extractor {
extendsDefaults = parseTrex(mvex.getLeafAtomOfType(Atom.TYPE_trex).data);
track = AtomParsers.parseTrak(moov.getContainerAtomOfType(Atom.TYPE_trak),
moov.getLeafAtomOfType(Atom.TYPE_mvhd));
Assertions.checkState(track != null);
checkState(track != null);
trackOutput.format(track.mediaFormat);
}
private void onMoofContainerAtomRead(ContainerAtom moof) {
private void onMoofContainerAtomRead(ContainerAtom moof) throws ParserException {
fragmentRun.reset();
parseMoof(track, extendsDefaults, moof, fragmentRun, workaroundFlags, extendedTypeScratch);
sampleIndex = 0;
}
private static void checkState(boolean expression) throws ParserException {
if (!expression) {
throw new ParserException();
}
}
private static void checkState(boolean expression, String errorMessage) throws ParserException {
if (!expression) {
throw new ParserException(errorMessage);
}
}
/**
* Parses a trex atom (defined in 14496-12).
*/
@ -332,9 +344,10 @@ public final class FragmentedMp4Extractor implements Extractor {
}
private static void parseMoof(Track track, DefaultSampleValues extendsDefaults,
ContainerAtom moof, TrackFragment out, int workaroundFlags, byte[] extendedTypeScratch) {
ContainerAtom moof, TrackFragment out, int workaroundFlags, byte[] extendedTypeScratch)
throws ParserException {
// This extractor only supports one traf per moof.
Assertions.checkArgument(1 == moof.getChildAtomOfTypeCount(Atom.TYPE_traf));
checkState(1 == moof.getChildAtomOfTypeCount(Atom.TYPE_traf));
parseTraf(track, extendsDefaults, moof.getContainerAtomOfType(Atom.TYPE_traf),
out, workaroundFlags, extendedTypeScratch);
}
@ -343,9 +356,10 @@ public final class FragmentedMp4Extractor implements Extractor {
* Parses a traf atom (defined in 14496-12).
*/
private static void parseTraf(Track track, DefaultSampleValues extendsDefaults,
ContainerAtom traf, TrackFragment out, int workaroundFlags, byte[] extendedTypeScratch) {
ContainerAtom traf, TrackFragment out, int workaroundFlags, byte[] extendedTypeScratch)
throws ParserException {
// This extractor only supports one trun per traf.
Assertions.checkArgument(1 == traf.getChildAtomOfTypeCount(Atom.TYPE_trun));
checkState(1 == traf.getChildAtomOfTypeCount(Atom.TYPE_trun));
LeafAtom tfdtAtom = traf.getLeafAtomOfType(Atom.TYPE_tfdt);
long decodeTime;
if (tfdtAtom == null || (workaroundFlags & WORKAROUND_IGNORE_TFDT_BOX) != 0) {
@ -387,7 +401,7 @@ public final class FragmentedMp4Extractor implements Extractor {
}
private static void parseSaiz(TrackEncryptionBox encryptionBox, ParsableByteArray saiz,
TrackFragment out) {
TrackFragment out) throws ParserException {
int vectorSize = encryptionBox.initializationVectorSize;
saiz.setPosition(Atom.HEADER_SIZE);
int fullAtom = saiz.readInt();
@ -399,7 +413,7 @@ public final class FragmentedMp4Extractor implements Extractor {
int sampleCount = saiz.readUnsignedIntToInt();
if (sampleCount != out.length) {
throw new IllegalStateException("Length mismatch: " + sampleCount + ", " + out.length);
throw new ParserException("Length mismatch: " + sampleCount + ", " + out.length);
}
int totalSize = 0;
@ -424,7 +438,7 @@ public final class FragmentedMp4Extractor implements Extractor {
* @param saio The saio atom to parse.
* @param out The track fragment to populate with data from the saio atom.
*/
private static void parseSaio(ParsableByteArray saio, TrackFragment out) {
private static void parseSaio(ParsableByteArray saio, TrackFragment out) throws ParserException {
saio.setPosition(Atom.HEADER_SIZE);
int fullAtom = saio.readInt();
int flags = Atom.parseFullAtomFlags(fullAtom);
@ -435,7 +449,7 @@ public final class FragmentedMp4Extractor implements Extractor {
int entryCount = saio.readUnsignedIntToInt();
if (entryCount != 1) {
// We only support one trun element currently, so always expect one entry.
throw new IllegalStateException("Unexpected saio entry count: " + entryCount);
throw new ParserException("Unexpected saio entry count: " + entryCount);
}
int version = Atom.parseFullAtomVersion(fullAtom);
@ -558,7 +572,7 @@ public final class FragmentedMp4Extractor implements Extractor {
}
private static void parseUuid(ParsableByteArray uuid, TrackFragment out,
byte[] extendedTypeScratch) {
byte[] extendedTypeScratch) throws ParserException {
uuid.setPosition(Atom.HEADER_SIZE);
uuid.readBytes(extendedTypeScratch, 0, 16);
@ -573,24 +587,25 @@ public final class FragmentedMp4Extractor implements Extractor {
parseSenc(uuid, 16, out);
}
private static void parseSenc(ParsableByteArray senc, TrackFragment out) {
private static void parseSenc(ParsableByteArray senc, TrackFragment out) throws ParserException {
parseSenc(senc, 0, out);
}
private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out) {
private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out)
throws ParserException {
senc.setPosition(Atom.HEADER_SIZE + offset);
int fullAtom = senc.readInt();
int flags = Atom.parseFullAtomFlags(fullAtom);
if ((flags & 0x01 /* override_track_encryption_box_parameters */) != 0) {
// TODO: Implement this.
throw new IllegalStateException("Overriding TrackEncryptionBox parameters is unsupported");
throw new ParserException("Overriding TrackEncryptionBox parameters is unsupported.");
}
boolean subsampleEncryption = (flags & 0x02 /* use_subsample_encryption */) != 0;
int sampleCount = senc.readUnsignedIntToInt();
if (sampleCount != out.length) {
throw new IllegalStateException("Length mismatch: " + sampleCount + ", " + out.length);
throw new ParserException("Length mismatch: " + sampleCount + ", " + out.length);
}
Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
@ -601,7 +616,8 @@ public final class FragmentedMp4Extractor implements Extractor {
/**
* Parses a sidx atom (defined in 14496-12).
*/
private static ChunkIndex parseSidx(ParsableByteArray atom, long inputPosition) {
private static ChunkIndex parseSidx(ParsableByteArray atom, long inputPosition)
throws ParserException {
atom.setPosition(Atom.HEADER_SIZE);
int fullAtom = atom.readInt();
int version = Atom.parseFullAtomVersion(fullAtom);
@ -633,7 +649,7 @@ public final class FragmentedMp4Extractor implements Extractor {
int type = 0x80000000 & firstInt;
if (type != 0) {
throw new IllegalStateException("Unhandled indirect reference");
throw new ParserException("Unhandled indirect reference");
}
long referenceDuration = atom.readUnsignedInt();
@ -656,7 +672,7 @@ public final class FragmentedMp4Extractor implements Extractor {
private void readEncryptionData(ExtractorInput input) throws IOException, InterruptedException {
int bytesToSkip = (int) (fragmentRun.auxiliaryDataPosition - input.getPosition());
Assertions.checkState(bytesToSkip >= 0, "Offset to encryption data was negative.");
checkState(bytesToSkip >= 0, "Offset to encryption data was negative.");
input.skipFully(bytesToSkip);
fragmentRun.fillEncryptionData(input);
parserState = STATE_READING_SAMPLE_START;
@ -679,13 +695,13 @@ public final class FragmentedMp4Extractor implements Extractor {
private boolean readSample(ExtractorInput input) throws IOException, InterruptedException {
if (sampleIndex == 0) {
int bytesToSkip = (int) (fragmentRun.dataPosition - input.getPosition());
Assertions.checkState(bytesToSkip >= 0, "Offset to sample data was negative.");
checkState(bytesToSkip >= 0, "Offset to sample data was negative.");
input.skipFully(bytesToSkip);
}
if (sampleIndex >= fragmentRun.length) {
int bytesToSkip = (int) (endOfMdatPosition - input.getPosition());
Assertions.checkState(bytesToSkip >= 0, "Offset to end of mdat was negative.");
checkState(bytesToSkip >= 0, "Offset to end of mdat was negative.");
input.skipFully(bytesToSkip);
// We've run out of samples in the current mdat atom.
enterReadingAtomHeaderState();

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer.extractor.webm;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.extractor.ExtractorInput;
import com.google.android.exoplayer.util.Assertions;
@ -100,7 +101,7 @@ import java.util.Stack;
return true;
case TYPE_UNSIGNED_INT:
if (elementContentSize > MAX_INTEGER_ELEMENT_SIZE_BYTES) {
throw new IllegalStateException("Invalid integer size: " + elementContentSize);
throw new ParserException("Invalid integer size: " + elementContentSize);
}
output.integerElement(elementId, readInteger(input, (int) elementContentSize));
elementState = ELEMENT_STATE_READ_ID;
@ -108,14 +109,14 @@ import java.util.Stack;
case TYPE_FLOAT:
if (elementContentSize != VALID_FLOAT32_ELEMENT_SIZE_BYTES
&& elementContentSize != VALID_FLOAT64_ELEMENT_SIZE_BYTES) {
throw new IllegalStateException("Invalid float size: " + elementContentSize);
throw new ParserException("Invalid float size: " + elementContentSize);
}
output.floatElement(elementId, readFloat(input, (int) elementContentSize));
elementState = ELEMENT_STATE_READ_ID;
return true;
case TYPE_STRING:
if (elementContentSize > Integer.MAX_VALUE) {
throw new IllegalStateException("String element size: " + elementContentSize);
throw new ParserException("String element size: " + elementContentSize);
}
output.stringElement(elementId, readString(input, (int) elementContentSize));
elementState = ELEMENT_STATE_READ_ID;
@ -129,7 +130,7 @@ import java.util.Stack;
elementState = ELEMENT_STATE_READ_ID;
break;
default:
throw new IllegalStateException("Invalid element type " + type);
throw new ParserException("Invalid element type " + type);
}
}
}

View File

@ -26,7 +26,6 @@ import com.google.android.exoplayer.extractor.ExtractorOutput;
import com.google.android.exoplayer.extractor.PositionHolder;
import com.google.android.exoplayer.extractor.SeekMap;
import com.google.android.exoplayer.extractor.TrackOutput;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.LongArray;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.NalUnitUtil;
@ -738,7 +737,7 @@ public final class WebmExtractor implements Extractor {
contentSize - blockTrackNumberLength - headerSize - totalSamplesSize;
} else {
// Lacing is always in the range 0--3.
throw new IllegalStateException("Unexpected lacing value: " + lacing);
throw new ParserException("Unexpected lacing value: " + lacing);
}
}
@ -1257,7 +1256,9 @@ public final class WebmExtractor implements Extractor {
// TODO: Deduplicate with AtomParsers.parseAvcCFromParent.
buffer.setPosition(4);
int nalUnitLengthFieldLength = (buffer.readUnsignedByte() & 0x03) + 1;
Assertions.checkState(nalUnitLengthFieldLength != 3);
if (nalUnitLengthFieldLength == 3) {
throw new ParserException();
}
List<byte[]> initializationData = new ArrayList<>();
int numSequenceParameterSets = buffer.readUnsignedByte() & 0x1F;
for (int i = 0; i < numSequenceParameterSets; i++) {