Simplify MediaSourceList setup and make class final.
The class was only non-final to allow mocking. Using the real class in the test works equally well. PiperOrigin-RevId: 317858805
This commit is contained in:
parent
093f9931b4
commit
9d8f54ab3a
@ -186,10 +186,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
internalPlaybackThread.start();
|
||||
handler = clock.createHandler(internalPlaybackThread.getLooper(), this);
|
||||
deliverPendingMessageAtStartPositionRequired = true;
|
||||
mediaSourceList = new MediaSourceList(this);
|
||||
if (analyticsCollector != null) {
|
||||
mediaSourceList.setAnalyticsCollector(eventHandler, analyticsCollector);
|
||||
}
|
||||
mediaSourceList = new MediaSourceList(/* listener= */ this, analyticsCollector, eventHandler);
|
||||
}
|
||||
|
||||
public void experimental_setReleaseTimeoutMs(long releaseTimeoutMs) {
|
||||
|
@ -52,7 +52,7 @@ import java.util.Set;
|
||||
*
|
||||
* <p>With the exception of the constructor, all methods are called on the playback thread.
|
||||
*/
|
||||
/* package */ class MediaSourceList {
|
||||
/* package */ final class MediaSourceList {
|
||||
|
||||
/** Listener for source events. */
|
||||
public interface MediaSourceListInfoRefreshListener {
|
||||
@ -81,8 +81,20 @@ import java.util.Set;
|
||||
|
||||
@Nullable private TransferListener mediaTransferListener;
|
||||
|
||||
@SuppressWarnings("initialization")
|
||||
public MediaSourceList(MediaSourceListInfoRefreshListener listener) {
|
||||
/**
|
||||
* Creates the media source list.
|
||||
*
|
||||
* @param listener The {@link MediaSourceListInfoRefreshListener} to be informed of timeline
|
||||
* changes.
|
||||
* @param analyticsCollector An optional {@link AnalyticsCollector} to be registered for media
|
||||
* source events.
|
||||
* @param analyticsCollectorHandler The {@link Handler} to call {@link AnalyticsCollector} methods
|
||||
* on.
|
||||
*/
|
||||
public MediaSourceList(
|
||||
MediaSourceListInfoRefreshListener listener,
|
||||
@Nullable AnalyticsCollector analyticsCollector,
|
||||
Handler analyticsCollectorHandler) {
|
||||
mediaSourceListInfoListener = listener;
|
||||
shuffleOrder = new DefaultShuffleOrder(0);
|
||||
mediaSourceByMediaPeriod = new IdentityHashMap<>();
|
||||
@ -91,6 +103,12 @@ import java.util.Set;
|
||||
eventDispatcher = new MediaSourceEventListener.EventDispatcher();
|
||||
childSources = new HashMap<>();
|
||||
enabledMediaSourceHolders = new HashSet<>();
|
||||
if (analyticsCollector != null) {
|
||||
eventDispatcher.addEventListener(
|
||||
analyticsCollectorHandler, analyticsCollector, MediaSourceEventListener.class);
|
||||
eventDispatcher.addEventListener(
|
||||
analyticsCollectorHandler, analyticsCollector, DrmSessionEventListener.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,8 +118,7 @@ import java.util.Set;
|
||||
* @param shuffleOrder The new shuffle order.
|
||||
* @return The new {@link Timeline}.
|
||||
*/
|
||||
public final Timeline setMediaSources(
|
||||
List<MediaSourceHolder> holders, ShuffleOrder shuffleOrder) {
|
||||
public Timeline setMediaSources(List<MediaSourceHolder> holders, ShuffleOrder shuffleOrder) {
|
||||
removeMediaSourcesInternal(/* fromIndex= */ 0, /* toIndex= */ mediaSourceHolders.size());
|
||||
return addMediaSources(/* index= */ this.mediaSourceHolders.size(), holders, shuffleOrder);
|
||||
}
|
||||
@ -115,7 +132,7 @@ import java.util.Set;
|
||||
* @param shuffleOrder The new shuffle order.
|
||||
* @return The new {@link Timeline}.
|
||||
*/
|
||||
public final Timeline addMediaSources(
|
||||
public Timeline addMediaSources(
|
||||
int index, List<MediaSourceHolder> holders, ShuffleOrder shuffleOrder) {
|
||||
if (!holders.isEmpty()) {
|
||||
this.shuffleOrder = shuffleOrder;
|
||||
@ -165,8 +182,7 @@ import java.util.Set;
|
||||
* @throws IllegalArgumentException When the range is malformed, i.e. {@code fromIndex} < 0,
|
||||
* {@code toIndex} > {@link #getSize()}, {@code fromIndex} > {@code toIndex}
|
||||
*/
|
||||
public final Timeline removeMediaSourceRange(
|
||||
int fromIndex, int toIndex, ShuffleOrder shuffleOrder) {
|
||||
public Timeline removeMediaSourceRange(int fromIndex, int toIndex, ShuffleOrder shuffleOrder) {
|
||||
Assertions.checkArgument(fromIndex >= 0 && fromIndex <= toIndex && toIndex <= getSize());
|
||||
this.shuffleOrder = shuffleOrder;
|
||||
removeMediaSourcesInternal(fromIndex, toIndex);
|
||||
@ -185,7 +201,7 @@ import java.util.Set;
|
||||
* @throws IllegalArgumentException When an index is invalid, i.e. {@code currentIndex} < 0,
|
||||
* {@code currentIndex} >= {@link #getSize()}, {@code newIndex} < 0
|
||||
*/
|
||||
public final Timeline moveMediaSource(int currentIndex, int newIndex, ShuffleOrder shuffleOrder) {
|
||||
public Timeline moveMediaSource(int currentIndex, int newIndex, ShuffleOrder shuffleOrder) {
|
||||
return moveMediaSourceRange(currentIndex, currentIndex + 1, newIndex, shuffleOrder);
|
||||
}
|
||||
|
||||
@ -228,39 +244,28 @@ import java.util.Set;
|
||||
}
|
||||
|
||||
/** Clears the playlist. */
|
||||
public final Timeline clear(@Nullable ShuffleOrder shuffleOrder) {
|
||||
public Timeline clear(@Nullable ShuffleOrder shuffleOrder) {
|
||||
this.shuffleOrder = shuffleOrder != null ? shuffleOrder : this.shuffleOrder.cloneAndClear();
|
||||
removeMediaSourcesInternal(/* fromIndex= */ 0, /* toIndex= */ getSize());
|
||||
return createTimeline();
|
||||
}
|
||||
|
||||
/** Whether the playlist is prepared. */
|
||||
public final boolean isPrepared() {
|
||||
public boolean isPrepared() {
|
||||
return isPrepared;
|
||||
}
|
||||
|
||||
/** Returns the number of media sources in the playlist. */
|
||||
public final int getSize() {
|
||||
public int getSize() {
|
||||
return mediaSourceHolders.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AnalyticsCollector}.
|
||||
*
|
||||
* @param handler The handler on which to call the collector.
|
||||
* @param analyticsCollector The analytics collector.
|
||||
*/
|
||||
public final void setAnalyticsCollector(Handler handler, AnalyticsCollector analyticsCollector) {
|
||||
eventDispatcher.addEventListener(handler, analyticsCollector, MediaSourceEventListener.class);
|
||||
eventDispatcher.addEventListener(handler, analyticsCollector, DrmSessionEventListener.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new shuffle order to use when shuffling the child media sources.
|
||||
*
|
||||
* @param shuffleOrder A {@link ShuffleOrder}.
|
||||
*/
|
||||
public final Timeline setShuffleOrder(ShuffleOrder shuffleOrder) {
|
||||
public Timeline setShuffleOrder(ShuffleOrder shuffleOrder) {
|
||||
int size = getSize();
|
||||
if (shuffleOrder.getLength() != size) {
|
||||
shuffleOrder =
|
||||
@ -273,7 +278,7 @@ import java.util.Set;
|
||||
}
|
||||
|
||||
/** Prepares the playlist. */
|
||||
public final void prepare(@Nullable TransferListener mediaTransferListener) {
|
||||
public void prepare(@Nullable TransferListener mediaTransferListener) {
|
||||
Assertions.checkState(!isPrepared);
|
||||
this.mediaTransferListener = mediaTransferListener;
|
||||
for (int i = 0; i < mediaSourceHolders.size(); i++) {
|
||||
@ -312,7 +317,7 @@ import java.util.Set;
|
||||
*
|
||||
* @param mediaPeriod The period to release.
|
||||
*/
|
||||
public final void releasePeriod(MediaPeriod mediaPeriod) {
|
||||
public void releasePeriod(MediaPeriod mediaPeriod) {
|
||||
MediaSourceHolder holder =
|
||||
Assertions.checkNotNull(mediaSourceByMediaPeriod.remove(mediaPeriod));
|
||||
holder.mediaSource.releasePeriod(mediaPeriod);
|
||||
@ -324,7 +329,7 @@ import java.util.Set;
|
||||
}
|
||||
|
||||
/** Releases the playlist. */
|
||||
public final void release() {
|
||||
public void release() {
|
||||
for (MediaSourceAndListener childSource : childSources.values()) {
|
||||
try {
|
||||
childSource.mediaSource.releaseSource(childSource.caller);
|
||||
@ -340,14 +345,14 @@ import java.util.Set;
|
||||
}
|
||||
|
||||
/** Throws any pending error encountered while loading or refreshing. */
|
||||
public final void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||
for (MediaSourceAndListener childSource : childSources.values()) {
|
||||
childSource.mediaSource.maybeThrowSourceInfoRefreshError();
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a timeline reflecting the current state of the playlist. */
|
||||
public final Timeline createTimeline() {
|
||||
public Timeline createTimeline() {
|
||||
if (mediaSourceHolders.isEmpty()) {
|
||||
return Timeline.EMPTY;
|
||||
}
|
||||
|
@ -23,18 +23,19 @@ import static org.robolectric.annotation.LooperMode.Mode.LEGACY;
|
||||
import android.net.Uri;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||
import com.google.android.exoplayer2.source.ShuffleOrder;
|
||||
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
||||
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
||||
import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline;
|
||||
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
||||
import com.google.android.exoplayer2.testutil.FakeShuffleOrder;
|
||||
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
||||
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import java.util.Collections;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -70,12 +71,15 @@ public final class MediaPeriodQueueTest {
|
||||
private Allocator allocator;
|
||||
private MediaSourceList mediaSourceList;
|
||||
private FakeMediaSource fakeMediaSource;
|
||||
private MediaSourceList.MediaSourceHolder mediaSourceHolder;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mediaPeriodQueue = new MediaPeriodQueue();
|
||||
mediaSourceList = mock(MediaSourceList.class);
|
||||
mediaSourceList =
|
||||
new MediaSourceList(
|
||||
mock(MediaSourceList.MediaSourceListInfoRefreshListener.class),
|
||||
/* analyticsCollector= */ null,
|
||||
Util.createHandlerForCurrentOrMainLooper());
|
||||
rendererCapabilities = new RendererCapabilities[0];
|
||||
trackSelector = mock(TrackSelector.class);
|
||||
allocator = mock(Allocator.class);
|
||||
@ -408,10 +412,13 @@ public final class MediaPeriodQueueTest {
|
||||
|
||||
private void setupTimeline(Timeline timeline) {
|
||||
fakeMediaSource = new FakeMediaSource(timeline);
|
||||
mediaSourceHolder = new MediaSourceList.MediaSourceHolder(fakeMediaSource, false);
|
||||
MediaSourceList.MediaSourceHolder mediaSourceHolder =
|
||||
new MediaSourceList.MediaSourceHolder(fakeMediaSource, /* useLazyPreparation= */ false);
|
||||
mediaSourceList.setMediaSources(
|
||||
ImmutableList.of(mediaSourceHolder), new FakeShuffleOrder(/* length= */ 1));
|
||||
mediaSourceHolder.mediaSource.prepareSourceInternal(/* mediaTransferListener */ null);
|
||||
|
||||
Timeline playlistTimeline = createPlaylistTimeline();
|
||||
Timeline playlistTimeline = mediaSourceList.createTimeline();
|
||||
firstPeriodUid = playlistTimeline.getUidOfPeriod(/* periodIndex= */ 0);
|
||||
|
||||
playbackInfo =
|
||||
@ -443,13 +450,7 @@ public final class MediaPeriodQueueTest {
|
||||
SinglePeriodAdTimeline adTimeline =
|
||||
new SinglePeriodAdTimeline(CONTENT_TIMELINE, adPlaybackState);
|
||||
fakeMediaSource.setNewSourceInfo(adTimeline);
|
||||
playbackInfo = playbackInfo.copyWithTimeline(createPlaylistTimeline());
|
||||
}
|
||||
|
||||
private MediaSourceList.PlaylistTimeline createPlaylistTimeline() {
|
||||
return new MediaSourceList.PlaylistTimeline(
|
||||
Collections.singleton(mediaSourceHolder),
|
||||
new ShuffleOrder.DefaultShuffleOrder(/* length= */ 1));
|
||||
playbackInfo = playbackInfo.copyWithTimeline(mediaSourceList.createTimeline());
|
||||
}
|
||||
|
||||
private void advance() {
|
||||
|
@ -31,6 +31,7 @@ import com.google.android.exoplayer2.source.ShuffleOrder;
|
||||
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
||||
import com.google.android.exoplayer2.testutil.FakeShuffleOrder;
|
||||
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -51,7 +52,10 @@ public class MediaSourceListTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
mediaSourceList =
|
||||
new MediaSourceList(mock(MediaSourceList.MediaSourceListInfoRefreshListener.class));
|
||||
new MediaSourceList(
|
||||
mock(MediaSourceList.MediaSourceListInfoRefreshListener.class),
|
||||
/* analyticsCollector= */ null,
|
||||
Util.createHandlerForCurrentOrMainLooper());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user