Improve MediaPeriodHolder documentation and member access.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=215205796
This commit is contained in:
tonihei 2018-10-01 06:44:49 -07:00 committed by Oliver Woodman
parent d97d289b6b
commit 90ca3716aa
5 changed files with 187 additions and 69 deletions

View File

@ -993,12 +993,14 @@ import java.util.Collections;
MediaPeriodHolder periodHolder = queue.getPlayingPeriod(); MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod(); MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod();
boolean selectionsChangedForReadPeriod = true; boolean selectionsChangedForReadPeriod = true;
TrackSelectorResult newTrackSelectorResult = null;
while (true) { while (true) {
if (periodHolder == null || !periodHolder.prepared) { if (periodHolder == null || !periodHolder.prepared) {
// The reselection did not change any prepared periods. // The reselection did not change any prepared periods.
return; return;
} }
if (periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline)) { newTrackSelectorResult = periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline);
if (newTrackSelectorResult != null) {
// Selected tracks have changed for this period. // Selected tracks have changed for this period.
break; break;
} }
@ -1017,7 +1019,7 @@ import java.util.Collections;
boolean[] streamResetFlags = new boolean[renderers.length]; boolean[] streamResetFlags = new boolean[renderers.length];
long periodPositionUs = long periodPositionUs =
playingPeriodHolder.applyTrackSelection( playingPeriodHolder.applyTrackSelection(
playbackInfo.positionUs, recreateStreams, streamResetFlags); newTrackSelectorResult, playbackInfo.positionUs, recreateStreams, streamResetFlags);
if (playbackInfo.playbackState != Player.STATE_ENDED if (playbackInfo.playbackState != Player.STATE_ENDED
&& periodPositionUs != playbackInfo.positionUs) { && periodPositionUs != playbackInfo.positionUs) {
playbackInfo = playbackInfo.fromNewPosition(playbackInfo.periodId, periodPositionUs, playbackInfo = playbackInfo.fromNewPosition(playbackInfo.periodId, periodPositionUs,
@ -1047,7 +1049,7 @@ import java.util.Collections;
} }
playbackInfo = playbackInfo =
playbackInfo.copyWithTrackInfo( playbackInfo.copyWithTrackInfo(
playingPeriodHolder.trackGroups, playingPeriodHolder.trackSelectorResult); playingPeriodHolder.getTrackGroups(), playingPeriodHolder.getTrackSelectorResult());
enableRenderers(rendererWasEnabledFlags, enabledRendererCount); enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
} else { } else {
// Release and re-prepare/buffer periods after the one whose selection changed. // Release and re-prepare/buffer periods after the one whose selection changed.
@ -1056,7 +1058,7 @@ import java.util.Collections;
long loadingPeriodPositionUs = long loadingPeriodPositionUs =
Math.max( Math.max(
periodHolder.info.startPositionUs, periodHolder.toPeriodTime(rendererPositionUs)); periodHolder.info.startPositionUs, periodHolder.toPeriodTime(rendererPositionUs));
periodHolder.applyTrackSelection(loadingPeriodPositionUs, false); periodHolder.applyTrackSelection(newTrackSelectorResult, loadingPeriodPositionUs, false);
} }
} }
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ true); handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ true);
@ -1069,15 +1071,13 @@ import java.util.Collections;
private void updateTrackSelectionPlaybackSpeed(float playbackSpeed) { private void updateTrackSelectionPlaybackSpeed(float playbackSpeed) {
MediaPeriodHolder periodHolder = queue.getFrontPeriod(); MediaPeriodHolder periodHolder = queue.getFrontPeriod();
while (periodHolder != null) { while (periodHolder != null && periodHolder.prepared) {
if (periodHolder.trackSelectorResult != null) { TrackSelection[] trackSelections = periodHolder.getTrackSelectorResult().selections.getAll();
TrackSelection[] trackSelections = periodHolder.trackSelectorResult.selections.getAll();
for (TrackSelection trackSelection : trackSelections) { for (TrackSelection trackSelection : trackSelections) {
if (trackSelection != null) { if (trackSelection != null) {
trackSelection.onPlaybackSpeed(playbackSpeed); trackSelection.onPlaybackSpeed(playbackSpeed);
} }
} }
}
periodHolder = periodHolder.getNext(); periodHolder = periodHolder.getNext();
} }
} }
@ -1463,9 +1463,9 @@ import java.util.Collections;
return; return;
} }
TrackSelectorResult oldTrackSelectorResult = readingPeriodHolder.trackSelectorResult; TrackSelectorResult oldTrackSelectorResult = readingPeriodHolder.getTrackSelectorResult();
readingPeriodHolder = queue.advanceReadingPeriod(); readingPeriodHolder = queue.advanceReadingPeriod();
TrackSelectorResult newTrackSelectorResult = readingPeriodHolder.trackSelectorResult; TrackSelectorResult newTrackSelectorResult = readingPeriodHolder.getTrackSelectorResult();
boolean initialDiscontinuity = boolean initialDiscontinuity =
readingPeriodHolder.mediaPeriod.readDiscontinuity() != C.TIME_UNSET; readingPeriodHolder.mediaPeriod.readDiscontinuity() != C.TIME_UNSET;
@ -1536,7 +1536,7 @@ import java.util.Collections;
loadingPeriodHolder.handlePrepared( loadingPeriodHolder.handlePrepared(
mediaClock.getPlaybackParameters().speed, playbackInfo.timeline); mediaClock.getPlaybackParameters().speed, playbackInfo.timeline);
updateLoadControlTrackSelection( updateLoadControlTrackSelection(
loadingPeriodHolder.trackGroups, loadingPeriodHolder.trackSelectorResult); loadingPeriodHolder.getTrackGroups(), loadingPeriodHolder.getTrackSelectorResult());
if (!queue.hasPlayingPeriod()) { if (!queue.hasPlayingPeriod()) {
// This is the first prepared period, so start playing it. // This is the first prepared period, so start playing it.
MediaPeriodHolder playingPeriodHolder = queue.advancePlayingPeriod(); MediaPeriodHolder playingPeriodHolder = queue.advancePlayingPeriod();
@ -1596,11 +1596,11 @@ import java.util.Collections;
for (int i = 0; i < renderers.length; i++) { for (int i = 0; i < renderers.length; i++) {
Renderer renderer = renderers[i]; Renderer renderer = renderers[i];
rendererWasEnabledFlags[i] = renderer.getState() != Renderer.STATE_DISABLED; rendererWasEnabledFlags[i] = renderer.getState() != Renderer.STATE_DISABLED;
if (newPlayingPeriodHolder.trackSelectorResult.isRendererEnabled(i)) { if (newPlayingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)) {
enabledRendererCount++; enabledRendererCount++;
} }
if (rendererWasEnabledFlags[i] if (rendererWasEnabledFlags[i]
&& (!newPlayingPeriodHolder.trackSelectorResult.isRendererEnabled(i) && (!newPlayingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)
|| (renderer.isCurrentStreamFinal() || (renderer.isCurrentStreamFinal()
&& renderer.getStream() == oldPlayingPeriodHolder.sampleStreams[i]))) { && renderer.getStream() == oldPlayingPeriodHolder.sampleStreams[i]))) {
// The renderer should be disabled before playing the next period, either because it's not // The renderer should be disabled before playing the next period, either because it's not
@ -1611,7 +1611,8 @@ import java.util.Collections;
} }
playbackInfo = playbackInfo =
playbackInfo.copyWithTrackInfo( playbackInfo.copyWithTrackInfo(
newPlayingPeriodHolder.trackGroups, newPlayingPeriodHolder.trackSelectorResult); newPlayingPeriodHolder.getTrackGroups(),
newPlayingPeriodHolder.getTrackSelectorResult());
enableRenderers(rendererWasEnabledFlags, enabledRendererCount); enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
} }
@ -1621,7 +1622,7 @@ import java.util.Collections;
int enabledRendererCount = 0; int enabledRendererCount = 0;
MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod(); MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
for (int i = 0; i < renderers.length; i++) { for (int i = 0; i < renderers.length; i++) {
if (playingPeriodHolder.trackSelectorResult.isRendererEnabled(i)) { if (playingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)) {
enableRenderer(i, rendererWasEnabledFlags[i], enabledRendererCount++); enableRenderer(i, rendererWasEnabledFlags[i], enabledRendererCount++);
} }
} }
@ -1634,10 +1635,10 @@ import java.util.Collections;
Renderer renderer = renderers[rendererIndex]; Renderer renderer = renderers[rendererIndex];
enabledRenderers[enabledRendererIndex] = renderer; enabledRenderers[enabledRendererIndex] = renderer;
if (renderer.getState() == Renderer.STATE_DISABLED) { if (renderer.getState() == Renderer.STATE_DISABLED) {
TrackSelectorResult trackSelectorResult = playingPeriodHolder.getTrackSelectorResult();
RendererConfiguration rendererConfiguration = RendererConfiguration rendererConfiguration =
playingPeriodHolder.trackSelectorResult.rendererConfigurations[rendererIndex]; trackSelectorResult.rendererConfigurations[rendererIndex];
TrackSelection newSelection = playingPeriodHolder.trackSelectorResult.selections.get( TrackSelection newSelection = trackSelectorResult.selections.get(rendererIndex);
rendererIndex);
Format[] formats = getFormats(newSelection); Format[] formats = getFormats(newSelection);
// The renderer needs enabling with its new track selection. // The renderer needs enabling with its new track selection.
boolean playing = playWhenReady && playbackInfo.playbackState == Player.STATE_READY; boolean playing = playWhenReady && playbackInfo.playbackState == Player.STATE_READY;
@ -1674,7 +1675,8 @@ import java.util.Collections;
&& loadingMediaPeriodHolder != null && loadingMediaPeriodHolder != null
&& loadingMediaPeriodHolder.prepared) { && loadingMediaPeriodHolder.prepared) {
updateLoadControlTrackSelection( updateLoadControlTrackSelection(
loadingMediaPeriodHolder.trackGroups, loadingMediaPeriodHolder.trackSelectorResult); loadingMediaPeriodHolder.getTrackGroups(),
loadingMediaPeriodHolder.getTrackSelectorResult());
} }
} }

