use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.
the class ExoPlayerImplInternal method reselectTracksInternal.
private void reselectTracksInternal() throws ExoPlaybackException {
float playbackSpeed = mediaClock.getPlaybackParameters().speed;
// Reselect tracks on each period in turn, until the selection changes.
MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod();
boolean selectionsChangedForReadPeriod = true;
TrackSelectorResult newTrackSelectorResult;
while (true) {
if (periodHolder == null || !periodHolder.prepared) {
// The reselection did not change any prepared periods.
return;
}
newTrackSelectorResult = periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline);
if (!newTrackSelectorResult.isEquivalent(periodHolder.getTrackSelectorResult())) {
// Selected tracks have changed for this period.
break;
}
if (periodHolder == readingPeriodHolder) {
// The track reselection didn't affect any period that has been read.
selectionsChangedForReadPeriod = false;
}
periodHolder = periodHolder.getNext();
}
if (selectionsChangedForReadPeriod) {
// Update streams and rebuffer for the new selection, recreating all streams if reading ahead.
MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
boolean recreateStreams = queue.removeAfter(playingPeriodHolder);
boolean[] streamResetFlags = new boolean[renderers.length];
long periodPositionUs = playingPeriodHolder.applyTrackSelection(newTrackSelectorResult, playbackInfo.positionUs, recreateStreams, streamResetFlags);
boolean hasDiscontinuity = playbackInfo.playbackState != Player.STATE_ENDED && periodPositionUs != playbackInfo.positionUs;
playbackInfo = handlePositionDiscontinuity(playbackInfo.periodId, periodPositionUs, playbackInfo.requestedContentPositionUs, playbackInfo.discontinuityStartPositionUs, hasDiscontinuity, Player.DISCONTINUITY_REASON_INTERNAL);
if (hasDiscontinuity) {
resetRendererPosition(periodPositionUs);
}
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
for (int i = 0; i < renderers.length; i++) {
Renderer renderer = renderers[i];
rendererWasEnabledFlags[i] = isRendererEnabled(renderer);
SampleStream sampleStream = playingPeriodHolder.sampleStreams[i];
if (rendererWasEnabledFlags[i]) {
if (sampleStream != renderer.getStream()) {
// We need to disable the renderer.
disableRenderer(renderer);
} else if (streamResetFlags[i]) {
// The renderer will continue to consume from its current stream, but needs to be reset.
renderer.resetPosition(rendererPositionUs);
}
}
}
enableRenderers(rendererWasEnabledFlags);
} else {
// Release and re-prepare/buffer periods after the one whose selection changed.
queue.removeAfter(periodHolder);
if (periodHolder.prepared) {
long loadingPeriodPositionUs = max(periodHolder.info.startPositionUs, periodHolder.toPeriodTime(rendererPositionUs));
periodHolder.applyTrackSelection(newTrackSelectorResult, loadingPeriodPositionUs, false);
}
}
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */
true);
if (playbackInfo.playbackState != Player.STATE_ENDED) {
maybeContinueLoading();
updatePlaybackPositions();
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
}
}
use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.
the class ExoPlayerImplInternal method replaceStreamsOrDisableRendererForTransition.
private boolean replaceStreamsOrDisableRendererForTransition() throws ExoPlaybackException {
MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod();
TrackSelectorResult newTrackSelectorResult = readingPeriodHolder.getTrackSelectorResult();
boolean needsToWaitForRendererToEnd = false;
for (int i = 0; i < renderers.length; i++) {
Renderer renderer = renderers[i];
if (!isRendererEnabled(renderer)) {
continue;
}
boolean rendererIsReadingOldStream = renderer.getStream() != readingPeriodHolder.sampleStreams[i];
boolean rendererShouldBeEnabled = newTrackSelectorResult.isRendererEnabled(i);
if (rendererShouldBeEnabled && !rendererIsReadingOldStream) {
// All done.
continue;
}
if (!renderer.isCurrentStreamFinal()) {
// The renderer stream is not final, so we can replace the sample streams immediately.
Format[] formats = getFormats(newTrackSelectorResult.selections[i]);
renderer.replaceStream(formats, readingPeriodHolder.sampleStreams[i], readingPeriodHolder.getStartPositionRendererTime(), readingPeriodHolder.getRendererOffset());
} else if (renderer.isEnded()) {
// The renderer has finished playback, so we can disable it now.
disableRenderer(renderer);
} else {
// We need to wait until rendering finished before disabling the renderer.
needsToWaitForRendererToEnd = true;
}
}
return !needsToWaitForRendererToEnd;
}
use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.
the class DefaultTrackSelectorTest method selectTracksSelectTrackWithSelectionFlag.
/**
* Tests that track selector will select audio track with {@link C#SELECTION_FLAG_DEFAULT} given
* default values of {@link Parameters}.
*/
@Test
public void selectTracksSelectTrackWithSelectionFlag() throws Exception {
Format.Builder formatBuilder = AUDIO_FORMAT.buildUpon();
Format audioFormat = formatBuilder.setSelectionFlags(0).build();
Format formatWithSelectionFlag = formatBuilder.setSelectionFlags(C.SELECTION_FLAG_DEFAULT).build();
TrackGroupArray trackGroups = wrapFormats(audioFormat, formatWithSelectionFlag);
TrackSelectorResult result = trackSelector.selectTracks(new RendererCapabilities[] { ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES }, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, formatWithSelectionFlag);
}
use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.
the class DefaultTrackSelectorTest method selectTracksPreferTrackWithinCapabilities.
/**
* Tests that track selector will prefer tracks that are within renderer's capabilities over track
* that exceed renderer's capabilities.
*/
@Test
public void selectTracksPreferTrackWithinCapabilities() throws Exception {
Format.Builder formatBuilder = AUDIO_FORMAT.buildUpon();
Format supportedFormat = formatBuilder.setId("supportedFormat").build();
Format exceededFormat = formatBuilder.setId("exceededFormat").build();
TrackGroupArray trackGroups = wrapFormats(exceededFormat, supportedFormat);
Map<String, Integer> mappedCapabilities = new HashMap<>();
mappedCapabilities.put(supportedFormat.id, FORMAT_HANDLED);
mappedCapabilities.put(exceededFormat.id, FORMAT_EXCEEDS_CAPABILITIES);
RendererCapabilities mappedAudioRendererCapabilities = new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, mappedCapabilities);
TrackSelectorResult result = trackSelector.selectTracks(new RendererCapabilities[] { mappedAudioRendererCapabilities }, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, supportedFormat);
}
use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.
the class DefaultTrackSelectorTest method textTrackSelectionFlags.
/**
* Tests text track selection flags.
*/
@Test
public void textTrackSelectionFlags() throws ExoPlaybackException {
Format.Builder formatBuilder = TEXT_FORMAT.buildUpon().setLanguage("eng");
Format forcedOnly = formatBuilder.setSelectionFlags(C.SELECTION_FLAG_FORCED).build();
Format forcedDefault = formatBuilder.setSelectionFlags(C.SELECTION_FLAG_FORCED | C.SELECTION_FLAG_DEFAULT).build();
Format defaultOnly = formatBuilder.setSelectionFlags(C.SELECTION_FLAG_DEFAULT).build();
Format noFlag = formatBuilder.setSelectionFlags(0).build();
RendererCapabilities[] textRendererCapabilities = new RendererCapabilities[] { ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES };
// There is no text language preference, the first track flagged as default should be selected.
TrackGroupArray trackGroups = wrapFormats(forcedOnly, forcedDefault, defaultOnly, noFlag);
TrackSelectorResult result = trackSelector.selectTracks(textRendererCapabilities, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, forcedDefault);
// Ditto.
trackGroups = wrapFormats(forcedOnly, noFlag, defaultOnly);
result = trackSelector.selectTracks(textRendererCapabilities, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, defaultOnly);
// Default flags are disabled and no language preference is provided, so no text track is
// selected.
trackGroups = wrapFormats(defaultOnly, noFlag, forcedOnly, forcedDefault);
trackSelector.setParameters(defaultParameters.buildUpon().setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_DEFAULT));
result = trackSelector.selectTracks(textRendererCapabilities, trackGroups, periodId, TIMELINE);
assertNoSelection(result.selections[0]);
// All selection flags are disabled and there is no language preference, so nothing should be
// selected.
trackGroups = wrapFormats(forcedOnly, forcedDefault, defaultOnly, noFlag);
trackSelector.setParameters(trackSelector.getParameters().buildUpon().setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_DEFAULT | C.SELECTION_FLAG_FORCED));
result = trackSelector.selectTracks(textRendererCapabilities, trackGroups, periodId, TIMELINE);
assertNoSelection(result.selections[0]);
// There is a preferred language, so a language-matching track flagged as default should
// be selected, and the one without forced flag should be preferred.
trackSelector.setParameters(defaultParameters.buildUpon().setPreferredTextLanguage("eng"));
result = trackSelector.selectTracks(textRendererCapabilities, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, defaultOnly);
// Same as above, but the default flag is disabled. If multiple tracks match the preferred
// language, those not flagged as forced are preferred, as they likely include the contents of
// forced subtitles.
trackGroups = wrapFormats(noFlag, forcedOnly, forcedDefault, defaultOnly);
trackSelector.setParameters(trackSelector.getParameters().buildUpon().setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_DEFAULT));
result = trackSelector.selectTracks(textRendererCapabilities, trackGroups, periodId, TIMELINE);
assertFixedSelection(result.selections[0], trackGroups, noFlag);
}
Aggregations