Search in sources :

Example 91 with MediaPeriodId

use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.

the class ExoPlayerImpl method getDuration.

@Override
public long getDuration() {
    verifyApplicationThread();
    if (isPlayingAd()) {
        MediaPeriodId periodId = playbackInfo.periodId;
        playbackInfo.timeline.getPeriodByUid(periodId.periodUid, period);
        long adDurationUs = period.getAdDurationUs(periodId.adGroupIndex, periodId.adIndexInAdGroup);
        return Util.usToMs(adDurationUs);
    }
    return getContentDuration();
}
Also used : MediaPeriodId(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)

Example 92 with MediaPeriodId

use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.

the class ExoPlayerImplInternal method seekToPeriodPosition.

private long seekToPeriodPosition(MediaPeriodId periodId, long periodPositionUs, boolean forceDisableRenderers, boolean forceBufferingState) throws ExoPlaybackException {
    stopRenderers();
    isRebuffering = false;
    if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
        setState(Player.STATE_BUFFERING);
    }
    // Find the requested period if it already exists.
    @Nullable MediaPeriodHolder oldPlayingPeriodHolder = queue.getPlayingPeriod();
    @Nullable MediaPeriodHolder newPlayingPeriodHolder = oldPlayingPeriodHolder;
    while (newPlayingPeriodHolder != null) {
        if (periodId.equals(newPlayingPeriodHolder.info.id)) {
            break;
        }
        newPlayingPeriodHolder = newPlayingPeriodHolder.getNext();
    }
    // renderer timestamps, or if forced.
    if (forceDisableRenderers || oldPlayingPeriodHolder != newPlayingPeriodHolder || (newPlayingPeriodHolder != null && newPlayingPeriodHolder.toRendererTime(periodPositionUs) < 0)) {
        for (Renderer renderer : renderers) {
            disableRenderer(renderer);
        }
        if (newPlayingPeriodHolder != null) {
            // Update the queue and reenable renderers if the requested media period already exists.
            while (queue.getPlayingPeriod() != newPlayingPeriodHolder) {
                queue.advancePlayingPeriod();
            }
            queue.removeAfter(newPlayingPeriodHolder);
            newPlayingPeriodHolder.setRendererOffset(MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US);
            enableRenderers();
        }
    }
    // Do the actual seeking.
    if (newPlayingPeriodHolder != null) {
        queue.removeAfter(newPlayingPeriodHolder);
        if (!newPlayingPeriodHolder.prepared) {
            newPlayingPeriodHolder.info = newPlayingPeriodHolder.info.copyWithStartPositionUs(periodPositionUs);
        } else if (newPlayingPeriodHolder.hasEnabledTracks) {
            periodPositionUs = newPlayingPeriodHolder.mediaPeriod.seekToUs(periodPositionUs);
            newPlayingPeriodHolder.mediaPeriod.discardBuffer(periodPositionUs - backBufferDurationUs, retainBackBufferFromKeyframe);
        }
        resetRendererPosition(periodPositionUs);
        maybeContinueLoading();
    } else {
        // New period has not been prepared.
        queue.clear();
        resetRendererPosition(periodPositionUs);
    }
    handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */
    false);
    handler.sendEmptyMessage(MSG_DO_SOME_WORK);
    return periodPositionUs;
}
Also used : TextRenderer(com.google.android.exoplayer2.text.TextRenderer) Nullable(androidx.annotation.Nullable)

Example 93 with MediaPeriodId

use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.

the class ExoPlayerImplInternal method isUsingPlaceholderPeriod.

private static boolean isUsingPlaceholderPeriod(PlaybackInfo playbackInfo, Timeline.Period period) {
    MediaPeriodId periodId = playbackInfo.periodId;
    Timeline timeline = playbackInfo.timeline;
    return timeline.isEmpty() || timeline.getPeriodByUid(periodId.periodUid, period).isPlaceholder;
}
Also used : MediaPeriodId(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)

Example 94 with MediaPeriodId

use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.

the class ExoPlayerImplInternal method seekToInternal.