View File

@ -29,30 +29,38 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Holds a {@link MediaPeriod} with information required to play it as part of a timeline. */ /** Holds a {@link MediaPeriod} with information required to play it as part of a timeline. */
/* package */ final class MediaPeriodHolder { /* package */ final class MediaPeriodHolder {
private static final String TAG = "MediaPeriodHolder"; private static final String TAG = "MediaPeriodHolder";
/** The {@link MediaPeriod} wrapped by this class. */
public final MediaPeriod mediaPeriod; public final MediaPeriod mediaPeriod;
/** The unique timeline period identifier the media period belongs to. */
public final Object uid; public final Object uid;
public final SampleStream[] sampleStreams; /**
public final boolean[] mayRetainStreamFlags; * The sample streams for each renderer associated with this period. May contain null elements.
*/
public final @NullableType SampleStream[] sampleStreams;
/** Whether the media period has finished preparing. */
public boolean prepared; public boolean prepared;
/** Whether any of the tracks of this media period are enabled. */
public boolean hasEnabledTracks; public boolean hasEnabledTracks;
/** {@link MediaPeriodInfo} about this media period. */
public MediaPeriodInfo info; public MediaPeriodInfo info;
public TrackGroupArray trackGroups;
public TrackSelectorResult trackSelectorResult;
private final boolean[] mayRetainStreamFlags;
private final RendererCapabilities[] rendererCapabilities; private final RendererCapabilities[] rendererCapabilities;
private final TrackSelector trackSelector; private final TrackSelector trackSelector;
private final MediaSource mediaSource; private final MediaSource mediaSource;
private MediaPeriodHolder next; @Nullable private MediaPeriodHolder next;
@Nullable private TrackGroupArray trackGroups;
@Nullable private TrackSelectorResult trackSelectorResult;
private long rendererPositionOffsetUs; private long rendererPositionOffsetUs;
private TrackSelectorResult periodTrackSelectorResult;
/** /**
* Creates a new holder with information required to play it as part of a timeline. * Creates a new holder with information required to play it as part of a timeline.
@ -76,7 +84,7 @@ import com.google.android.exoplayer2.util.Log;
this.rendererPositionOffsetUs = rendererPositionOffsetUs - info.startPositionUs; this.rendererPositionOffsetUs = rendererPositionOffsetUs - info.startPositionUs;
this.trackSelector = trackSelector; this.trackSelector = trackSelector;
this.mediaSource = mediaSource; this.mediaSource = mediaSource;
this.uid = Assertions.checkNotNull(info.id.periodUid); this.uid = info.id.periodUid;
this.info = info; this.info = info;
sampleStreams = new SampleStream[rendererCapabilities.length]; sampleStreams = new SampleStream[rendererCapabilities.length];
mayRetainStreamFlags = new boolean[rendererCapabilities.length]; mayRetainStreamFlags = new boolean[rendererCapabilities.length];
@ -92,31 +100,38 @@ import com.google.android.exoplayer2.util.Log;
this.mediaPeriod = mediaPeriod; this.mediaPeriod = mediaPeriod;
} }
/**
* Converts time relative to the start of the period to the respective renderer time using {@link
* #getRendererOffset()}, in microseconds.
*/
public long toRendererTime(long periodTimeUs) { public long toRendererTime(long periodTimeUs) {
return periodTimeUs + getRendererOffset(); return periodTimeUs + getRendererOffset();
} }
/**
* Converts renderer time to the respective time relative to the start of the period using {@link
* #getRendererOffset()}, in microseconds.
*/
public long toPeriodTime(long rendererTimeUs) { public long toPeriodTime(long rendererTimeUs) {
return rendererTimeUs - getRendererOffset(); return rendererTimeUs - getRendererOffset();
} }
/** Returns the renderer time of the start of the period, in microseconds. */
public long getRendererOffset() { public long getRendererOffset() {
return rendererPositionOffsetUs; return rendererPositionOffsetUs;
} }
/** Returns start position of period in renderer time. */
public long getStartPositionRendererTime() { public long getStartPositionRendererTime() {
return info.startPositionUs + rendererPositionOffsetUs; return info.startPositionUs + rendererPositionOffsetUs;
} }
/** Returns whether the period is fully buffered. */
public boolean isFullyBuffered() { public boolean isFullyBuffered() {
return prepared return prepared
&& (!hasEnabledTracks || mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE); && (!hasEnabledTracks || mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE);
} }
public long getDurationUs() {
return info.durationUs;
}
/** /**
* Returns the buffered position in microseconds. If the period is buffered to the end then * Returns the buffered position in microseconds. If the period is buffered to the end then
* {@link C#TIME_END_OF_SOURCE} is returned unless {@code convertEosToDuration} is true, in which * {@link C#TIME_END_OF_SOURCE} is returned unless {@code convertEosToDuration} is true, in which
@ -137,65 +152,132 @@ import com.google.android.exoplayer2.util.Log;
: bufferedPositionUs; : bufferedPositionUs;
} }
/**
* Returns the next load time relative to the start of the period, or {@link C#TIME_END_OF_SOURCE}
* if loading has finished.
*/
public long getNextLoadPositionUs() { public long getNextLoadPositionUs() {
return !prepared ? 0 : mediaPeriod.getNextLoadPositionUs(); return !prepared ? 0 : mediaPeriod.getNextLoadPositionUs();
} }
/**
* Handles period preparation.
*
* @param playbackSpeed The current playback speed.
* @param timeline The current {@link Timeline}.
* @throws ExoPlaybackException If an error occurs during track selection.
*/
public void handlePrepared(float playbackSpeed, Timeline timeline) throws ExoPlaybackException { public void handlePrepared(float playbackSpeed, Timeline timeline) throws ExoPlaybackException {
prepared = true; prepared = true;
trackGroups = mediaPeriod.getTrackGroups(); trackGroups = mediaPeriod.getTrackGroups();
selectTracks(playbackSpeed, timeline); TrackSelectorResult selectorResult =
long newStartPositionUs = applyTrackSelection(info.startPositionUs, false); Assertions.checkNotNull(selectTracks(playbackSpeed, timeline));
long newStartPositionUs =
applyTrackSelection(
selectorResult, info.startPositionUs, /* forceRecreateStreams= */ false);
rendererPositionOffsetUs += info.startPositionUs - newStartPositionUs; rendererPositionOffsetUs += info.startPositionUs - newStartPositionUs;
info = info.copyWithStartPositionUs(newStartPositionUs); info = info.copyWithStartPositionUs(newStartPositionUs);
} }
/**
* Reevaluates the buffer of the media period at the given renderer position. Should only be
* called if this is the loading media period.
*
* @param rendererPositionUs The playing position in renderer time, in microseconds.
*/
public void reevaluateBuffer(long rendererPositionUs) { public void reevaluateBuffer(long rendererPositionUs) {
Assertions.checkState(isLoadingMediaPeriod());
if (prepared) { if (prepared) {
mediaPeriod.reevaluateBuffer(toPeriodTime(rendererPositionUs)); mediaPeriod.reevaluateBuffer(toPeriodTime(rendererPositionUs));
} }
} }
/**
* Continues loading the media period at the given renderer position. Should only be called if
* this is the loading media period.
*
* @param rendererPositionUs The load position in renderer time, in microseconds.
*/
public void continueLoading(long rendererPositionUs) { public void continueLoading(long rendererPositionUs) {
Assertions.checkState(isLoadingMediaPeriod());
long loadingPeriodPositionUs = toPeriodTime(rendererPositionUs); long loadingPeriodPositionUs = toPeriodTime(rendererPositionUs);
mediaPeriod.continueLoading(loadingPeriodPositionUs); mediaPeriod.continueLoading(loadingPeriodPositionUs);
} }
public boolean selectTracks(float playbackSpeed, Timeline timeline) throws ExoPlaybackException { /**
* Selects tracks for the period and returns the new result if the selection changed. Must only be
* called if {@link #prepared} is {@code true}.
*
* @param playbackSpeed The current playback speed.
* @param timeline The current {@link Timeline}.
* @return The {@link TrackSelectorResult} if the result changed. Or null if nothing changed.
* @throws ExoPlaybackException If an error occurs during track selection.
*/
@Nullable
public TrackSelectorResult selectTracks(float playbackSpeed, Timeline timeline)
throws ExoPlaybackException {
TrackSelectorResult selectorResult = TrackSelectorResult selectorResult =
trackSelector.selectTracks(rendererCapabilities, trackGroups, info.id, timeline); trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
if (selectorResult.isEquivalent(periodTrackSelectorResult)) { if (selectorResult.isEquivalent(trackSelectorResult)) {
return false; return null;
} }
trackSelectorResult = selectorResult; for (TrackSelection trackSelection : selectorResult.selections.getAll()) {
for (TrackSelection trackSelection : trackSelectorResult.selections.getAll()) {
if (trackSelection != null) { if (trackSelection != null) {
trackSelection.onPlaybackSpeed(playbackSpeed); trackSelection.onPlaybackSpeed(playbackSpeed);
} }
} }
return true; return selectorResult;
}
public long applyTrackSelection(long positionUs, boolean forceRecreateStreams) {
return applyTrackSelection(
positionUs, forceRecreateStreams, new boolean[rendererCapabilities.length]);
} }
/**
* Applies a {@link TrackSelectorResult} to the period.
*
* @param trackSelectorResult The {@link TrackSelectorResult} to apply.
* @param positionUs The position relative to the start of the period at which to apply the new
* track selections, in microseconds.
* @param forceRecreateStreams Whether all streams are forced to be recreated.
* @return The actual position relative to the start of the period at which the new track
* selections are applied.
*/
public long applyTrackSelection( public long applyTrackSelection(
long positionUs, boolean forceRecreateStreams, boolean[] streamResetFlags) { TrackSelectorResult trackSelectorResult, long positionUs, boolean forceRecreateStreams) {
for (int i = 0; i < trackSelectorResult.length; i++) { return applyTrackSelection(
trackSelectorResult,
positionUs,
forceRecreateStreams,
new boolean[rendererCapabilities.length]);
}
/**
* Applies a {@link TrackSelectorResult} to the period.
*
* @param newTrackSelectorResult The {@link TrackSelectorResult} to apply.
* @param positionUs The position relative to the start of the period at which to apply the new
* track selections, in microseconds.
* @param forceRecreateStreams Whether all streams are forced to be recreated.
* @param streamResetFlags Will be populated to indicate which streams have been reset or were
* newly created.
* @return The actual position relative to the start of the period at which the new track
* selections are applied.
*/
public long applyTrackSelection(
TrackSelectorResult newTrackSelectorResult,
long positionUs,
boolean forceRecreateStreams,
boolean[] streamResetFlags) {
for (int i = 0; i < newTrackSelectorResult.length; i++) {
mayRetainStreamFlags[i] = mayRetainStreamFlags[i] =
!forceRecreateStreams && trackSelectorResult.isEquivalent(periodTrackSelectorResult, i); !forceRecreateStreams && newTrackSelectorResult.isEquivalent(trackSelectorResult, i);
} }
// Undo the effect of previous call to associate no-sample renderers with empty tracks // Undo the effect of previous call to associate no-sample renderers with empty tracks
// so the mediaPeriod receives back whatever it sent us before. // so the mediaPeriod receives back whatever it sent us before.
disassociateNoSampleRenderersWithEmptySampleStream(sampleStreams); disassociateNoSampleRenderersWithEmptySampleStream(sampleStreams);
disableTrackSelectionsInResult(); disableTrackSelectionsInResult();
periodTrackSelectorResult = trackSelectorResult; trackSelectorResult = newTrackSelectorResult;
enableTrackSelectionsInResult(); enableTrackSelectionsInResult();
// Disable streams on the period and get new streams for updated/newly-enabled tracks. // Disable streams on the period and get new streams for updated/newly-enabled tracks.
TrackSelectionArray trackSelections = trackSelectorResult.selections; TrackSelectionArray trackSelections = newTrackSelectorResult.selections;
positionUs = positionUs =
mediaPeriod.selectTracks( mediaPeriod.selectTracks(
trackSelections.getAll(), trackSelections.getAll(),
@ -209,7 +291,7 @@ import com.google.android.exoplayer2.util.Log;
hasEnabledTracks = false; hasEnabledTracks = false;
for (int i = 0; i < sampleStreams.length; i++) { for (int i = 0; i < sampleStreams.length; i++) {
if (sampleStreams[i] != null) { if (sampleStreams[i] != null) {
Assertions.checkState(trackSelectorResult.isRendererEnabled(i)); Assertions.checkState(newTrackSelectorResult.isRendererEnabled(i));
// hasEnabledTracks should be true only when non-empty streams exists. // hasEnabledTracks should be true only when non-empty streams exists.
if (rendererCapabilities[i].getTrackType() != C.TRACK_TYPE_NONE) { if (rendererCapabilities[i].getTrackType() != C.TRACK_TYPE_NONE) {
hasEnabledTracks = true; hasEnabledTracks = true;
@ -221,9 +303,10 @@ import com.google.android.exoplayer2.util.Log;
return positionUs; return positionUs;
} }
/** Releases the media period. No other method should be called after the release. */
public void release() { public void release() {
disableTrackSelectionsInResult(); disableTrackSelectionsInResult();
periodTrackSelectorResult = null; trackSelectorResult = null;
try { try {
if (info.id.endPositionUs != C.TIME_END_OF_SOURCE) { if (info.id.endPositionUs != C.TIME_END_OF_SOURCE) {
mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod); mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod);
@ -236,6 +319,12 @@ import com.google.android.exoplayer2.util.Log;
} }
} }
/**
* Sets the next media period holder in the queue.
*
* @param nextMediaPeriodHolder The next holder, or null if this will be the new loading media
* period holder at the end of the queue.
*/
public void setNext(@Nullable MediaPeriodHolder nextMediaPeriodHolder) { public void setNext(@Nullable MediaPeriodHolder nextMediaPeriodHolder) {
if (nextMediaPeriodHolder == next) { if (nextMediaPeriodHolder == next) {
return; return;
@ -245,18 +334,39 @@ import com.google.android.exoplayer2.util.Log;
enableTrackSelectionsInResult(); enableTrackSelectionsInResult();
} }
/**
* Returns the next media period holder in the queue, or null if this is the last media period
* (and thus the loading media period).
*/
@Nullable @Nullable
public MediaPeriodHolder getNext() { public MediaPeriodHolder getNext() {
return next; return next;
} }
/**
* Returns the {@link TrackGroupArray} exposed by this media period. Must only be called if {@link
* #prepared} is {@code true}.
*/
public TrackGroupArray getTrackGroups() {
return Assertions.checkNotNull(trackGroups);
}
/**
* Returns the {@link TrackSelectorResult} which is currently applied. Must only be called if
* {@link #prepared} is {@code true}.
*/
public TrackSelectorResult getTrackSelectorResult() {
return Assertions.checkNotNull(trackSelectorResult);
}
private void enableTrackSelectionsInResult() { private void enableTrackSelectionsInResult() {
if (!isLoadingMediaPeriod() || periodTrackSelectorResult == null) { TrackSelectorResult trackSelectorResult = this.trackSelectorResult;
if (!isLoadingMediaPeriod() || trackSelectorResult == null) {
return; return;
} }
for (int i = 0; i < periodTrackSelectorResult.length; i++) { for (int i = 0; i < trackSelectorResult.length; i++) {
boolean rendererEnabled = periodTrackSelectorResult.isRendererEnabled(i); boolean rendererEnabled = trackSelectorResult.isRendererEnabled(i);
TrackSelection trackSelection = periodTrackSelectorResult.selections.get(i); TrackSelection trackSelection = trackSelectorResult.selections.get(i);
if (rendererEnabled && trackSelection != null) { if (rendererEnabled && trackSelection != null) {
trackSelection.enable(); trackSelection.enable();
} }
@ -264,12 +374,13 @@ import com.google.android.exoplayer2.util.Log;
} }
private void disableTrackSelectionsInResult() { private void disableTrackSelectionsInResult() {
if (!isLoadingMediaPeriod() || periodTrackSelectorResult == null) { TrackSelectorResult trackSelectorResult = this.trackSelectorResult;
if (!isLoadingMediaPeriod() || trackSelectorResult == null) {
return; return;
} }
for (int i = 0; i < periodTrackSelectorResult.length; i++) { for (int i = 0; i < trackSelectorResult.length; i++) {
boolean rendererEnabled = periodTrackSelectorResult.isRendererEnabled(i); boolean rendererEnabled = trackSelectorResult.isRendererEnabled(i);
TrackSelection trackSelection = periodTrackSelectorResult.selections.get(i); TrackSelection trackSelection = trackSelectorResult.selections.get(i);
if (rendererEnabled && trackSelection != null) { if (rendererEnabled && trackSelection != null) {
trackSelection.disable(); trackSelection.disable();
} }
@ -280,7 +391,8 @@ import com.google.android.exoplayer2.util.Log;
* For each renderer of type {@link C#TRACK_TYPE_NONE}, we will remove the dummy {@link * For each renderer of type {@link C#TRACK_TYPE_NONE}, we will remove the dummy {@link
* EmptySampleStream} that was associated with it. * EmptySampleStream} that was associated with it.
*/ */
private void disassociateNoSampleRenderersWithEmptySampleStream(SampleStream[] sampleStreams) { private void disassociateNoSampleRenderersWithEmptySampleStream(
@NullableType SampleStream[] sampleStreams) {
for (int i = 0; i < rendererCapabilities.length; i++) { for (int i = 0; i < rendererCapabilities.length; i++) {
if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE) { if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE) {
sampleStreams[i] = null; sampleStreams[i] = null;
@ -292,7 +404,9 @@ import com.google.android.exoplayer2.util.Log;
* For each renderer of type {@link C#TRACK_TYPE_NONE} that was enabled, we will associate it with * For each renderer of type {@link C#TRACK_TYPE_NONE} that was enabled, we will associate it with
* a dummy {@link EmptySampleStream}. * a dummy {@link EmptySampleStream}.
*/ */
private void associateNoSampleRenderersWithEmptySampleStream(SampleStream[] sampleStreams) { private void associateNoSampleRenderersWithEmptySampleStream(
@NullableType SampleStream[] sampleStreams) {
TrackSelectorResult trackSelectorResult = Assertions.checkNotNull(this.trackSelectorResult);
for (int i = 0; i < rendererCapabilities.length; i++) { for (int i = 0; i < rendererCapabilities.length; i++) {
if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE
&& trackSelectorResult.isRendererEnabled(i)) { && trackSelectorResult.isRendererEnabled(i)) {

View File

@ -215,7 +215,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Override @Override
public long selectTracks( public long selectTracks(
TrackSelection[] selections, @NullableType TrackSelection[] selections,
boolean[] mayRetainStreamFlags, boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams, @NullableType SampleStream[] streams,
boolean[] streamResetFlags, boolean[] streamResetFlags,

View File

@ -21,6 +21,7 @@ import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import java.io.IOException; import java.io.IOException;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** /**
* Loads media corresponding to a {@link Timeline.Period}, and allows that media to be read. All * Loads media corresponding to a {@link Timeline.Period}, and allows that media to be read. All
@ -108,9 +109,9 @@ public interface MediaPeriod extends SequenceableLoader {
* @return The actual position at which the tracks were enabled, in microseconds. * @return The actual position at which the tracks were enabled, in microseconds.
*/ */
long selectTracks( long selectTracks(
TrackSelection[] selections, @NullableType TrackSelection[] selections,
boolean[] mayRetainStreamFlags, boolean[] mayRetainStreamFlags,
SampleStream[] streams, @NullableType SampleStream[] streams,
boolean[] streamResetFlags, boolean[] streamResetFlags,
long positionUs); long positionUs);

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.trackselection; package com.google.android.exoplayer2.trackselection;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.compatqual.NullableType;
@ -70,7 +71,7 @@ public final class TrackSelectorResult {
* will be returned. * will be returned.
* @return Whether this result is equivalent to {@code other} for all renderers. * @return Whether this result is equivalent to {@code other} for all renderers.
*/ */
public boolean isEquivalent(TrackSelectorResult other) { public boolean isEquivalent(@Nullable TrackSelectorResult other) {
if (other == null || other.selections.length != selections.length) { if (other == null || other.selections.length != selections.length) {
return false; return false;
} }
@ -93,7 +94,7 @@ public final class TrackSelectorResult {
* @return Whether this result is equivalent to {@code other} for the renderer at the specified * @return Whether this result is equivalent to {@code other} for the renderer at the specified
* index. * index.
*/ */
public boolean isEquivalent(TrackSelectorResult other, int index) { public boolean isEquivalent(@Nullable TrackSelectorResult other, int index) {
if (other == null) { if (other == null) {
return false; return false;
} }