Search in sources :

Example 6 with TrackSelectorResult

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);
    }
}
Also used : TrackSelectorResult(com.google.android.exoplayer2.trackselection.TrackSelectorResult) TextRenderer(com.google.android.exoplayer2.text.TextRenderer) SampleStream(com.google.android.exoplayer2.source.SampleStream)

Example 7 with TrackSelectorResult

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;
}
Also used : TrackSelectorResult(com.google.android.exoplayer2.trackselection.TrackSelectorResult) TextRenderer(com.google.android.exoplayer2.text.TextRenderer)

Example 8 with TrackSelectorResult

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);
}
Also used : Format(com.google.android.exoplayer2.Format) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) Test(org.junit.Test)

Example 9 with TrackSelectorResult

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);
}
Also used : Format(com.google.android.exoplayer2.Format) HashMap(java.util.HashMap) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Test(org.junit.Test)

Example 10 with TrackSelectorResult

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);
}
Also used : Format(com.google.android.exoplayer2.Format) TrackGroupArray(com.google.android.exoplayer2.source.TrackGroupArray) RendererCapabilities(com.google.android.exoplayer2.RendererCapabilities) Test(org.junit.Test)

Aggregations

TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)102 Test (org.junit.Test)96 Format (com.google.android.exoplayer2.Format)79 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)48 TrackSelectorResult (com.google.android.exoplayer2.trackselection.TrackSelectorResult)24 HashMap (java.util.HashMap)16 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)14 TrackSelection (com.google.android.exoplayer2.trackselection.TrackSelection)9 ParametersBuilder (com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder)8 SampleStream (com.google.android.exoplayer2.source.SampleStream)7 TrackSelectionOverride (com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride)6 Nullable (androidx.annotation.Nullable)5 Capabilities (com.google.android.exoplayer2.RendererCapabilities.Capabilities)5 TextRenderer (com.google.android.exoplayer2.text.TextRenderer)4 BaseTrackSelection (com.google.android.exoplayer2.trackselection.BaseTrackSelection)4 SelectionOverride (com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)4 ExoPlaybackException (com.google.android.exoplayer2.ExoPlaybackException)3 AdaptiveSupport (com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport)3 MediaPeriodId (com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)3 ExoTrackSelection (com.google.android.exoplayer2.trackselection.ExoTrackSelection)3