Add DefaultPreloadManager.Builder

The `DefaultPreloadManager.Builder` is able to build the `DefaultPreloadManager` and `ExoPlayer` instances with the consistently shared configurations. Apps can:

* Simply setup the `DefaultPreloadManager` and `ExoPlayer` with all default configurations via `build()` and `buildExoPlayer()`;
* Or customize the shared configurations by the setters on `DefaultPreloadManager.Builder` and setup via `build()` and `buildExoPlayer()`;
* Or customize the player-only configurations for `ExoPlayer` via `buildExoPlayer(ExoPlayer.Builder)`.

PiperOrigin-RevId: 684852808
This commit is contained in:
tianyifeng 2024-10-11 08:52:28 -07:00 committed by Copybara-Service
parent 337e59e733
commit 98dc7f2def
7 changed files with 368 additions and 218 deletions

View File

@ -48,6 +48,9 @@
* Add method `MediaSourceEventListener.EventDispatcher.dispatchEvent()` to * Add method `MediaSourceEventListener.EventDispatcher.dispatchEvent()` to
allow invoking events of subclass listeners allow invoking events of subclass listeners
([1736](https://github.com/androidx/media/pull/1736)). ([1736](https://github.com/androidx/media/pull/1736)).
* Add `DefaultPreloadManager.Builder` that builds the
`DefaultPreloadManager` and `ExoPlayer` instances with consistently
shared configurations.
* Transformer: * Transformer:
* Make setting the image duration using * Make setting the image duration using
`MediaItem.Builder.setImageDurationMs` mandatory for image export. `MediaItem.Builder.setImageDurationMs` mandatory for image export.

View File

@ -15,16 +15,13 @@
*/ */
package androidx.media3.demo.shortform package androidx.media3.demo.shortform
import android.content.Context
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.LoadControl import androidx.media3.exoplayer.source.preload.DefaultPreloadManager.Builder
import androidx.media3.exoplayer.RenderersFactory
import androidx.media3.exoplayer.upstream.BandwidthMeter
import androidx.media3.exoplayer.util.EventLogger import androidx.media3.exoplayer.util.EventLogger
import com.google.common.collect.BiMap import com.google.common.collect.BiMap
import com.google.common.collect.HashBiMap import com.google.common.collect.HashBiMap
@ -34,14 +31,7 @@ import java.util.LinkedList
import java.util.Queue import java.util.Queue
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
class PlayerPool( class PlayerPool(private val numberOfPlayers: Int, preloadManagerBuilder: Builder) {
private val numberOfPlayers: Int,
context: Context,
playbackLooper: Looper,
loadControl: LoadControl,
renderersFactory: RenderersFactory,
bandwidthMeter: BandwidthMeter,
) {
/** Creates a player instance to be used by the pool. */ /** Creates a player instance to be used by the pool. */
interface PlayerFactory { interface PlayerFactory {
@ -52,8 +42,7 @@ class PlayerPool(
private val availablePlayerQueue: Queue<Int> = LinkedList() private val availablePlayerQueue: Queue<Int> = LinkedList()
private val playerMap: BiMap<Int, ExoPlayer> = Maps.synchronizedBiMap(HashBiMap.create()) private val playerMap: BiMap<Int, ExoPlayer> = Maps.synchronizedBiMap(HashBiMap.create())
private val playerRequestTokenSet: MutableSet<Int> = Collections.synchronizedSet(HashSet<Int>()) private val playerRequestTokenSet: MutableSet<Int> = Collections.synchronizedSet(HashSet<Int>())
private val playerFactory: PlayerFactory = private val playerFactory: PlayerFactory = DefaultPlayerFactory(preloadManagerBuilder)
DefaultPlayerFactory(context, playbackLooper, loadControl, renderersFactory, bandwidthMeter)
fun acquirePlayer(token: Int, callback: (ExoPlayer) -> Unit) { fun acquirePlayer(token: Int, callback: (ExoPlayer) -> Unit) {
synchronized(playerMap) { synchronized(playerMap) {
@ -126,23 +115,11 @@ class PlayerPool(
} }
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
private class DefaultPlayerFactory( private class DefaultPlayerFactory(private val preloadManagerBuilder: Builder) : PlayerFactory {
private val context: Context,
private val playbackLooper: Looper,
private val loadControl: LoadControl,
private val renderersFactory: RenderersFactory,
private val bandwidthMeter: BandwidthMeter,
) : PlayerFactory {
private var playerCounter = 0 private var playerCounter = 0
override fun createPlayer(): ExoPlayer { override fun createPlayer(): ExoPlayer {
val player = val player = preloadManagerBuilder.buildExoPlayer()
ExoPlayer.Builder(context)
.setPlaybackLooper(playbackLooper)
.setLoadControl(loadControl)
.setRenderersFactory(renderersFactory)
.setBandwidthMeter(bandwidthMeter)
.build()
player.addAnalyticsListener(EventLogger("player-$playerCounter")) player.addAnalyticsListener(EventLogger("player-$playerCounter"))
playerCounter++ playerCounter++
player.repeatMode = ExoPlayer.REPEAT_MODE_ONE player.repeatMode = ExoPlayer.REPEAT_MODE_ONE

View File

@ -16,8 +16,6 @@
package androidx.media3.demo.shortform.viewpager package androidx.media3.demo.shortform.viewpager
import android.content.Context import android.content.Context
import android.os.HandlerThread
import android.os.Process
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.OptIn import androidx.annotation.OptIn
@ -29,14 +27,9 @@ import androidx.media3.demo.shortform.MediaItemDatabase
import androidx.media3.demo.shortform.PlayerPool import androidx.media3.demo.shortform.PlayerPool
import androidx.media3.demo.shortform.R import androidx.media3.demo.shortform.R
import androidx.media3.exoplayer.DefaultLoadControl import androidx.media3.exoplayer.DefaultLoadControl
import androidx.media3.exoplayer.DefaultRendererCapabilitiesList
import androidx.media3.exoplayer.DefaultRenderersFactory
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.exoplayer.source.preload.DefaultPreloadManager import androidx.media3.exoplayer.source.preload.DefaultPreloadManager
import androidx.media3.exoplayer.source.preload.DefaultPreloadManager.Status.STAGE_LOADED_FOR_DURATION_MS import androidx.media3.exoplayer.source.preload.DefaultPreloadManager.Status.STAGE_LOADED_FOR_DURATION_MS
import androidx.media3.exoplayer.source.preload.TargetPreloadStatusControl import androidx.media3.exoplayer.source.preload.TargetPreloadStatusControl
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlin.math.abs import kotlin.math.abs
@ -46,8 +39,6 @@ class ViewPagerMediaAdapter(
numberOfPlayers: Int, numberOfPlayers: Int,
context: Context, context: Context,
) : RecyclerView.Adapter<ViewPagerMediaHolder>() { ) : RecyclerView.Adapter<ViewPagerMediaHolder>() {
private val playbackThread: HandlerThread =
HandlerThread("playback-thread", Process.THREAD_PRIORITY_AUDIO)
private val preloadManager: DefaultPreloadManager private val preloadManager: DefaultPreloadManager
private val currentMediaItemsAndIndexes: ArrayDeque<Pair<MediaItem, Int>> = ArrayDeque() private val currentMediaItemsAndIndexes: ArrayDeque<Pair<MediaItem, Int>> = ArrayDeque()
private var playerPool: PlayerPool private var playerPool: PlayerPool
@ -64,7 +55,6 @@ class ViewPagerMediaAdapter(
} }
init { init {
playbackThread.start()
val loadControl = val loadControl =
DefaultLoadControl.Builder() DefaultLoadControl.Builder()
.setBufferDurationsMs( .setBufferDurationsMs(
@ -75,29 +65,11 @@ class ViewPagerMediaAdapter(
) )
.setPrioritizeTimeOverSizeThresholds(true) .setPrioritizeTimeOverSizeThresholds(true)
.build() .build()
val renderersFactory = DefaultRenderersFactory(context) val preloadManagerBuilder =
playerPool = DefaultPreloadManager.Builder(context, DefaultPreloadControl()).setLoadControl(loadControl)
PlayerPool( playerPool = PlayerPool(numberOfPlayers, preloadManagerBuilder)
numberOfPlayers,
context,
playbackThread.looper,
loadControl,
renderersFactory,
DefaultBandwidthMeter.getSingletonInstance(context),
)
holderMap = mutableMapOf() holderMap = mutableMapOf()
val trackSelector = DefaultTrackSelector(context) preloadManager = preloadManagerBuilder.build()
trackSelector.init({}, DefaultBandwidthMeter.getSingletonInstance(context))
preloadManager =
DefaultPreloadManager(
DefaultPreloadControl(),
DefaultMediaSourceFactory(context),
trackSelector,
DefaultBandwidthMeter.getSingletonInstance(context),
DefaultRendererCapabilitiesList.Factory(renderersFactory),
loadControl.allocator,
playbackThread.looper,
)
for (i in 0 until MANAGED_ITEM_COUNT) { for (i in 0 until MANAGED_ITEM_COUNT) {
addMediaItem(index = i, isAddingToRightEnd = true) addMediaItem(index = i, isAddingToRightEnd = true)
} }
@ -157,9 +129,8 @@ class ViewPagerMediaAdapter(
} }
fun onDestroy() { fun onDestroy() {
preloadManager.release()
playerPool.destroyPlayers() playerPool.destroyPlayers()
playbackThread.quit() preloadManager.release()
} }
fun onPageSelected(position: Int) { fun onPageSelected(position: Int) {

View File

@ -28,6 +28,7 @@ import androidx.media3.common.util.ListenerSet;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.MediaSource;
import com.google.common.base.Supplier;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -47,15 +48,15 @@ public abstract class BasePreloadManager<T> {
protected final Comparator<T> rankingDataComparator; protected final Comparator<T> rankingDataComparator;
protected final TargetPreloadStatusControl<T> targetPreloadStatusControl; protected final TargetPreloadStatusControl<T> targetPreloadStatusControl;
protected final MediaSource.Factory mediaSourceFactory; protected Supplier<MediaSource.Factory> mediaSourceFactorySupplier;
public BuilderBase( public BuilderBase(
Comparator<T> rankingDataComparator, Comparator<T> rankingDataComparator,
TargetPreloadStatusControl<T> targetPreloadStatusControl, TargetPreloadStatusControl<T> targetPreloadStatusControl,
MediaSource.Factory mediaSourceFactory) { Supplier<MediaSource.Factory> mediaSourceFactorySupplier) {
this.rankingDataComparator = rankingDataComparator; this.rankingDataComparator = rankingDataComparator;
this.targetPreloadStatusControl = targetPreloadStatusControl; this.targetPreloadStatusControl = targetPreloadStatusControl;
this.mediaSourceFactory = mediaSourceFactory; this.mediaSourceFactorySupplier = mediaSourceFactorySupplier;
} }
public abstract BasePreloadManager<T> build(); public abstract BasePreloadManager<T> build();

View File

@ -17,25 +17,38 @@ package androidx.media3.exoplayer.source.preload;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.Math.abs; import static java.lang.Math.abs;
import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.ElementType.TYPE_USE;
import android.content.Context;
import android.os.Looper; import android.os.Looper;
import android.os.Process;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.DefaultLoadControl;
import androidx.media3.exoplayer.DefaultRendererCapabilitiesList;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.Renderer; import androidx.media3.exoplayer.LoadControl;
import androidx.media3.exoplayer.PlaybackLooperProvider;
import androidx.media3.exoplayer.RendererCapabilitiesList; import androidx.media3.exoplayer.RendererCapabilitiesList;
import androidx.media3.exoplayer.RenderersFactory; import androidx.media3.exoplayer.RenderersFactory;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.SampleQueue; import androidx.media3.exoplayer.source.SampleQueue;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
import androidx.media3.exoplayer.trackselection.TrackSelector; import androidx.media3.exoplayer.trackselection.TrackSelector;
import androidx.media3.exoplayer.upstream.Allocator; import androidx.media3.exoplayer.upstream.Allocator;
import androidx.media3.exoplayer.upstream.BandwidthMeter; import androidx.media3.exoplayer.upstream.BandwidthMeter;
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -49,6 +62,211 @@ import java.util.Comparator;
@UnstableApi @UnstableApi
public final class DefaultPreloadManager extends BasePreloadManager<Integer> { public final class DefaultPreloadManager extends BasePreloadManager<Integer> {
/** A builder for {@link DefaultPreloadManager} instances. */
public static final class Builder extends BuilderBase<Integer> {
private final Context context;
private PlaybackLooperProvider preloadLooperProvider;
private TrackSelector.Factory trackSelectorFactory;
private Supplier<BandwidthMeter> bandwidthMeterSupplier;
private Supplier<RenderersFactory> renderersFactorySupplier;
private Supplier<LoadControl> loadControlSupplier;
private boolean buildCalled;
private boolean buildExoPlayerCalled;
/**
* Creates a builder.
*
* @param context A {@link Context}.
* @param targetPreloadStatusControl A {@link TargetPreloadStatusControl<Integer>}.
*/
public Builder(
Context context, TargetPreloadStatusControl<Integer> targetPreloadStatusControl) {
super(
new RankingDataComparator(),
targetPreloadStatusControl,
Suppliers.memoize(() -> new DefaultMediaSourceFactory(context)));
this.context = context;
this.preloadLooperProvider = new PlaybackLooperProvider();
this.trackSelectorFactory = DefaultTrackSelector::new;
this.bandwidthMeterSupplier = () -> DefaultBandwidthMeter.getSingletonInstance(context);
this.renderersFactorySupplier = Suppliers.memoize(() -> new DefaultRenderersFactory(context));
this.loadControlSupplier = Suppliers.memoize(DefaultLoadControl::new);
}
/**
* Sets the {@link MediaSource.Factory} that will be used by the built {@link
* DefaultPreloadManager} and {@link ExoPlayer}.
*
* <p>The default is a {@link DefaultMediaSourceFactory}.
*
* @param mediaSourceFactory A {@link MediaSource.Factory}
* @return This builder.
* @throws IllegalStateException If {@link #build()}, {@link #buildExoPlayer()} or {@link
* #buildExoPlayer(ExoPlayer.Builder)} has already been called.
*/
@CanIgnoreReturnValue
public Builder setMediaSourceFactory(MediaSource.Factory mediaSourceFactory) {
checkState(!buildCalled && !buildExoPlayerCalled);
this.mediaSourceFactorySupplier = () -> mediaSourceFactory;
return this;
}
/**
* Sets the {@link RenderersFactory} that will be used by the built {@link
* DefaultPreloadManager} and {@link ExoPlayer}.
*
* <p>The default is a {@link DefaultRenderersFactory}.
*
* @param renderersFactory A {@link RenderersFactory}.
* @return This builder.
* @throws IllegalStateException If {@link #build()}, {@link #buildExoPlayer()} or {@link
* #buildExoPlayer(ExoPlayer.Builder)} has already been called.
*/
@CanIgnoreReturnValue
public Builder setRenderersFactory(RenderersFactory renderersFactory) {
checkState(!buildCalled && !buildExoPlayerCalled);
this.renderersFactorySupplier = () -> renderersFactory;
return this;
}
/**
* Sets the {@link TrackSelector.Factory} that will be used by the built {@link
* DefaultPreloadManager} and {@link ExoPlayer}.
*
* <p>The default is a {@link TrackSelector.Factory} that always creates a new {@link
* DefaultTrackSelector}.
*
* @param trackSelectorFactory A {@link TrackSelector.Factory}.
* @return This builder.
* @throws IllegalStateException If {@link #build()}, {@link #buildExoPlayer()} or {@link
* #buildExoPlayer(ExoPlayer.Builder)} has already been called.
*/
@CanIgnoreReturnValue
public Builder setTrackSelectorFactory(TrackSelector.Factory trackSelectorFactory) {
checkState(!buildCalled && !buildExoPlayerCalled);
this.trackSelectorFactory = trackSelectorFactory;
return this;
}
/**
* Sets the {@link LoadControl} that will be used by the built {@link DefaultPreloadManager} and
* {@link ExoPlayer}.
*
* <p>The default is a {@link DefaultLoadControl}.
*
* @param loadControl A {@link LoadControl}.
* @return This builder.
* @throws IllegalStateException If {@link #build()}, {@link #buildExoPlayer()} or {@link
* #buildExoPlayer(ExoPlayer.Builder)} has already been called.
*/
@CanIgnoreReturnValue
public Builder setLoadControl(LoadControl loadControl) {
checkState(!buildCalled && !buildExoPlayerCalled);
this.loadControlSupplier = () -> loadControl;
return this;
}
/**
* Sets the {@link BandwidthMeter} that will be used by the built {@link DefaultPreloadManager}
* and {@link ExoPlayer}.
*
* <p>The default is a {@link DefaultBandwidthMeter}.
*
* @param bandwidthMeter A {@link BandwidthMeter}.
* @return This builder.
* @throws IllegalStateException If {@link #build()}, {@link #buildExoPlayer()} or {@link
* #buildExoPlayer(ExoPlayer.Builder)} has already been called.
*/
@CanIgnoreReturnValue
public Builder setBandwidthMeter(BandwidthMeter bandwidthMeter) {
checkState(!buildCalled && !buildExoPlayerCalled);
this.bandwidthMeterSupplier = () -> bandwidthMeter;
return this;
}
/**
* Sets the {@link Looper} that will be used for preload and playback.
*
* <p>The backing thread should run with priority {@link Process#THREAD_PRIORITY_AUDIO} and
* should handle messages within 10ms.
*
* <p>The default is a looper that is associated with a new thread created internally.
*
* @param preloadLooper A {@link Looper}.
* @return This builder.
* @throws IllegalStateException If {@link #build()}, {@link #buildExoPlayer()} or {@link
* #buildExoPlayer(ExoPlayer.Builder)} has already been called.
*/
@CanIgnoreReturnValue
public Builder setPreloadLooper(Looper preloadLooper) {
checkState(!buildCalled && !buildExoPlayerCalled);
this.preloadLooperProvider = new PlaybackLooperProvider(preloadLooper);
return this;
}
/**
* Builds an {@link ExoPlayer}.
*
* <p>See {@link #buildExoPlayer(ExoPlayer.Builder)} for the list of values populated on and
* resulting from this builder that the built {@link ExoPlayer} uses.
*
* <p>For the other configurations than above, the built {@link ExoPlayer} uses the default
* values, see {@link ExoPlayer.Builder#Builder(Context)} for the list of default values.
*
* @return An {@link ExoPlayer} instance.
*/
public ExoPlayer buildExoPlayer() {
return buildExoPlayer(new ExoPlayer.Builder(context));
}
/**
* Builds an {@link ExoPlayer} with an {@link ExoPlayer.Builder} passed in.
*
* <p>The built {@link ExoPlayer} uses the following values populated on and resulting from this
* builder:
*
* <ul>
* <li>{@link #setMediaSourceFactory(MediaSource.Factory) MediaSource.Factory}
* <li>{@link #setRenderersFactory(RenderersFactory) RenderersFactory}
* <li>{@link #setTrackSelectorFactory(TrackSelector.Factory) TrackSelector.Factory}
* <li>{@link #setLoadControl(LoadControl) LoadControl}
* <li>{@link #setBandwidthMeter(BandwidthMeter) BandwidthMeter}
* <li>{@linkplain #setPreloadLooper(Looper)} preload looper}
* </ul>
*
* <p>For the other configurations than above, the built {@link ExoPlayer} uses the values from
* the passed {@link ExoPlayer.Builder}.
*
* @param exoPlayerBuilder An {@link ExoPlayer.Builder} that is used to build the {@link
* ExoPlayer}.
* @return An {@link ExoPlayer} instance.
*/
public ExoPlayer buildExoPlayer(ExoPlayer.Builder exoPlayerBuilder) {
buildExoPlayerCalled = true;
return exoPlayerBuilder
.setMediaSourceFactory(mediaSourceFactorySupplier.get())
.setBandwidthMeter(bandwidthMeterSupplier.get())
.setRenderersFactory(renderersFactorySupplier.get())
.setLoadControl(loadControlSupplier.get())
.setPlaybackLooperProvider(preloadLooperProvider)
.setTrackSelector(trackSelectorFactory.createTrackSelector(context))
.build();
}
/**
* Builds a {@link DefaultPreloadManager} instance.
*
* @throws IllegalStateException If this method has already been called.
*/
@Override
public DefaultPreloadManager build() {
checkState(!buildCalled);
buildCalled = true;
return new DefaultPreloadManager(this);
}
}
/** /**
* An implementation of {@link TargetPreloadStatusControl.PreloadStatus} that describes the * An implementation of {@link TargetPreloadStatusControl.PreloadStatus} that describes the
* preload status of the {@link PreloadMediaSource}. * preload status of the {@link PreloadMediaSource}.
@ -106,30 +324,39 @@ public final class DefaultPreloadManager extends BasePreloadManager<Integer> {
} }
private final RendererCapabilitiesList rendererCapabilitiesList; private final RendererCapabilitiesList rendererCapabilitiesList;
private final TrackSelector trackSelector;
private final PlaybackLooperProvider preloadLooperProvider;
private final PreloadMediaSource.Factory preloadMediaSourceFactory; private final PreloadMediaSource.Factory preloadMediaSourceFactory;
private final boolean deprecatedConstructorCalled;
private DefaultPreloadManager(Builder builder) {
super(
new RankingDataComparator(),
builder.targetPreloadStatusControl,
builder.mediaSourceFactorySupplier.get());
rendererCapabilitiesList =
new DefaultRendererCapabilitiesList.Factory(builder.renderersFactorySupplier.get())
.createRendererCapabilitiesList();
preloadLooperProvider = builder.preloadLooperProvider;
trackSelector = builder.trackSelectorFactory.createTrackSelector(builder.context);
BandwidthMeter bandwidthMeter = builder.bandwidthMeterSupplier.get();
trackSelector.init(() -> {}, bandwidthMeter);
preloadMediaSourceFactory =
new PreloadMediaSource.Factory(
builder.mediaSourceFactorySupplier.get(),
new SourcePreloadControl(),
trackSelector,
bandwidthMeter,
rendererCapabilitiesList.getRendererCapabilities(),
builder.loadControlSupplier.get().getAllocator(),
preloadLooperProvider.obtainLooper());
deprecatedConstructorCalled = false;
}
/** /**
* Constructs a new instance. * @deprecated Use {@link Builder} instead.
*
* @param targetPreloadStatusControl The {@link TargetPreloadStatusControl}.
* @param mediaSourceFactory The {@link MediaSource.Factory}.
* @param trackSelector The {@link TrackSelector}. The instance passed should be {@link
* TrackSelector#init(TrackSelector.InvalidationListener, BandwidthMeter) initialized}.
* @param bandwidthMeter The {@link BandwidthMeter}. It should be the same bandwidth meter of the
* {@link ExoPlayer} that will play the managed {@link PreloadMediaSource}.
* @param rendererCapabilitiesListFactory The {@link RendererCapabilitiesList.Factory}. To make
* preloading work properly, it must create a {@link RendererCapabilitiesList} holding an
* {@linkplain RendererCapabilitiesList#getRendererCapabilities() array of renderer
* capabilities} that matches the {@linkplain ExoPlayer#getRendererCount() count} and the
* {@linkplain ExoPlayer#getRendererType(int) renderer types} of the array of {@linkplain
* Renderer renderers} created by the {@link RenderersFactory} used by the {@link ExoPlayer}
* that will play the managed {@link PreloadMediaSource}.
* @param allocator The {@link Allocator}. It should be the same allocator of the {@link
* ExoPlayer} that will play the managed {@link PreloadMediaSource}.
* @param preloadLooper The {@link Looper} that will be used for preloading. It should be the same
* playback looper of the {@link ExoPlayer} that will play the managed {@link
* PreloadMediaSource}.
*/ */
@Deprecated
public DefaultPreloadManager( public DefaultPreloadManager(
TargetPreloadStatusControl<Integer> targetPreloadStatusControl, TargetPreloadStatusControl<Integer> targetPreloadStatusControl,
MediaSource.Factory mediaSourceFactory, MediaSource.Factory mediaSourceFactory,
@ -141,6 +368,8 @@ public final class DefaultPreloadManager extends BasePreloadManager<Integer> {
super(new RankingDataComparator(), targetPreloadStatusControl, mediaSourceFactory); super(new RankingDataComparator(), targetPreloadStatusControl, mediaSourceFactory);
this.rendererCapabilitiesList = this.rendererCapabilitiesList =
rendererCapabilitiesListFactory.createRendererCapabilitiesList(); rendererCapabilitiesListFactory.createRendererCapabilitiesList();
this.preloadLooperProvider = new PlaybackLooperProvider(preloadLooper);
this.trackSelector = trackSelector;
preloadMediaSourceFactory = preloadMediaSourceFactory =
new PreloadMediaSource.Factory( new PreloadMediaSource.Factory(
mediaSourceFactory, mediaSourceFactory,
@ -149,7 +378,8 @@ public final class DefaultPreloadManager extends BasePreloadManager<Integer> {
bandwidthMeter, bandwidthMeter,
rendererCapabilitiesList.getRendererCapabilities(), rendererCapabilitiesList.getRendererCapabilities(),
allocator, allocator,
preloadLooper); preloadLooperProvider.obtainLooper());
deprecatedConstructorCalled = true;
} }
/** /**
@ -189,6 +419,12 @@ public final class DefaultPreloadManager extends BasePreloadManager<Integer> {
@Override @Override
protected void releaseInternal() { protected void releaseInternal() {
rendererCapabilitiesList.release(); rendererCapabilitiesList.release();
preloadLooperProvider.releaseLooper();
if (!deprecatedConstructorCalled) {
// TODO: Remove the property deprecatedConstructorCalled and release the TrackSelector anyway
// after the deprecated constructor is removed.
trackSelector.release();
}
} }
private static final class RankingDataComparator implements Comparator<Integer> { private static final class RankingDataComparator implements Comparator<Integer> {

View File

@ -17,6 +17,7 @@ package androidx.media3.exoplayer.trackselection;
import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Assertions.checkStateNotNull;
import android.content.Context;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.AudioAttributes; import androidx.media3.common.AudioAttributes;
@ -94,6 +95,21 @@ import androidx.media3.exoplayer.upstream.BandwidthMeter;
@UnstableApi @UnstableApi
public abstract class TrackSelector { public abstract class TrackSelector {
/**
* Factory for creating {@linkplain TrackSelector track selectors} from {@linkplain Context
* contexts}.
*/
public interface Factory {
/**
* Creates a new {@link TrackSelector} with the specified {@link Context}.
*
* @param context The context.
* @return The new {@linkplain TrackSelector track selector}.
*/
TrackSelector createTrackSelector(Context context);
}
/** Notified when selections previously made by a {@link TrackSelector} are no longer valid. */ /** Notified when selections previously made by a {@link TrackSelector} are no longer valid. */
public interface InvalidationListener { public interface InvalidationListener {

View File

@ -39,9 +39,7 @@ import androidx.media3.common.util.SystemClock;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.datasource.DefaultDataSource; import androidx.media3.datasource.DefaultDataSource;
import androidx.media3.datasource.TransferListener; import androidx.media3.datasource.TransferListener;
import androidx.media3.exoplayer.DefaultRendererCapabilitiesList;
import androidx.media3.exoplayer.Renderer; import androidx.media3.exoplayer.Renderer;
import androidx.media3.exoplayer.RendererCapabilitiesList;
import androidx.media3.exoplayer.RenderersFactory; import androidx.media3.exoplayer.RenderersFactory;
import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.drm.DrmSessionEventListener; import androidx.media3.exoplayer.drm.DrmSessionEventListener;
@ -53,11 +51,7 @@ import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.MediaSourceEventListener; import androidx.media3.exoplayer.source.MediaSourceEventListener;
import androidx.media3.exoplayer.source.ProgressiveMediaSource; import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.exoplayer.source.TrackGroupArray; import androidx.media3.exoplayer.source.TrackGroupArray;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
import androidx.media3.exoplayer.trackselection.TrackSelector;
import androidx.media3.exoplayer.upstream.Allocator; import androidx.media3.exoplayer.upstream.Allocator;
import androidx.media3.exoplayer.upstream.BandwidthMeter;
import androidx.media3.exoplayer.upstream.DefaultAllocator;
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter; import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter;
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy; import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
import androidx.media3.test.utils.FakeAudioRenderer; import androidx.media3.test.utils.FakeAudioRenderer;
@ -84,19 +78,14 @@ import org.mockito.Mock;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class DefaultPreloadManagerTest { public class DefaultPreloadManagerTest {
private Context context;
@Mock private TargetPreloadStatusControl<Integer> mockTargetPreloadStatusControl; @Mock private TargetPreloadStatusControl<Integer> mockTargetPreloadStatusControl;
private TrackSelector trackSelector; private RenderersFactory renderersFactory;
private Allocator allocator;
private BandwidthMeter bandwidthMeter;
private RendererCapabilitiesList.Factory rendererCapabilitiesListFactory;
@Before @Before
public void setUp() { public void setUp() {
trackSelector = new DefaultTrackSelector(ApplicationProvider.getApplicationContext()); context = ApplicationProvider.getApplicationContext();
allocator = new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE); renderersFactory =
bandwidthMeter =
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
RenderersFactory renderersFactory =
(handler, videoListener, audioListener, textOutput, metadataOutput) -> (handler, videoListener, audioListener, textOutput, metadataOutput) ->
new Renderer[] { new Renderer[] {
new FakeVideoRenderer( new FakeVideoRenderer(
@ -106,21 +95,15 @@ public class DefaultPreloadManagerTest {
SystemClock.DEFAULT.createHandler(handler.getLooper(), /* callback= */ null), SystemClock.DEFAULT.createHandler(handler.getLooper(), /* callback= */ null),
audioListener) audioListener)
}; };
rendererCapabilitiesListFactory = new DefaultRendererCapabilitiesList.Factory(renderersFactory);
trackSelector.init(/* listener= */ () -> {}, bandwidthMeter);
} }
@Test @Test
public void addByMediaItems_getCorrectCountAndSources() { public void addByMediaItems_getCorrectCountAndSources() {
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, mockTargetPreloadStatusControl)
mockTargetPreloadStatusControl, .setRenderersFactory(renderersFactory)
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext()), .setPreloadLooper(Util.getCurrentOrMainLooper())
trackSelector, .build();
bandwidthMeter,
rendererCapabilitiesListFactory,
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem1 = MediaItem mediaItem1 =
mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build(); mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build();
@ -138,14 +121,10 @@ public class DefaultPreloadManagerTest {
@Test @Test
public void addByMediaSources_getCorrectCountAndSources() { public void addByMediaSources_getCorrectCountAndSources() {
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, mockTargetPreloadStatusControl)
mockTargetPreloadStatusControl, .setRenderersFactory(renderersFactory)
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext()), .setPreloadLooper(Util.getCurrentOrMainLooper())
trackSelector, .build();
bandwidthMeter,
rendererCapabilitiesListFactory,
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem1 = MediaItem mediaItem1 =
mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build(); mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build();
@ -167,14 +146,10 @@ public class DefaultPreloadManagerTest {
@Test @Test
public void getMediaSourceForMediaItemNotAdded() { public void getMediaSourceForMediaItemNotAdded() {
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, mockTargetPreloadStatusControl)
mockTargetPreloadStatusControl, .setRenderersFactory(renderersFactory)
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext()), .setPreloadLooper(Util.getCurrentOrMainLooper())
trackSelector, .build();
bandwidthMeter,
rendererCapabilitiesListFactory,
allocator,
Util.getCurrentOrMainLooper());
MediaItem mediaItem = MediaItem mediaItem =
new MediaItem.Builder() new MediaItem.Builder()
.setMediaId("mediaId1") .setMediaId("mediaId1")
@ -206,14 +181,11 @@ public class DefaultPreloadManagerTest {
HandlerThread preloadThread = new HandlerThread("preload"); HandlerThread preloadThread = new HandlerThread("preload");
preloadThread.start(); preloadThread.start();
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mediaSourceFactory)
mediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(preloadThread.getLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
preloadThread.getLooper());
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener(); TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
preloadManager.addListener(preloadManagerListener); preloadManager.addListener(preloadManagerListener);
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
@ -268,14 +240,11 @@ public class DefaultPreloadManagerTest {
HandlerThread preloadThread = new HandlerThread("preload"); HandlerThread preloadThread = new HandlerThread("preload");
preloadThread.start(); preloadThread.start();
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mediaSourceFactory)
mediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(preloadThread.getLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
preloadThread.getLooper());
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener(); TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
preloadManager.addListener(preloadManagerListener); preloadManager.addListener(preloadManagerListener);
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
@ -325,14 +294,11 @@ public class DefaultPreloadManagerTest {
HandlerThread preloadThread = new HandlerThread("preload"); HandlerThread preloadThread = new HandlerThread("preload");
preloadThread.start(); preloadThread.start();
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(fakeMediaSourceFactory)
fakeMediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(preloadThread.getLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
preloadThread.getLooper());
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener(); TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
preloadManager.addListener(preloadManagerListener); preloadManager.addListener(preloadManagerListener);
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
@ -352,7 +318,9 @@ public class DefaultPreloadManagerTest {
PreloadMediaSource preloadMediaSource0 = PreloadMediaSource preloadMediaSource0 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem0); (PreloadMediaSource) preloadManager.getMediaSource(mediaItem0);
preloadMediaSource0.prepareSource( preloadMediaSource0.prepareSource(
(source, timeline) -> {}, bandwidthMeter.getTransferListener(), PlayerId.UNSET); (source, timeline) -> {},
DefaultBandwidthMeter.getSingletonInstance(context).getTransferListener(),
PlayerId.UNSET);
wrappedMediaSource0.setAllowPreparation(true); wrappedMediaSource0.setAllowPreparation(true);
wrappedMediaSource1.setAllowPreparation(true); wrappedMediaSource1.setAllowPreparation(true);
shadowOf(preloadThread.getLooper()).idle(); shadowOf(preloadThread.getLooper()).idle();
@ -377,14 +345,11 @@ public class DefaultPreloadManagerTest {
HandlerThread preloadThread = new HandlerThread("preload"); HandlerThread preloadThread = new HandlerThread("preload");
preloadThread.start(); preloadThread.start();
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(fakeMediaSourceFactory)
fakeMediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(preloadThread.getLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
preloadThread.getLooper());
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener(); TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
preloadManager.addListener(preloadManagerListener); preloadManager.addListener(preloadManagerListener);
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
@ -451,14 +416,11 @@ public class DefaultPreloadManagerTest {
HandlerThread preloadThread = new HandlerThread("preload"); HandlerThread preloadThread = new HandlerThread("preload");
preloadThread.start(); preloadThread.start();
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mediaSourceFactory)
mediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(preloadThread.getLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
preloadThread.getLooper());
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener(); TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
preloadManager.addListener(preloadManagerListener); preloadManager.addListener(preloadManagerListener);
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
@ -549,14 +511,11 @@ public class DefaultPreloadManagerTest {
HandlerThread preloadThread = new HandlerThread("preload"); HandlerThread preloadThread = new HandlerThread("preload");
preloadThread.start(); preloadThread.start();
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mediaSourceFactory)
mediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(preloadThread.getLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
preloadThread.getLooper());
TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener(); TestPreloadManagerListener preloadManagerListener = new TestPreloadManagerListener();
preloadManager.addListener(preloadManagerListener); preloadManager.addListener(preloadManagerListener);
preloadManager.add(mediaItem0, /* rankingData= */ 0); preloadManager.add(mediaItem0, /* rankingData= */ 0);
@ -633,14 +592,11 @@ public class DefaultPreloadManagerTest {
}; };
}); });
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mockMediaSourceFactory)
mockMediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(Util.getCurrentOrMainLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem0 = MediaItem mediaItem0 =
mediaItemBuilder mediaItemBuilder
@ -685,7 +641,9 @@ public class DefaultPreloadManagerTest {
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem4); (PreloadMediaSource) preloadManager.getMediaSource(mediaItem4);
// Simulate that preloadMediaSource4 is using by the player. // Simulate that preloadMediaSource4 is using by the player.
preloadMediaSource4.prepareSource( preloadMediaSource4.prepareSource(
(source, timeline) -> {}, bandwidthMeter.getTransferListener(), PlayerId.UNSET); (source, timeline) -> {},
DefaultBandwidthMeter.getSingletonInstance(context).getTransferListener(),
PlayerId.UNSET);
currentPlayingIndex.set(4); currentPlayingIndex.set(4);
preloadManager.setCurrentPlayingIndex(4); preloadManager.setCurrentPlayingIndex(4);
@ -706,14 +664,11 @@ public class DefaultPreloadManagerTest {
rankingData -> new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED); rankingData -> new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED);
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mockMediaSourceFactory)
mockMediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(Util.getCurrentOrMainLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem1 = MediaItem mediaItem1 =
mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build(); mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build();
@ -757,14 +712,11 @@ public class DefaultPreloadManagerTest {
rankingData -> new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED); rankingData -> new DefaultPreloadManager.Status(STAGE_SOURCE_PREPARED);
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mockMediaSourceFactory)
mockMediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(Util.getCurrentOrMainLooper())
bandwidthMeter, .build();
rendererCapabilitiesListFactory,
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem1 = MediaItem mediaItem1 =
mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build(); mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build();
@ -834,14 +786,11 @@ public class DefaultPreloadManagerTest {
return underlyingRenderers.toArray(new Renderer[2]); return underlyingRenderers.toArray(new Renderer[2]);
}; };
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mockMediaSourceFactory)
mockMediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(Util.getCurrentOrMainLooper())
bandwidthMeter, .build();
new DefaultRendererCapabilitiesList.Factory(renderersFactory),
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem1 = MediaItem mediaItem1 =
mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build(); mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build();
@ -905,14 +854,11 @@ public class DefaultPreloadManagerTest {
return underlyingRenderers.toArray(new Renderer[2]); return underlyingRenderers.toArray(new Renderer[2]);
}; };
DefaultPreloadManager preloadManager = DefaultPreloadManager preloadManager =
new DefaultPreloadManager( new DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
targetPreloadStatusControl, .setMediaSourceFactory(mockMediaSourceFactory)
mockMediaSourceFactory, .setRenderersFactory(renderersFactory)
trackSelector, .setPreloadLooper(Util.getCurrentOrMainLooper())
bandwidthMeter, .build();
new DefaultRendererCapabilitiesList.Factory(renderersFactory),
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder(); MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem1 = MediaItem mediaItem1 =
mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build(); mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build();