mirror of
https://github.com/androidx/media.git
synced 2025-05-06 07:00:19 +08:00
ExoPlayerImplInternal cleanup
- Fix handling of the currently playing period being removed. This didn't do the right thing at all. - Relax rule on seekToPeriodPosition re-using an existing holder. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=140014791
This commit is contained in:
parent
b3726cf761
commit
eb62d00ea4
@ -166,11 +166,9 @@ import java.io.IOException;
|
|||||||
private SeekPosition pendingSeekPosition;
|
private SeekPosition pendingSeekPosition;
|
||||||
private long rendererPositionUs;
|
private long rendererPositionUs;
|
||||||
|
|
||||||
private boolean isTimelineReady;
|
|
||||||
private boolean isTimelineEnded;
|
|
||||||
private MediaPeriodHolder playingPeriodHolder;
|
|
||||||
private MediaPeriodHolder readingPeriodHolder;
|
|
||||||
private MediaPeriodHolder loadingPeriodHolder;
|
private MediaPeriodHolder loadingPeriodHolder;
|
||||||
|
private MediaPeriodHolder readingPeriodHolder;
|
||||||
|
private MediaPeriodHolder playingPeriodHolder;
|
||||||
|
|
||||||
private Timeline timeline;
|
private Timeline timeline;
|
||||||
|
|
||||||
@ -451,7 +449,6 @@ import java.io.IOException;
|
|||||||
|
|
||||||
private void doSomeWork() throws ExoPlaybackException, IOException {
|
private void doSomeWork() throws ExoPlaybackException, IOException {
|
||||||
long operationStartTimeMs = SystemClock.elapsedRealtime();
|
long operationStartTimeMs = SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
updatePeriods();
|
updatePeriods();
|
||||||
if (playingPeriodHolder == null) {
|
if (playingPeriodHolder == null) {
|
||||||
// We're still waiting for the first period to be prepared.
|
// We're still waiting for the first period to be prepared.
|
||||||
@ -489,23 +486,28 @@ import java.io.IOException;
|
|||||||
if (allRenderersEnded
|
if (allRenderersEnded
|
||||||
&& (playingPeriodDurationUs == C.TIME_UNSET
|
&& (playingPeriodDurationUs == C.TIME_UNSET
|
||||||
|| playingPeriodDurationUs <= playbackInfo.positionUs)
|
|| playingPeriodDurationUs <= playbackInfo.positionUs)
|
||||||
&& isTimelineEnded) {
|
&& playingPeriodHolder.isLast) {
|
||||||
setState(ExoPlayer.STATE_ENDED);
|
setState(ExoPlayer.STATE_ENDED);
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
} else if (state == ExoPlayer.STATE_BUFFERING) {
|
} else if (state == ExoPlayer.STATE_BUFFERING) {
|
||||||
if ((enabledRenderers.length > 0
|
boolean isNewlyReady = enabledRenderers.length > 0
|
||||||
? (allRenderersReadyOrEnded && haveSufficientBuffer(rebuffering)) : isTimelineReady)) {
|
? (allRenderersReadyOrEnded && haveSufficientBuffer(rebuffering))
|
||||||
|
: isTimelineReady(playingPeriodDurationUs);
|
||||||
|
if (isNewlyReady) {
|
||||||
setState(ExoPlayer.STATE_READY);
|
setState(ExoPlayer.STATE_READY);
|
||||||
if (playWhenReady) {
|
if (playWhenReady) {
|
||||||
startRenderers();
|
startRenderers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (state == ExoPlayer.STATE_READY
|
} else if (state == ExoPlayer.STATE_READY) {
|
||||||
&& (enabledRenderers.length > 0 ? !allRenderersReadyOrEnded : !isTimelineReady)) {
|
boolean isStillReady = enabledRenderers.length > 0 ? allRenderersReadyOrEnded
|
||||||
|
: isTimelineReady(playingPeriodDurationUs);
|
||||||
|
if (!isStillReady) {
|
||||||
rebuffering = playWhenReady;
|
rebuffering = playWhenReady;
|
||||||
setState(ExoPlayer.STATE_BUFFERING);
|
setState(ExoPlayer.STATE_BUFFERING);
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (state == ExoPlayer.STATE_BUFFERING) {
|
if (state == ExoPlayer.STATE_BUFFERING) {
|
||||||
for (Renderer renderer : enabledRenderers) {
|
for (Renderer renderer : enabledRenderers) {
|
||||||
@ -572,13 +574,6 @@ import java.io.IOException;
|
|||||||
rebuffering = false;
|
rebuffering = false;
|
||||||
setState(ExoPlayer.STATE_BUFFERING);
|
setState(ExoPlayer.STATE_BUFFERING);
|
||||||
|
|
||||||
if (readingPeriodHolder != playingPeriodHolder && (periodIndex == playingPeriodHolder.index
|
|
||||||
|| periodIndex == readingPeriodHolder.index)) {
|
|
||||||
// Clear the timeline because a renderer is reading ahead to the next period and the seek is
|
|
||||||
// to either the playing or reading period.
|
|
||||||
periodIndex = C.INDEX_UNSET;
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaPeriodHolder newPlayingPeriodHolder = null;
|
MediaPeriodHolder newPlayingPeriodHolder = null;
|
||||||
if (playingPeriodHolder == null) {
|
if (playingPeriodHolder == null) {
|
||||||
// We're still waiting for the first period to be prepared.
|
// We're still waiting for the first period to be prepared.
|
||||||
@ -598,8 +593,10 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable all the renderers if the period is changing.
|
// Disable all the renderers if the period being played is changing, or if the renderers are
|
||||||
if (newPlayingPeriodHolder != playingPeriodHolder) {
|
// reading from a period other than the one being played.
|
||||||
|
if (playingPeriodHolder != newPlayingPeriodHolder
|
||||||
|
|| playingPeriodHolder != readingPeriodHolder) {
|
||||||
for (Renderer renderer : enabledRenderers) {
|
for (Renderer renderer : enabledRenderers) {
|
||||||
renderer.disable();
|
renderer.disable();
|
||||||
}
|
}
|
||||||
@ -608,25 +605,24 @@ import java.io.IOException;
|
|||||||
rendererMediaClockSource = null;
|
rendererMediaClockSource = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update loaded periods.
|
// Update the holders.
|
||||||
if (newPlayingPeriodHolder != null) {
|
if (newPlayingPeriodHolder != null) {
|
||||||
newPlayingPeriodHolder.next = null;
|
newPlayingPeriodHolder.next = null;
|
||||||
|
loadingPeriodHolder = newPlayingPeriodHolder;
|
||||||
|
readingPeriodHolder = newPlayingPeriodHolder;
|
||||||
setPlayingPeriodHolder(newPlayingPeriodHolder);
|
setPlayingPeriodHolder(newPlayingPeriodHolder);
|
||||||
updateTimelineState();
|
|
||||||
readingPeriodHolder = playingPeriodHolder;
|
|
||||||
loadingPeriodHolder = playingPeriodHolder;
|
|
||||||
if (playingPeriodHolder.hasEnabledTracks) {
|
if (playingPeriodHolder.hasEnabledTracks) {
|
||||||
periodPositionUs = playingPeriodHolder.mediaPeriod.seekToUs(periodPositionUs);
|
periodPositionUs = playingPeriodHolder.mediaPeriod.seekToUs(periodPositionUs);
|
||||||
}
|
}
|
||||||
resetRendererPosition(periodPositionUs);
|
resetRendererPosition(periodPositionUs);
|
||||||
maybeContinueLoading();
|
maybeContinueLoading();
|
||||||
} else {
|
} else {
|
||||||
playingPeriodHolder = null;
|
|
||||||
readingPeriodHolder = null;
|
|
||||||
loadingPeriodHolder = null;
|
loadingPeriodHolder = null;
|
||||||
|
readingPeriodHolder = null;
|
||||||
|
playingPeriodHolder = null;
|
||||||
resetRendererPosition(periodPositionUs);
|
resetRendererPosition(periodPositionUs);
|
||||||
}
|
}
|
||||||
updatePlaybackPositions();
|
|
||||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||||
return periodPositionUs;
|
return periodPositionUs;
|
||||||
}
|
}
|
||||||
@ -678,11 +674,9 @@ import java.io.IOException;
|
|||||||
mediaSource.releaseSource();
|
mediaSource.releaseSource();
|
||||||
mediaSource = null;
|
mediaSource = null;
|
||||||
}
|
}
|
||||||
isTimelineReady = false;
|
|
||||||
isTimelineEnded = false;
|
|
||||||
playingPeriodHolder = null;
|
|
||||||
readingPeriodHolder = null;
|
|
||||||
loadingPeriodHolder = null;
|
loadingPeriodHolder = null;
|
||||||
|
readingPeriodHolder = null;
|
||||||
|
playingPeriodHolder = null;
|
||||||
timeline = null;
|
timeline = null;
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@ -739,8 +733,8 @@ import java.io.IOException;
|
|||||||
boolean recreateStreams = readingPeriodHolder != playingPeriodHolder;
|
boolean recreateStreams = readingPeriodHolder != playingPeriodHolder;
|
||||||
releasePeriodHoldersFrom(playingPeriodHolder.next);
|
releasePeriodHoldersFrom(playingPeriodHolder.next);
|
||||||
playingPeriodHolder.next = null;
|
playingPeriodHolder.next = null;
|
||||||
readingPeriodHolder = playingPeriodHolder;
|
|
||||||
loadingPeriodHolder = playingPeriodHolder;
|
loadingPeriodHolder = playingPeriodHolder;
|
||||||
|
readingPeriodHolder = playingPeriodHolder;
|
||||||
|
|
||||||
boolean[] streamResetFlags = new boolean[renderers.length];
|
boolean[] streamResetFlags = new boolean[renderers.length];
|
||||||
long periodPositionUs = playingPeriodHolder.updatePeriodTrackSelection(
|
long periodPositionUs = playingPeriodHolder.updatePeriodTrackSelection(
|
||||||
@ -802,6 +796,12 @@ import java.io.IOException;
|
|||||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isTimelineReady(long playingPeriodDurationUs) {
|
||||||
|
return playingPeriodDurationUs == C.TIME_UNSET
|
||||||
|
|| playbackInfo.positionUs < playingPeriodDurationUs
|
||||||
|
|| (playingPeriodHolder.next != null && playingPeriodHolder.next.prepared);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean haveSufficientBuffer(boolean rebuffering) {
|
private boolean haveSufficientBuffer(boolean rebuffering) {
|
||||||
if (loadingPeriodHolder == null) {
|
if (loadingPeriodHolder == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -880,17 +880,23 @@ import java.io.IOException;
|
|||||||
stopInternal();
|
stopInternal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Release all loaded periods.
|
// We resolved a subsequent period. Seek to the default position in the corresponding window.
|
||||||
releasePeriodHoldersFrom(periodHolder);
|
|
||||||
playingPeriodHolder = null;
|
|
||||||
readingPeriodHolder = null;
|
|
||||||
loadingPeriodHolder = null;
|
|
||||||
// Find the default initial position in the window and seek to it.
|
|
||||||
Pair<Integer, Long> defaultPosition = getPeriodPosition(
|
Pair<Integer, Long> defaultPosition = getPeriodPosition(
|
||||||
timeline.getPeriod(newPeriodIndex, period).windowIndex, C.TIME_UNSET);
|
timeline.getPeriod(newPeriodIndex, period).windowIndex, C.TIME_UNSET);
|
||||||
newPeriodIndex = defaultPosition.first;
|
newPeriodIndex = defaultPosition.first;
|
||||||
long newPlayingPositionUs = defaultPosition.second;
|
long newPositionUs = defaultPosition.second;
|
||||||
playbackInfo = new PlaybackInfo(newPeriodIndex, newPlayingPositionUs);
|
timeline.getPeriod(newPeriodIndex, period, true);
|
||||||
|
// Clear the index of each holder that doesn't contain the default position. If a holder
|
||||||
|
// contains the default position then update its index so it can be re-used when seeking.
|
||||||
|
Object newPeriodUid = period.uid;
|
||||||
|
periodHolder.index = C.INDEX_UNSET;
|
||||||
|
while (periodHolder.next != null) {
|
||||||
|
periodHolder = periodHolder.next;
|
||||||
|
periodHolder.index = periodHolder.uid.equals(newPeriodUid) ? newPeriodIndex : C.INDEX_UNSET;
|
||||||
|
}
|
||||||
|
// Actually do the seek.
|
||||||
|
newPositionUs = seekToPeriodPosition(newPeriodIndex, newPositionUs);
|
||||||
|
playbackInfo = new PlaybackInfo(newPeriodIndex, newPositionUs);
|
||||||
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
notifySourceInfoRefresh(manifest, processedInitialSeekCount);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -900,13 +906,13 @@ import java.io.IOException;
|
|||||||
boolean isLastPeriod = periodIndex == timeline.getPeriodCount() - 1
|
boolean isLastPeriod = periodIndex == timeline.getPeriodCount() - 1
|
||||||
&& !timeline.getWindow(period.windowIndex, window).isDynamic;
|
&& !timeline.getWindow(period.windowIndex, window).isDynamic;
|
||||||
periodHolder.setIndex(periodIndex, isLastPeriod);
|
periodHolder.setIndex(periodIndex, isLastPeriod);
|
||||||
|
boolean seenReadingPeriod = periodHolder == readingPeriodHolder;
|
||||||
if (periodIndex != playbackInfo.periodIndex) {
|
if (periodIndex != playbackInfo.periodIndex) {
|
||||||
playbackInfo = playbackInfo.copyWithPeriodIndex(periodIndex);
|
playbackInfo = playbackInfo.copyWithPeriodIndex(periodIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are subsequent holders, update the index for each of them. If we find a holder
|
// If there are subsequent holders, update the index for each of them. If we find a holder
|
||||||
// that's inconsistent with the new timeline then take appropriate action.
|
// that's inconsistent with the new timeline then take appropriate action.
|
||||||
boolean seenReadingPeriod = false;
|
|
||||||
while (periodHolder.next != null) {
|
while (periodHolder.next != null) {
|
||||||
MediaPeriodHolder previousPeriodHolder = periodHolder;
|
MediaPeriodHolder previousPeriodHolder = periodHolder;
|
||||||
periodHolder = periodHolder.next;
|
periodHolder = periodHolder.next;
|
||||||
@ -921,17 +927,11 @@ import java.io.IOException;
|
|||||||
} else {
|
} else {
|
||||||
// The holder is inconsistent with the new timeline.
|
// The holder is inconsistent with the new timeline.
|
||||||
if (!seenReadingPeriod) {
|
if (!seenReadingPeriod) {
|
||||||
// Renderers may have read from a period that's been removed, so release all loaded
|
// Renderers may have read from a period that's been removed. Seek back to the current
|
||||||
// periods and seek to the current position of the playing period index.
|
// position of the playing period to make sure none of the removed period is played.
|
||||||
periodIndex = playingPeriodHolder.index;
|
periodIndex = playingPeriodHolder.index;
|
||||||
releasePeriodHoldersFrom(playingPeriodHolder);
|
|
||||||
playingPeriodHolder = null;
|
|
||||||
readingPeriodHolder = null;
|
|
||||||
loadingPeriodHolder = null;
|
|
||||||
long newPositionUs = seekToPeriodPosition(periodIndex, playbackInfo.positionUs);
|
long newPositionUs = seekToPeriodPosition(periodIndex, playbackInfo.positionUs);
|
||||||
if (newPositionUs != playbackInfo.positionUs) {
|
|
||||||
playbackInfo = new PlaybackInfo(periodIndex, newPositionUs);
|
playbackInfo = new PlaybackInfo(periodIndex, newPositionUs);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Update the loading period to be the last period that's still valid, and release all
|
// Update the loading period to be the last period that's still valid, and release all
|
||||||
// subsequent periods.
|
// subsequent periods.
|
||||||
@ -1150,7 +1150,6 @@ import java.io.IOException;
|
|||||||
updatePlaybackPositions();
|
updatePlaybackPositions();
|
||||||
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
||||||
}
|
}
|
||||||
updateTimelineState();
|
|
||||||
|
|
||||||
if (readingPeriodHolder.isLast) {
|
if (readingPeriodHolder.isLast) {
|
||||||
// The renderers have their final SampleStreams.
|
// The renderers have their final SampleStreams.
|
||||||
@ -1202,8 +1201,8 @@ import java.io.IOException;
|
|||||||
if (playingPeriodHolder == null) {
|
if (playingPeriodHolder == null) {
|
||||||
// This is the first prepared period, so start playing it.
|
// This is the first prepared period, so start playing it.
|
||||||
readingPeriodHolder = loadingPeriodHolder;
|
readingPeriodHolder = loadingPeriodHolder;
|
||||||
|
resetRendererPosition(readingPeriodHolder.startPositionUs);
|
||||||
setPlayingPeriodHolder(readingPeriodHolder);
|
setPlayingPeriodHolder(readingPeriodHolder);
|
||||||
updateTimelineState();
|
|
||||||
}
|
}
|
||||||
maybeContinueLoading();
|
maybeContinueLoading();
|
||||||
}
|
}
|
||||||
@ -1242,12 +1241,7 @@ import java.io.IOException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setPlayingPeriodHolder(MediaPeriodHolder periodHolder) throws ExoPlaybackException {
|
private void setPlayingPeriodHolder(MediaPeriodHolder periodHolder) throws ExoPlaybackException {
|
||||||
boolean isFirstPeriod = playingPeriodHolder == null;
|
|
||||||
playingPeriodHolder = periodHolder;
|
playingPeriodHolder = periodHolder;
|
||||||
if (isFirstPeriod) {
|
|
||||||
resetRendererPosition(playingPeriodHolder.startPositionUs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int enabledRendererCount = 0;
|
int enabledRendererCount = 0;
|
||||||
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
|
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
|
||||||
for (int i = 0; i < renderers.length; i++) {
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
@ -1274,15 +1268,6 @@ import java.io.IOException;
|
|||||||
enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
|
enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTimelineState() {
|
|
||||||
long playingPeriodDurationUs = timeline.getPeriod(playingPeriodHolder.index, period)
|
|
||||||
.getDurationUs();
|
|
||||||
isTimelineReady = playingPeriodDurationUs == C.TIME_UNSET
|
|
||||||
|| playbackInfo.positionUs < playingPeriodDurationUs
|
|
||||||
|| (playingPeriodHolder.next != null && playingPeriodHolder.next.prepared);
|
|
||||||
isTimelineEnded = playingPeriodHolder.isLast;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableRenderers(boolean[] rendererWasEnabledFlags, int enabledRendererCount)
|
private void enableRenderers(boolean[] rendererWasEnabledFlags, int enabledRendererCount)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
enabledRenderers = new Renderer[enabledRendererCount];
|
enabledRenderers = new Renderer[enabledRendererCount];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user