Commit 56205893 by tonihei Committed by Oliver Woodman

Remove initial discontinuity from ClippingMediaSource

(Fixing GitHub issue #2923)

Cuurently, ClippingMediaSource issues an initial discontinuity. This causes the
renderers to be disabled and re-enabled when this media source is used in a sequence
with other sources (or in a loop).

This change disables the use of an initial discontinuity for audio-only media under
the assumption that audio streams have random access capabilities.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=159221963
parent c7948f2f
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
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.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException; import java.io.IOException;
/** /**
...@@ -49,10 +51,29 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb ...@@ -49,10 +51,29 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
* @param mediaPeriod The media period to clip. * @param mediaPeriod The media period to clip.
*/ */
public ClippingMediaPeriod(MediaPeriod mediaPeriod) { public ClippingMediaPeriod(MediaPeriod mediaPeriod) {
this(mediaPeriod, true);
}
/**
* Creates a new clipping media period that provides a clipped view of the specified
* {@link MediaPeriod}'s sample streams.
* <p>
* The clipping start/end positions must be specified by calling {@link #setClipping(long, long)}
* on the playback thread before preparation completes.
* <p>
* If the start point is guaranteed to be a key frame, pass {@code false} to {@code
* enableInitialPositionDiscontinuity} to suppress an initial discontinuity when the period is
* first read from.
*
* @param mediaPeriod The media period to clip.
* @param enableInitialDiscontinuity Whether the initial discontinuity should be enabled.
*/
public ClippingMediaPeriod(MediaPeriod mediaPeriod, boolean enableInitialDiscontinuity) {
this.mediaPeriod = mediaPeriod; this.mediaPeriod = mediaPeriod;
startUs = C.TIME_UNSET; startUs = C.TIME_UNSET;
endUs = C.TIME_UNSET; endUs = C.TIME_UNSET;
sampleStreams = new ClippingSampleStream[0]; sampleStreams = new ClippingSampleStream[0];
pendingInitialDiscontinuity = enableInitialDiscontinuity;
} }
/** /**
...@@ -94,6 +115,9 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb ...@@ -94,6 +115,9 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
} }
long enablePositionUs = mediaPeriod.selectTracks(selections, mayRetainStreamFlags, long enablePositionUs = mediaPeriod.selectTracks(selections, mayRetainStreamFlags,
internalStreams, streamResetFlags, positionUs + startUs); internalStreams, streamResetFlags, positionUs + startUs);
if (pendingInitialDiscontinuity) {
pendingInitialDiscontinuity = startUs != 0 && shouldKeepInitialDiscontinuity(selections);
}
Assertions.checkState(enablePositionUs == positionUs + startUs Assertions.checkState(enablePositionUs == positionUs + startUs
|| (enablePositionUs >= startUs || (enablePositionUs >= startUs
&& (endUs == C.TIME_END_OF_SOURCE || enablePositionUs <= endUs))); && (endUs == C.TIME_END_OF_SOURCE || enablePositionUs <= endUs)));
...@@ -179,6 +203,15 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb ...@@ -179,6 +203,15 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
@Override @Override
public void onPrepared(MediaPeriod mediaPeriod) { public void onPrepared(MediaPeriod mediaPeriod) {
Assertions.checkState(startUs != C.TIME_UNSET && endUs != C.TIME_UNSET); Assertions.checkState(startUs != C.TIME_UNSET && endUs != C.TIME_UNSET);
callback.onPrepared(this);
}
@Override
public void onContinueLoadingRequested(MediaPeriod source) {
callback.onContinueLoadingRequested(this);
}
private static boolean shouldKeepInitialDiscontinuity(TrackSelection[] selections) {
// If the clipping start position is non-zero, the clipping sample streams will adjust // If the clipping start position is non-zero, the clipping sample streams will adjust
// timestamps on buffers they read from the unclipped sample streams. These adjusted buffer // timestamps on buffers they read from the unclipped sample streams. These adjusted buffer
// timestamps can be negative, because sample streams provide buffers starting at a key-frame, // timestamps can be negative, because sample streams provide buffers starting at a key-frame,
...@@ -186,13 +219,17 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb ...@@ -186,13 +219,17 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
// negative timestamp, its offset timestamp can jump backwards compared to the last timestamp // negative timestamp, its offset timestamp can jump backwards compared to the last timestamp
// read in the previous period. Renderer implementations may not allow this, so we signal a // read in the previous period. Renderer implementations may not allow this, so we signal a
// discontinuity which resets the renderers before they read the clipping sample stream. // discontinuity which resets the renderers before they read the clipping sample stream.
pendingInitialDiscontinuity = startUs != 0; // However, for audio-only track selections we assume to have random access seek behaviour and
callback.onPrepared(this); // do not need an initial discontinuity to reset the renderer.
} for (TrackSelection trackSelection : selections) {
if (trackSelection != null) {
@Override Format selectedFormat = trackSelection.getSelectedFormat();
public void onContinueLoadingRequested(MediaPeriod source) { if (!MimeTypes.isAudio(selectedFormat.sampleMimeType)) {
callback.onContinueLoadingRequested(this); return true;
}
}
}
return false;
} }
/** /**
......
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