Search in sources :

Example 1 with Timeline

use of androidx.media3.common.Timeline in project media by androidx.

the class CastPlayer method updateInternalStateAndNotifyIfChanged.

// Internal methods.
// Call deprecated callbacks.
@SuppressWarnings("deprecation")
private void updateInternalStateAndNotifyIfChanged() {
    if (remoteMediaClient == null) {
        // There is no session. We leave the state of the player as it is now.
        return;
    }
    int oldWindowIndex = this.currentWindowIndex;
    @Nullable Object oldPeriodUid = !getCurrentTimeline().isEmpty() ? getCurrentTimeline().getPeriod(oldWindowIndex, period, /* setIds= */
    true).uid : null;
    updatePlayerStateAndNotifyIfChanged(/* resultCallback= */
    null);
    updateRepeatModeAndNotifyIfChanged(/* resultCallback= */
    null);
    updatePlaybackRateAndNotifyIfChanged(/* resultCallback= */
    null);
    boolean playingPeriodChangedByTimelineChange = updateTimelineAndNotifyIfChanged();
    Timeline currentTimeline = getCurrentTimeline();
    currentWindowIndex = fetchCurrentWindowIndex(remoteMediaClient, currentTimeline);
    @Nullable Object currentPeriodUid = !currentTimeline.isEmpty() ? currentTimeline.getPeriod(currentWindowIndex, period, /* setIds= */
    true).uid : null;
    if (!playingPeriodChangedByTimelineChange && !Util.areEqual(oldPeriodUid, currentPeriodUid) && pendingSeekCount == 0) {
        // Report discontinuity and media item auto transition.
        currentTimeline.getPeriod(oldWindowIndex, period, /* setIds= */
        true);
        currentTimeline.getWindow(oldWindowIndex, window);
        long windowDurationMs = window.getDurationMs();
        PositionInfo oldPosition = new PositionInfo(window.uid, period.windowIndex, window.mediaItem, period.uid, period.windowIndex, /* positionMs= */
        windowDurationMs, /* contentPositionMs= */
        windowDurationMs, /* adGroupIndex= */
        C.INDEX_UNSET, /* adIndexInAdGroup= */
        C.INDEX_UNSET);
        currentTimeline.getPeriod(currentWindowIndex, period, /* setIds= */
        true);
        currentTimeline.getWindow(currentWindowIndex, window);
        PositionInfo newPosition = new PositionInfo(window.uid, period.windowIndex, window.mediaItem, period.uid, period.windowIndex, /* positionMs= */
        window.getDefaultPositionMs(), /* contentPositionMs= */
        window.getDefaultPositionMs(), /* adGroupIndex= */
        C.INDEX_UNSET, /* adIndexInAdGroup= */
        C.INDEX_UNSET);
        listeners.queueEvent(Player.EVENT_POSITION_DISCONTINUITY, listener -> {
            listener.onPositionDiscontinuity(DISCONTINUITY_REASON_AUTO_TRANSITION);
            listener.onPositionDiscontinuity(oldPosition, newPosition, DISCONTINUITY_REASON_AUTO_TRANSITION);
        });
        listeners.queueEvent(Player.EVENT_MEDIA_ITEM_TRANSITION, listener -> listener.onMediaItemTransition(getCurrentMediaItem(), MEDIA_ITEM_TRANSITION_REASON_AUTO));
    }
    if (updateTracksAndSelectionsAndNotifyIfChanged()) {
        listeners.queueEvent(Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksChanged(currentTrackGroups, currentTrackSelection));
        listeners.queueEvent(Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksInfoChanged(currentTracksInfo));
    }
    updateAvailableCommandsAndNotifyIfChanged();
    listeners.flushEvents();
}
Also used : Timeline(androidx.media3.common.Timeline) Nullable(androidx.annotation.Nullable)

Example 2 with Timeline

use of androidx.media3.common.Timeline in project media by androidx.

the class CastPlayer method setMediaItemsInternal.

@Nullable
private PendingResult<MediaChannelResult> setMediaItemsInternal(MediaQueueItem[] mediaQueueItems, int startIndex, long startPositionMs, @RepeatMode int repeatMode) {
    if (remoteMediaClient == null || mediaQueueItems.length == 0) {
        return null;
    }
    startPositionMs = startPositionMs == C.TIME_UNSET ? 0 : startPositionMs;
    if (startIndex == C.INDEX_UNSET) {
        startIndex = getCurrentMediaItemIndex();
        startPositionMs = getCurrentPosition();
    }
    Timeline currentTimeline = getCurrentTimeline();
    if (!currentTimeline.isEmpty()) {
        pendingMediaItemRemovalPosition = getCurrentPositionInfo();
    }
    return remoteMediaClient.queueLoad(mediaQueueItems, min(startIndex, mediaQueueItems.length - 1), getCastRepeatMode(repeatMode), startPositionMs, /* customData= */
    null);
}
Also used : Timeline(androidx.media3.common.Timeline) Nullable(androidx.annotation.Nullable)

Example 3 with Timeline

use of androidx.media3.common.Timeline in project media by androidx.

the class CastPlayerTest method removeCurrentMediaItem_byRemoteClient_notifiesPositionDiscontinuity.

@Test
// Mocks deprecated method used by the CastPlayer.
@SuppressWarnings("deprecation")
public void removeCurrentMediaItem_byRemoteClient_notifiesPositionDiscontinuity() {
    MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */
    1);
    MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */
    2);
    List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
    castPlayer.addMediaItems(mediaItems);
    updateTimeLine(mediaItems, new int[] { 1, 2 }, /* currentItemId= */
    1, new int[] { MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_BUFFERED }, /* durationsMs= */
    new long[] { 20_000L, 30_000L }, /* positionMs= */
    1234);
    // Update with the new timeline after removal on the device.
    updateTimeLine(ImmutableList.of(mediaItem2), /* mediaQueueItemIds= */
    new int[] { 2 }, /* currentItemId= */
    2, new int[] { MediaInfo.STREAM_TYPE_BUFFERED }, /* durationsMs= */
    new long[] { 30_000L }, /* positionMs= */
    0);
    Player.PositionInfo oldPosition = new Player.PositionInfo(/* windowUid= */
    1, /* windowIndex= */
    0, new MediaItem.Builder().setUri(Uri.EMPTY).setTag(1).build(), /* periodUid= */
    1, /* periodIndex= */
    0, // position at which we receive the timeline change
    0, // position at which we receive the timeline change
    0, /* adGroupIndex= */
    C.INDEX_UNSET, /* adIndexInAdGroup= */
    C.INDEX_UNSET);
    Player.PositionInfo newPosition = new Player.PositionInfo(/* windowUid= */
    2, /* windowIndex= */
    0, new MediaItem.Builder().setUri(Uri.EMPTY).setTag(2).build(), /* periodUid= */
    2, /* periodIndex= */
    0, /* positionMs= */
    0, /* contentPositionMs= */
    0, /* adGroupIndex= */
    C.INDEX_UNSET, /* adIndexInAdGroup= */
    C.INDEX_UNSET);
    InOrder inOrder = Mockito.inOrder(mockListener);
    inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_REMOVE));
    inOrder.verify(mockListener).onPositionDiscontinuity(eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_REMOVE));
    inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
    inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
}
Also used : Player(androidx.media3.common.Player) InOrder(org.mockito.InOrder) MediaItem(androidx.media3.common.MediaItem) Test(org.junit.Test)

Example 4 with Timeline

use of androidx.media3.common.Timeline in project media by androidx.

the class CastPlayerTest method updateTimeLine.

private void updateTimeLine(List<MediaItem> mediaItems, int[] mediaQueueItemIds, int currentItemId, int[] streamTypes, long[] durationsMs, long positionMs) {
    // Set up mocks to allow the player to update the timeline.
    List<MediaQueueItem> queueItems = new ArrayList<>();
    for (int i = 0; i < mediaQueueItemIds.length; i++) {
        MediaItem mediaItem = mediaItems.get(i);
        int mediaQueueItemId = mediaQueueItemIds[i];
        int streamType = streamTypes[i];
        long durationMs = durationsMs[i];
        MediaInfo.Builder mediaInfoBuilder = new MediaInfo.Builder(mediaItem.localConfiguration.uri.toString()).setStreamType(streamType).setContentType(mediaItem.localConfiguration.mimeType);
        if (durationMs != C.TIME_UNSET) {
            mediaInfoBuilder.setStreamDuration(durationMs);
        }
        MediaInfo mediaInfo = mediaInfoBuilder.build();
        MediaQueueItem mediaQueueItem = mock(MediaQueueItem.class);
        when(mediaQueueItem.getItemId()).thenReturn(mediaQueueItemId);
        when(mediaQueueItem.getMedia()).thenReturn(mediaInfo);
        queueItems.add(mediaQueueItem);
        if (mediaQueueItemId == currentItemId) {
            when(mockRemoteMediaClient.getCurrentItem()).thenReturn(mediaQueueItem);
            when(mockMediaStatus.getMediaInfo()).thenReturn(mediaInfo);
        }
    }
    if (positionMs != C.TIME_UNSET) {
        when(mockRemoteMediaClient.getApproximateStreamPosition()).thenReturn(positionMs);
    }
    when(mockMediaQueue.getItemIds()).thenReturn(mediaQueueItemIds);
    when(mockMediaStatus.getQueueItems()).thenReturn(queueItems);
    when(mockMediaStatus.getCurrentItemId()).thenReturn(currentItemId == C.INDEX_UNSET ? 0 : currentItemId);
    // Call listener to update the timeline of the player.
    remoteMediaClientCallback.onStatusUpdated();
}
Also used : MediaInfo(com.google.android.gms.cast.MediaInfo) MediaItem(androidx.media3.common.MediaItem) ArrayList(java.util.ArrayList) MediaQueueItem(com.google.android.gms.cast.MediaQueueItem)

Example 5 with Timeline

use of androidx.media3.common.Timeline in project media by androidx.

the class CastPlayerTest method autoTransition_notifiesPositionDiscontinuity.

@Test
// Mocks deprecated method used by the CastPlayer.
@SuppressWarnings("deprecation")
public void autoTransition_notifiesPositionDiscontinuity() {
    int[] mediaQueueItemIds = new int[] { 1, 2 };
    int[] streamTypes = { MediaInfo.STREAM_TYPE_BUFFERED, MediaInfo.STREAM_TYPE_BUFFERED };
    long[] durationsFirstMs = { 12500, C.TIME_UNSET };
    // When the remote Cast player transitions to an item that wasn't played before, the media state
    // delivers the duration for that media item which updates the timeline accordingly.
    long[] durationsSecondMs = { 12500, 22000 };
    List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
    castPlayer.addMediaItems(mediaItems);
    updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */
    1, /* streamTypes= */
    streamTypes, /* durationsMs= */
    durationsFirstMs, /* positionMs= */
    C.TIME_UNSET);
    updateTimeLine(mediaItems, mediaQueueItemIds, /* currentItemId= */
    2, /* streamTypes= */
    streamTypes, /* durationsMs= */
    durationsSecondMs, /* positionMs= */
    C.TIME_UNSET);
    Player.PositionInfo oldPosition = new Player.PositionInfo(/* windowUid= */
    1, /* windowIndex= */
    0, new MediaItem.Builder().setUri(Uri.EMPTY).setTag(1).build(), /* periodUid= */
    1, /* periodIndex= */
    0, /* positionMs= */
    12500, /* contentPositionMs= */
    12500, /* adGroupIndex= */
    C.INDEX_UNSET, /* adIndexInAdGroup= */
    C.INDEX_UNSET);
    Player.PositionInfo newPosition = new Player.PositionInfo(/* windowUid= */
    2, /* windowIndex= */
    1, new MediaItem.Builder().setUri(Uri.EMPTY).setTag(2).build(), /* periodUid= */
    2, /* periodIndex= */
    1, /* positionMs= */
    0, /* contentPositionMs= */
    0, /* adGroupIndex= */
    C.INDEX_UNSET, /* adIndexInAdGroup= */
    C.INDEX_UNSET);
    InOrder inOrder = Mockito.inOrder(mockListener);
    inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
    inOrder.verify(mockListener).onPositionDiscontinuity(eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
    inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
    inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
}
Also used : Player(androidx.media3.common.Player) InOrder(org.mockito.InOrder) MediaItem(androidx.media3.common.MediaItem) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)412 Timeline (androidx.media3.common.Timeline)369 FakeTimeline (androidx.media3.test.utils.FakeTimeline)246 FakeMediaSource (androidx.media3.test.utils.FakeMediaSource)140 SinglePeriodTimeline (androidx.media3.exoplayer.source.SinglePeriodTimeline)125 NoUidTimeline (androidx.media3.test.utils.NoUidTimeline)110 TestExoPlayerBuilder (androidx.media3.test.utils.TestExoPlayerBuilder)109 MediaItem (androidx.media3.common.MediaItem)89 TimelineWindowDefinition (androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition)89 MediaPeriodId (androidx.media3.exoplayer.source.MediaSource.MediaPeriodId)85 Player (androidx.media3.common.Player)83 TrackGroupArray (androidx.media3.common.TrackGroupArray)76 ActionSchedule (androidx.media3.test.utils.ActionSchedule)74 AtomicReference (java.util.concurrent.atomic.AtomicReference)63 ExoPlayerTestRunner (androidx.media3.test.utils.ExoPlayerTestRunner)60 CountDownLatch (java.util.concurrent.CountDownLatch)59 LargeTest (androidx.test.filters.LargeTest)56 Format (androidx.media3.common.Format)54 Nullable (androidx.annotation.Nullable)52 AdPlaybackState (androidx.media3.common.AdPlaybackState)52