private void seekToInternal(SeekPosition seekPosition) throws ExoPlaybackException {
    playbackInfoUpdate.incrementPendingOperationAcks(/* operationAcks= */
    1);
    MediaPeriodId periodId;
    long periodPositionUs;
    long requestedContentPositionUs;
    boolean seekPositionAdjusted;
    @Nullable Pair<Object, Long> resolvedSeekPosition = resolveSeekPositionUs(playbackInfo.timeline, seekPosition, /* trySubsequentPeriods= */
    true, repeatMode, shuffleModeEnabled, window, period);
    if (resolvedSeekPosition == null) {
        // The seek position was valid for the timeline that it was performed into, but the
        // timeline has changed or is not ready and a suitable seek position could not be resolved.
        Pair<MediaPeriodId, Long> firstPeriodAndPositionUs = getPlaceholderFirstMediaPeriodPositionUs(playbackInfo.timeline);
        periodId = firstPeriodAndPositionUs.first;
        periodPositionUs = firstPeriodAndPositionUs.second;
        requestedContentPositionUs = C.TIME_UNSET;
        seekPositionAdjusted = !playbackInfo.timeline.isEmpty();
    } else {
        // Update the resolved seek position to take ads into account.
        Object periodUid = resolvedSeekPosition.first;
        long resolvedContentPositionUs = resolvedSeekPosition.second;
        requestedContentPositionUs = seekPosition.windowPositionUs == C.TIME_UNSET ? C.TIME_UNSET : resolvedContentPositionUs;
        periodId = queue.resolveMediaPeriodIdForAdsAfterPeriodPositionChange(playbackInfo.timeline, periodUid, resolvedContentPositionUs);
        if (periodId.isAd()) {
            playbackInfo.timeline.getPeriodByUid(periodId.periodUid, period);
            periodPositionUs = period.getFirstAdIndexToPlay(periodId.adGroupIndex) == periodId.adIndexInAdGroup ? period.getAdResumePositionUs() : 0;
            seekPositionAdjusted = true;
        } else {
            periodPositionUs = resolvedContentPositionUs;
            seekPositionAdjusted = seekPosition.windowPositionUs == C.TIME_UNSET;
        }
    }
    try {
        if (playbackInfo.timeline.isEmpty()) {
            // Save seek position for later, as we are still waiting for a prepared source.
            pendingInitialSeekPosition = seekPosition;
        } else if (resolvedSeekPosition == null) {
            // End playback, as we didn't manage to find a valid seek position.
            if (playbackInfo.playbackState != Player.STATE_IDLE) {
                setState(Player.STATE_ENDED);
            }
            resetInternal(/* resetRenderers= */
            false, /* resetPosition= */
            true, /* releaseMediaSourceList= */
            false, /* resetError= */
            true);
        } else {
            // Execute the seek in the current media periods.
            long newPeriodPositionUs = periodPositionUs;
            if (periodId.equals(playbackInfo.periodId)) {
                MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
                if (playingPeriodHolder != null && playingPeriodHolder.prepared && newPeriodPositionUs != 0) {
                    newPeriodPositionUs = playingPeriodHolder.mediaPeriod.getAdjustedSeekPositionUs(newPeriodPositionUs, seekParameters);
                }
                if (Util.usToMs(newPeriodPositionUs) == Util.usToMs(playbackInfo.positionUs) && (playbackInfo.playbackState == Player.STATE_BUFFERING || playbackInfo.playbackState == Player.STATE_READY)) {
                    // Seek will be performed to the current position. Do nothing.
                    periodPositionUs = playbackInfo.positionUs;
                    return;
                }
            }
            newPeriodPositionUs = seekToPeriodPosition(periodId, newPeriodPositionUs, /* forceBufferingState= */
            playbackInfo.playbackState == Player.STATE_ENDED);
            seekPositionAdjusted |= periodPositionUs != newPeriodPositionUs;
            periodPositionUs = newPeriodPositionUs;
            updatePlaybackSpeedSettingsForNewPeriod(/* newTimeline= */
            playbackInfo.timeline, /* newPeriodId= */
            periodId, /* oldTimeline= */
            playbackInfo.timeline, /* oldPeriodId= */
            playbackInfo.periodId, /* positionForTargetOffsetOverrideUs= */
            requestedContentPositionUs);
        }
    } finally {
        playbackInfo = handlePositionDiscontinuity(periodId, periodPositionUs, requestedContentPositionUs, /* discontinuityStartPositionUs= */
        periodPositionUs, /* reportDiscontinuity= */
        seekPositionAdjusted, Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
    }
}
Also used : MediaPeriodId(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId) Nullable(androidx.annotation.Nullable)

Example 95 with MediaPeriodId

use of com.google.android.exoplayer2.source.MediaSource.MediaPeriodId in project ExoPlayer by google.

the class ExoPlayerImplInternal method resetInternal.

private void resetInternal(boolean resetRenderers, boolean resetPosition, boolean releaseMediaSourceList, boolean resetError) {
    handler.removeMessages(MSG_DO_SOME_WORK);
    pendingRecoverableRendererError = null;
    isRebuffering = false;
    mediaClock.stop();
    rendererPositionUs = MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US;
    for (Renderer renderer : renderers) {
        try {
            disableRenderer(renderer);
        } catch (ExoPlaybackException | RuntimeException e) {
            // There's nothing we can do.
            Log.e(TAG, "Disable failed.", e);
        }
    }
    if (resetRenderers) {
        for (Renderer renderer : renderers) {
            if (renderersToReset.remove(renderer)) {
                try {
                    renderer.reset();
                } catch (RuntimeException e) {
                    // There's nothing we can do.
                    Log.e(TAG, "Reset failed.", e);
                }
            }
        }
    }
    enabledRendererCount = 0;
    MediaPeriodId mediaPeriodId = playbackInfo.periodId;
    long startPositionUs = playbackInfo.positionUs;
    long requestedContentPositionUs = playbackInfo.periodId.isAd() || isUsingPlaceholderPeriod(playbackInfo, period) ? playbackInfo.requestedContentPositionUs : playbackInfo.positionUs;
    boolean resetTrackInfo = false;
    if (resetPosition) {
        pendingInitialSeekPosition = null;
        Pair<MediaPeriodId, Long> firstPeriodAndPositionUs = getPlaceholderFirstMediaPeriodPositionUs(playbackInfo.timeline);
        mediaPeriodId = firstPeriodAndPositionUs.first;
        startPositionUs = firstPeriodAndPositionUs.second;
        requestedContentPositionUs = C.TIME_UNSET;
        if (!mediaPeriodId.equals(playbackInfo.periodId)) {
            resetTrackInfo = true;
        }
    }
    queue.clear();
    shouldContinueLoading = false;
    playbackInfo = new PlaybackInfo(playbackInfo.timeline, mediaPeriodId, requestedContentPositionUs, /* discontinuityStartPositionUs= */
    startPositionUs, playbackInfo.playbackState, resetError ? null : playbackInfo.playbackError, /* isLoading= */
    false, resetTrackInfo ? TrackGroupArray.EMPTY : playbackInfo.trackGroups, resetTrackInfo ? emptyTrackSelectorResult : playbackInfo.trackSelectorResult, resetTrackInfo ? ImmutableList.of() : playbackInfo.staticMetadata, mediaPeriodId, playbackInfo.playWhenReady, playbackInfo.playbackSuppressionReason, playbackInfo.playbackParameters, /* bufferedPositionUs= */
    startPositionUs, /* totalBufferedDurationUs= */
    0, /* positionUs= */
    startPositionUs, offloadSchedulingEnabled, /* sleepingForOffload= */
    false);
    if (releaseMediaSourceList) {
        mediaSourceList.release();
    }
}
Also used : TextRenderer(com.google.android.exoplayer2.text.TextRenderer) MediaPeriodId(com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)

Aggregations

MediaPeriodId (com.google.android.exoplayer2.source.MediaSource.MediaPeriodId)106 Test (org.junit.Test)85 FakeTimeline (com.google.android.exoplayer2.testutil.FakeTimeline)75 Timeline (com.google.android.exoplayer2.Timeline)50 EventTime (com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)48 FakeMediaSource (com.google.android.exoplayer2.testutil.FakeMediaSource)28 TimelineWindowDefinition (com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition)28 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)27 Nullable (androidx.annotation.Nullable)26 Allocator (com.google.android.exoplayer2.upstream.Allocator)22 SinglePeriodTimeline (com.google.android.exoplayer2.source.SinglePeriodTimeline)19 DrmSessionManager (com.google.android.exoplayer2.drm.DrmSessionManager)17 TransferListener (com.google.android.exoplayer2.upstream.TransferListener)16 TrackGroupArray (com.google.android.exoplayer2.source.TrackGroupArray)15 AdPlaybackState (com.google.android.exoplayer2.source.ads.AdPlaybackState)15 FakeMediaPeriod (com.google.android.exoplayer2.testutil.FakeMediaPeriod)15 TestExoPlayerBuilder (com.google.android.exoplayer2.testutil.TestExoPlayerBuilder)15 ActionSchedule (com.google.android.exoplayer2.testutil.ActionSchedule)13 DrmSessionEventListener (com.google.android.exoplayer2.drm.DrmSessionEventListener)12 MediaPeriod (com.google.android.exoplayer2.source.MediaPeriod)11