mirror of
https://github.com/androidx/media.git
synced 2025-04-29 14:26:50 +08:00
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:
parent
337e59e733
commit
98dc7f2def
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
|
@ -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> {
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user