Commit 1fa61feb by aquilescanta Committed by Oliver Woodman

Migrate AtomParsers to using new ParserException fields

PiperOrigin-RevId: 375133184
parent e793a903
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.mp4; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.mp4;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.MimeTypes.getMimeTypeFromMp4ObjectType; import static com.google.android.exoplayer2.util.MimeTypes.getMimeTypeFromMp4ObjectType;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import static java.lang.Math.max; import static java.lang.Math.max;
import android.util.Pair; import android.util.Pair;
...@@ -29,10 +30,10 @@ import com.google.android.exoplayer2.audio.Ac3Util; ...@@ -29,10 +30,10 @@ import com.google.android.exoplayer2.audio.Ac3Util;
import com.google.android.exoplayer2.audio.Ac4Util; import com.google.android.exoplayer2.audio.Ac4Util;
import com.google.android.exoplayer2.audio.OpusUtil; import com.google.android.exoplayer2.audio.OpusUtil;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.extractor.ExtractorUtil;
import com.google.android.exoplayer2.extractor.GaplessInfoHolder; import com.google.android.exoplayer2.extractor.GaplessInfoHolder;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.mp4.SmtaMetadataEntry; import com.google.android.exoplayer2.metadata.mp4.SmtaMetadataEntry;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.CodecSpecificDataUtil; import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
...@@ -351,7 +352,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -351,7 +352,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
} else { } else {
@Nullable Atom.LeafAtom stz2Atom = stblAtom.getLeafAtomOfType(Atom.TYPE_stz2); @Nullable Atom.LeafAtom stz2Atom = stblAtom.getLeafAtomOfType(Atom.TYPE_stz2);
if (stz2Atom == null) { if (stz2Atom == null) {
throw new ParserException("Track has no sample table size information"); throw ParserException.createForMalformedContainer(
"Track has no sample table size information", /* cause= */ null);
} }
sampleSizeBox = new Stz2SampleSizeBox(stz2Atom); sampleSizeBox = new Stz2SampleSizeBox(stz2Atom);
} }
...@@ -919,7 +921,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -919,7 +921,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
for (int i = 0; i < numberOfEntries; i++) { for (int i = 0; i < numberOfEntries; i++) {
int childStartPosition = stsd.getPosition(); int childStartPosition = stsd.getPosition();
int childAtomSize = stsd.readInt(); int childAtomSize = stsd.readInt();
Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive");
int childAtomType = stsd.readInt(); int childAtomType = stsd.readInt();
if (childAtomType == Atom.TYPE_avc1 if (childAtomType == Atom.TYPE_avc1
|| childAtomType == Atom.TYPE_avc3 || childAtomType == Atom.TYPE_avc3
...@@ -1105,10 +1107,10 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1105,10 +1107,10 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
// Handle optional terminating four zero bytes in MOV files. // Handle optional terminating four zero bytes in MOV files.
break; break;
} }
Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive");
int childAtomType = parent.readInt(); int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_avcC) { if (childAtomType == Atom.TYPE_avcC) {
Assertions.checkState(mimeType == null); ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = MimeTypes.VIDEO_H264; mimeType = MimeTypes.VIDEO_H264;
parent.setPosition(childStartPosition + Atom.HEADER_SIZE); parent.setPosition(childStartPosition + Atom.HEADER_SIZE);
AvcConfig avcConfig = AvcConfig.parse(parent); AvcConfig avcConfig = AvcConfig.parse(parent);
...@@ -1119,7 +1121,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1119,7 +1121,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
} }
codecs = avcConfig.codecs; codecs = avcConfig.codecs;
} else if (childAtomType == Atom.TYPE_hvcC) { } else if (childAtomType == Atom.TYPE_hvcC) {
Assertions.checkState(mimeType == null); ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = MimeTypes.VIDEO_H265; mimeType = MimeTypes.VIDEO_H265;
parent.setPosition(childStartPosition + Atom.HEADER_SIZE); parent.setPosition(childStartPosition + Atom.HEADER_SIZE);
HevcConfig hevcConfig = HevcConfig.parse(parent); HevcConfig hevcConfig = HevcConfig.parse(parent);
...@@ -1133,16 +1135,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1133,16 +1135,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
mimeType = MimeTypes.VIDEO_DOLBY_VISION; mimeType = MimeTypes.VIDEO_DOLBY_VISION;
} }
} else if (childAtomType == Atom.TYPE_vpcC) { } else if (childAtomType == Atom.TYPE_vpcC) {
Assertions.checkState(mimeType == null); ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = (atomType == Atom.TYPE_vp08) ? MimeTypes.VIDEO_VP8 : MimeTypes.VIDEO_VP9; mimeType = (atomType == Atom.TYPE_vp08) ? MimeTypes.VIDEO_VP8 : MimeTypes.VIDEO_VP9;
} else if (childAtomType == Atom.TYPE_av1C) { } else if (childAtomType == Atom.TYPE_av1C) {
Assertions.checkState(mimeType == null); ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = MimeTypes.VIDEO_AV1; mimeType = MimeTypes.VIDEO_AV1;
} else if (childAtomType == Atom.TYPE_d263) { } else if (childAtomType == Atom.TYPE_d263) {
Assertions.checkState(mimeType == null); ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = MimeTypes.VIDEO_H263; mimeType = MimeTypes.VIDEO_H263;
} else if (childAtomType == Atom.TYPE_esds) { } else if (childAtomType == Atom.TYPE_esds) {
Assertions.checkState(mimeType == null); ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
Pair<@NullableType String, byte @NullableType []> mimeTypeAndInitializationDataBytes = Pair<@NullableType String, byte @NullableType []> mimeTypeAndInitializationDataBytes =
parseEsdsFromParent(parent, childStartPosition); parseEsdsFromParent(parent, childStartPosition);
mimeType = mimeTypeAndInitializationDataBytes.first; mimeType = mimeTypeAndInitializationDataBytes.first;
...@@ -1370,7 +1372,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1370,7 +1372,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
while (childPosition - position < size) { while (childPosition - position < size) {
parent.setPosition(childPosition); parent.setPosition(childPosition);
int childAtomSize = parent.readInt(); int childAtomSize = parent.readInt();
Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive");
int childAtomType = parent.readInt(); int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_mhaC) { if (childAtomType == Atom.TYPE_mhaC) {
// See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord // See ISO_IEC_23008-3;2019 MHADecoderConfigurationRecord
...@@ -1481,12 +1483,13 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1481,12 +1483,13 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
* Returns the position of the esds box within a parent, or {@link C#POSITION_UNSET} if no esds * Returns the position of the esds box within a parent, or {@link C#POSITION_UNSET} if no esds
* box is found * box is found
*/ */
private static int findEsdsPosition(ParsableByteArray parent, int position, int size) { private static int findEsdsPosition(ParsableByteArray parent, int position, int size)
throws ParserException {
int childAtomPosition = parent.getPosition(); int childAtomPosition = parent.getPosition();
while (childAtomPosition - position < size) { while (childAtomPosition - position < size) {
parent.setPosition(childAtomPosition); parent.setPosition(childAtomPosition);
int childAtomSize = parent.readInt(); int childAtomSize = parent.readInt();
Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive");
int childType = parent.readInt(); int childType = parent.readInt();
if (childType == Atom.TYPE_esds) { if (childType == Atom.TYPE_esds) {
return childAtomPosition; return childAtomPosition;
...@@ -1546,12 +1549,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1546,12 +1549,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
*/ */
@Nullable @Nullable
private static Pair<Integer, TrackEncryptionBox> parseSampleEntryEncryptionData( private static Pair<Integer, TrackEncryptionBox> parseSampleEntryEncryptionData(
ParsableByteArray parent, int position, int size) { ParsableByteArray parent, int position, int size) throws ParserException {
int childPosition = parent.getPosition(); int childPosition = parent.getPosition();
while (childPosition - position < size) { while (childPosition - position < size) {
parent.setPosition(childPosition); parent.setPosition(childPosition);
int childAtomSize = parent.readInt(); int childAtomSize = parent.readInt();
Assertions.checkState(childAtomSize > 0, "childAtomSize should be positive"); ExtractorUtil.checkContainerInput(childAtomSize > 0, "childAtomSize must be positive");
int childAtomType = parent.readInt(); int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_sinf) { if (childAtomType == Atom.TYPE_sinf) {
@Nullable @Nullable
...@@ -1568,7 +1571,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1568,7 +1571,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Nullable @Nullable
/* package */ static Pair<Integer, TrackEncryptionBox> parseCommonEncryptionSinfFromParent( /* package */ static Pair<Integer, TrackEncryptionBox> parseCommonEncryptionSinfFromParent(
ParsableByteArray parent, int position, int size) { ParsableByteArray parent, int position, int size) throws ParserException {
int childPosition = position + Atom.HEADER_SIZE; int childPosition = position + Atom.HEADER_SIZE;
int schemeInformationBoxPosition = C.POSITION_UNSET; int schemeInformationBoxPosition = C.POSITION_UNSET;
int schemeInformationBoxSize = 0; int schemeInformationBoxSize = 0;
...@@ -1595,15 +1598,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1595,15 +1598,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|| C.CENC_TYPE_cbc1.equals(schemeType) || C.CENC_TYPE_cbc1.equals(schemeType)
|| C.CENC_TYPE_cens.equals(schemeType) || C.CENC_TYPE_cens.equals(schemeType)
|| C.CENC_TYPE_cbcs.equals(schemeType)) { || C.CENC_TYPE_cbcs.equals(schemeType)) {
Assertions.checkStateNotNull(dataFormat, "frma atom is mandatory"); ExtractorUtil.checkContainerInput(dataFormat != null, "frma atom is mandatory");
Assertions.checkState( ExtractorUtil.checkContainerInput(
schemeInformationBoxPosition != C.POSITION_UNSET, "schi atom is mandatory"); schemeInformationBoxPosition != C.POSITION_UNSET, "schi atom is mandatory");
@Nullable
TrackEncryptionBox encryptionBox = TrackEncryptionBox encryptionBox =
Assertions.checkStateNotNull(
parseSchiFromParent( parseSchiFromParent(
parent, schemeInformationBoxPosition, schemeInformationBoxSize, schemeType), parent, schemeInformationBoxPosition, schemeInformationBoxSize, schemeType);
"tenc atom is mandatory"); ExtractorUtil.checkContainerInput(encryptionBox != null, "tenc atom is mandatory");
return Pair.create(dataFormat, encryptionBox); return Pair.create(dataFormat, castNonNull(encryptionBox));
} else { } else {
return null; return null;
} }
...@@ -1714,7 +1717,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1714,7 +1717,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private int remainingSamplesPerChunkChanges; private int remainingSamplesPerChunkChanges;
public ChunkIterator( public ChunkIterator(
ParsableByteArray stsc, ParsableByteArray chunkOffsets, boolean chunkOffsetsAreLongs) { ParsableByteArray stsc, ParsableByteArray chunkOffsets, boolean chunkOffsetsAreLongs)
throws ParserException {
this.stsc = stsc; this.stsc = stsc;
this.chunkOffsets = chunkOffsets; this.chunkOffsets = chunkOffsets;
this.chunkOffsetsAreLongs = chunkOffsetsAreLongs; this.chunkOffsetsAreLongs = chunkOffsetsAreLongs;
...@@ -1722,7 +1726,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1722,7 +1726,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
length = chunkOffsets.readUnsignedIntToInt(); length = chunkOffsets.readUnsignedIntToInt();
stsc.setPosition(Atom.FULL_HEADER_SIZE); stsc.setPosition(Atom.FULL_HEADER_SIZE);
remainingSamplesPerChunkChanges = stsc.readUnsignedIntToInt(); remainingSamplesPerChunkChanges = stsc.readUnsignedIntToInt();
Assertions.checkState(stsc.readInt() == 1, "first_chunk must be 1"); ExtractorUtil.checkContainerInput(stsc.readInt() == 1, "first_chunk must be 1");
index = -1; index = -1;
} }
......
...@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat; ...@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import org.junit.Test; import org.junit.Test;
...@@ -38,7 +39,7 @@ public final class AtomParsersTest { ...@@ -38,7 +39,7 @@ public final class AtomParsersTest {
Util.getBytesFromHexString(ATOM_HEADER + "00000010" + SAMPLE_COUNT + "0001000200030004"); Util.getBytesFromHexString(ATOM_HEADER + "00000010" + SAMPLE_COUNT + "0001000200030004");
@Test @Test
public void parseCommonEncryptionSinfFromParentIgnoresUnknownSchemeType() { public void parseCommonEncryptionSinfFromParentIgnoresUnknownSchemeType() throws ParserException {
byte[] cencSinf = byte[] cencSinf =
new byte[] { new byte[] {
0, 0, 0, 24, 115, 105, 110, 102, // size (4), 'sinf' (4) 0, 0, 0, 24, 115, 105, 110, 102, // size (4), 'sinf' (4)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment