Used fixed time frame in clipping media period.
Currently, whenever the clipping is updated, we move the time frame of the clipped period to start at 0. This causes problems when we are already playing this period and the renderer position does no longer match the stream positions. This change keeps the time frame of the clipped media period as it is and instead specifies the offset of the window in the period. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=189570277
This commit is contained in:
parent
371f3acea8
commit
6b527da462
@ -81,9 +81,12 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
mayRetainStreamFlags = new boolean[rendererCapabilities.length];
|
||||
MediaPeriod mediaPeriod = mediaSource.createPeriod(info.id, allocator);
|
||||
if (info.endPositionUs != C.TIME_END_OF_SOURCE) {
|
||||
ClippingMediaPeriod clippingMediaPeriod = new ClippingMediaPeriod(mediaPeriod, true);
|
||||
clippingMediaPeriod.setClipping(0, info.endPositionUs);
|
||||
mediaPeriod = clippingMediaPeriod;
|
||||
mediaPeriod =
|
||||
new ClippingMediaPeriod(
|
||||
mediaPeriod,
|
||||
/* enableInitialDiscontinuity= */ true,
|
||||
/* startUs= */ 0,
|
||||
info.endPositionUs);
|
||||
}
|
||||
this.mediaPeriod = mediaPeriod;
|
||||
}
|
||||
|
@ -43,35 +43,36 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
/* package */ long endUs;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Creates a new clipping media period that provides a clipped view of the specified {@link
|
||||
* MediaPeriod}'s sample streams.
|
||||
*
|
||||
* <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.
|
||||
* @param startUs The clipping start time, in microseconds.
|
||||
* @param endUs The clipping end time, in microseconds, or {@link C#TIME_END_OF_SOURCE} to
|
||||
* indicate the end of the period.
|
||||
*/
|
||||
public ClippingMediaPeriod(MediaPeriod mediaPeriod, boolean enableInitialDiscontinuity) {
|
||||
public ClippingMediaPeriod(
|
||||
MediaPeriod mediaPeriod, boolean enableInitialDiscontinuity, long startUs, long endUs) {
|
||||
this.mediaPeriod = mediaPeriod;
|
||||
sampleStreams = new ClippingSampleStream[0];
|
||||
pendingInitialDiscontinuityPositionUs = enableInitialDiscontinuity ? 0 : C.TIME_UNSET;
|
||||
startUs = C.TIME_UNSET;
|
||||
endUs = C.TIME_UNSET;
|
||||
pendingInitialDiscontinuityPositionUs = enableInitialDiscontinuity ? startUs : C.TIME_UNSET;
|
||||
this.startUs = startUs;
|
||||
this.endUs = endUs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clipping start/end times for this period, in microseconds.
|
||||
* Updates the clipping start/end times for this period, in microseconds.
|
||||
*
|
||||
* @param startUs The clipping start time, in microseconds.
|
||||
* @param endUs The clipping end time, in microseconds, or {@link C#TIME_END_OF_SOURCE} to
|
||||
* indicate the end of the period.
|
||||
*/
|
||||
public void setClipping(long startUs, long endUs) {
|
||||
public void updateClipping(long startUs, long endUs) {
|
||||
this.startUs = startUs;
|
||||
this.endUs = endUs;
|
||||
}
|
||||
@ -79,7 +80,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
@Override
|
||||
public void prepare(MediaPeriod.Callback callback, long positionUs) {
|
||||
this.callback = callback;
|
||||
mediaPeriod.prepare(this, startUs + positionUs);
|
||||
mediaPeriod.prepare(this, positionUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -101,13 +102,19 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
sampleStreams[i] = (ClippingSampleStream) streams[i];
|
||||
childStreams[i] = sampleStreams[i] != null ? sampleStreams[i].childStream : null;
|
||||
}
|
||||
long enablePositionUs = mediaPeriod.selectTracks(selections, mayRetainStreamFlags,
|
||||
childStreams, streamResetFlags, positionUs + startUs) - startUs;
|
||||
pendingInitialDiscontinuityPositionUs = isPendingInitialDiscontinuity() && positionUs == 0
|
||||
&& shouldKeepInitialDiscontinuity(startUs, selections) ? enablePositionUs : C.TIME_UNSET;
|
||||
Assertions.checkState(enablePositionUs == positionUs
|
||||
|| (enablePositionUs >= 0
|
||||
&& (endUs == C.TIME_END_OF_SOURCE || startUs + enablePositionUs <= endUs)));
|
||||
long enablePositionUs =
|
||||
mediaPeriod.selectTracks(
|
||||
selections, mayRetainStreamFlags, childStreams, streamResetFlags, positionUs);
|
||||
pendingInitialDiscontinuityPositionUs =
|
||||
isPendingInitialDiscontinuity()
|
||||
&& positionUs == startUs
|
||||
&& shouldKeepInitialDiscontinuity(startUs, selections)
|
||||
? enablePositionUs
|
||||
: C.TIME_UNSET;
|
||||
Assertions.checkState(
|
||||
enablePositionUs == positionUs
|
||||
|| (enablePositionUs >= startUs
|
||||
&& (endUs == C.TIME_END_OF_SOURCE || enablePositionUs <= endUs)));
|
||||
for (int i = 0; i < streams.length; i++) {
|
||||
if (childStreams[i] == null) {
|
||||
sampleStreams[i] = null;
|
||||
@ -121,12 +128,12 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
|
||||
@Override
|
||||
public void discardBuffer(long positionUs, boolean toKeyframe) {
|
||||
mediaPeriod.discardBuffer(positionUs + startUs, toKeyframe);
|
||||
mediaPeriod.discardBuffer(positionUs, toKeyframe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reevaluateBuffer(long positionUs) {
|
||||
mediaPeriod.reevaluateBuffer(positionUs + startUs);
|
||||
mediaPeriod.reevaluateBuffer(positionUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -144,7 +151,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
}
|
||||
Assertions.checkState(discontinuityUs >= startUs);
|
||||
Assertions.checkState(endUs == C.TIME_END_OF_SOURCE || discontinuityUs <= endUs);
|
||||
return discontinuityUs - startUs;
|
||||
return discontinuityUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -154,7 +161,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
|| (endUs != C.TIME_END_OF_SOURCE && bufferedPositionUs >= endUs)) {
|
||||
return C.TIME_END_OF_SOURCE;
|
||||
}
|
||||
return Math.max(0, bufferedPositionUs - startUs);
|
||||
return bufferedPositionUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -165,23 +172,21 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
sampleStream.clearSentEos();
|
||||
}
|
||||
}
|
||||
long offsetPositionUs = positionUs + startUs;
|
||||
long seekUs = mediaPeriod.seekToUs(offsetPositionUs);
|
||||
long seekUs = mediaPeriod.seekToUs(positionUs);
|
||||
Assertions.checkState(
|
||||
seekUs == offsetPositionUs
|
||||
seekUs == positionUs
|
||||
|| (seekUs >= startUs && (endUs == C.TIME_END_OF_SOURCE || seekUs <= endUs)));
|
||||
return seekUs - startUs;
|
||||
return seekUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
|
||||
if (positionUs == 0) {
|
||||
if (positionUs == startUs) {
|
||||
// Never adjust seeks to the start of the clipped view.
|
||||
return 0;
|
||||
return startUs;
|
||||
}
|
||||
long offsetPositionUs = positionUs + startUs;
|
||||
SeekParameters clippedSeekParameters = clipSeekParameters(offsetPositionUs, seekParameters);
|
||||
return mediaPeriod.getAdjustedSeekPositionUs(offsetPositionUs, clippedSeekParameters) - startUs;
|
||||
SeekParameters clippedSeekParameters = clipSeekParameters(positionUs, seekParameters);
|
||||
return mediaPeriod.getAdjustedSeekPositionUs(positionUs, clippedSeekParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -191,19 +196,18 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
|| (endUs != C.TIME_END_OF_SOURCE && nextLoadPositionUs >= endUs)) {
|
||||
return C.TIME_END_OF_SOURCE;
|
||||
}
|
||||
return nextLoadPositionUs - startUs;
|
||||
return nextLoadPositionUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return mediaPeriod.continueLoading(positionUs + startUs);
|
||||
return mediaPeriod.continueLoading(positionUs);
|
||||
}
|
||||
|
||||
// MediaPeriod.Callback implementation.
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||
Assertions.checkState(startUs != C.TIME_UNSET && endUs != C.TIME_UNSET);
|
||||
callback.onPrepared(this);
|
||||
}
|
||||
|
||||
@ -216,17 +220,17 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
return pendingInitialDiscontinuityPositionUs != C.TIME_UNSET;
|
||||
}
|
||||
|
||||
private SeekParameters clipSeekParameters(long offsetPositionUs, SeekParameters seekParameters) {
|
||||
long toleranceBeforeMs = Math.min(offsetPositionUs - startUs, seekParameters.toleranceBeforeUs);
|
||||
long toleranceAfterMs =
|
||||
private SeekParameters clipSeekParameters(long positionUs, SeekParameters seekParameters) {
|
||||
long toleranceBeforeUs = Math.min(positionUs - startUs, seekParameters.toleranceBeforeUs);
|
||||
long toleranceAfterUs =
|
||||
endUs == C.TIME_END_OF_SOURCE
|
||||
? seekParameters.toleranceAfterUs
|
||||
: Math.min(endUs - offsetPositionUs, seekParameters.toleranceAfterUs);
|
||||
if (toleranceBeforeMs == seekParameters.toleranceBeforeUs
|
||||
&& toleranceAfterMs == seekParameters.toleranceAfterUs) {
|
||||
: Math.min(endUs - positionUs, seekParameters.toleranceAfterUs);
|
||||
if (toleranceBeforeUs == seekParameters.toleranceBeforeUs
|
||||
&& toleranceAfterUs == seekParameters.toleranceAfterUs) {
|
||||
return seekParameters;
|
||||
} else {
|
||||
return new SeekParameters(toleranceBeforeMs, toleranceAfterMs);
|
||||
return new SeekParameters(toleranceBeforeUs, toleranceAfterUs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,9 +314,6 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
sentEos = true;
|
||||
return C.RESULT_BUFFER_READ;
|
||||
}
|
||||
if (result == C.RESULT_BUFFER_READ && !buffer.isEndOfStream()) {
|
||||
buffer.timeUs -= startUs;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -321,7 +322,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
if (isPendingInitialDiscontinuity()) {
|
||||
return C.RESULT_NOTHING_READ;
|
||||
}
|
||||
return childStream.skipData(startUs + positionUs);
|
||||
return childStream.skipData(positionUs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -141,10 +141,13 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
|
||||
ClippingMediaPeriod mediaPeriod = new ClippingMediaPeriod(
|
||||
mediaSource.createPeriod(id, allocator), enableInitialDiscontinuity);
|
||||
ClippingMediaPeriod mediaPeriod =
|
||||
new ClippingMediaPeriod(
|
||||
mediaSource.createPeriod(id, allocator),
|
||||
enableInitialDiscontinuity,
|
||||
periodStartUs,
|
||||
periodEndUs);
|
||||
mediaPeriods.add(mediaPeriod);
|
||||
mediaPeriod.setClipping(periodStartUs, periodEndUs);
|
||||
return mediaPeriod;
|
||||
}
|
||||
|
||||
@ -183,7 +186,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
endUs == C.TIME_END_OF_SOURCE ? C.TIME_END_OF_SOURCE : windowPositionInPeriodUs + endUs;
|
||||
int count = mediaPeriods.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mediaPeriods.get(i).setClipping(periodStartUs, periodEndUs);
|
||||
mediaPeriods.get(i).updateClipping(periodStartUs, periodEndUs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,7 +236,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
public Window getWindow(int windowIndex, Window window, boolean setIds,
|
||||
long defaultPositionProjectionUs) {
|
||||
timeline.getWindow(/* windowIndex= */ 0, window, setIds, defaultPositionProjectionUs);
|
||||
window.positionInFirstPeriodUs = 0;
|
||||
window.positionInFirstPeriodUs += startUs;
|
||||
window.durationUs = durationUs;
|
||||
if (window.defaultPositionUs != C.TIME_UNSET) {
|
||||
window.defaultPositionUs = Math.max(window.defaultPositionUs, startUs);
|
||||
@ -254,10 +257,11 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
@Override
|
||||
public Period getPeriod(int periodIndex, Period period, boolean setIds) {
|
||||
timeline.getPeriod(/* periodIndex= */ 0, period, setIds);
|
||||
long positionInClippedWindowUs = period.getPositionInWindowUs() - startUs;
|
||||
long periodDurationUs =
|
||||
durationUs == C.TIME_UNSET ? C.TIME_UNSET : durationUs - positionInClippedWindowUs;
|
||||
return period.set(
|
||||
period.id, period.uid, /* windowIndex= */ 0, durationUs, /* positionInWindowUs= */ 0);
|
||||
period.id, period.uid, /* windowIndex= */ 0, periodDurationUs, positionInClippedWindowUs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public final class ClippingMediaSourceTest {
|
||||
assertThat(clippedTimeline.getWindow(0, window).getDurationUs())
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US);
|
||||
assertThat(clippedTimeline.getPeriod(0, period).getDurationUs())
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US);
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -121,7 +121,7 @@ public final class ClippingMediaSourceTest {
|
||||
assertThat(clippedTimeline.getWindow(0, window).getDurationUs())
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3);
|
||||
assertThat(clippedTimeline.getPeriod(0, period).getDurationUs())
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3);
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -164,7 +164,7 @@ public final class ClippingMediaSourceTest {
|
||||
assertThat(clippedTimeline.getWindow(0, window).getDurationUs())
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3);
|
||||
assertThat(clippedTimeline.getPeriod(0, period).getDurationUs())
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3);
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user