From d745384d9935cf2db3296bab06e12ca1ea5fe2b8 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Fri, 10 Apr 2015 22:55:12 +0100 Subject: [PATCH] Change decodeOnly to be a sample flag. --- .../java/com/google/android/exoplayer/C.java | 5 ++++ .../exoplayer/MediaCodecTrackRenderer.java | 6 ++-- .../android/exoplayer/SampleHolder.java | 30 ++++++++++++++----- .../exoplayer/chunk/ChunkSampleSource.java | 3 +- .../chunk/parser/webm/WebmExtractor.java | 4 +-- .../exoplayer/hls/HlsSampleSource.java | 4 ++- .../hls/parser/RollingSampleBuffer.java | 2 +- .../exoplayer/hls/parser/SampleQueue.java | 6 ++-- .../source/FrameworkSampleExtractor.java | 3 +- .../exoplayer/text/TextTrackRenderer.java | 2 +- .../exoplayer/text/eia608/Eia608Parser.java | 2 +- .../chunk/parser/webm/WebmExtractorTest.java | 6 ++-- 12 files changed, 47 insertions(+), 26 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/C.java b/library/src/main/java/com/google/android/exoplayer/C.java index a6d60b4ef7..8ff7888ad0 100644 --- a/library/src/main/java/com/google/android/exoplayer/C.java +++ b/library/src/main/java/com/google/android/exoplayer/C.java @@ -55,6 +55,11 @@ public final class C { @SuppressWarnings("InlinedApi") public static final int SAMPLE_FLAG_ENCRYPTED = MediaExtractor.SAMPLE_FLAG_ENCRYPTED; + /** + * Indicates that a sample should be decoded but not rendered. + */ + public static final int SAMPLE_FLAG_DECODE_ONLY = 0x8000000; + /** * @see MediaCodec#CRYPTO_MODE_AES_CTR */ diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java index f7402bf8e6..c46e688b87 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java @@ -604,7 +604,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { if (waitingForFirstSyncFrame) { // TODO: Find out if it's possible to supply samples prior to the first sync // frame for HE-AAC. - if ((sampleHolder.flags & C.SAMPLE_FLAG_SYNC) == 0) { + if (!sampleHolder.isSyncFrame()) { sampleHolder.data.clear(); if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) { // The buffer we just cleared contained reconfiguration data. We need to re-write this @@ -615,7 +615,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { } waitingForFirstSyncFrame = false; } - boolean sampleEncrypted = (sampleHolder.flags & C.SAMPLE_FLAG_ENCRYPTED) != 0; + boolean sampleEncrypted = sampleHolder.isEncrypted(); waitingForKeys = shouldWaitForKeys(sampleEncrypted); if (waitingForKeys) { return false; @@ -624,7 +624,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { int bufferSize = sampleHolder.data.position(); int adaptiveReconfigurationBytes = bufferSize - sampleHolder.size; long presentationTimeUs = sampleHolder.timeUs; - if (sampleHolder.decodeOnly) { + if (sampleHolder.isDecodeOnly()) { decodeOnlyPresentationTimestamps.add(presentationTimeUs); } if (sampleEncrypted) { diff --git a/library/src/main/java/com/google/android/exoplayer/SampleHolder.java b/library/src/main/java/com/google/android/exoplayer/SampleHolder.java index d548ea163a..59873e5921 100644 --- a/library/src/main/java/com/google/android/exoplayer/SampleHolder.java +++ b/library/src/main/java/com/google/android/exoplayer/SampleHolder.java @@ -50,8 +50,8 @@ public final class SampleHolder { public int size; /** - * Flags that accompany the sample. A combination of {@link C#SAMPLE_FLAG_SYNC} and - * {@link C#SAMPLE_FLAG_ENCRYPTED} + * Flags that accompany the sample. A combination of {@link C#SAMPLE_FLAG_SYNC}, + * {@link C#SAMPLE_FLAG_ENCRYPTED} and {@link C#SAMPLE_FLAG_DECODE_ONLY}. */ public int flags; @@ -60,11 +60,6 @@ public final class SampleHolder { */ public long timeUs; - /** - * If true then the sample should be decoded, but should not be presented. - */ - public boolean decodeOnly; - private final int bufferReplacementMode; /** @@ -95,6 +90,27 @@ public final class SampleHolder { return false; } + /** + * Returns whether {@link #flags} has {@link C#SAMPLE_FLAG_ENCRYPTED} set. + */ + public boolean isEncrypted() { + return (flags & C.SAMPLE_FLAG_ENCRYPTED) != 0; + } + + /** + * Returns whether {@link #flags} has {@link C#SAMPLE_FLAG_DECODE_ONLY} set. + */ + public boolean isDecodeOnly() { + return (flags & C.SAMPLE_FLAG_DECODE_ONLY) != 0; + } + + /** + * Returns whether {@link #flags} has {@link C#SAMPLE_FLAG_SYNC} set. + */ + public boolean isSyncFrame() { + return (flags & C.SAMPLE_FLAG_SYNC) != 0; + } + /** * Clears {@link #data}. Does nothing if {@link #data} is null. */ diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java index c50f3d7168..581513b6ae 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java @@ -358,7 +358,8 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { } if (mediaChunk.read(sampleHolder)) { - sampleHolder.decodeOnly = frameAccurateSeeking && sampleHolder.timeUs < lastSeekPositionUs; + boolean decodeOnly = frameAccurateSeeking && sampleHolder.timeUs < lastSeekPositionUs; + sampleHolder.flags |= decodeOnly ? C.SAMPLE_FLAG_DECODE_ONLY : 0; onSampleRead(mediaChunk, sampleHolder); return SAMPLE_READ; } else { diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractor.java b/library/src/main/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractor.java index 73551ba4dc..f9aca0375d 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractor.java @@ -467,8 +467,8 @@ public final class WebmExtractor implements Extractor { } long elementEndOffsetBytes = elementOffsetBytes + headerSizeBytes + contentsSizeBytes; simpleBlockTimecodeUs = clusterTimecodeUs + timecodeUs; - sampleHolder.flags = keyframe ? C.SAMPLE_FLAG_SYNC : 0; - sampleHolder.decodeOnly = invisible; + sampleHolder.flags = (keyframe ? C.SAMPLE_FLAG_SYNC : 0) + | (invisible ? C.SAMPLE_FLAG_DECODE_ONLY : 0); sampleHolder.timeUs = clusterTimecodeUs + timecodeUs; sampleHolder.size = (int) (elementEndOffsetBytes - reader.getBytesRead()); diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java index 85fb2be5cc..ed3a1c73e0 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer.hls; +import com.google.android.exoplayer.C; import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; @@ -223,7 +224,8 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { } if (extractor.getSample(track, sampleHolder)) { - sampleHolder.decodeOnly = frameAccurateSeeking && sampleHolder.timeUs < lastSeekPositionUs; + boolean decodeOnly = frameAccurateSeeking && sampleHolder.timeUs < lastSeekPositionUs; + sampleHolder.flags |= decodeOnly ? C.SAMPLE_FLAG_DECODE_ONLY : 0; return SAMPLE_READ; } diff --git a/library/src/main/java/com/google/android/exoplayer/hls/parser/RollingSampleBuffer.java b/library/src/main/java/com/google/android/exoplayer/hls/parser/RollingSampleBuffer.java index af7901f0f4..fe9eab4795 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/parser/RollingSampleBuffer.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/parser/RollingSampleBuffer.java @@ -97,7 +97,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; // Write the sample information into the holder and extrasHolder. infoQueue.peekSample(sampleHolder, extrasHolder); // Read encryption data if the sample is encrypted. - if ((sampleHolder.flags & C.SAMPLE_FLAG_ENCRYPTED) != 0) { + if (sampleHolder.isEncrypted()) { readEncryptionData(sampleHolder, extrasHolder); } // Write the sample data into the holder. diff --git a/library/src/main/java/com/google/android/exoplayer/hls/parser/SampleQueue.java b/library/src/main/java/com/google/android/exoplayer/hls/parser/SampleQueue.java index 4f78f494bb..e615567901 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/parser/SampleQueue.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/parser/SampleQueue.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer.hls.parser; -import com.google.android.exoplayer.C; import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.hls.parser.HlsExtractor.TrackOutput; @@ -128,8 +127,7 @@ public final class SampleQueue implements TrackOutput { } RollingSampleBuffer nextRollingBuffer = nextQueue.rollingBuffer; while (nextRollingBuffer.peekSample(sampleInfoHolder) - && (sampleInfoHolder.timeUs < firstPossibleSpliceTime - || (sampleInfoHolder.flags & C.SAMPLE_FLAG_SYNC) == 0)) { + && (sampleInfoHolder.timeUs < firstPossibleSpliceTime || !sampleInfoHolder.isSyncFrame())) { // Discard samples from the next queue for as long as they are before the earliest possible // splice time, or not keyframes. nextRollingBuffer.skipSample(); @@ -152,7 +150,7 @@ public final class SampleQueue implements TrackOutput { private boolean advanceToEligibleSample() { boolean haveNext = rollingBuffer.peekSample(sampleInfoHolder); if (needKeyframe) { - while (haveNext && (sampleInfoHolder.flags & C.SAMPLE_FLAG_SYNC) == 0) { + while (haveNext && !sampleInfoHolder.isSyncFrame()) { rollingBuffer.skipSample(); haveNext = rollingBuffer.peekSample(sampleInfoHolder); } diff --git a/library/src/main/java/com/google/android/exoplayer/source/FrameworkSampleExtractor.java b/library/src/main/java/com/google/android/exoplayer/source/FrameworkSampleExtractor.java index f8cc132ef2..c89f37de5f 100644 --- a/library/src/main/java/com/google/android/exoplayer/source/FrameworkSampleExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer/source/FrameworkSampleExtractor.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer.source; -import com.google.android.exoplayer.C; import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; @@ -164,7 +163,7 @@ public final class FrameworkSampleExtractor implements SampleExtractor { } sampleHolder.timeUs = mediaExtractor.getSampleTime(); sampleHolder.flags = mediaExtractor.getSampleFlags(); - if ((sampleHolder.flags & C.SAMPLE_FLAG_ENCRYPTED) != 0) { + if (sampleHolder.isEncrypted()) { sampleHolder.cryptoInfo.setFromExtractorV16(mediaExtractor); } diff --git a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java index e2452102d1..52af1c9c45 100644 --- a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java @@ -179,7 +179,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback { SampleHolder sampleHolder = parserHelper.getSampleHolder(); sampleHolder.clearData(); int result = source.readData(trackIndex, positionUs, formatHolder, sampleHolder, false); - if (result == SampleSource.SAMPLE_READ && !sampleHolder.decodeOnly) { + if (result == SampleSource.SAMPLE_READ && !sampleHolder.isDecodeOnly()) { parserHelper.startParseOperation(); textRendererNeedsUpdate = false; } else if (result == SampleSource.END_OF_STREAM) { diff --git a/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608Parser.java b/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608Parser.java index ddc29dbd59..4beede6eed 100644 --- a/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608Parser.java +++ b/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608Parser.java @@ -200,7 +200,7 @@ public class Eia608Parser { ClosedCaption[] captionArray = new ClosedCaption[captions.size()]; captions.toArray(captionArray); - return new ClosedCaptionList(sampleHolder.timeUs, sampleHolder.decodeOnly, captionArray); + return new ClosedCaptionList(sampleHolder.timeUs, sampleHolder.isDecodeOnly(), captionArray); } private static char getChar(byte ccData) { diff --git a/library/src/test/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractorTest.java b/library/src/test/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractorTest.java index 5e43a4cb7f..4a916a50f5 100644 --- a/library/src/test/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractorTest.java +++ b/library/src/test/java/com/google/android/exoplayer/chunk/parser/webm/WebmExtractorTest.java @@ -358,9 +358,9 @@ public class WebmExtractorTest extends InstrumentationTestCase { assertTrue(Arrays.equals( mediaSegment.videoBytes, Arrays.copyOf(sampleHolder.data.array(), sampleHolder.size))); assertEquals(timeUs, sampleHolder.timeUs); - assertEquals(keyframe, (sampleHolder.flags & C.SAMPLE_FLAG_SYNC) != 0); - assertEquals(invisible, sampleHolder.decodeOnly); - assertEquals(encrypted, (sampleHolder.flags & C.SAMPLE_FLAG_ENCRYPTED) != 0); + assertEquals(keyframe, sampleHolder.isSyncFrame()); + assertEquals(invisible, sampleHolder.isDecodeOnly()); + assertEquals(encrypted, sampleHolder.isEncrypted()); if (encrypted) { android.test.MoreAsserts.assertEquals(TEST_INITIALIZATION_VECTOR, sampleHolder.cryptoInfo.iv); assertEquals(C.CRYPTO_MODE_AES_CTR, sampleHolder.cryptoInfo.mode);