From 155a129d2c3bd887e9795fa329727e1374dc1f7d Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Wed, 6 Mar 2019 13:11:09 +0000 Subject: [PATCH] Make flags-only DecoderInputBuffer hold all flags Currently a flags-only DecoderInputBuffer may hold only the end-of-stream flag. This change makes flags-only buffer read any kind of flag set in the next sample. If no sample is available RESULT_NOTHING_READ is returned. PiperOrigin-RevId: 237027581 --- .../mediacodec/MediaCodecRenderer.java | 3 +- .../source/SampleMetadataQueue.java | 42 +++++++++++-------- .../exoplayer2/source/SampleQueue.java | 28 ++++++++----- .../exoplayer2/source/SampleStream.java | 20 +++++---- .../source/SingleSampleMediaPeriod.java | 5 ++- 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index 55846b0258..e0faad6fef 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -723,8 +723,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { if (result == C.RESULT_FORMAT_READ) { onInputFormatChanged(formatHolder.format); return true; - } else if (result == C.RESULT_BUFFER_READ) { - Assertions.checkState(flagsOnlyBuffer.isEndOfStream()); + } else if (result == C.RESULT_BUFFER_READ && flagsOnlyBuffer.isEndOfStream()) { inputStreamEnded = true; processEndOfStream(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java index ab5c5e57d9..25cc73d4ae 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java @@ -219,25 +219,31 @@ import com.google.android.exoplayer2.util.Util; * * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format. * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the - * end of the stream. If a sample is read then the buffer is populated with information - * about the sample, but not its data. The size and absolute position of the data in the - * rolling buffer is stored in {@code extrasHolder}, along with an encryption id if present - * and the absolute position of the first byte that may still be required after the current - * sample has been read. May be null if the caller requires that the format of the stream be - * read even if it's not changing. - * @param formatRequired Whether the caller requires that the format of the stream be read even - * if it's not changing. A sample will never be read if set to true, however it is still - * possible for the end of stream or nothing to be read. + * end of the stream. If a sample is read then the buffer is populated with information about + * the sample, but not its data. The size and absolute position of the data in the rolling + * buffer is stored in {@code extrasHolder}, along with an encryption id if present and the + * absolute position of the first byte that may still be required after the current sample has + * been read. If a {@link DecoderInputBuffer#isFlagsOnly() flags-only} buffer is passed, only + * the buffer flags may be populated by this method and the read position of the queue will + * not change. May be null if the caller requires that the format of the stream be read even + * if it's not changing. + * @param formatRequired Whether the caller requires that the format of the stream be read even if + * it's not changing. A sample will never be read if set to true, however it is still possible + * for the end of stream or nothing to be read. * @param loadingFinished True if an empty queue should be considered the end of the stream. - * @param downstreamFormat The current downstream {@link Format}. If the format of the next - * sample is different to the current downstream format then a format will be read. + * @param downstreamFormat The current downstream {@link Format}. If the format of the next sample + * is different to the current downstream format then a format will be read. * @param extrasHolder The holder into which extra sample information should be written. - * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} - * or {@link C#RESULT_BUFFER_READ}. + * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or + * {@link C#RESULT_BUFFER_READ}. */ @SuppressWarnings("ReferenceEquality") - public synchronized int read(FormatHolder formatHolder, DecoderInputBuffer buffer, - boolean formatRequired, boolean loadingFinished, Format downstreamFormat, + public synchronized int read( + FormatHolder formatHolder, + DecoderInputBuffer buffer, + boolean formatRequired, + boolean loadingFinished, + Format downstreamFormat, SampleExtrasHolder extrasHolder) { if (!hasNextSample()) { if (loadingFinished || isLastSampleQueued) { @@ -258,12 +264,12 @@ import com.google.android.exoplayer2.util.Util; return C.RESULT_FORMAT_READ; } + buffer.setFlags(flags[relativeReadIndex]); + buffer.timeUs = timesUs[relativeReadIndex]; if (buffer.isFlagsOnly()) { - return C.RESULT_NOTHING_READ; + return C.RESULT_BUFFER_READ; } - buffer.timeUs = timesUs[relativeReadIndex]; - buffer.setFlags(flags[relativeReadIndex]); extrasHolder.size = sizes[relativeReadIndex]; extrasHolder.offset = offsets[relativeReadIndex]; extrasHolder.cryptoData = cryptoDatas[relativeReadIndex]; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index 133de437d4..e8f4953436 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -317,8 +317,10 @@ public class SampleQueue implements TrackOutput { * * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format. * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the - * end of the stream. If the end of the stream has been reached, the - * {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer. + * end of the stream. If the end of the stream has been reached, the {@link + * C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer. If a {@link + * DecoderInputBuffer#isFlagsOnly() flags-only} buffer is passed, only the buffer flags may be + * populated by this method and the read position of the queue will not change. * @param formatRequired Whether the caller requires that the format of the stream be read even if * it's not changing. A sample will never be read if set to true, however it is still possible * for the end of stream or nothing to be read. @@ -328,8 +330,12 @@ public class SampleQueue implements TrackOutput { * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or * {@link C#RESULT_BUFFER_READ}. */ - public int read(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired, - boolean loadingFinished, long decodeOnlyUntilUs) { + public int read( + FormatHolder formatHolder, + DecoderInputBuffer buffer, + boolean formatRequired, + boolean loadingFinished, + long decodeOnlyUntilUs) { int result = metadataQueue.read(formatHolder, buffer, formatRequired, loadingFinished, downstreamFormat, extrasHolder); switch (result) { @@ -341,13 +347,15 @@ public class SampleQueue implements TrackOutput { if (buffer.timeUs < decodeOnlyUntilUs) { buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY); } - // Read encryption data if the sample is encrypted. - if (buffer.isEncrypted()) { - readEncryptionData(buffer, extrasHolder); + if (!buffer.isFlagsOnly()) { + // Read encryption data if the sample is encrypted. + if (buffer.isEncrypted()) { + readEncryptionData(buffer, extrasHolder); + } + // Write the sample data into the holder. + buffer.ensureSpaceForWrite(extrasHolder.size); + readData(extrasHolder.offset, buffer.data, extrasHolder.size); } - // Write the sample data into the holder. - buffer.ensureSpaceForWrite(extrasHolder.size); - readData(extrasHolder.offset, buffer.data, extrasHolder.size); } return C.RESULT_BUFFER_READ; case C.RESULT_NOTHING_READ: diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java index 06efc980e2..54293aa4c1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java @@ -45,18 +45,20 @@ public interface SampleStream { /** * Attempts to read from the stream. - *

- * If the stream has ended then {@link C#BUFFER_FLAG_END_OF_STREAM} flag is set on {@code buffer} - * and {@link C#RESULT_BUFFER_READ} is returned. Else if no data is available then - * {@link C#RESULT_NOTHING_READ} is returned. Else if the format of the media is changing or if - * {@code formatRequired} is set then {@code formatHolder} is populated and - * {@link C#RESULT_FORMAT_READ} is returned. Else {@code buffer} is populated and - * {@link C#RESULT_BUFFER_READ} is returned. + * + *

If the stream has ended then {@link C#BUFFER_FLAG_END_OF_STREAM} flag is set on {@code + * buffer} and {@link C#RESULT_BUFFER_READ} is returned. Else if no data is available then {@link + * C#RESULT_NOTHING_READ} is returned. Else if the format of the media is changing or if {@code + * formatRequired} is set then {@code formatHolder} is populated and {@link C#RESULT_FORMAT_READ} + * is returned. Else {@code buffer} is populated and {@link C#RESULT_BUFFER_READ} is returned. * * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format. * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the - * end of the stream. If the end of the stream has been reached, the - * {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer. + * end of the stream. If the end of the stream has been reached, the {@link + * C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer. If a {@link + * DecoderInputBuffer#isFlagsOnly() flags-only} buffer is passed, then no {@link + * DecoderInputBuffer#data} will be read and the read position of the stream will not change, + * but the flags of the buffer will be populated. * @param formatRequired Whether the caller requires that the format of the stream be read even if * it's not changing. A sample will never be read if set to true, however it is still possible * for the end of stream or nothing to be read. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java index 3fb61767d6..e0c2a00df3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java @@ -326,8 +326,11 @@ import java.util.Arrays; return C.RESULT_FORMAT_READ; } else if (loadingFinished) { if (loadingSucceeded) { - buffer.timeUs = 0; buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME); + buffer.timeUs = 0; + if (buffer.isFlagsOnly()) { + return C.RESULT_BUFFER_READ; + } buffer.ensureSpaceForWrite(sampleSize); buffer.data.put(sampleData, 0, sampleSize); } else {