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
This commit is contained in:
bachinger 2023-12-19 11:50:26 -08:00 committed by Copybara-Service
parent 486230fbd7
commit 36b7a49d52
4 changed files with 44 additions and 46 deletions

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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() {