Search in sources :

Example 1 with TrackSelectorResult

use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.

the class ExoPlayerImplInternal method updatePeriods.

private void updatePeriods() throws ExoPlaybackException, IOException {
    if (timeline == null) {
        // We're waiting to get information about periods.
        mediaSource.maybeThrowSourceInfoRefreshError();
        return;
    }
    // Update the loading period if required.
    maybeUpdateLoadingPeriod();
    if (loadingPeriodHolder == null || loadingPeriodHolder.isFullyBuffered()) {
        setIsLoading(false);
    } else if (loadingPeriodHolder != null && loadingPeriodHolder.needsContinueLoading) {
        maybeContinueLoading();
    }
    if (playingPeriodHolder == null) {
        // We're waiting for the first period to be prepared.
        return;
    }
    // Update the playing and reading periods.
    while (playingPeriodHolder != readingPeriodHolder && rendererPositionUs >= playingPeriodHolder.next.rendererPositionOffsetUs) {
        // All enabled renderers' streams have been read to the end, and the playback position reached
        // the end of the playing period, so advance playback to the next period.
        playingPeriodHolder.release();
        setPlayingPeriodHolder(playingPeriodHolder.next);
        playbackInfo = new PlaybackInfo(playingPeriodHolder.index, playingPeriodHolder.startPositionUs);
        updatePlaybackPositions();
        eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
    }
    if (readingPeriodHolder.isLast) {
        for (int i = 0; i < renderers.length; i++) {
            Renderer renderer = renderers[i];
            SampleStream sampleStream = readingPeriodHolder.sampleStreams[i];
            // stream in case of playlist changes that cause the stream to be no longer final.
            if (sampleStream != null && renderer.getStream() == sampleStream && renderer.hasReadStreamToEnd()) {
                renderer.setCurrentStreamFinal();
            }
        }
        return;
    }
    for (int i = 0; i < renderers.length; i++) {
        Renderer renderer = renderers[i];
        SampleStream sampleStream = readingPeriodHolder.sampleStreams[i];
        if (renderer.getStream() != sampleStream || (sampleStream != null && !renderer.hasReadStreamToEnd())) {
            return;
        }
    }
    if (readingPeriodHolder.next != null && readingPeriodHolder.next.prepared) {
        TrackSelectorResult oldTrackSelectorResult = readingPeriodHolder.trackSelectorResult;
        readingPeriodHolder = readingPeriodHolder.next;
        TrackSelectorResult newTrackSelectorResult = readingPeriodHolder.trackSelectorResult;
        boolean initialDiscontinuity = readingPeriodHolder.mediaPeriod.readDiscontinuity() != C.TIME_UNSET;
        for (int i = 0; i < renderers.length; i++) {
            Renderer renderer = renderers[i];
            TrackSelection oldSelection = oldTrackSelectorResult.selections.get(i);
            if (oldSelection == null) {
            // The renderer has no current stream and will be enabled when we play the next period.
            } else if (initialDiscontinuity) {
                // The new period starts with a discontinuity, so the renderer will play out all data then
                // be disabled and re-enabled when it starts playing the next period.
                renderer.setCurrentStreamFinal();
            } else if (!renderer.isCurrentStreamFinal()) {
                TrackSelection newSelection = newTrackSelectorResult.selections.get(i);
                RendererConfiguration oldConfig = oldTrackSelectorResult.rendererConfigurations[i];
                RendererConfiguration newConfig = newTrackSelectorResult.rendererConfigurations[i];
                if (newSelection != null && newConfig.equals(oldConfig)) {
                    // Replace the renderer's SampleStream so the transition to playing the next period can
                    // be seamless.
                    Format[] formats = new Format[newSelection.length()];
                    for (int j = 0; j < formats.length; j++) {
                        formats[j] = newSelection.getFormat(j);
                    }
                    renderer.replaceStream(formats, readingPeriodHolder.sampleStreams[i], readingPeriodHolder.getRendererOffset());
                } else {
                    // The renderer will be disabled when transitioning to playing the next period, either
                    // because there's no new selection or because a configuration change is required. Mark
                    // the SampleStream as final to play out any remaining data.
                    renderer.setCurrentStreamFinal();
                }
            }
        }
    }
}
Also used : TrackSelectorResult(com.google.android.exoplayer2.trackselection.TrackSelectorResult) TrackSelection(com.google.android.exoplayer2.trackselection.TrackSelection) SampleStream(com.google.android.exoplayer2.source.SampleStream)

