Throw ParserException if parsing unsupported media

This is for consistency with what we do elsewhere;
specifically in FragmentedMp4Extractor.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=163974960
This commit is contained in:
olly 2017-08-02 07:07:38 -07:00 committed by Oliver Woodman
parent 22ea9ed687
commit 49b83c01ca
10 changed files with 44 additions and 27 deletions

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.extractor.ts; package com.google.android.exoplayer2.extractor.ts;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator;
import com.google.android.exoplayer2.testutil.FakeExtractorOutput; import com.google.android.exoplayer2.testutil.FakeExtractorOutput;
import com.google.android.exoplayer2.testutil.FakeTrackOutput; import com.google.android.exoplayer2.testutil.FakeTrackOutput;
@ -154,20 +155,20 @@ public class AdtsReaderTest extends TestCase {
} }
} }
public void testAdtsDataOnly() throws Exception { public void testAdtsDataOnly() throws ParserException {
data.setPosition(ID3_DATA_1.length + ID3_DATA_2.length); data.setPosition(ID3_DATA_1.length + ID3_DATA_2.length);
feed(); feed();
assertSampleCounts(0, 1); assertSampleCounts(0, 1);
adtsOutput.assertSample(0, ADTS_CONTENT, 0, C.BUFFER_FLAG_KEY_FRAME, null); adtsOutput.assertSample(0, ADTS_CONTENT, 0, C.BUFFER_FLAG_KEY_FRAME, null);
} }
private void feedLimited(int limit) { private void feedLimited(int limit) throws ParserException {
maybeStartPacket(); maybeStartPacket();
data.setLimit(limit); data.setLimit(limit);
feed(); feed();
} }
private void feed() { private void feed() throws ParserException {
maybeStartPacket(); maybeStartPacket();
adtsReader.consume(data); adtsReader.consume(data);
} }

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.flv;
import android.util.Pair; import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.CodecSpecificDataUtil; import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
@ -85,7 +86,7 @@ import java.util.Collections;
} }
@Override @Override
protected void parsePayload(ParsableByteArray data, long timeUs) { protected void parsePayload(ParsableByteArray data, long timeUs) throws ParserException {
if (audioFormat == AUDIO_FORMAT_MP3) { if (audioFormat == AUDIO_FORMAT_MP3) {
int sampleSize = data.bytesLeft(); int sampleSize = data.bytesLeft();
output.sampleData(data, sampleSize); output.sampleData(data, sampleSize);

View File

@ -816,7 +816,7 @@ import java.util.List;
private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType, int position, private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType, int position,
int size, int trackId, String language, boolean isQuickTime, DrmInitData drmInitData, int size, int trackId, String language, boolean isQuickTime, DrmInitData drmInitData,
StsdData out, int entryIndex) { StsdData out, int entryIndex) throws ParserException {
parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE); parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
int quickTimeSoundDescriptionVersion = 0; int quickTimeSoundDescriptionVersion = 0;

View File

@ -19,6 +19,7 @@ import android.util.Log;
import android.util.Pair; import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.DummyTrackOutput; import com.google.android.exoplayer2.extractor.DummyTrackOutput;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
@ -128,7 +129,7 @@ public final class AdtsReader implements ElementaryStreamReader {
} }
@Override @Override
public void consume(ParsableByteArray data) { public void consume(ParsableByteArray data) throws ParserException {
while (data.bytesLeft() > 0) { while (data.bytesLeft() > 0) {
switch (state) { switch (state) {
case STATE_FINDING_SAMPLE: case STATE_FINDING_SAMPLE:
@ -276,7 +277,7 @@ public final class AdtsReader implements ElementaryStreamReader {
/** /**
* Parses the sample header. * Parses the sample header.
*/ */
private void parseAdtsHeader() { private void parseAdtsHeader() throws ParserException {
adtsScratch.setPosition(0); adtsScratch.setPosition(0);
if (!hasOutputFormat) { if (!hasOutputFormat) {

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.extractor.ts; package com.google.android.exoplayer2.extractor.ts;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
@ -50,8 +51,9 @@ public interface ElementaryStreamReader {
* Consumes (possibly partial) data from the current packet. * Consumes (possibly partial) data from the current packet.
* *
* @param data The data to consume. * @param data The data to consume.
* @throws ParserException If the data could not be parsed.
*/ */
void consume(ParsableByteArray data); void consume(ParsableByteArray data) throws ParserException;
/** /**
* Called when a packet ends. * Called when a packet ends.

View File

@ -19,6 +19,7 @@ import android.support.annotation.Nullable;
import android.util.Pair; import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator;
@ -98,7 +99,7 @@ public final class LatmReader implements ElementaryStreamReader {
} }
@Override @Override
public void consume(ParsableByteArray data) { public void consume(ParsableByteArray data) throws ParserException {
int bytesToRead; int bytesToRead;
while (data.bytesLeft() > 0) { while (data.bytesLeft() > 0) {
switch (state) { switch (state) {
@ -148,7 +149,7 @@ public final class LatmReader implements ElementaryStreamReader {
* *
* @param data A {@link ParsableBitArray} containing the AudioMuxElement's bytes. * @param data A {@link ParsableBitArray} containing the AudioMuxElement's bytes.
*/ */
private void parseAudioMuxElement(ParsableBitArray data) { private void parseAudioMuxElement(ParsableBitArray data) throws ParserException {
boolean useSameStreamMux = data.readBit(); boolean useSameStreamMux = data.readBit();
if (!useSameStreamMux) { if (!useSameStreamMux) {
streamMuxRead = true; streamMuxRead = true;
@ -159,7 +160,7 @@ public final class LatmReader implements ElementaryStreamReader {
if (audioMuxVersionA == 0) { if (audioMuxVersionA == 0) {
if (numSubframes != 0) { if (numSubframes != 0) {
throw new UnsupportedOperationException(); throw new ParserException();
} }
int muxSlotLengthBytes = parsePayloadLengthInfo(data); int muxSlotLengthBytes = parsePayloadLengthInfo(data);
parsePayloadMux(data, muxSlotLengthBytes); parsePayloadMux(data, muxSlotLengthBytes);
@ -167,14 +168,14 @@ public final class LatmReader implements ElementaryStreamReader {
data.skipBits((int) otherDataLenBits); data.skipBits((int) otherDataLenBits);
} }
} else { } else {
throw new UnsupportedOperationException(); // Not defined by ISO/IEC 14496-3:2009. throw new ParserException(); // Not defined by ISO/IEC 14496-3:2009.
} }
} }
/** /**
* Parses a StreamMuxConfig as defined in ISO/IEC 14496-3:2009 Section 1.7.3.1, Table 1.42. * Parses a StreamMuxConfig as defined in ISO/IEC 14496-3:2009 Section 1.7.3.1, Table 1.42.
*/ */
private void parseStreamMuxConfig(ParsableBitArray data) { private void parseStreamMuxConfig(ParsableBitArray data) throws ParserException {
audioMuxVersion = data.readBits(1); audioMuxVersion = data.readBits(1);
audioMuxVersionA = audioMuxVersion == 1 ? data.readBits(1) : 0; audioMuxVersionA = audioMuxVersion == 1 ? data.readBits(1) : 0;
if (audioMuxVersionA == 0) { if (audioMuxVersionA == 0) {
@ -182,13 +183,13 @@ public final class LatmReader implements ElementaryStreamReader {
latmGetValue(data); // Skip taraBufferFullness. latmGetValue(data); // Skip taraBufferFullness.
} }
if (!data.readBit()) { if (!data.readBit()) {
throw new UnsupportedOperationException(); throw new ParserException();
} }
numSubframes = data.readBits(6); numSubframes = data.readBits(6);
int numProgram = data.readBits(4); int numProgram = data.readBits(4);
int numLayer = data.readBits(3); int numLayer = data.readBits(3);
if (numProgram != 0 || numLayer != 0) { if (numProgram != 0 || numLayer != 0) {
throw new UnsupportedOperationException(); throw new ParserException();
} }
if (audioMuxVersion == 0) { if (audioMuxVersion == 0) {
int startPosition = data.getPosition(); int startPosition = data.getPosition();
@ -228,7 +229,7 @@ public final class LatmReader implements ElementaryStreamReader {
data.skipBits(8); // crcCheckSum. data.skipBits(8); // crcCheckSum.
} }
} else { } else {
throw new UnsupportedOperationException(); // This is not defined by ISO/IEC 14496-3:2009. throw new ParserException(); // This is not defined by ISO/IEC 14496-3:2009.
} }
} }
@ -253,7 +254,7 @@ public final class LatmReader implements ElementaryStreamReader {
} }
} }
private int parseAudioSpecificConfig(ParsableBitArray data) { private int parseAudioSpecificConfig(ParsableBitArray data) throws ParserException {
int bitsLeft = data.bitsLeft(); int bitsLeft = data.bitsLeft();
Pair<Integer, Integer> config = CodecSpecificDataUtil.parseAacAudioSpecificConfig(data); Pair<Integer, Integer> config = CodecSpecificDataUtil.parseAacAudioSpecificConfig(data);
sampleRateHz = config.first; sampleRateHz = config.first;
@ -261,7 +262,7 @@ public final class LatmReader implements ElementaryStreamReader {
return bitsLeft - data.bitsLeft(); return bitsLeft - data.bitsLeft();
} }
private int parsePayloadLengthInfo(ParsableBitArray data) { private int parsePayloadLengthInfo(ParsableBitArray data) throws ParserException {
int muxSlotLengthBytes = 0; int muxSlotLengthBytes = 0;
// Assuming single program and single layer. // Assuming single program and single layer.
if (frameLengthType == 0) { if (frameLengthType == 0) {
@ -272,7 +273,7 @@ public final class LatmReader implements ElementaryStreamReader {
} while (tmp == 255); } while (tmp == 255);
return muxSlotLengthBytes; return muxSlotLengthBytes;
} else { } else {
throw new UnsupportedOperationException(); throw new ParserException();
} }
} }

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
import android.util.Log; import android.util.Log;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
@ -77,7 +78,8 @@ public final class PesReader implements TsPayloadReader {
} }
@Override @Override
public final void consume(ParsableByteArray data, boolean payloadUnitStartIndicator) { public final void consume(ParsableByteArray data, boolean payloadUnitStartIndicator)
throws ParserException {
if (payloadUnitStartIndicator) { if (payloadUnitStartIndicator) {
switch (state) { switch (state) {
case STATE_FINDING_HEADER: case STATE_FINDING_HEADER:

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
import android.util.SparseArray; import android.util.SparseArray;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
@ -30,7 +31,7 @@ import com.google.android.exoplayer2.util.TimestampAdjuster;
import java.io.IOException; import java.io.IOException;
/** /**
* Facilitates the extraction of data from the MPEG-2 TS container format. * Facilitates the extraction of data from the MPEG-2 PS container format.
*/ */
public final class PsExtractor implements Extractor { public final class PsExtractor implements Extractor {
@ -275,8 +276,9 @@ public final class PsExtractor implements Extractor {
* Consumes the payload of a PS packet. * Consumes the payload of a PS packet.
* *
* @param data The PES packet. The position will be set to the start of the payload. * @param data The PES packet. The position will be set to the start of the payload.
* @throws ParserException If the payload could not be parsed.
*/ */
public void consume(ParsableByteArray data) { public void consume(ParsableByteArray data) throws ParserException {
data.readBytes(pesScratch.data, 0, 3); data.readBytes(pesScratch.data, 0, 3);
pesScratch.setPosition(0); pesScratch.setPosition(0);
parseHeader(); parseHeader();

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.extractor.ts; package com.google.android.exoplayer2.extractor.ts;
import android.util.SparseArray; import android.util.SparseArray;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
@ -196,7 +197,8 @@ public interface TsPayloadReader {
* *
* @param data The TS packet. The position will be set to the start of the payload. * @param data The TS packet. The position will be set to the start of the payload.
* @param payloadUnitStartIndicator Whether payloadUnitStartIndicator was set on the TS packet. * @param payloadUnitStartIndicator Whether payloadUnitStartIndicator was set on the TS packet.
* @throws ParserException If the payload could not be parsed.
*/ */
void consume(ParsableByteArray data, boolean payloadUnitStartIndicator); void consume(ParsableByteArray data, boolean payloadUnitStartIndicator) throws ParserException;
} }

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.util;
import android.util.Pair; import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -85,8 +86,10 @@ public final class CodecSpecificDataUtil {
* *
* @param audioSpecificConfig A byte array containing the AudioSpecificConfig to parse. * @param audioSpecificConfig A byte array containing the AudioSpecificConfig to parse.
* @return A pair consisting of the sample rate in Hz and the channel count. * @return A pair consisting of the sample rate in Hz and the channel count.
* @throws ParserException If the AudioSpecificConfig cannot be parsed as it's not supported.
*/ */
public static Pair<Integer, Integer> parseAacAudioSpecificConfig(byte[] audioSpecificConfig) { public static Pair<Integer, Integer> parseAacAudioSpecificConfig(byte[] audioSpecificConfig)
throws ParserException {
return parseAacAudioSpecificConfig(new ParsableBitArray(audioSpecificConfig)); return parseAacAudioSpecificConfig(new ParsableBitArray(audioSpecificConfig));
} }
@ -96,8 +99,10 @@ public final class CodecSpecificDataUtil {
* @param bitArray A {@link ParsableBitArray} containing the AudioSpecificConfig to parse. The * @param bitArray A {@link ParsableBitArray} containing the AudioSpecificConfig to parse. The
* position is advanced to the end of the AudioSpecificConfig. * position is advanced to the end of the AudioSpecificConfig.
* @return A pair consisting of the sample rate in Hz and the channel count. * @return A pair consisting of the sample rate in Hz and the channel count.
* @throws ParserException If the AudioSpecificConfig cannot be parsed as it's not supported.
*/ */
public static Pair<Integer, Integer> parseAacAudioSpecificConfig(ParsableBitArray bitArray) { public static Pair<Integer, Integer> parseAacAudioSpecificConfig(ParsableBitArray bitArray)
throws ParserException {
int audioObjectType = getAacAudioObjectType(bitArray); int audioObjectType = getAacAudioObjectType(bitArray);
int sampleRate = getAacSamplingFrequency(bitArray); int sampleRate = getAacSamplingFrequency(bitArray);
int channelConfiguration = bitArray.readBits(4); int channelConfiguration = bitArray.readBits(4);
@ -131,7 +136,7 @@ public final class CodecSpecificDataUtil {
parseGaSpecificConfig(bitArray, audioObjectType, channelConfiguration); parseGaSpecificConfig(bitArray, audioObjectType, channelConfiguration);
break; break;
default: default:
throw new UnsupportedOperationException(); throw new ParserException("Unsupported audio object type: " + audioObjectType);
} }
switch (audioObjectType) { switch (audioObjectType) {
case 17: case 17:
@ -142,7 +147,7 @@ public final class CodecSpecificDataUtil {
case 23: case 23:
int epConfig = bitArray.readBits(2); int epConfig = bitArray.readBits(2);
if (epConfig == 2 || epConfig == 3) { if (epConfig == 2 || epConfig == 3) {
throw new UnsupportedOperationException(); throw new ParserException("Unsupported epConfig: " + epConfig);
} }
break; break;
} }