From 9981a83c0512e5a29077d5df2f2b29911260dee1 Mon Sep 17 00:00:00 2001 From: eguven Date: Mon, 23 May 2016 02:31:15 -0700 Subject: [PATCH] Fix Ogg/Flac sync exception. Restores input position after flac block size read. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=122978325 --- .../extractor/ogg/OggExtractorFileTests.java | 26 +++++++++++++------ .../exoplayer/testutil/FakeTrackOutput.java | 9 ++++--- .../exoplayer/extractor/ogg/FlacReader.java | 17 +++++++----- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggExtractorFileTests.java b/library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggExtractorFileTests.java index 7342dde691..74361cd65b 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggExtractorFileTests.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggExtractorFileTests.java @@ -43,10 +43,20 @@ public final class OggExtractorFileTests extends InstrumentationTestCase { } public void testFlac() throws Exception { - parseFile(FLAC_TEST_FILE, false, false, false, MimeTypes.AUDIO_FLAC, 2741000, 33); - parseFile(FLAC_TEST_FILE, false, true, false, MimeTypes.AUDIO_FLAC, 2741000, 33); - parseFile(FLAC_TEST_FILE, true, false, true, MimeTypes.AUDIO_FLAC, 2741000, 33); - parseFile(FLAC_TEST_FILE, true, true, true, MimeTypes.AUDIO_FLAC, 2741000, 33); + testFlac(false, false, false); + testFlac(false, true, false); + testFlac(true, false, true); + testFlac(true, true, true); + } + + private void testFlac(boolean simulateIOErrors, boolean simulateUnknownLength, + boolean simulatePartialReads) throws Exception { + FakeTrackOutput trackOutput = parseFile(FLAC_TEST_FILE, simulateIOErrors, simulateUnknownLength, + simulatePartialReads, MimeTypes.AUDIO_FLAC, 2741000, 33); + for (int i = 0; i < 33; i++) { + byte[] sampleData = trackOutput.getSampleData(i); + assertTrue(FlacReader.isAudioPacket(sampleData)); + } } public void testFlacNoSeektable() throws Exception { @@ -56,10 +66,9 @@ public final class OggExtractorFileTests extends InstrumentationTestCase { parseFile(FLAC_NS_TEST_FILE, true, true, true, MimeTypes.AUDIO_FLAC, C.UNSET_TIME_US, 33); } - private void parseFile(String testFile, boolean simulateIOErrors, boolean simulateUnknownLength, - boolean simulatePartialReads, String expectedMimeType, long expectedDuration, - int expectedSampleCount) - throws Exception { + private FakeTrackOutput parseFile(String testFile, boolean simulateIOErrors, + boolean simulateUnknownLength, boolean simulatePartialReads, String expectedMimeType, + long expectedDuration, int expectedSampleCount) throws Exception { byte[] fileData = TestUtil.getByteArray(getInstrumentation(), testFile); FakeExtractorInput input = new FakeExtractorInput.Builder().setData(fileData) .setSimulateIOErrors(simulateIOErrors) @@ -89,6 +98,7 @@ public final class OggExtractorFileTests extends InstrumentationTestCase { assertEquals(expectedDuration != C.UNSET_TIME_US, seekMap.isSeekable()); trackOutput.assertSampleCount(expectedSampleCount); + return trackOutput; } } diff --git a/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeTrackOutput.java b/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeTrackOutput.java index d96d639dec..d2a83d3741 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeTrackOutput.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/testutil/FakeTrackOutput.java @@ -21,7 +21,6 @@ import com.google.android.exoplayer.extractor.TrackOutput; import com.google.android.exoplayer.util.ParsableByteArray; import android.test.MoreAsserts; - import junit.framework.Assert; import java.io.IOException; @@ -86,8 +85,7 @@ public final class FakeTrackOutput implements TrackOutput { } public void assertSample(int index, byte[] data, long timeUs, int flags, byte[] encryptionKey) { - byte[] actualData = Arrays.copyOfRange(sampleData, sampleStartOffsets.get(index), - sampleEndOffsets.get(index)); + byte[] actualData = getSampleData(index); MoreAsserts.assertEquals(data, actualData); Assert.assertEquals(timeUs, (long) sampleTimesUs.get(index)); Assert.assertEquals(flags, (int) sampleFlags.get(index)); @@ -99,6 +97,11 @@ public final class FakeTrackOutput implements TrackOutput { } } + public byte[] getSampleData(int index) { + return Arrays.copyOfRange(sampleData, sampleStartOffsets.get(index), + sampleEndOffsets.get(index)); + } + public void assertEquals(FakeTrackOutput expected) { Assert.assertEquals(expected.format, format); Assert.assertEquals(expected.sampleTimesUs.size(), sampleTimesUs.size()); diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/ogg/FlacReader.java b/library/src/main/java/com/google/android/exoplayer/extractor/ogg/FlacReader.java index 3513484a34..9508aedfc1 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/ogg/FlacReader.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/ogg/FlacReader.java @@ -47,9 +47,14 @@ import java.util.List; data.readUnsignedInt() == 0x464C4143; // ASCII signature "FLAC" } + //@VisibleForTesting + public static boolean isAudioPacket(byte[] data) { + return data[0] == AUDIO_PACKET_TYPE; + } + @Override protected long preparePayload(ParsableByteArray packet) { - if (packet.data[0] != AUDIO_PACKET_TYPE) { + if (!isAudioPacket(packet.data)) { return -1; } return getFlacFrameBlockSize(packet); @@ -71,7 +76,7 @@ import java.util.List; Assertions.checkArgument(flacOggSeeker == null); flacOggSeeker = new FlacOggSeeker(); flacOggSeeker.parseSeekTable(packet); - } else if (data[0] == AUDIO_PACKET_TYPE) { + } else if (isAudioPacket(data)) { if (flacOggSeeker != null) { flacOggSeeker.setFirstFrameOffset(position); setupData.oggSeeker = flacOggSeeker; @@ -96,11 +101,9 @@ import java.util.List; // skip the sample number packet.skipBytes(FRAME_HEADER_SAMPLE_NUMBER_OFFSET); packet.readUtf8EncodedLong(); - if (blockSizeCode == 6) { - return packet.readUnsignedByte() + 1; - } else { - return packet.readUnsignedShort() + 1; - } + int value = blockSizeCode == 6 ? packet.readUnsignedByte() : packet.readUnsignedShort(); + packet.setPosition(0); + return value + 1; case 8: case 9: case 10: