diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java index bac2804a7c..6d472853a8 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java @@ -295,7 +295,7 @@ import java.util.concurrent.atomic.AtomicBoolean; deliverPendingMessageAtStartPositionRequired = true; HandlerWrapper eventHandler = clock.createHandler(applicationLooper, /* callback= */ null); - queue = new MediaPeriodQueue(analyticsCollector, eventHandler); + queue = new MediaPeriodQueue(analyticsCollector, eventHandler, this::createMediaPeriodHolder); mediaSourceList = new MediaSourceList(/* listener= */ this, analyticsCollector, eventHandler, playerId); @@ -313,6 +313,18 @@ import java.util.concurrent.atomic.AtomicBoolean; handler = clock.createHandler(this.playbackLooper, this); } + private MediaPeriodHolder createMediaPeriodHolder( + MediaPeriodInfo mediaPeriodInfo, long rendererPositionOffsetUs) { + return new MediaPeriodHolder( + rendererCapabilities, + rendererPositionOffsetUs, + trackSelector, + loadControl.getAllocator(), + mediaSourceList, + mediaPeriodInfo, + emptyTrackSelectorResult); + } + public void experimentalSetForegroundModeTimeoutMs(long setForegroundModeTimeoutMs) { this.setForegroundModeTimeoutMs = setForegroundModeTimeoutMs; } @@ -2110,14 +2122,7 @@ import java.util.concurrent.atomic.AtomicBoolean; @Nullable MediaPeriodInfo info = queue.getNextMediaPeriodInfo(rendererPositionUs, playbackInfo); if (info != null) { - MediaPeriodHolder mediaPeriodHolder = - queue.enqueueNextMediaPeriodHolder( - rendererCapabilities, - trackSelector, - loadControl.getAllocator(), - mediaSourceList, - info, - emptyTrackSelectorResult); + MediaPeriodHolder mediaPeriodHolder = queue.enqueueNextMediaPeriodHolder(info); mediaPeriodHolder.mediaPeriod.prepare(this, info.startPositionUs); if (queue.getPlayingPeriod() == mediaPeriodHolder) { resetRendererPosition(info.startPositionUs); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodHolder.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodHolder.java index b4a95c4910..99f5d7dffc 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodHolder.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodHolder.java @@ -470,4 +470,8 @@ import androidx.media3.exoplayer.upstream.Allocator; Log.e(TAG, "Period release failed.", e); } } + + /* package */ interface Factory { + MediaPeriodHolder create(MediaPeriodInfo info, long rendererPositionOffsetUs); + } } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodQueue.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodQueue.java index 3db1140dbb..2da4adcb1c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodQueue.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/MediaPeriodQueue.java @@ -31,9 +31,6 @@ import androidx.media3.common.util.HandlerWrapper; import androidx.media3.exoplayer.analytics.AnalyticsCollector; import androidx.media3.exoplayer.source.MediaPeriod; import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId; -import androidx.media3.exoplayer.trackselection.TrackSelector; -import androidx.media3.exoplayer.trackselection.TrackSelectorResult; -import androidx.media3.exoplayer.upstream.Allocator; import com.google.common.collect.ImmutableList; /** @@ -74,6 +71,7 @@ import com.google.common.collect.ImmutableList; private final Timeline.Window window; private final AnalyticsCollector analyticsCollector; private final HandlerWrapper analyticsCollectorHandler; + private final MediaPeriodHolder.Factory mediaPeriodHolderFactory; private long nextWindowSequenceNumber; private @RepeatMode int repeatMode; @@ -91,11 +89,15 @@ import com.google.common.collect.ImmutableList; * @param analyticsCollector An {@link AnalyticsCollector} to be informed of queue changes. * @param analyticsCollectorHandler The {@link Handler} to call {@link AnalyticsCollector} methods * on. + * @param mediaPeriodHolderFactory A {@link MediaPeriodHolder.Factory} to create holders. */ public MediaPeriodQueue( - AnalyticsCollector analyticsCollector, HandlerWrapper analyticsCollectorHandler) { + AnalyticsCollector analyticsCollector, + HandlerWrapper analyticsCollectorHandler, + MediaPeriodHolder.Factory mediaPeriodHolderFactory) { this.analyticsCollector = analyticsCollector; this.analyticsCollectorHandler = analyticsCollectorHandler; + this.mediaPeriodHolderFactory = mediaPeriodHolderFactory; period = new Timeline.Period(); window = new Timeline.Window(); } @@ -171,34 +173,15 @@ import com.google.common.collect.ImmutableList; * Enqueues a new media period holder based on the specified information as the new loading media * period, and returns it. * - * @param rendererCapabilities The renderer capabilities. - * @param trackSelector The track selector. - * @param allocator The allocator. - * @param mediaSourceList The list of media sources. * @param info Information used to identify this media period in its timeline period. - * @param emptyTrackSelectorResult A {@link TrackSelectorResult} with empty selections for each - * renderer. */ - public MediaPeriodHolder enqueueNextMediaPeriodHolder( - RendererCapabilities[] rendererCapabilities, - TrackSelector trackSelector, - Allocator allocator, - MediaSourceList mediaSourceList, - MediaPeriodInfo info, - TrackSelectorResult emptyTrackSelectorResult) { + public MediaPeriodHolder enqueueNextMediaPeriodHolder(MediaPeriodInfo info) { long rendererPositionOffsetUs = loading == null ? INITIAL_RENDERER_POSITION_OFFSET_US : (loading.getRendererOffset() + loading.info.durationUs - info.startPositionUs); MediaPeriodHolder newPeriodHolder = - new MediaPeriodHolder( - rendererCapabilities, - rendererPositionOffsetUs, - trackSelector, - allocator, - mediaSourceList, - info, - emptyTrackSelectorResult); + mediaPeriodHolderFactory.create(info, rendererPositionOffsetUs); if (loading != null) { loading.setNext(newPeriodHolder); } else { diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java index f0ea953a01..a16c6bf5e5 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/MediaPeriodQueueTest.java @@ -105,7 +105,23 @@ public final class MediaPeriodQueueTest { Looper.getMainLooper()); HandlerWrapper handler = Clock.DEFAULT.createHandler(Looper.getMainLooper(), /* callback= */ null); - mediaPeriodQueue = new MediaPeriodQueue(analyticsCollector, handler); + mediaPeriodQueue = + new MediaPeriodQueue( + analyticsCollector, + handler, + (info, rendererPositionOffsetUs) -> + new MediaPeriodHolder( + rendererCapabilities, + rendererPositionOffsetUs, + trackSelector, + allocator, + mediaSourceList, + info, + new TrackSelectorResult( + new RendererConfiguration[0], + new ExoTrackSelection[0], + Tracks.EMPTY, + /* info= */ null))); mediaSourceList = new MediaSourceList( mock(MediaSourceList.MediaSourceListInfoRefreshListener.class), @@ -1442,17 +1458,7 @@ public final class MediaPeriodQueueTest { } private void enqueueNext() { - mediaPeriodQueue.enqueueNextMediaPeriodHolder( - rendererCapabilities, - trackSelector, - allocator, - mediaSourceList, - getNextMediaPeriodInfo(), - new TrackSelectorResult( - new RendererConfiguration[0], - new ExoTrackSelection[0], - Tracks.EMPTY, - /* info= */ null)); + mediaPeriodQueue.enqueueNextMediaPeriodHolder(getNextMediaPeriodInfo()); } private void clear() {