From 36b7a49d52f965c0e13ebc462fa1192add15a672 Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 19 Dec 2023 11:50:26 -0800 Subject: [PATCH] Use factory to create media period holders in the queue This is a refactoring that allows the `MediaPeriodQueue` to create media period holders without all the collaborators being passes in to `enqueueNextMediaPeriodHolder(...)`. The factory is presumably also helpful in unit test to know whether and when exactly a holder is created in the preloading process. PiperOrigin-RevId: 592301400 --- .../exoplayer/ExoPlayerImplInternal.java | 23 ++++++++----- .../media3/exoplayer/MediaPeriodHolder.java | 4 +++ .../media3/exoplayer/MediaPeriodQueue.java | 33 +++++-------------- .../exoplayer/MediaPeriodQueueTest.java | 30 ++++++++++------- 4 files changed, 44 insertions(+), 46 deletions(-) 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() {