Example 2 with TrackSelectorResult

use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.

the class DownloadHelper method runTrackSelection.

/**
 * Runs the track selection for a given period index with the current parameters. The selected
 * tracks will be added to {@link #trackSelectionsByPeriodAndRenderer}.
 */
@RequiresNonNull({ "trackGroupArrays", "trackSelectionsByPeriodAndRenderer", "mediaPreparer", "mediaPreparer.timeline" })
private TrackSelectorResult runTrackSelection(int periodIndex) {
    try {
        TrackSelectorResult trackSelectorResult = trackSelector.selectTracks(rendererCapabilities, trackGroupArrays[periodIndex], new MediaPeriodId(mediaPreparer.timeline.getUidOfPeriod(periodIndex)), mediaPreparer.timeline);
        for (int i = 0; i < trackSelectorResult.length; i++) {
            @Nullable ExoTrackSelection newSelection = trackSelectorResult.selections[i];
            if (newSelection == null) {
                continue;
            }
            List<ExoTrackSelection> existingSelectionList = trackSelectionsByPeriodAndRenderer[periodIndex][i];
            boolean mergedWithExistingSelection = false;
            for (int j = 0; j < existingSelectionList.size(); j++) {
                ExoTrackSelection existingSelection = existingSelectionList.get(j);
                if (existingSelection.getTrackGroup().equals(newSelection.getTrackGroup())) {
                    // Merge with existing selection.
                    scratchSet.clear();
                    for (int k = 0; k < existingSelection.length(); k++) {
                        scratchSet.put(existingSelection.getIndexInTrackGroup(k), 0);
                    }
                    for (int k = 0; k < newSelection.length(); k++) {
                        scratchSet.put(newSelection.getIndexInTrackGroup(k), 0);
                    }
                    int[] mergedTracks = new int[scratchSet.size()];
                    for (int k = 0; k < scratchSet.size(); k++) {
                        mergedTracks[k] = scratchSet.keyAt(k);
                    }
                    existingSelectionList.set(j, new DownloadTrackSelection(existingSelection.getTrackGroup(), mergedTracks));
                    mergedWithExistingSelection = true;
                    break;
                }
            }
            if (!mergedWithExistingSelection) {
                existingSelectionList.add(newSelection);
            }
        }
        return trackSelectorResult;
    } catch (ExoPlaybackException e) {
        // DefaultTrackSelector does not throw exceptions during track selection.
        throw new UnsupportedOperationException(e);
    }
}
Also used : TrackSelectorResult(com.google.android.exoplayer2.trackselection.TrackSelectorResult) ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection) MediaPeriodId(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId) ExoPlaybackException(com.google.android.exoplayer2.ExoPlaybackException) Nullable(androidx.annotation.Nullable) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 3 with TrackSelectorResult

use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.

the class DownloadHelper method onMediaPrepared.

// Initialization of array of Lists.
@SuppressWarnings("unchecked")
private void onMediaPrepared() {
    checkNotNull(mediaPreparer);
    checkNotNull(mediaPreparer.mediaPeriods);
    checkNotNull(mediaPreparer.timeline);
    int periodCount = mediaPreparer.mediaPeriods.length;
    int rendererCount = rendererCapabilities.length;
    trackSelectionsByPeriodAndRenderer = (List<ExoTrackSelection>[][]) new List<?>[periodCount][rendererCount];
    immutableTrackSelectionsByPeriodAndRenderer = (List<ExoTrackSelection>[][]) new List<?>[periodCount][rendererCount];
    for (int i = 0; i < periodCount; i++) {
        for (int j = 0; j < rendererCount; j++) {
            trackSelectionsByPeriodAndRenderer[i][j] = new ArrayList<>();
            immutableTrackSelectionsByPeriodAndRenderer[i][j] = Collections.unmodifiableList(trackSelectionsByPeriodAndRenderer[i][j]);
        }
    }
    trackGroupArrays = new TrackGroupArray[periodCount];
    mappedTrackInfos = new MappedTrackInfo[periodCount];
    for (int i = 0; i < periodCount; i++) {
        trackGroupArrays[i] = mediaPreparer.mediaPeriods[i].getTrackGroups();
        TrackSelectorResult trackSelectorResult = runTrackSelection(/* periodIndex= */
        i);
        trackSelector.onSelectionActivated(trackSelectorResult.info);
        mappedTrackInfos[i] = checkNotNull(trackSelector.getCurrentMappedTrackInfo());
    }
    setPreparedWithMedia();
    checkNotNull(callbackHandler).post(() -> checkNotNull(callback).onPrepared(this));
}
Also used : TrackSelectorResult(com.google.android.exoplayer2.trackselection.TrackSelectorResult) ExoTrackSelection(com.google.android.exoplayer2.trackselection.ExoTrackSelection) List(java.util.List) ArrayList(java.util.ArrayList)

