mirror of
https://github.com/androidx/media.git
synced 2025-05-15 11:39:56 +08:00
Don't apply speed adjustment if windowStartTime is unknown.
This may happen for HLS live streams without program date time information. Issue: #8560 PiperOrigin-RevId: 356227729
This commit is contained in:
parent
a08514315f
commit
5211f06dc2
@ -1,5 +1,11 @@
|
|||||||
# Release notes
|
# Release notes
|
||||||
|
|
||||||
|
### 2.13.1 (not yet released)
|
||||||
|
|
||||||
|
* Core library:
|
||||||
|
* Fix playback issue for HLS live streams without program date time
|
||||||
|
information ([#8560](https://github.com/google/ExoPlayer/issues/8560)).
|
||||||
|
|
||||||
### 2.13.0 (2021-02-04)
|
### 2.13.0 (2021-02-04)
|
||||||
|
|
||||||
* Core library:
|
* Core library:
|
||||||
|
@ -880,7 +880,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
// Adjust live playback speed to new position.
|
// Adjust live playback speed to new position.
|
||||||
if (playbackInfo.playWhenReady
|
if (playbackInfo.playWhenReady
|
||||||
&& playbackInfo.playbackState == Player.STATE_READY
|
&& playbackInfo.playbackState == Player.STATE_READY
|
||||||
&& isCurrentPeriodInMovingLiveWindow()
|
&& shouldUseLivePlaybackSpeedControl(playbackInfo.timeline, playbackInfo.periodId)
|
||||||
&& playbackInfo.playbackParameters.speed == 1f) {
|
&& playbackInfo.playbackParameters.speed == 1f) {
|
||||||
float adjustedSpeed =
|
float adjustedSpeed =
|
||||||
livePlaybackSpeedControl.getAdjustedPlaybackSpeed(
|
livePlaybackSpeedControl.getAdjustedPlaybackSpeed(
|
||||||
@ -1051,17 +1051,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
- (periodPositionUs + period.getPositionInWindowUs());
|
- (periodPositionUs + period.getPositionInWindowUs());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCurrentPeriodInMovingLiveWindow() {
|
private boolean shouldUseLivePlaybackSpeedControl(
|
||||||
return isInMovingLiveWindow(playbackInfo.timeline, playbackInfo.periodId);
|
Timeline timeline, MediaPeriodId mediaPeriodId) {
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInMovingLiveWindow(Timeline timeline, MediaPeriodId mediaPeriodId) {
|
|
||||||
if (mediaPeriodId.isAd() || timeline.isEmpty()) {
|
if (mediaPeriodId.isAd() || timeline.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int windowIndex = timeline.getPeriodByUid(mediaPeriodId.periodUid, period).windowIndex;
|
int windowIndex = timeline.getPeriodByUid(mediaPeriodId.periodUid, period).windowIndex;
|
||||||
timeline.getWindow(windowIndex, window);
|
timeline.getWindow(windowIndex, window);
|
||||||
return window.isLive() && window.isDynamic;
|
return window.isLive() && window.isDynamic && window.windowStartTimeMs != C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleNextWork(long thisOperationStartTimeMs, long intervalMs) {
|
private void scheduleNextWork(long thisOperationStartTimeMs, long intervalMs) {
|
||||||
@ -1725,7 +1722,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
// Renderers are ready and we're loading. Ask the LoadControl whether to transition.
|
// Renderers are ready and we're loading. Ask the LoadControl whether to transition.
|
||||||
long targetLiveOffsetUs =
|
long targetLiveOffsetUs =
|
||||||
isInMovingLiveWindow(playbackInfo.timeline, queue.getPlayingPeriod().info.id)
|
shouldUseLivePlaybackSpeedControl(playbackInfo.timeline, queue.getPlayingPeriod().info.id)
|
||||||
? livePlaybackSpeedControl.getTargetLiveOffsetUs()
|
? livePlaybackSpeedControl.getTargetLiveOffsetUs()
|
||||||
: C.TIME_UNSET;
|
: C.TIME_UNSET;
|
||||||
MediaPeriodHolder loadingHolder = queue.getLoadingPeriod();
|
MediaPeriodHolder loadingHolder = queue.getLoadingPeriod();
|
||||||
@ -1831,7 +1828,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
Timeline oldTimeline,
|
Timeline oldTimeline,
|
||||||
MediaPeriodId oldPeriodId,
|
MediaPeriodId oldPeriodId,
|
||||||
long positionForTargetOffsetOverrideUs) {
|
long positionForTargetOffsetOverrideUs) {
|
||||||
if (newTimeline.isEmpty() || !isInMovingLiveWindow(newTimeline, newPeriodId)) {
|
if (newTimeline.isEmpty() || !shouldUseLivePlaybackSpeedControl(newTimeline, newPeriodId)) {
|
||||||
// Live playback speed control is unused.
|
// Live playback speed control is unused.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ import com.google.android.exoplayer2.source.MediaSource;
|
|||||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
||||||
import com.google.android.exoplayer2.source.SilenceMediaSource;
|
import com.google.android.exoplayer2.source.SilenceMediaSource;
|
||||||
|
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
||||||
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;
|
||||||
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
||||||
@ -83,6 +84,7 @@ import com.google.android.exoplayer2.testutil.ExoPlayerTestRunner;
|
|||||||
import com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet;
|
import com.google.android.exoplayer2.testutil.FakeAdaptiveDataSet;
|
||||||
import com.google.android.exoplayer2.testutil.FakeAdaptiveMediaSource;
|
import com.google.android.exoplayer2.testutil.FakeAdaptiveMediaSource;
|
||||||
import com.google.android.exoplayer2.testutil.FakeChunkSource;
|
import com.google.android.exoplayer2.testutil.FakeChunkSource;
|
||||||
|
import com.google.android.exoplayer2.testutil.FakeClock;
|
||||||
import com.google.android.exoplayer2.testutil.FakeDataSource;
|
import com.google.android.exoplayer2.testutil.FakeDataSource;
|
||||||
import com.google.android.exoplayer2.testutil.FakeMediaClockRenderer;
|
import com.google.android.exoplayer2.testutil.FakeMediaClockRenderer;
|
||||||
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
|
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
|
||||||
@ -8833,6 +8835,42 @@ public final class ExoPlayerTest {
|
|||||||
assertThat(liveOffsetAtEnd).isIn(Range.closed(1_900L, 2_100L));
|
assertThat(liveOffsetAtEnd).isIn(Range.closed(1_900L, 2_100L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void targetLiveOffsetInMedia_unknownWindowStartTime_doesNotAdjustLiveOffset()
|
||||||
|
throws Exception {
|
||||||
|
FakeClock fakeClock = new AutoAdvancingFakeClock(/* initialTimeMs= */ 987_654_321L);
|
||||||
|
ExoPlayer player = new TestExoPlayerBuilder(context).setClock(fakeClock).build();
|
||||||
|
MediaItem mediaItem =
|
||||||
|
new MediaItem.Builder().setUri(Uri.EMPTY).setLiveTargetOffsetMs(4_000).build();
|
||||||
|
Timeline liveTimeline =
|
||||||
|
new SinglePeriodTimeline(
|
||||||
|
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
||||||
|
/* windowStartTimeMs= */ C.TIME_UNSET,
|
||||||
|
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
|
||||||
|
/* periodDurationUs= */ 1000 * C.MICROS_PER_SECOND,
|
||||||
|
/* windowDurationUs= */ 1000 * C.MICROS_PER_SECOND,
|
||||||
|
/* windowPositionInPeriodUs= */ 0,
|
||||||
|
/* windowDefaultStartPositionUs= */ 0,
|
||||||
|
/* isSeekable= */ true,
|
||||||
|
/* isDynamic= */ true,
|
||||||
|
/* manifest= */ null,
|
||||||
|
mediaItem,
|
||||||
|
mediaItem.liveConfiguration);
|
||||||
|
player.pause();
|
||||||
|
player.setMediaSource(new FakeMediaSource(liveTimeline));
|
||||||
|
player.prepare();
|
||||||
|
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
|
||||||
|
|
||||||
|
long playbackStartTimeMs = fakeClock.elapsedRealtime();
|
||||||
|
TestPlayerRunHelper.playUntilPosition(player, /* windowIndex= */ 0, /* positionMs= */ 999_000);
|
||||||
|
long playbackEndTimeMs = fakeClock.elapsedRealtime();
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
// Assert that the time it took to play 999 seconds of media is 999 seconds (asserting that no
|
||||||
|
// playback speed adjustment was used).
|
||||||
|
assertThat(playbackEndTimeMs - playbackStartTimeMs).isEqualTo(999_000);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noTargetLiveOffsetInMedia_doesNotAdjustLiveOffset() throws Exception {
|
public void noTargetLiveOffsetInMedia_doesNotAdjustLiveOffset() throws Exception {
|
||||||
long windowStartUnixTimeMs = 987_654_321_000L;
|
long windowStartUnixTimeMs = 987_654_321_000L;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user