From 17d7a0cb4bb1396541eca2bfbc3bc14a6873a496 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 18 Apr 2016 07:58:28 -0700 Subject: [PATCH] Make RollingSampleBuffer implement TrackOutput This is the first step toward merging of RollingSampleBuffer and DefaultTrackOutput, which is a precursor to removing some indirection for DASH/SS playbacks, and to moving HLS playbacks to use a single output buffer per track (with inline splicing). Where this is heading is that sample format changes will eventually be attached to samples in the rolling buffer. This will eliminate the need for piping sample formats around the edges of the rolling buffer (e.g. via redirection in ChunkExtractorWrapper and BaseMediaChunk.getSampleFormat). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=120123093 --- .../exoplayer/chunk/ContainerMediaChunk.java | 5 +- .../exoplayer/chunk/InitializationChunk.java | 18 ------ .../exoplayer/dash/DashChunkSource.java | 7 ++- .../extractor/DefaultTrackOutput.java | 18 ++---- .../extractor/ExtractorSampleSource.java | 2 +- .../extractor/RollingSampleBuffer.java | 57 ++++++++----------- .../exoplayer/hls/HlsExtractorWrapper.java | 2 +- 7 files changed, 36 insertions(+), 73 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ContainerMediaChunk.java b/library/src/main/java/com/google/android/exoplayer/chunk/ContainerMediaChunk.java index a7856dfe34..5a19970d3c 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ContainerMediaChunk.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ContainerMediaChunk.java @@ -37,9 +37,8 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe private final ChunkExtractorWrapper extractorWrapper; private final long sampleOffsetUs; - private Format sampleFormat; - private DrmInitData drmInitData; - + private volatile DrmInitData drmInitData; + private volatile Format sampleFormat; private volatile int bytesLoaded; private volatile boolean loadCanceled; diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/InitializationChunk.java b/library/src/main/java/com/google/android/exoplayer/chunk/InitializationChunk.java index b5d5991c85..63f66e2a69 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/InitializationChunk.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/InitializationChunk.java @@ -68,15 +68,6 @@ public final class InitializationChunk extends Chunk implements SingleTrackMetad return bytesLoaded; } - /** - * True if a {@link Format} was parsed from the chunk. False otherwise. - *

- * Should be called after loading has completed. - */ - public boolean hasSampleFormat() { - return sampleFormat != null; - } - /** * Returns a {@link Format} parsed from the chunk, or null. *

@@ -86,15 +77,6 @@ public final class InitializationChunk extends Chunk implements SingleTrackMetad return sampleFormat; } - /** - * True if a {@link DrmInitData} was parsed from the chunk. False otherwise. - *

- * Should be called after loading has completed. - */ - public boolean hasDrmInitData() { - return drmInitData != null; - } - /** * Returns a {@link DrmInitData} parsed from the chunk, or null. *

diff --git a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java index 6b8edf0ffc..68ee85b20f 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java @@ -289,8 +289,9 @@ public class DashChunkSource implements ChunkSource { InitializationChunk initializationChunk = (InitializationChunk) chunk; RepresentationHolder representationHolder = representationHolders[getTrackIndex(initializationChunk.format)]; - if (initializationChunk.hasSampleFormat()) { - representationHolder.sampleFormat = initializationChunk.getSampleFormat(); + Format sampleFormat = initializationChunk.getSampleFormat(); + if (sampleFormat != null) { + representationHolder.sampleFormat = sampleFormat; } // The null check avoids overwriting an index obtained from the manifest with one obtained // from the stream. If the manifest defines an index then the stream shouldn't, but in cases @@ -302,7 +303,7 @@ public class DashChunkSource implements ChunkSource { } // The null check avoids overwriting drmInitData obtained from the manifest with drmInitData // obtained from the stream, as per DASH IF Interoperability Recommendations V3.0, 7.5.3. - if (drmInitData == null && initializationChunk.hasDrmInitData()) { + if (drmInitData == null) { drmInitData = initializationChunk.getDrmInitData(); } } diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/DefaultTrackOutput.java b/library/src/main/java/com/google/android/exoplayer/extractor/DefaultTrackOutput.java index 1e4bf157ff..597b5bea5e 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/DefaultTrackOutput.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/DefaultTrackOutput.java @@ -41,7 +41,6 @@ public class DefaultTrackOutput implements TrackOutput { // Accessed by both the loading and consuming threads. private volatile long largestParsedTimestampUs; - private volatile Format format; /** * @param allocator An {@link Allocator} from which allocations for sample data can be obtained. @@ -95,18 +94,11 @@ public class DefaultTrackOutput implements TrackOutput { return rollingBuffer.getReadIndex(); } - /** - * True if the output has received a format. False otherwise. - */ - public boolean hasFormat() { - return format != null; - } - /** * The format most recently received by the output, or null if a format has yet to be received. */ public Format getFormat() { - return format; + return rollingBuffer.getUpstreamFormat(); } /** @@ -234,25 +226,25 @@ public class DefaultTrackOutput implements TrackOutput { @Override public void format(Format format) { - this.format = format; + rollingBuffer.format(format); } @Override public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput) throws IOException, InterruptedException { - return rollingBuffer.appendData(input, length, allowEndOfInput); + return rollingBuffer.sampleData(input, length, allowEndOfInput); } @Override public void sampleData(ParsableByteArray buffer, int length) { - rollingBuffer.appendData(buffer, length); + rollingBuffer.sampleData(buffer, length); } @Override public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) { timeUs += sampleOffsetUs; largestParsedTimestampUs = Math.max(largestParsedTimestampUs, timeUs); - rollingBuffer.commitSample(timeUs, flags, size, offset, encryptionKey); + rollingBuffer.sampleMetadata(timeUs, flags, size, offset, encryptionKey); } } diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java index d6f70c11d1..bf4131538c 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java @@ -640,7 +640,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu private boolean haveFormatsForAllTracks() { for (int i = 0; i < sampleQueues.size(); i++) { - if (!sampleQueues.valueAt(i).hasFormat()) { + if (sampleQueues.valueAt(i).getFormat() == null) { return false; } } diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/RollingSampleBuffer.java b/library/src/main/java/com/google/android/exoplayer/extractor/RollingSampleBuffer.java index f2de8dcce4..bc889e5cef 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/RollingSampleBuffer.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/RollingSampleBuffer.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer.extractor; import com.google.android.exoplayer.C; import com.google.android.exoplayer.DecoderInputBuffer; +import com.google.android.exoplayer.Format; import com.google.android.exoplayer.upstream.Allocation; import com.google.android.exoplayer.upstream.Allocator; import com.google.android.exoplayer.util.Assertions; @@ -30,7 +31,7 @@ import java.util.concurrent.LinkedBlockingDeque; /** * A rolling buffer of sample data and corresponding sample information. */ -/* package */ final class RollingSampleBuffer { +/* package */ final class RollingSampleBuffer implements TrackOutput { private static final int INITIAL_SCRATCH_SIZE = 32; @@ -50,6 +51,9 @@ import java.util.concurrent.LinkedBlockingDeque; private Allocation lastAllocation; private int lastAllocationOffset; + // Accessed by both the loading and consuming threads. + private volatile Format upstreamFormat; + /** * @param allocator An {@link Allocator} from which allocations for sample data can be obtained. */ @@ -131,6 +135,13 @@ import java.util.concurrent.LinkedBlockingDeque; return infoQueue.getReadIndex(); } + /** + * Returns the current upstream format. + */ + public Format getUpstreamFormat() { + return upstreamFormat; + } + /** * Fills {@code buffer} with information about the current sample, but does not write its data. *

@@ -344,19 +355,13 @@ import java.util.concurrent.LinkedBlockingDeque; // Called by the loading thread. - /** - * Appends data to the rolling buffer. - * - * @param input The source from which to read. - * @param length The maximum length of the read. - * @param allowEndOfInput True if encountering the end of the input having appended no data is - * allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it - * should be considered an error, causing an {@link EOFException} to be thrown. - * @return The number of bytes appended, or {@link C#RESULT_END_OF_INPUT} if the input has ended. - * @throws IOException If an error occurs reading from the source. - * @throws InterruptedException If the thread has been interrupted. - */ - public int appendData(ExtractorInput input, int length, boolean allowEndOfInput) + @Override + public void format(Format format) { + upstreamFormat = format; + } + + @Override + public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput) throws IOException, InterruptedException { length = prepareForAppend(length); int bytesAppended = input.read(lastAllocation.data, @@ -372,13 +377,8 @@ import java.util.concurrent.LinkedBlockingDeque; return bytesAppended; } - /** - * Appends data to the rolling buffer. - * - * @param buffer A buffer containing the data to append. - * @param length The length of the data to append. - */ - public void appendData(ParsableByteArray buffer, int length) { + @Override + public void sampleData(ParsableByteArray buffer, int length) { while (length > 0) { int thisAppendLength = prepareForAppend(length); buffer.readBytes(lastAllocation.data, lastAllocation.translateOffset(lastAllocationOffset), @@ -389,19 +389,8 @@ import java.util.concurrent.LinkedBlockingDeque; } } - /** - * Indicates the end point for the current sample, making it available for consumption. - * - * @param sampleTimeUs The sample timestamp. - * @param flags Flags that accompany the sample. See {@code C.BUFFER_FLAG_*}. - * @param size The size of the sample, in bytes. - * @param offset The number of bytes that have been passed to - * {@link #appendData(ExtractorInput, int, boolean)} or - * {@link #appendData(ParsableByteArray, int)} since the last byte belonging to the sample - * being committed. - * @param encryptionKey The encryption key associated with the sample, or null. - */ - public void commitSample(long sampleTimeUs, int flags, int size, int offset, + @Override + public void sampleMetadata(long sampleTimeUs, int flags, int size, int offset, byte[] encryptionKey) { long absoluteOffset = totalBytesWritten - size - offset; infoQueue.commitSample(sampleTimeUs, flags, absoluteOffset, size, encryptionKey); diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsExtractorWrapper.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsExtractorWrapper.java index c625154bbf..1099bc860e 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsExtractorWrapper.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsExtractorWrapper.java @@ -81,7 +81,7 @@ public final class HlsExtractorWrapper implements ExtractorOutput { public boolean isPrepared() { if (!prepared && tracksBuilt) { for (int i = 0; i < sampleQueues.size(); i++) { - if (!sampleQueues.valueAt(i).hasFormat()) { + if (sampleQueues.valueAt(i).getFormat() == null) { return false; } }