Allow renderers to read ahead further than the next source.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=125951381
This commit is contained in:
andrewlewis 2016-06-27 06:51:50 -07:00 committed by Oliver Woodman
parent 6031f89fe9
commit fdd90256f4

View File

@ -111,7 +111,6 @@ import java.util.ArrayList;
private int customMessagesProcessed; private int customMessagesProcessed;
private long elapsedRealtimeUs; private long elapsedRealtimeUs;
private long sourceOffsetUs;
private long internalPositionUs; private long internalPositionUs;
public ExoPlayerImplInternal(TrackRenderer[] renderers, TrackSelector trackSelector, public ExoPlayerImplInternal(TrackRenderer[] renderers, TrackSelector trackSelector,
@ -356,7 +355,7 @@ import java.util.ArrayList;
} else { } else {
internalPositionUs = standaloneMediaClock.getPositionUs(); internalPositionUs = standaloneMediaClock.getPositionUs();
} }
positionUs = internalPositionUs - sourceOffsetUs; positionUs = internalPositionUs - timeline.playingSource.offsetUs;
} }
playbackInfo.positionUs = positionUs; playbackInfo.positionUs = positionUs;
elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000; elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
@ -469,7 +468,6 @@ import java.util.ArrayList;
if (sourceIndex != playbackInfo.sourceIndex) { if (sourceIndex != playbackInfo.sourceIndex) {
playbackInfo = new PlaybackInfo(sourceIndex); playbackInfo = new PlaybackInfo(sourceIndex);
playbackInfo.positionUs = seekPositionUs;
updatePlaybackPositions(); updatePlaybackPositions();
eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget(); eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget();
} }
@ -483,7 +481,7 @@ import java.util.ArrayList;
} }
private void resetInternalPosition(long sourcePositionUs) throws ExoPlaybackException { private void resetInternalPosition(long sourcePositionUs) throws ExoPlaybackException {
internalPositionUs = sourceOffsetUs + sourcePositionUs; internalPositionUs = timeline.playingSource.offsetUs + sourcePositionUs;
standaloneMediaClock.setPositionUs(internalPositionUs); standaloneMediaClock.setPositionUs(internalPositionUs);
for (TrackRenderer renderer : enabledRenderers) { for (TrackRenderer renderer : enabledRenderers) {
renderer.reset(internalPositionUs); renderer.reset(internalPositionUs);
@ -575,7 +573,6 @@ import java.util.ArrayList;
private int pendingSourceIndex; private int pendingSourceIndex;
private long playingSourceEndPositionUs; private long playingSourceEndPositionUs;
private long bufferingSourceOffsetUs;
public Timeline(TrackRenderer[] renderers) { public Timeline(TrackRenderer[] renderers) {
this.renderers = renderers; this.renderers = renderers;
@ -607,6 +604,7 @@ import java.util.ArrayList;
public void updateSources() throws ExoPlaybackException, IOException { public void updateSources() throws ExoPlaybackException, IOException {
// TODO[playlists]: Let sample source providers invalidate sources that are already buffering. // TODO[playlists]: Let sample source providers invalidate sources that are already buffering.
// Update the buffering source.
int sourceCount = sampleSourceProvider.getSourceCount(); int sourceCount = sampleSourceProvider.getSourceCount();
if (bufferingSource == null if (bufferingSource == null
|| (bufferingSource.isFullyBuffered() && bufferingSource.index || (bufferingSource.isFullyBuffered() && bufferingSource.index
@ -619,14 +617,12 @@ import java.util.ArrayList;
if (sampleSource != null) { if (sampleSource != null) {
Source newSource = new Source(sampleSource, sourceIndex, renderers.length); Source newSource = new Source(sampleSource, sourceIndex, renderers.length);
if (bufferingSource != null) { if (bufferingSource != null) {
bufferingSource.nextSource = newSource; bufferingSource.setNextSource(newSource);
bufferingSourceOffsetUs += bufferingSource.sampleSource.getDurationUs();
} }
bufferingSource = newSource; bufferingSource = newSource;
} }
} }
} }
if (bufferingSource != null) { if (bufferingSource != null) {
if (!bufferingSource.prepared) { if (!bufferingSource.prepared) {
// Continue preparation. // Continue preparation.
@ -638,55 +634,46 @@ import java.util.ArrayList;
bufferingSource.selectTracks(result.first, result.second, startPositionUs); bufferingSource.selectTracks(result.first, result.second, startPositionUs);
if (playingSource == null) { if (playingSource == null) {
// This is the first prepared source, so start playing it. // This is the first prepared source, so start playing it.
setPlayingSource(bufferingSource, 0); readingSource = bufferingSource;
setPlayingSource(readingSource);
} }
} }
} }
if (bufferingSource.hasEnabledTracks) { if (bufferingSource.hasEnabledTracks) {
long sourcePositionUs = internalPositionUs - bufferingSourceOffsetUs; long sourcePositionUs = internalPositionUs - bufferingSource.offsetUs;
bufferingSource.sampleSource.continueBuffering(sourcePositionUs); bufferingSource.sampleSource.continueBuffering(sourcePositionUs);
} }
} }
// Update the playing and reading sources.
if (playingSource == null) { if (playingSource == null) {
return; return;
} }
if (playingSourceEndPositionUs == C.UNSET_TIME_US && playingSource.isFullyBuffered()) {
if (readingSource != playingSource) { playingSourceEndPositionUs = playingSource.offsetUs
if (playingSourceEndPositionUs != C.UNSET_TIME_US + playingSource.sampleSource.getDurationUs();
&& internalPositionUs >= playingSourceEndPositionUs) { }
while (playingSource.nextSource != null && playingSource.nextSource.prepared
&& internalPositionUs >= playingSource.nextSource.offsetUs) {
playingSource.release(); playingSource.release();
setPlayingSource(readingSource, playingSourceEndPositionUs); if (readingSource == playingSource) {
readingSource = playingSource.nextSource;
}
setPlayingSource(playingSource.nextSource);
playbackInfo = new PlaybackInfo(playingSource.index); playbackInfo = new PlaybackInfo(playingSource.index);
updatePlaybackPositions(); updatePlaybackPositions();
eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget(); eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget();
} else { }
// We're reading ahead, but it's not time to update the playing source yet. if (readingSource == null) {
return; return;
} }
}
// Check whether all enabled renderers have read to the end of their TrackStreams.
for (TrackRenderer renderer : enabledRenderers) { for (TrackRenderer renderer : enabledRenderers) {
if (!renderer.hasReadStreamToEnd()) { if (!renderer.hasReadStreamToEnd()) {
return; return;
} }
} }
// TODO: Is playingSourceEndPositionUs equivalent to playbackInfo.durationUs? if (readingSource.nextSource != null && readingSource.nextSource.prepared) {
if (playingSourceEndPositionUs == C.UNSET_TIME_US) { readingSource = readingSource.nextSource;
playingSourceEndPositionUs = sourceOffsetUs + playingSource.sampleSource.getDurationUs();
}
if (sourceCount != SampleSourceProvider.UNKNOWN_SOURCE_COUNT
&& readingSource.index == sourceCount - 1) {
// This is the last source, so signal the renderers to read the end of the stream.
for (TrackRenderer renderer : enabledRenderers) {
renderer.setCurrentTrackStreamIsFinal();
}
readingSource = null;
playingSourceEndPositionUs = C.UNSET_TIME_US;
} else if (playingSource.nextSource != null && playingSource.nextSource.prepared) {
readingSource = playingSource.nextSource;
TrackSelectionArray newTrackSelections = readingSource.trackSelections; TrackSelectionArray newTrackSelections = readingSource.trackSelections;
TrackGroupArray groups = readingSource.sampleSource.getTrackGroups(); TrackGroupArray groups = readingSource.sampleSource.getTrackGroups();
for (int i = 0; i < renderers.length; i++) { for (int i = 0; i < renderers.length; i++) {
@ -701,7 +688,7 @@ import java.util.ArrayList;
formats[j] = groups.get(selection.group).getFormat(selection.getTrack(j)); formats[j] = groups.get(selection.group).getFormat(selection.getTrack(j));
} }
renderer.replaceTrackStream(formats, readingSource.trackStreams[i], renderer.replaceTrackStream(formats, readingSource.trackStreams[i],
playingSourceEndPositionUs); readingSource.offsetUs);
} else { } else {
// The renderer will be disabled when transitioning to playing the next source. Send // The renderer will be disabled when transitioning to playing the next source. Send
// end-of-stream to play out any remaining data. // end-of-stream to play out any remaining data.
@ -709,6 +696,13 @@ import java.util.ArrayList;
} }
} }
} }
} else if (sourceCount != SampleSourceProvider.UNKNOWN_SOURCE_COUNT
&& readingSource.index == sourceCount - 1) {
readingSource = null;
// This is the last source, so signal the renderers to read the end of the stream.
for (TrackRenderer renderer : enabledRenderers) {
renderer.setCurrentTrackStreamIsFinal();
}
} }
} }
@ -727,15 +721,14 @@ import java.util.ArrayList;
if (newPlayingSource != null) { if (newPlayingSource != null) {
newPlayingSource.nextSource = null; newPlayingSource.nextSource = null;
setPlayingSource(newPlayingSource, sourceOffsetUs); setPlayingSource(newPlayingSource);
readingSource = playingSource;
bufferingSource = playingSource; bufferingSource = playingSource;
bufferingSourceOffsetUs = sourceOffsetUs;
} else { } else {
// TODO[REFACTOR]: We need to disable the renderers somewhere in here? // TODO[REFACTOR]: We need to disable the renderers somewhere in here?
playingSource = null; playingSource = null;
readingSource = null; readingSource = null;
bufferingSource = null; bufferingSource = null;
bufferingSourceOffsetUs = 0;
pendingSourceIndex = sourceIndex; pendingSourceIndex = sourceIndex;
} }
} }
@ -756,7 +749,8 @@ import java.util.ArrayList;
for (int j = 0; j < formats.length; j++) { for (int j = 0; j < formats.length; j++) {
formats[j] = groups.get(selection.group).getFormat(selection.getTrack(j)); formats[j] = groups.get(selection.group).getFormat(selection.getTrack(j));
} }
renderer.replaceTrackStream(formats, playingSource.trackStreams[i], sourceOffsetUs); renderer.replaceTrackStream(formats, playingSource.trackStreams[i],
playingSource.offsetUs);
} }
} }
} }
@ -772,7 +766,6 @@ import java.util.ArrayList;
readingSource = playingSource; readingSource = playingSource;
bufferingSource = playingSource; bufferingSource = playingSource;
playingSourceEndPositionUs = C.UNSET_TIME_US; playingSourceEndPositionUs = C.UNSET_TIME_US;
bufferingSourceOffsetUs = sourceOffsetUs;
// Update the track selection for the playing source. // Update the track selection for the playing source.
Pair<TrackSelectionArray, Object> result = Pair<TrackSelectionArray, Object> result =
@ -814,20 +807,14 @@ import java.util.ArrayList;
bufferingSource = null; bufferingSource = null;
playingSourceEndPositionUs = C.UNSET_TIME_US; playingSourceEndPositionUs = C.UNSET_TIME_US;
pendingSourceIndex = 0; pendingSourceIndex = 0;
sourceOffsetUs = 0;
bufferingSourceOffsetUs = 0;
playbackInfo = new PlaybackInfo(0); playbackInfo = new PlaybackInfo(0);
eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget(); eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget();
} }
private void setPlayingSource(Source source, long offsetUs) throws ExoPlaybackException { private void setPlayingSource(Source source) throws ExoPlaybackException {
sourceOffsetUs = offsetUs;
// Disable/enable renderers for the new source. // Disable/enable renderers for the new source.
int enabledRendererCount = disableRenderers(true, source.trackSelections); int enabledRendererCount = disableRenderers(true, source.trackSelections);
if (playingSource != source) {
trackSelector.onSelectionActivated(source.trackSelectionData); trackSelector.onSelectionActivated(source.trackSelectionData);
}
readingSource = source;
playingSource = source; playingSource = source;
playingSourceEndPositionUs = C.UNSET_TIME_US; playingSourceEndPositionUs = C.UNSET_TIME_US;
enableRenderers(source.trackSelections, enabledRendererCount); enableRenderers(source.trackSelections, enabledRendererCount);
@ -902,7 +889,7 @@ import java.util.ArrayList;
} }
// Enable the renderer. // Enable the renderer.
renderer.enable(formats, playingSource.trackStreams[i], internalPositionUs, joining, renderer.enable(formats, playingSource.trackStreams[i], internalPositionUs, joining,
sourceOffsetUs); playingSource.offsetUs);
MediaClock mediaClock = renderer.getMediaClock(); MediaClock mediaClock = renderer.getMediaClock();
if (mediaClock != null) { if (mediaClock != null) {
if (rendererMediaClock != null) { if (rendererMediaClock != null) {
@ -936,7 +923,7 @@ import java.util.ArrayList;
public boolean hasEnabledTracks; public boolean hasEnabledTracks;
public TrackSelectionArray trackSelections; public TrackSelectionArray trackSelections;
public Object trackSelectionData; public Object trackSelectionData;
public long offsetUs;
public Source nextSource; public Source nextSource;
public Source(SampleSource sampleSource, int index, int rendererCount) { public Source(SampleSource sampleSource, int index, int rendererCount) {
@ -950,6 +937,11 @@ import java.util.ArrayList;
|| sampleSource.getBufferedPositionUs() == C.END_OF_SOURCE_US); || sampleSource.getBufferedPositionUs() == C.END_OF_SOURCE_US);
} }
public void setNextSource(Source nextSource) {
this.nextSource = nextSource;
nextSource.offsetUs = offsetUs + sampleSource.getDurationUs();
}
public boolean prepare(long startPositionUs) throws IOException { public boolean prepare(long startPositionUs) throws IOException {
if (sampleSource.prepare(startPositionUs)) { if (sampleSource.prepare(startPositionUs)) {
prepared = true; prepared = true;