Example 4 with TrackSelectorResult

use of com.google.android.exoplayer2.trackselection.TrackSelectorResult in project ExoPlayer by google.

the class MediaPeriodQueueTest method setupTimeline.

private void setupTimeline(Timeline timeline) {
    fakeMediaSource = new FakeMediaSource(timeline);
    MediaSourceList.MediaSourceHolder mediaSourceHolder = new MediaSourceList.MediaSourceHolder(fakeMediaSource, /* useLazyPreparation= */
    false);
    mediaSourceList.setMediaSources(ImmutableList.of(mediaSourceHolder), new FakeShuffleOrder(/* length= */
    1));
    mediaSourceHolder.mediaSource.prepareSource(mock(MediaSourceCaller.class), /* mediaTransferListener */
    null, PlayerId.UNSET);
    Timeline playlistTimeline = mediaSourceList.createTimeline();
    firstPeriodUid = playlistTimeline.getUidOfPeriod(/* periodIndex= */
    0);
    playbackInfo = new PlaybackInfo(playlistTimeline, mediaPeriodQueue.resolveMediaPeriodIdForAds(playlistTimeline, firstPeriodUid, /* positionUs= */
    0), /* requestedContentPositionUs= */
    C.TIME_UNSET, /* discontinuityStartPositionUs= */
    0, Player.STATE_READY, /* playbackError= */
    null, /* isLoading= */
    false, /* trackGroups= */
    null, /* trackSelectorResult= */
    null, /* staticMetadata= */
    ImmutableList.of(), /* loadingMediaPeriodId= */
    null, /* playWhenReady= */
    false, Player.PLAYBACK_SUPPRESSION_REASON_NONE, /* playbackParameters= */
    PlaybackParameters.DEFAULT, /* bufferedPositionUs= */
    0, /* totalBufferedDurationUs= */
    0, /* positionUs= */
    0, /* offloadSchedulingEnabled= */
    false, /* sleepingForOffload= */
    false);
}
Also used : MediaSourceCaller(com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller) SinglePeriodTimeline(com.google.android.exoplayer2.source.SinglePeriodTimeline) SinglePeriodAdTimeline(com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline) FakeTimeline(com.google.android.exoplayer2.testutil.FakeTimeline) FakeMediaSource(com.google.android.exoplayer2.testutil.FakeMediaSource) FakeShuffleOrder(com.google.android.exoplayer2.testutil.FakeShuffleOrder)

Example 5 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)

Aggregations

TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)61 Test (org.junit.Test)58 Format (com.google.android.exoplayer2.Format)47 RendererCapabilities (com.google.android.exoplayer2.RendererCapabilities)29 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)11 TrackSelectorResult (com.google.android.exoplayer2.trackselection.TrackSelectorResult)10 HashMap (java.util.HashMap)8 ParametersBuilder (com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder)7 TrackSelectionOverride (com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride)6 TextRenderer (com.google.android.exoplayer2.text.TextRenderer)4 Nullable (androidx.annotation.Nullable)3 Capabilities (com.google.android.exoplayer2.RendererCapabilities.Capabilities)3 SampleStream (com.google.android.exoplayer2.source.SampleStream)3 ExoTrackSelection (com.google.android.exoplayer2.trackselection.ExoTrackSelection)3 SelectionOverride (com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride)2 CheckResult (androidx.annotation.CheckResult)1 ExoPlaybackException (com.google.android.exoplayer2.ExoPlaybackException)1 AdaptiveSupport (com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport)1 RendererConfiguration (com.google.android.exoplayer2.RendererConfiguration)1 TracksInfo (com.google.android.exoplayer2.TracksInfo)1