Commit 2d9177b7 by olly Committed by Ian Baker

SampleStream/SampleQueue: Introduce read flags

- SampleQueue.peek is replaced with SampleQueue.read with
  FLAG_PEEK. This also exposes peek functionality through
  SampleStream.
- Use of DecoderInputBuffer.isFlagsOnly is replaced with
  FLAG_OMIT_SAMPLE_DATA. This flag can be used with or
  without FLAG_PEEK, where-as previously the read position
  would never be advanced for an isFlagsOnly buffer.
- formatRequired is replaced with FLAG_FORMAT_REQUIRED.

PiperOrigin-RevId: 363460105
parent 31f65f63
Showing with 290 additions and 221 deletions
...@@ -111,12 +111,8 @@ public class DecoderInputBuffer extends Buffer { ...@@ -111,12 +111,8 @@ public class DecoderInputBuffer extends Buffer {
@BufferReplacementMode private final int bufferReplacementMode; @BufferReplacementMode private final int bufferReplacementMode;
private final int paddingSize; private final int paddingSize;
/** /** Returns a new instance that's not able to hold any data. */
* Creates a new instance for which {@link #isFlagsOnly()} will return true. public static DecoderInputBuffer newNoDataInstance() {
*
* @return A new flags only input buffer.
*/
public static DecoderInputBuffer newFlagsOnlyInstance() {
return new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); return new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED);
} }
...@@ -201,14 +197,6 @@ public class DecoderInputBuffer extends Buffer { ...@@ -201,14 +197,6 @@ public class DecoderInputBuffer extends Buffer {
} }
/** /**
* Returns whether the buffer is only able to hold flags, meaning {@link #data} is null and
* its replacement mode is {@link #BUFFER_REPLACEMENT_MODE_DISABLED}.
*/
public final boolean isFlagsOnly() {
return data == null && bufferReplacementMode == BUFFER_REPLACEMENT_MODE_DISABLED;
}
/**
* Returns whether the {@link C#BUFFER_FLAG_ENCRYPTED} flag is set. * Returns whether the {@link C#BUFFER_FLAG_ENCRYPTED} flag is set.
*/ */
public final boolean isEncrypted() { public final boolean isEncrypted() {
......
...@@ -21,6 +21,8 @@ import androidx.annotation.Nullable; ...@@ -21,6 +21,8 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer.InsufficientCapacityException; import com.google.android.exoplayer2.decoder.DecoderInputBuffer.InsufficientCapacityException;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.source.SampleStream.ReadFlags;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
import java.io.IOException; import java.io.IOException;
...@@ -225,8 +227,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { ...@@ -225,8 +227,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
* @param formats The enabled formats. * @param formats The enabled formats.
* @param startPositionUs The start position of the new stream in renderer time (microseconds). * @param startPositionUs The start position of the new stream in renderer time (microseconds).
* @param offsetUs The offset that will be added to the timestamps of buffers read via {@link * @param offsetUs The offset that will be added to the timestamps of buffers read via {@link
* #readSource(FormatHolder, DecoderInputBuffer, boolean)} so that decoder input buffers have * #readSource} so that decoder input buffers have monotonically increasing timestamps.
* monotonically increasing timestamps.
* @throws ExoPlaybackException If an error occurs. * @throws ExoPlaybackException If an error occurs.
*/ */
protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs)
...@@ -383,20 +384,17 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { ...@@ -383,20 +384,17 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
* @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the * @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 * 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. * C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
* @param formatRequired Whether the caller requires that the format of the stream be read even if * @param readFlags Flags controlling the behavior of this read operation.
* it's not changing. A sample will never be read if set to true, however it is still possible * @return The {@link ReadDataResult result} of the read operation.
* for the end of stream or nothing to be read. * @throws InsufficientCapacityException If the {@code buffer} has insufficient capacity to hold
* @return The status of read, one of {@link SampleStream.ReadDataResult}.
* @throws InsufficientCapacityException If the {@code buffer} is not a {@link
* DecoderInputBuffer#isFlagsOnly() flags-only} buffer and has insufficient capacity to hold
* the data of a sample being read. The buffer {@link DecoderInputBuffer#timeUs timestamp} and * the data of a sample being read. The buffer {@link DecoderInputBuffer#timeUs timestamp} and
* flags are populated if this exception is thrown, but the read position is not advanced. * flags are populated if this exception is thrown, but the read position is not advanced.
*/ */
@SampleStream.ReadDataResult @ReadDataResult
protected final int readSource( protected final int readSource(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
@SampleStream.ReadDataResult @ReadDataResult
int result = Assertions.checkNotNull(stream).readData(formatHolder, buffer, formatRequired); int result = Assertions.checkNotNull(stream).readData(formatHolder, buffer, readFlags);
if (result == C.RESULT_BUFFER_READ) { if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) { if (buffer.isEndOfStream()) {
readingPositionUs = C.TIME_END_OF_SOURCE; readingPositionUs = C.TIME_END_OF_SOURCE;
......
...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.audio; ...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.audio;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_DRM_SESSION_CHANGED; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_DRM_SESSION_CHANGED;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_REUSE_NOT_IMPLEMENTED; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_REUSE_NOT_IMPLEMENTED;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static java.lang.Math.max; import static java.lang.Math.max;
import android.os.Handler; import android.os.Handler;
...@@ -45,7 +46,7 @@ import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; ...@@ -45,7 +46,7 @@ import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
...@@ -189,7 +190,7 @@ public abstract class DecoderAudioRenderer< ...@@ -189,7 +190,7 @@ public abstract class DecoderAudioRenderer<
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = new EventDispatcher(eventHandler, eventListener);
this.audioSink = audioSink; this.audioSink = audioSink;
audioSink.setListener(new AudioSinkListener()); audioSink.setListener(new AudioSinkListener());
flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); flagsOnlyBuffer = DecoderInputBuffer.newNoDataInstance();
decoderReinitializationState = REINITIALIZATION_STATE_NONE; decoderReinitializationState = REINITIALIZATION_STATE_NONE;
audioTrackNeedsConfigure = true; audioTrackNeedsConfigure = true;
} }
...@@ -273,7 +274,7 @@ public abstract class DecoderAudioRenderer< ...@@ -273,7 +274,7 @@ public abstract class DecoderAudioRenderer<
// We don't have a format yet, so try and read one. // We don't have a format yet, so try and read one.
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
flagsOnlyBuffer.clear(); flagsOnlyBuffer.clear();
@SampleStream.ReadDataResult int result = readSource(formatHolder, flagsOnlyBuffer, true); @ReadDataResult int result = readSource(formatHolder, flagsOnlyBuffer, FLAG_REQUIRE_FORMAT);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder); onInputFormatChanged(formatHolder);
} else if (result == C.RESULT_BUFFER_READ) { } else if (result == C.RESULT_BUFFER_READ) {
...@@ -438,7 +439,7 @@ public abstract class DecoderAudioRenderer< ...@@ -438,7 +439,7 @@ public abstract class DecoderAudioRenderer<
} }
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
switch (readSource(formatHolder, inputBuffer, /* formatRequired= */ false)) { switch (readSource(formatHolder, inputBuffer, /* readFlags= */ 0)) {
case C.RESULT_NOTHING_READ: case C.RESULT_NOTHING_READ:
return false; return false;
case C.RESULT_FORMAT_READ: case C.RESULT_FORMAT_READ:
......
...@@ -23,6 +23,9 @@ import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE ...@@ -23,6 +23,9 @@ import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_YES_WITH_FLUSH; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_YES_WITH_FLUSH;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_YES_WITH_RECONFIGURATION; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_YES_WITH_RECONFIGURATION;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_OMIT_SAMPLE_DATA;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_PEEK;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkState; import static com.google.android.exoplayer2.util.Assertions.checkState;
import static java.lang.Math.max; import static java.lang.Math.max;
...@@ -57,6 +60,8 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; ...@@ -57,6 +60,8 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.source.SampleStream.ReadFlags;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
...@@ -294,7 +299,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -294,7 +299,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private final MediaCodecSelector mediaCodecSelector; private final MediaCodecSelector mediaCodecSelector;
private final boolean enableDecoderFallback; private final boolean enableDecoderFallback;
private final float assumedMinimumCodecOperatingRate; private final float assumedMinimumCodecOperatingRate;
private final DecoderInputBuffer flagsOnlyBuffer; private final DecoderInputBuffer noDataBuffer;
private final DecoderInputBuffer buffer; private final DecoderInputBuffer buffer;
private final DecoderInputBuffer bypassSampleBuffer; private final DecoderInputBuffer bypassSampleBuffer;
private final BatchBuffer bypassBatchBuffer; private final BatchBuffer bypassBatchBuffer;
...@@ -388,7 +393,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -388,7 +393,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
this.mediaCodecSelector = checkNotNull(mediaCodecSelector); this.mediaCodecSelector = checkNotNull(mediaCodecSelector);
this.enableDecoderFallback = enableDecoderFallback; this.enableDecoderFallback = enableDecoderFallback;
this.assumedMinimumCodecOperatingRate = assumedMinimumCodecOperatingRate; this.assumedMinimumCodecOperatingRate = assumedMinimumCodecOperatingRate;
flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); noDataBuffer = DecoderInputBuffer.newNoDataInstance();
buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
bypassSampleBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT); bypassSampleBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT);
bypassBatchBuffer = new BatchBuffer(); bypassBatchBuffer = new BatchBuffer();
...@@ -816,7 +821,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -816,7 +821,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
renderToEndOfStream(); renderToEndOfStream();
return; return;
} }
if (inputFormat == null && !readToFlagsOnlyBuffer(/* requireFormat= */ true)) { if (inputFormat == null && !readSourceOmittingSampleData(FLAG_REQUIRE_FORMAT)) {
// We still don't have a format and can't make progress without one. // We still don't have a format and can't make progress without one.
return; return;
} }
...@@ -837,9 +842,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -837,9 +842,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
decoderCounters.skippedInputBufferCount += skipSource(positionUs); decoderCounters.skippedInputBufferCount += skipSource(positionUs);
// We need to read any format changes despite not having a codec so that drmSession can be // We need to read any format changes despite not having a codec so that drmSession can be
// updated, and so that we have the most recent format should the codec be initialized. We // updated, and so that we have the most recent format should the codec be initialized. We
// may also reach the end of the stream. Note that readSource will not read a sample into a // may also reach the end of the stream. FLAG_PEEK is used because we don't want to advance
// flags-only buffer. // the source further than skipSource has already done.
readToFlagsOnlyBuffer(/* requireFormat= */ false); readSourceOmittingSampleData(FLAG_PEEK);
} }
decoderCounters.ensureUpdated(); decoderCounters.ensureUpdated();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
...@@ -972,16 +977,24 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -972,16 +977,24 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return new MediaCodecDecoderException(cause, codecInfo); return new MediaCodecDecoderException(cause, codecInfo);
} }
/** Reads into {@link #flagsOnlyBuffer} and returns whether a {@link Format} was read. */ /**
private boolean readToFlagsOnlyBuffer(boolean requireFormat) throws ExoPlaybackException { * Reads from the source when sample data is not required. If a format or an end of stream buffer
* is read, it will be handled before the call returns.
*
* @param readFlags Additional {@link ReadFlags}. {@link SampleStream#FLAG_OMIT_SAMPLE_DATA} is
* added internally, and so does not need to be passed.
* @return Whether a format was read and processed.
*/
private boolean readSourceOmittingSampleData(@SampleStream.ReadFlags int readFlags)
throws ExoPlaybackException {
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
flagsOnlyBuffer.clear(); noDataBuffer.clear();
@SampleStream.ReadDataResult @ReadDataResult
int result = readSource(formatHolder, flagsOnlyBuffer, requireFormat); int result = readSource(formatHolder, noDataBuffer, readFlags | FLAG_OMIT_SAMPLE_DATA);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder); onInputFormatChanged(formatHolder);
return true; return true;
} else if (result == C.RESULT_BUFFER_READ && flagsOnlyBuffer.isEndOfStream()) { } else if (result == C.RESULT_BUFFER_READ && noDataBuffer.isEndOfStream()) {
inputStreamEnded = true; inputStreamEnded = true;
processEndOfStream(); processEndOfStream();
} }
...@@ -1248,8 +1261,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1248,8 +1261,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
int adaptiveReconfigurationBytes = buffer.data.position(); int adaptiveReconfigurationBytes = buffer.data.position();
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
@SampleStream.ReadDataResult @ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */ 0);
int result = readSource(formatHolder, buffer, /* formatRequired= */ false);
if (hasReadStreamToEnd()) { if (hasReadStreamToEnd()) {
// Notify output queue of the last buffer's timestamp. // Notify output queue of the last buffer's timestamp.
...@@ -2264,8 +2276,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -2264,8 +2276,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
bypassSampleBuffer.clear(); bypassSampleBuffer.clear();
while (true) { while (true) {
bypassSampleBuffer.clear(); bypassSampleBuffer.clear();
@SampleStream.ReadDataResult @ReadDataResult int result = readSource(formatHolder, bypassSampleBuffer, /* readFlags= */ 0);
int result = readSource(formatHolder, bypassSampleBuffer, /* formatRequired= */ false);
switch (result) { switch (result) {
case C.RESULT_FORMAT_READ: case C.RESULT_FORMAT_READ:
onInputFormatChanged(formatHolder); onInputFormatChanged(formatHolder);
......
...@@ -27,7 +27,7 @@ import com.google.android.exoplayer2.C; ...@@ -27,7 +27,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -125,7 +125,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { ...@@ -125,7 +125,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
if (!inputStreamEnded && pendingMetadataCount < MAX_PENDING_METADATA_COUNT) { if (!inputStreamEnded && pendingMetadataCount < MAX_PENDING_METADATA_COUNT) {
buffer.clear(); buffer.clear();
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
@SampleStream.ReadDataResult int result = readSource(formatHolder, buffer, false); @ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */ 0);
if (result == C.RESULT_BUFFER_READ) { if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) { if (buffer.isEndOfStream()) {
inputStreamEnded = true; inputStreamEnded = true;
......
...@@ -299,7 +299,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb ...@@ -299,7 +299,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
@Override @Override
public int readData( public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean requireFormat) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
if (isPendingInitialDiscontinuity()) { if (isPendingInitialDiscontinuity()) {
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
...@@ -307,7 +307,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb ...@@ -307,7 +307,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
return C.RESULT_BUFFER_READ; return C.RESULT_BUFFER_READ;
} }
@ReadDataResult int result = childStream.readData(formatHolder, buffer, requireFormat); @ReadDataResult int result = childStream.readData(formatHolder, buffer, readFlags);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
Format format = Assertions.checkNotNull(formatHolder.format); Format format = Assertions.checkNotNull(formatHolder.format);
if (format.encoderDelay != 0 || format.encoderPadding != 0) { if (format.encoderDelay != 0 || format.encoderPadding != 0) {
......
...@@ -35,8 +35,8 @@ public final class EmptySampleStream implements SampleStream { ...@@ -35,8 +35,8 @@ public final class EmptySampleStream implements SampleStream {
} }
@Override @Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, public int readData(
boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
return C.RESULT_BUFFER_READ; return C.RESULT_BUFFER_READ;
} }
......
...@@ -440,8 +440,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -440,8 +440,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override @Override
public int readData( public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
int readResult = sampleStream.readData(formatHolder, buffer, formatRequired); int readResult = sampleStream.readData(formatHolder, buffer, readFlags);
if (readResult == C.RESULT_BUFFER_READ) { if (readResult == C.RESULT_BUFFER_READ) {
buffer.timeUs = max(0, buffer.timeUs + timeOffsetUs); buffer.timeUs = max(0, buffer.timeUs + timeOffsetUs);
} }
......
...@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput; ...@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.icy.IcyHeaders; import com.google.android.exoplayer2.metadata.icy.IcyHeaders;
import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener; import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener;
import com.google.android.exoplayer2.source.SampleStream.ReadFlags;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection; import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
...@@ -478,13 +479,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -478,13 +479,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
int sampleQueueIndex, int sampleQueueIndex,
FormatHolder formatHolder, FormatHolder formatHolder,
DecoderInputBuffer buffer, DecoderInputBuffer buffer,
boolean formatRequired) { @ReadFlags int readFlags) {
if (suppressRead()) { if (suppressRead()) {
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
maybeNotifyDownstreamFormat(sampleQueueIndex); maybeNotifyDownstreamFormat(sampleQueueIndex);
int result = int result =
sampleQueues[sampleQueueIndex].read(formatHolder, buffer, formatRequired, loadingFinished); sampleQueues[sampleQueueIndex].read(formatHolder, buffer, readFlags, loadingFinished);
if (result == C.RESULT_NOTHING_READ) { if (result == C.RESULT_NOTHING_READ) {
maybeStartDeferredRetry(sampleQueueIndex); maybeStartDeferredRetry(sampleQueueIndex);
} }
...@@ -947,9 +948,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -947,9 +948,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Override @Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, public int readData(
boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
return ProgressiveMediaPeriod.this.readData(track, formatHolder, buffer, formatRequired); return ProgressiveMediaPeriod.this.readData(track, formatHolder, buffer, readFlags);
} }
@Override @Override
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_OMIT_SAMPLE_DATA;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_PEEK;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static com.google.android.exoplayer2.util.Assertions.checkArgument; import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static java.lang.Math.max; import static java.lang.Math.max;
...@@ -36,6 +39,7 @@ import com.google.android.exoplayer2.drm.DrmSessionEventListener; ...@@ -36,6 +39,7 @@ import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSessionManager.DrmSessionReference; import com.google.android.exoplayer2.drm.DrmSessionManager.DrmSessionReference;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.source.SampleStream.ReadFlags;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataReader; import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -380,20 +384,6 @@ public class SampleQueue implements TrackOutput { ...@@ -380,20 +384,6 @@ public class SampleQueue implements TrackOutput {
return mayReadSample(getRelativeIndex(readPosition)); return mayReadSample(getRelativeIndex(readPosition));
} }
/** Equivalent to {@link #read}, except it never advances the read position. */
public final int peek(
FormatHolder formatHolder,
DecoderInputBuffer buffer,
boolean formatRequired,
boolean loadingFinished) {
int result =
peekSampleMetadata(formatHolder, buffer, formatRequired, loadingFinished, extrasHolder);
if (result == C.RESULT_BUFFER_READ && !buffer.isEndOfStream() && !buffer.isFlagsOnly()) {
sampleDataQueue.peekToBuffer(buffer, extrasHolder);
}
return result;
}
/** /**
* Attempts to read from the queue. * Attempts to read from the queue.
* *
...@@ -403,18 +393,12 @@ public class SampleQueue implements TrackOutput { ...@@ -403,18 +393,12 @@ public class SampleQueue implements TrackOutput {
* @param formatHolder A {@link FormatHolder} to populate in the case of reading a format. * @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 * @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 * 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 * C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
* DecoderInputBuffer#isFlagsOnly() flags-only} buffer is passed and a sample is read, then * @param readFlags Flags controlling the behavior of this read operation.
* only the buffer {@link DecoderInputBuffer#timeUs timestamp} and flags will be populated,
* and the read position will not be advanced.
* @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 loadingFinished True if an empty queue should be considered the end of the stream.
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
* {@link C#RESULT_BUFFER_READ}. * {@link C#RESULT_BUFFER_READ}.
* @throws InsufficientCapacityException If the {@code buffer} is not a {@link * @throws InsufficientCapacityException If the {@code buffer} has insufficient capacity to hold
* DecoderInputBuffer#isFlagsOnly() flags-only} buffer and has insufficient capacity to hold
* the data of a sample being read. The buffer {@link DecoderInputBuffer#timeUs timestamp} and * the data of a sample being read. The buffer {@link DecoderInputBuffer#timeUs timestamp} and
* flags are populated if this exception is thrown, but the read position is not advanced. * flags are populated if this exception is thrown, but the read position is not advanced.
*/ */
...@@ -422,13 +406,27 @@ public class SampleQueue implements TrackOutput { ...@@ -422,13 +406,27 @@ public class SampleQueue implements TrackOutput {
public int read( public int read(
FormatHolder formatHolder, FormatHolder formatHolder,
DecoderInputBuffer buffer, DecoderInputBuffer buffer,
boolean formatRequired, @ReadFlags int readFlags,
boolean loadingFinished) { boolean loadingFinished) {
int result = int result =
peekSampleMetadata(formatHolder, buffer, formatRequired, loadingFinished, extrasHolder); peekSampleMetadata(
if (result == C.RESULT_BUFFER_READ && !buffer.isEndOfStream() && !buffer.isFlagsOnly()) { formatHolder,
sampleDataQueue.readToBuffer(buffer, extrasHolder); buffer,
readPosition++; /* formatRequired= */ (readFlags & FLAG_REQUIRE_FORMAT) != 0,
loadingFinished,
extrasHolder);
if (result == C.RESULT_BUFFER_READ && !buffer.isEndOfStream()) {
boolean peek = (readFlags & FLAG_PEEK) != 0;
if ((readFlags & FLAG_OMIT_SAMPLE_DATA) == 0) {
if (peek) {
sampleDataQueue.peekToBuffer(buffer, extrasHolder);
} else {
sampleDataQueue.readToBuffer(buffer, extrasHolder);
}
}
if (!peek) {
readPosition++;
}
} }
return result; return result;
} }
......
...@@ -30,7 +30,43 @@ import java.lang.annotation.RetentionPolicy; ...@@ -30,7 +30,43 @@ import java.lang.annotation.RetentionPolicy;
*/ */
public interface SampleStream { public interface SampleStream {
/** Return values of {@link #readData(FormatHolder, DecoderInputBuffer, boolean)}. */ /**
* Flags that can be specified when calling {@link #readData}. Possible flag values are {@link
* #FLAG_PEEK}, {@link #FLAG_REQUIRE_FORMAT} and {@link #FLAG_OMIT_SAMPLE_DATA}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef(
flag = true,
value = {FLAG_PEEK, FLAG_REQUIRE_FORMAT, FLAG_OMIT_SAMPLE_DATA})
@interface ReadFlags {}
/** Specifies that the read position should not be advanced if a sample buffer is read. */
int FLAG_PEEK = 1;
/**
* Specifies that if a sample buffer would normally be read next, the format of the stream should
* be read instead. In detail, the effect of this flag is as follows:
*
* <ul>
* <li>If a sample buffer would be read were the flag not set, then the stream format will be
* read instead.
* <li>If nothing would be read were the flag not set, then the stream format will be read if
* it's known. If the stream format is not known then behavior is unchanged.
* <li>If an end of stream buffer would be read were the flag not set, then behavior is
* unchanged.
* </ul>
*/
int FLAG_REQUIRE_FORMAT = 1 << 1;
/**
* Specifies that {@link DecoderInputBuffer#data}, {@link DecoderInputBuffer#supplementalData} and
* {@link DecoderInputBuffer#cryptoInfo} should not be populated when reading a sample buffer.
*
* <p>This flag is useful for efficiently reading or (when combined with {@link #FLAG_PEEK})
* peeking sample metadata. It can also be used for efficiency by a caller wishing to skip a
* sample buffer.
*/
int FLAG_OMIT_SAMPLE_DATA = 1 << 2;
/** Return values of {@link #readData}. */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({C.RESULT_NOTHING_READ, C.RESULT_FORMAT_READ, C.RESULT_BUFFER_READ}) @IntDef({C.RESULT_NOTHING_READ, C.RESULT_FORMAT_READ, C.RESULT_BUFFER_READ})
...@@ -38,10 +74,9 @@ public interface SampleStream { ...@@ -38,10 +74,9 @@ public interface SampleStream {
/** /**
* Returns whether data is available to be read. * Returns whether data is available to be read.
* <p> *
* Note: If the stream has ended then a buffer with the end of stream flag can always be read from * <p>Note: If the stream has ended then a buffer with the end of stream flag can always be read
* {@link #readData(FormatHolder, DecoderInputBuffer, boolean)}. Hence an ended stream is always * from {@link #readData}. Hence an ended stream is always ready.
* ready.
* *
* @return Whether data is available to be read. * @return Whether data is available to be read.
*/ */
...@@ -66,21 +101,15 @@ public interface SampleStream { ...@@ -66,21 +101,15 @@ public interface SampleStream {
* @param formatHolder A {@link FormatHolder} to populate in the case of reading a format. * @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 * @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 * 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 * C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
* DecoderInputBuffer#isFlagsOnly() flags-only} buffer is passed and a sample is read, then * @param readFlags Flags controlling the behavior of this read operation.
* only the buffer {@link DecoderInputBuffer#timeUs timestamp} and flags will be populated, * @return The {@link ReadDataResult result} of the read operation.
* and the read position will not be advanced. * @throws InsufficientCapacityException If the {@code buffer} has insufficient capacity to hold
* @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.
* @return The status of read, one of {@link ReadDataResult}.
* @throws InsufficientCapacityException If the {@code buffer} is not a {@link
* DecoderInputBuffer#isFlagsOnly() flags-only} buffer and has insufficient capacity to hold
* the data of a sample being read. The buffer {@link DecoderInputBuffer#timeUs timestamp} and * the data of a sample being read. The buffer {@link DecoderInputBuffer#timeUs timestamp} and
* flags are populated if this exception is thrown, but the read position is not advanced. * flags are populated if this exception is thrown, but the read position is not advanced.
*/ */
@ReadDataResult @ReadDataResult
int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired); int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags);
/** /**
* Attempts to skip to the keyframe before the specified position, or to the end of the stream if * Attempts to skip to the keyframe before the specified position, or to the end of the stream if
...@@ -90,5 +119,4 @@ public interface SampleStream { ...@@ -90,5 +119,4 @@ public interface SampleStream {
* @return The number of samples that were skipped. * @return The number of samples that were skipped.
*/ */
int skipData(long positionUs); int skipData(long positionUs);
} }
...@@ -292,8 +292,8 @@ public final class SilenceMediaSource extends BaseMediaSource { ...@@ -292,8 +292,8 @@ public final class SilenceMediaSource extends BaseMediaSource {
@Override @Override
public int readData( public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
if (!sentFormat || formatRequired) { if (!sentFormat || (readFlags & FLAG_REQUIRE_FORMAT) != 0) {
formatHolder.format = FORMAT; formatHolder.format = FORMAT;
sentFormat = true; sentFormat = true;
return C.RESULT_FORMAT_READ; return C.RESULT_FORMAT_READ;
...@@ -307,14 +307,14 @@ public final class SilenceMediaSource extends BaseMediaSource { ...@@ -307,14 +307,14 @@ public final class SilenceMediaSource extends BaseMediaSource {
buffer.timeUs = getAudioPositionUs(positionBytes); buffer.timeUs = getAudioPositionUs(positionBytes);
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME); buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
if (buffer.isFlagsOnly()) {
return C.RESULT_BUFFER_READ;
}
int bytesToWrite = (int) min(SILENCE_SAMPLE.length, bytesRemaining); int bytesToWrite = (int) min(SILENCE_SAMPLE.length, bytesRemaining);
buffer.ensureSpaceForWrite(bytesToWrite); if ((readFlags & FLAG_OMIT_SAMPLE_DATA) == 0) {
buffer.data.put(SILENCE_SAMPLE, /* offset= */ 0, bytesToWrite); buffer.ensureSpaceForWrite(bytesToWrite);
positionBytes += bytesToWrite; buffer.data.put(SILENCE_SAMPLE, /* offset= */ 0, bytesToWrite);
}
if ((readFlags & FLAG_PEEK) == 0) {
positionBytes += bytesToWrite;
}
return C.RESULT_BUFFER_READ; return C.RESULT_BUFFER_READ;
} }
......
...@@ -349,31 +349,39 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -349,31 +349,39 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override @Override
public int readData( public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean requireFormat) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
maybeNotifyDownstreamFormat(); maybeNotifyDownstreamFormat();
if (streamState == STREAM_STATE_END_OF_STREAM) { if (streamState == STREAM_STATE_END_OF_STREAM) {
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return C.RESULT_BUFFER_READ; return C.RESULT_BUFFER_READ;
} else if (requireFormat || streamState == STREAM_STATE_SEND_FORMAT) { }
if ((readFlags & FLAG_REQUIRE_FORMAT) != 0 || streamState == STREAM_STATE_SEND_FORMAT) {
formatHolder.format = format; formatHolder.format = format;
streamState = STREAM_STATE_SEND_SAMPLE; streamState = STREAM_STATE_SEND_SAMPLE;
return C.RESULT_FORMAT_READ; return C.RESULT_FORMAT_READ;
} else if (loadingFinished) { }
if (sampleData != null) {
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME); if (!loadingFinished) {
buffer.timeUs = 0; return C.RESULT_NOTHING_READ;
if (buffer.isFlagsOnly()) { }
return C.RESULT_BUFFER_READ;
} if (sampleData == null) {
buffer.ensureSpaceForWrite(sampleSize); buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
buffer.data.put(sampleData, 0, sampleSize);
} else {
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
}
streamState = STREAM_STATE_END_OF_STREAM; streamState = STREAM_STATE_END_OF_STREAM;
return C.RESULT_BUFFER_READ; return C.RESULT_BUFFER_READ;
} }
return C.RESULT_NOTHING_READ;
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
buffer.timeUs = 0;
if ((readFlags & FLAG_OMIT_SAMPLE_DATA) == 0) {
buffer.ensureSpaceForWrite(sampleSize);
buffer.data.put(sampleData, 0, sampleSize);
}
if ((readFlags & FLAG_PEEK) == 0) {
streamState = STREAM_STATE_END_OF_STREAM;
}
return C.RESULT_BUFFER_READ;
} }
@Override @Override
......
...@@ -381,8 +381,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -381,8 +381,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
@Override @Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, public int readData(
boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
if (isPendingReset()) { if (isPendingReset()) {
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
...@@ -395,7 +395,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -395,7 +395,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
maybeNotifyPrimaryTrackFormatChanged(); maybeNotifyPrimaryTrackFormatChanged();
return primarySampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished); return primarySampleQueue.read(formatHolder, buffer, readFlags, loadingFinished);
} }
@Override @Override
...@@ -862,8 +862,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -862,8 +862,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
@Override @Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, public int readData(
boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
if (isPendingReset()) { if (isPendingReset()) {
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
...@@ -875,7 +875,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -875,7 +875,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
maybeNotifyDownstreamFormat(); maybeNotifyDownstreamFormat();
return sampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished); return sampleQueue.read(formatHolder, buffer, readFlags, loadingFinished);
} }
public void release() { public void release() {
......
...@@ -29,7 +29,7 @@ import com.google.android.exoplayer2.C; ...@@ -29,7 +29,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -273,7 +273,7 @@ public final class TextRenderer extends BaseRenderer implements Callback { ...@@ -273,7 +273,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
return; return;
} }
// Try and read the next subtitle from the source. // Try and read the next subtitle from the source.
@SampleStream.ReadDataResult int result = readSource(formatHolder, nextInputBuffer, false); @ReadDataResult int result = readSource(formatHolder, nextInputBuffer, /* readFlags= */ 0);
if (result == C.RESULT_BUFFER_READ) { if (result == C.RESULT_BUFFER_READ) {
if (nextInputBuffer.isEndOfStream()) { if (nextInputBuffer.isEndOfStream()) {
inputStreamEnded = true; inputStreamEnded = true;
......
...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.video; ...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.video;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_DRM_SESSION_CHANGED; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_DRM_SESSION_CHANGED;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_REUSE_NOT_IMPLEMENTED; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_REUSE_NOT_IMPLEMENTED;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static java.lang.Math.max; import static java.lang.Math.max;
import android.os.Handler; import android.os.Handler;
...@@ -41,7 +42,7 @@ import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation; ...@@ -41,7 +42,7 @@ import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.TimedValueQueue; import com.google.android.exoplayer2.util.TimedValueQueue;
...@@ -165,7 +166,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -165,7 +166,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
joiningDeadlineMs = C.TIME_UNSET; joiningDeadlineMs = C.TIME_UNSET;
clearReportedVideoSize(); clearReportedVideoSize();
formatQueue = new TimedValueQueue<>(); formatQueue = new TimedValueQueue<>();
flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); flagsOnlyBuffer = DecoderInputBuffer.newNoDataInstance();
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = new EventDispatcher(eventHandler, eventListener);
decoderReinitializationState = REINITIALIZATION_STATE_NONE; decoderReinitializationState = REINITIALIZATION_STATE_NONE;
outputMode = C.VIDEO_OUTPUT_MODE_NONE; outputMode = C.VIDEO_OUTPUT_MODE_NONE;
...@@ -183,7 +184,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -183,7 +184,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
// We don't have a format yet, so try and read one. // We don't have a format yet, so try and read one.
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
flagsOnlyBuffer.clear(); flagsOnlyBuffer.clear();
@SampleStream.ReadDataResult int result = readSource(formatHolder, flagsOnlyBuffer, true); @ReadDataResult int result = readSource(formatHolder, flagsOnlyBuffer, FLAG_REQUIRE_FORMAT);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder); onInputFormatChanged(formatHolder);
} else if (result == C.RESULT_BUFFER_READ) { } else if (result == C.RESULT_BUFFER_READ) {
...@@ -745,7 +746,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { ...@@ -745,7 +746,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
} }
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
switch (readSource(formatHolder, inputBuffer, /* formatRequired= */ false)) { switch (readSource(formatHolder, inputBuffer, /* readFlags= */ 0)) {
case C.RESULT_NOTHING_READ: case C.RESULT_NOTHING_READ:
return false; return false;
case C.RESULT_FORMAT_READ: case C.RESULT_FORMAT_READ:
......
...@@ -24,7 +24,7 @@ import com.google.android.exoplayer2.FormatHolder; ...@@ -24,7 +24,7 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -94,8 +94,7 @@ public final class CameraMotionRenderer extends BaseRenderer { ...@@ -94,8 +94,7 @@ public final class CameraMotionRenderer extends BaseRenderer {
while (!hasReadStreamToEnd() && lastTimestampUs < positionUs + SAMPLE_WINDOW_DURATION_US) { while (!hasReadStreamToEnd() && lastTimestampUs < positionUs + SAMPLE_WINDOW_DURATION_US) {
buffer.clear(); buffer.clear();
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
@SampleStream.ReadDataResult @ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */ 0);
int result = readSource(formatHolder, buffer, /* formatRequired= */ false);
if (result != C.RESULT_BUFFER_READ || buffer.isEndOfStream()) { if (result != C.RESULT_BUFFER_READ || buffer.isEndOfStream()) {
return; return;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM; import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample; import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
...@@ -93,11 +94,11 @@ public final class MergingMediaPeriodTest { ...@@ -93,11 +94,11 @@ public final class MergingMediaPeriodTest {
FormatHolder formatHolder = new FormatHolder(); FormatHolder formatHolder = new FormatHolder();
DecoderInputBuffer inputBuffer = DecoderInputBuffer inputBuffer =
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL); new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
assertThat(streams[1].readData(formatHolder, inputBuffer, /* formatRequired= */ true)) assertThat(streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT))
.isEqualTo(C.RESULT_FORMAT_READ); .isEqualTo(C.RESULT_FORMAT_READ);
assertThat(formatHolder.format).isEqualTo(childFormat12); assertThat(formatHolder.format).isEqualTo(childFormat12);
assertThat(streams[2].readData(formatHolder, inputBuffer, /* formatRequired= */ true)) assertThat(streams[2].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT))
.isEqualTo(C.RESULT_FORMAT_READ); .isEqualTo(C.RESULT_FORMAT_READ);
assertThat(formatHolder.format).isEqualTo(childFormat21); assertThat(formatHolder.format).isEqualTo(childFormat21);
} }
...@@ -134,20 +135,20 @@ public final class MergingMediaPeriodTest { ...@@ -134,20 +135,20 @@ public final class MergingMediaPeriodTest {
FormatHolder formatHolder = new FormatHolder(); FormatHolder formatHolder = new FormatHolder();
DecoderInputBuffer inputBuffer = DecoderInputBuffer inputBuffer =
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL); new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
streams[0].readData(formatHolder, inputBuffer, /* formatRequired= */ true); streams[0].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
streams[1].readData(formatHolder, inputBuffer, /* formatRequired= */ true); streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod1 = FakeMediaPeriodWithSelectTracksPosition childMediaPeriod1 =
(FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(0); (FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(0);
assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0); assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0);
assertThat(streams[0].readData(formatHolder, inputBuffer, /* formatRequired= */ false)) assertThat(streams[0].readData(formatHolder, inputBuffer, /* readFlags= */ 0))
.isEqualTo(C.RESULT_BUFFER_READ); .isEqualTo(C.RESULT_BUFFER_READ);
assertThat(inputBuffer.timeUs).isEqualTo(123_000L); assertThat(inputBuffer.timeUs).isEqualTo(123_000L);
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod2 = FakeMediaPeriodWithSelectTracksPosition childMediaPeriod2 =
(FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(1); (FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(1);
assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L); assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L);
assertThat(streams[1].readData(formatHolder, inputBuffer, /* formatRequired= */ false)) assertThat(streams[1].readData(formatHolder, inputBuffer, /* readFlags= */ 0))
.isEqualTo(C.RESULT_BUFFER_READ); .isEqualTo(C.RESULT_BUFFER_READ);
assertThat(inputBuffer.timeUs).isEqualTo(456_000 - 3000); assertThat(inputBuffer.timeUs).isEqualTo(456_000 - 3000);
} }
......
...@@ -20,6 +20,8 @@ import static com.google.android.exoplayer2.C.BUFFER_FLAG_KEY_FRAME; ...@@ -20,6 +20,8 @@ import static com.google.android.exoplayer2.C.BUFFER_FLAG_KEY_FRAME;
import static com.google.android.exoplayer2.C.RESULT_BUFFER_READ; import static com.google.android.exoplayer2.C.RESULT_BUFFER_READ;
import static com.google.android.exoplayer2.C.RESULT_FORMAT_READ; import static com.google.android.exoplayer2.C.RESULT_FORMAT_READ;
import static com.google.android.exoplayer2.C.RESULT_NOTHING_READ; import static com.google.android.exoplayer2.C.RESULT_NOTHING_READ;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_OMIT_SAMPLE_DATA;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_PEEK;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static java.lang.Long.MAX_VALUE; import static java.lang.Long.MAX_VALUE;
import static java.lang.Long.MIN_VALUE; import static java.lang.Long.MIN_VALUE;
...@@ -208,14 +210,11 @@ public final class SampleQueueTest { ...@@ -208,14 +210,11 @@ public final class SampleQueueTest {
sampleQueue.format(FORMAT_1); sampleQueue.format(FORMAT_1);
clearFormatHolderAndInputBuffer(); clearFormatHolderAndInputBuffer();
int result = int result =
sampleQueue.peek( sampleQueue.read(formatHolder, inputBuffer, FLAG_PEEK, /* loadingFinished= */ false);
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
// formatHolder should be populated. // formatHolder should be populated.
assertThat(formatHolder.format).isEqualTo(FORMAT_1); assertThat(formatHolder.format).isEqualTo(FORMAT_1);
result = result = sampleQueue.read(formatHolder, inputBuffer, FLAG_PEEK, /* loadingFinished= */ false);
sampleQueue.peek(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_NOTHING_READ); assertThat(result).isEqualTo(RESULT_NOTHING_READ);
} }
...@@ -454,7 +453,7 @@ public final class SampleQueueTest { ...@@ -454,7 +453,7 @@ public final class SampleQueueTest {
int result = int result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession); assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
assertReadEncryptedSample(/* sampleIndex= */ 0); assertReadEncryptedSample(/* sampleIndex= */ 0);
...@@ -463,13 +462,13 @@ public final class SampleQueueTest { ...@@ -463,13 +462,13 @@ public final class SampleQueueTest {
assertThat(formatHolder.drmSession).isNull(); assertThat(formatHolder.drmSession).isNull();
result = result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
assertThat(formatHolder.drmSession).isNull(); assertThat(formatHolder.drmSession).isNull();
assertReadEncryptedSample(/* sampleIndex= */ 2); assertReadEncryptedSample(/* sampleIndex= */ 2);
result = result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession); assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
} }
...@@ -484,7 +483,7 @@ public final class SampleQueueTest { ...@@ -484,7 +483,7 @@ public final class SampleQueueTest {
int result = int result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession); assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
assertReadEncryptedSample(/* sampleIndex= */ 0); assertReadEncryptedSample(/* sampleIndex= */ 0);
...@@ -493,13 +492,13 @@ public final class SampleQueueTest { ...@@ -493,13 +492,13 @@ public final class SampleQueueTest {
assertThat(formatHolder.drmSession).isNull(); assertThat(formatHolder.drmSession).isNull();
result = result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
assertThat(formatHolder.drmSession).isSameInstanceAs(mockPlaceholderDrmSession); assertThat(formatHolder.drmSession).isSameInstanceAs(mockPlaceholderDrmSession);
assertReadEncryptedSample(/* sampleIndex= */ 2); assertReadEncryptedSample(/* sampleIndex= */ 2);
result = result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession); assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
assertReadEncryptedSample(/* sampleIndex= */ 3); assertReadEncryptedSample(/* sampleIndex= */ 3);
...@@ -527,7 +526,7 @@ public final class SampleQueueTest { ...@@ -527,7 +526,7 @@ public final class SampleQueueTest {
int result = int result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
// Fill cryptoInfo.iv with non-zero data. When the 8 byte initialization vector is written into // Fill cryptoInfo.iv with non-zero data. When the 8 byte initialization vector is written into
...@@ -537,7 +536,7 @@ public final class SampleQueueTest { ...@@ -537,7 +536,7 @@ public final class SampleQueueTest {
result = result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_BUFFER_READ); assertThat(result).isEqualTo(RESULT_BUFFER_READ);
// Assert cryptoInfo.iv contains the 8-byte initialization vector and that the trailing 8 bytes // Assert cryptoInfo.iv contains the 8-byte initialization vector and that the trailing 8 bytes
...@@ -1558,7 +1557,11 @@ public final class SampleQueueTest { ...@@ -1558,7 +1557,11 @@ public final class SampleQueueTest {
private void assertReadNothing(boolean formatRequired) { private void assertReadNothing(boolean formatRequired) {
clearFormatHolderAndInputBuffer(); clearFormatHolderAndInputBuffer();
int result = int result =
sampleQueue.read(formatHolder, inputBuffer, formatRequired, /* loadingFinished= */ false); sampleQueue.read(
formatHolder,
inputBuffer,
formatRequired ? SampleStream.FLAG_REQUIRE_FORMAT : 0,
/* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_NOTHING_READ); assertThat(result).isEqualTo(RESULT_NOTHING_READ);
// formatHolder should not be populated. // formatHolder should not be populated.
assertThat(formatHolder.format).isNull(); assertThat(formatHolder.format).isNull();
...@@ -1576,7 +1579,11 @@ public final class SampleQueueTest { ...@@ -1576,7 +1579,11 @@ public final class SampleQueueTest {
private void assertReadEndOfStream(boolean formatRequired) { private void assertReadEndOfStream(boolean formatRequired) {
clearFormatHolderAndInputBuffer(); clearFormatHolderAndInputBuffer();
int result = int result =
sampleQueue.read(formatHolder, inputBuffer, formatRequired, /* loadingFinished= */ true); sampleQueue.read(
formatHolder,
inputBuffer,
formatRequired ? SampleStream.FLAG_REQUIRE_FORMAT : 0,
/* loadingFinished= */ true);
assertThat(result).isEqualTo(RESULT_BUFFER_READ); assertThat(result).isEqualTo(RESULT_BUFFER_READ);
// formatHolder should not be populated. // formatHolder should not be populated.
assertThat(formatHolder.format).isNull(); assertThat(formatHolder.format).isNull();
...@@ -1597,7 +1604,11 @@ public final class SampleQueueTest { ...@@ -1597,7 +1604,11 @@ public final class SampleQueueTest {
private void assertReadFormat(boolean formatRequired, Format format) { private void assertReadFormat(boolean formatRequired, Format format) {
clearFormatHolderAndInputBuffer(); clearFormatHolderAndInputBuffer();
int result = int result =
sampleQueue.read(formatHolder, inputBuffer, formatRequired, /* loadingFinished= */ false); sampleQueue.read(
formatHolder,
inputBuffer,
formatRequired ? SampleStream.FLAG_REQUIRE_FORMAT : 0,
/* loadingFinished= */ false);
assertThat(result).isEqualTo(RESULT_FORMAT_READ); assertThat(result).isEqualTo(RESULT_FORMAT_READ);
// formatHolder should be populated. // formatHolder should be populated.
assertThat(formatHolder.format).isEqualTo(format); assertThat(formatHolder.format).isEqualTo(format);
...@@ -1641,40 +1652,62 @@ public final class SampleQueueTest { ...@@ -1641,40 +1652,62 @@ public final class SampleQueueTest {
byte[] sampleData, byte[] sampleData,
int offset, int offset,
int length) { int length) {
// Check that peeks yields the expected values. // Check that peek whilst omitting data yields the expected values.
clearFormatHolderAndInputBuffer(); formatHolder.format = null;
DecoderInputBuffer flagsOnlyBuffer = DecoderInputBuffer.newNoDataInstance();
int result = int result =
sampleQueue.peek( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder,
assertBufferReadResult( flagsOnlyBuffer,
FLAG_OMIT_SAMPLE_DATA | FLAG_PEEK,
/* loadingFinished= */ false);
assertSampleBufferReadResult(
flagsOnlyBuffer, result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted);
// Check that peek yields the expected values.
clearFormatHolderAndInputBuffer();
result = sampleQueue.read(formatHolder, inputBuffer, FLAG_PEEK, /* loadingFinished= */ false);
assertSampleBufferReadResult(
result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted, sampleData, offset, length); result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted, sampleData, offset, length);
// Check that read yields the expected values. // Check that read yields the expected values.
clearFormatHolderAndInputBuffer(); clearFormatHolderAndInputBuffer();
result = result =
sampleQueue.read( sampleQueue.read(
formatHolder, inputBuffer, /* formatRequired= */ false, /* loadingFinished= */ false); formatHolder, inputBuffer, /* readFlags= */ 0, /* loadingFinished= */ false);
assertBufferReadResult( assertSampleBufferReadResult(
result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted, sampleData, offset, length); result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted, sampleData, offset, length);
} }
private void assertBufferReadResult( private void assertSampleBufferReadResult(
DecoderInputBuffer inputBuffer,
int result, int result,
long timeUs, long timeUs,
boolean isKeyFrame, boolean isKeyFrame,
boolean isDecodeOnly, boolean isDecodeOnly,
boolean isEncrypted, boolean isEncrypted) {
byte[] sampleData,
int offset,
int length) {
assertThat(result).isEqualTo(RESULT_BUFFER_READ); assertThat(result).isEqualTo(RESULT_BUFFER_READ);
// formatHolder should not be populated. // formatHolder should not be populated.
assertThat(formatHolder.format).isNull(); assertThat(formatHolder.format).isNull();
// inputBuffer should be populated. // inputBuffer should be populated with metadata.
assertThat(inputBuffer.timeUs).isEqualTo(timeUs); assertThat(inputBuffer.timeUs).isEqualTo(timeUs);
assertThat(inputBuffer.isKeyFrame()).isEqualTo(isKeyFrame); assertThat(inputBuffer.isKeyFrame()).isEqualTo(isKeyFrame);
assertThat(inputBuffer.isDecodeOnly()).isEqualTo(isDecodeOnly); assertThat(inputBuffer.isDecodeOnly()).isEqualTo(isDecodeOnly);
assertThat(inputBuffer.isEncrypted()).isEqualTo(isEncrypted); assertThat(inputBuffer.isEncrypted()).isEqualTo(isEncrypted);
}
private void assertSampleBufferReadResult(
int result,
long timeUs,
boolean isKeyFrame,
boolean isDecodeOnly,
boolean isEncrypted,
byte[] sampleData,
int offset,
int length) {
assertSampleBufferReadResult(
inputBuffer, result, timeUs, isKeyFrame, isDecodeOnly, isEncrypted);
// inputBuffer should be populated with data.
inputBuffer.flip(); inputBuffer.flip();
assertThat(inputBuffer.data.limit()).isEqualTo(length); assertThat(inputBuffer.data.limit()).isEqualTo(length);
byte[] readData = new byte[length]; byte[] readData = new byte[length];
......
...@@ -98,9 +98,9 @@ import java.io.IOException; ...@@ -98,9 +98,9 @@ import java.io.IOException;
} }
@Override @Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, public int readData(
boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
if (formatRequired || !isFormatSentDownstream) { if ((readFlags & FLAG_REQUIRE_FORMAT) != 0 || !isFormatSentDownstream) {
formatHolder.format = upstreamFormat; formatHolder.format = upstreamFormat;
isFormatSentDownstream = true; isFormatSentDownstream = true;
return C.RESULT_FORMAT_READ; return C.RESULT_FORMAT_READ;
......
...@@ -360,8 +360,7 @@ public final class PlayerEmsgHandler implements Handler.Callback { ...@@ -360,8 +360,7 @@ public final class PlayerEmsgHandler implements Handler.Callback {
private MetadataInputBuffer dequeueSample() { private MetadataInputBuffer dequeueSample() {
buffer.clear(); buffer.clear();
int result = int result =
sampleQueue.read( sampleQueue.read(formatHolder, buffer, /* readFlags= */ 0, /* loadingFinished= */ false);
formatHolder, buffer, /* formatRequired= */ false, /* loadingFinished= */ false);
if (result == C.RESULT_BUFFER_READ) { if (result == C.RESULT_BUFFER_READ) {
buffer.flip(); buffer.flip();
return buffer; return buffer;
......
...@@ -58,7 +58,7 @@ public final class EventSampleStreamTest { ...@@ -58,7 +58,7 @@ public final class EventSampleStreamTest {
} }
/** /**
* Tests that {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} will * Tests that {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} will
* return format for the first call. * return format for the first call.
*/ */
@Test @Test
...@@ -106,7 +106,7 @@ public final class EventSampleStreamTest { ...@@ -106,7 +106,7 @@ public final class EventSampleStreamTest {
} }
/** /**
* Tests that {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} will * Tests that {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} will
* return sample data after the first call. * return sample data after the first call.
*/ */
@Test @Test
...@@ -127,8 +127,8 @@ public final class EventSampleStreamTest { ...@@ -127,8 +127,8 @@ public final class EventSampleStreamTest {
/** /**
* Tests that {@link EventSampleStream#skipData(long)} will skip until the given position, and the * Tests that {@link EventSampleStream#skipData(long)} will skip until the given position, and the
* next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} call will * next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return
* return sample data from that position. * sample data from that position.
*/ */
@Test @Test
public void skipDataThenReadDataReturnDataFromSkippedPosition() { public void skipDataThenReadDataReturnDataFromSkippedPosition() {
...@@ -153,7 +153,7 @@ public final class EventSampleStreamTest { ...@@ -153,7 +153,7 @@ public final class EventSampleStreamTest {
/** /**
* Tests that {@link EventSampleStream#seekToUs(long)} (long)} will seek to the given position, * Tests that {@link EventSampleStream#seekToUs(long)} (long)} will seek to the given position,
* and the next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} call * and the next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call
* will return sample data from that position. * will return sample data from that position.
*/ */
@Test @Test
...@@ -179,8 +179,8 @@ public final class EventSampleStreamTest { ...@@ -179,8 +179,8 @@ public final class EventSampleStreamTest {
/** /**
* Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the * Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the
* underlying event stream, but keep the read timestamp, so the next {@link * underlying event stream, but keep the read timestamp, so the next {@link
* EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} call will return sample * EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return sample data
* data from after the last read sample timestamp. * from after the last read sample timestamp.
*/ */
@Test @Test
public void updateEventStreamContinueToReadAfterLastReadSamplePresentationTime() { public void updateEventStreamContinueToReadAfterLastReadSamplePresentationTime() {
...@@ -213,8 +213,8 @@ public final class EventSampleStreamTest { ...@@ -213,8 +213,8 @@ public final class EventSampleStreamTest {
/** /**
* Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the * Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the
* underlying event stream, but keep the timestamp the stream has skipped to, so the next {@link * underlying event stream, but keep the timestamp the stream has skipped to, so the next {@link
* EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} call will return sample * EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return sample data
* data from the skipped position. * from the skipped position.
*/ */
@Test @Test
public void skipDataThenUpdateStreamContinueToReadFromSkippedPosition() { public void skipDataThenUpdateStreamContinueToReadFromSkippedPosition() {
...@@ -246,8 +246,8 @@ public final class EventSampleStreamTest { ...@@ -246,8 +246,8 @@ public final class EventSampleStreamTest {
* Tests that {@link EventSampleStream#skipData(long)} will only skip to the point right after it * Tests that {@link EventSampleStream#skipData(long)} will only skip to the point right after it
* last event. A following {@link EventSampleStream#updateEventStream(EventStream, boolean)} will * last event. A following {@link EventSampleStream#updateEventStream(EventStream, boolean)} will
* update the underlying event stream and keep the timestamp the stream has skipped to, so the * update the underlying event stream and keep the timestamp the stream has skipped to, so the
* next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} call will * next {@link EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return
* return sample data from the skipped position. * sample data from the skipped position.
*/ */
@Test @Test
public void skipDataThenUpdateStreamContinueToReadDoNotSkippedMoreThanAvailable() { public void skipDataThenUpdateStreamContinueToReadDoNotSkippedMoreThanAvailable() {
...@@ -280,8 +280,8 @@ public final class EventSampleStreamTest { ...@@ -280,8 +280,8 @@ public final class EventSampleStreamTest {
/** /**
* Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the * Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the
* underlying event stream, but keep the timestamp the stream has seek to, so the next {@link * underlying event stream, but keep the timestamp the stream has seek to, so the next {@link
* EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} call will return sample * EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return sample data
* data from the seek position. * from the seek position.
*/ */
@Test @Test
public void seekToUsThenUpdateStreamContinueToReadFromSeekPosition() { public void seekToUsThenUpdateStreamContinueToReadFromSeekPosition() {
...@@ -312,8 +312,8 @@ public final class EventSampleStreamTest { ...@@ -312,8 +312,8 @@ public final class EventSampleStreamTest {
/** /**
* Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the * Tests that {@link EventSampleStream#updateEventStream(EventStream, boolean)} will update the
* underlying event stream, but keep the timestamp the stream has seek to, so the next {@link * underlying event stream, but keep the timestamp the stream has seek to, so the next {@link
* EventSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)} call will return sample * EventSampleStream#readData(FormatHolder, DecoderInputBuffer, int)} call will return sample data
* data from the seek position. * from the seek position.
*/ */
@Test @Test
public void seekToThenUpdateStreamContinueToReadFromSeekPositionEvenSeekMoreThanAvailable() { public void seekToThenUpdateStreamContinueToReadFromSeekPositionEvenSeekMoreThanAvailable() {
...@@ -343,7 +343,7 @@ public final class EventSampleStreamTest { ...@@ -343,7 +343,7 @@ public final class EventSampleStreamTest {
private int readData(EventSampleStream sampleStream) { private int readData(EventSampleStream sampleStream) {
inputBuffer.clear(); inputBuffer.clear();
return sampleStream.readData(formatHolder, inputBuffer, false); return sampleStream.readData(formatHolder, inputBuffer, /* readFlags= */ 0);
} }
private EventMessage newEventMessageWithId(int id) { private EventMessage newEventMessageWithId(int id) {
......
...@@ -70,13 +70,14 @@ import java.io.IOException; ...@@ -70,13 +70,14 @@ import java.io.IOException;
} }
@Override @Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean requireFormat) { public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
if (sampleQueueIndex == HlsSampleStreamWrapper.SAMPLE_QUEUE_INDEX_NO_MAPPING_NON_FATAL) { if (sampleQueueIndex == HlsSampleStreamWrapper.SAMPLE_QUEUE_INDEX_NO_MAPPING_NON_FATAL) {
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return C.RESULT_BUFFER_READ; return C.RESULT_BUFFER_READ;
} }
return hasValidSampleQueueIndex() return hasValidSampleQueueIndex()
? sampleStreamWrapper.readData(sampleQueueIndex, formatHolder, buffer, requireFormat) ? sampleStreamWrapper.readData(sampleQueueIndex, formatHolder, buffer, readFlags)
: C.RESULT_NOTHING_READ; : C.RESULT_NOTHING_READ;
} }
......
...@@ -48,6 +48,7 @@ import com.google.android.exoplayer2.source.MediaSourceEventListener; ...@@ -48,6 +48,7 @@ import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleQueue; import com.google.android.exoplayer2.source.SampleQueue;
import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener; import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SampleStream.ReadFlags;
import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
...@@ -569,8 +570,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -569,8 +570,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
chunkSource.maybeThrowError(); chunkSource.maybeThrowError();
} }
public int readData(int sampleQueueIndex, FormatHolder formatHolder, DecoderInputBuffer buffer, public int readData(
boolean requireFormat) { int sampleQueueIndex,
FormatHolder formatHolder,
DecoderInputBuffer buffer,
@ReadFlags int readFlags) {
if (isPendingReset()) { if (isPendingReset()) {
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
...@@ -602,7 +606,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -602,7 +606,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
int result = int result =
sampleQueues[sampleQueueIndex].read(formatHolder, buffer, requireFormat, loadingFinished); sampleQueues[sampleQueueIndex].read(formatHolder, buffer, readFlags, loadingFinished);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
Format format = Assertions.checkNotNull(formatHolder.format); Format format = Assertions.checkNotNull(formatHolder.format);
if (sampleQueueIndex == primarySampleQueueIndex) { if (sampleQueueIndex == primarySampleQueueIndex) {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.transformer; package com.google.android.exoplayer2.transformer;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkState; import static com.google.android.exoplayer2.util.Assertions.checkState;
import static java.lang.Math.min; import static java.lang.Math.min;
...@@ -31,7 +32,7 @@ import com.google.android.exoplayer2.audio.AudioProcessor; ...@@ -31,7 +32,7 @@ import com.google.android.exoplayer2.audio.AudioProcessor;
import com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat; import com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat;
import com.google.android.exoplayer2.audio.SonicAudioProcessor; import com.google.android.exoplayer2.audio.SonicAudioProcessor;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
...@@ -273,8 +274,8 @@ import java.nio.ByteBuffer; ...@@ -273,8 +274,8 @@ import java.nio.ByteBuffer;
} }
decoderInputBuffer.clear(); decoderInputBuffer.clear();
@SampleStream.ReadDataResult @ReadDataResult
int result = readSource(getFormatHolder(), decoderInputBuffer, /* formatRequired= */ false); int result = readSource(getFormatHolder(), decoderInputBuffer, /* readFlags= */ 0);
switch (result) { switch (result) {
case C.RESULT_BUFFER_READ: case C.RESULT_BUFFER_READ:
mediaClock.updateTimeForTrackType(getTrackType(), decoderInputBuffer.timeUs); mediaClock.updateTimeForTrackType(getTrackType(), decoderInputBuffer.timeUs);
...@@ -373,8 +374,7 @@ import java.nio.ByteBuffer; ...@@ -373,8 +374,7 @@ import java.nio.ByteBuffer;
} }
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
@SampleStream.ReadDataResult @ReadDataResult int result = readSource(formatHolder, decoderInputBuffer, FLAG_REQUIRE_FORMAT);
int result = readSource(formatHolder, decoderInputBuffer, /* formatRequired= */ true);
if (result != C.RESULT_FORMAT_READ) { if (result != C.RESULT_FORMAT_READ) {
return false; return false;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.transformer; package com.google.android.exoplayer2.transformer;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -24,7 +25,7 @@ import com.google.android.exoplayer2.C; ...@@ -24,7 +25,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@RequiresApi(18) @RequiresApi(18)
...@@ -59,8 +60,7 @@ import java.nio.ByteBuffer; ...@@ -59,8 +60,7 @@ import java.nio.ByteBuffer;
if (!formatRead) { if (!formatRead) {
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
@SampleStream.ReadDataResult @ReadDataResult int result = readSource(formatHolder, buffer, FLAG_REQUIRE_FORMAT);
int result = readSource(formatHolder, buffer, /* formatRequired= */ true);
if (result != C.RESULT_FORMAT_READ) { if (result != C.RESULT_FORMAT_READ) {
return; return;
} }
...@@ -102,8 +102,7 @@ import java.nio.ByteBuffer; ...@@ -102,8 +102,7 @@ import java.nio.ByteBuffer;
*/ */
private boolean readAndTransformBuffer() { private boolean readAndTransformBuffer() {
buffer.clear(); buffer.clear();
@SampleStream.ReadDataResult @ReadDataResult int result = readSource(getFormatHolder(), buffer, /* readFlags= */ 0);
int result = readSource(getFormatHolder(), buffer, /* formatRequired= */ false);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
throw new IllegalStateException("Format changes are not supported."); throw new IllegalStateException("Format changes are not supported.");
} else if (result == C.RESULT_NOTHING_READ) { } else if (result == C.RESULT_NOTHING_READ) {
......
...@@ -25,7 +25,7 @@ import com.google.android.exoplayer2.Renderer; ...@@ -25,7 +25,7 @@ import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -92,8 +92,7 @@ public class FakeRenderer extends BaseRenderer { ...@@ -92,8 +92,7 @@ public class FakeRenderer extends BaseRenderer {
if (!hasPendingBuffer) { if (!hasPendingBuffer) {
FormatHolder formatHolder = getFormatHolder(); FormatHolder formatHolder = getFormatHolder();
buffer.clear(); buffer.clear();
@SampleStream.ReadDataResult @ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */ 0);
int result = readSource(formatHolder, buffer, /* formatRequired= */ false);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
DrmSession.replaceSession(currentDrmSession, formatHolder.drmSession); DrmSession.replaceSession(currentDrmSession, formatHolder.drmSession);
......
...@@ -43,7 +43,7 @@ import java.util.List; ...@@ -43,7 +43,7 @@ import java.util.List;
*/ */
public class FakeSampleStream implements SampleStream { public class FakeSampleStream implements SampleStream {
/** Item to customize a return value of {@link FakeSampleStream#readData}. */ /** Item to customize a return value of {@link SampleStream#readData}. */
public static final class FakeSampleStreamItem { public static final class FakeSampleStreamItem {
/** Item that designates the end of stream has been reached. */ /** Item that designates the end of stream has been reached. */
...@@ -265,12 +265,12 @@ public class FakeSampleStream implements SampleStream { ...@@ -265,12 +265,12 @@ public class FakeSampleStream implements SampleStream {
@Override @Override
public int readData( public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) { FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {
int result = sampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished); int result = sampleQueue.read(formatHolder, buffer, readFlags, loadingFinished);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
downstreamFormat = checkNotNull(formatHolder.format); downstreamFormat = checkNotNull(formatHolder.format);
} }
if (result == C.RESULT_BUFFER_READ && !buffer.isFlagsOnly()) { if (result == C.RESULT_BUFFER_READ && (readFlags & FLAG_OMIT_SAMPLE_DATA) == 0) {
maybeNotifyDownstreamFormat(buffer.timeUs); maybeNotifyDownstreamFormat(buffer.timeUs);
} }
return result; return result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment