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