Inform DefaultPreloadManager when player uses PreloadMediaSource

Add a new method `onUsedByPlayer(PreloadMediaSource)` for `PreloadMediaSource.PreloadControl`, which will be invoked when the player starts to use the `PreloadMediaSource`, or calling `PreloadMediaSource.preload` while the player is already using that source. `DefaultPreloadManager` will immediately preload the next source when receiving `onUsedByPlayer` event.

PiperOrigin-RevId: 616789121
This commit is contained in:
tianyifeng 2024-03-18 04:52:04 -07:00 committed by Copybara-Service
parent 87f4a3ca71
commit 2c8d07c2dd
6 changed files with 172 additions and 16 deletions

View File

@ -26,7 +26,6 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.common.util.Util import androidx.media3.common.util.Util
import androidx.media3.exoplayer.RendererCapabilities import androidx.media3.exoplayer.RendererCapabilities
import androidx.media3.exoplayer.RenderersFactory import androidx.media3.exoplayer.RenderersFactory
import androidx.media3.exoplayer.analytics.PlayerId
import androidx.media3.exoplayer.audio.AudioRendererEventListener import androidx.media3.exoplayer.audio.AudioRendererEventListener
import androidx.media3.exoplayer.source.MediaSource import androidx.media3.exoplayer.source.MediaSource
import androidx.media3.exoplayer.source.preload.PreloadMediaSource import androidx.media3.exoplayer.source.preload.PreloadMediaSource
@ -61,7 +60,7 @@ class MediaSourceManager(
bandwidthMeter, bandwidthMeter,
getRendererCapabilities(renderersFactory = renderersFactory), getRendererCapabilities(renderersFactory = renderersFactory),
allocator, allocator,
preloadLooper preloadLooper,
) )
} }
@ -104,7 +103,7 @@ class MediaSourceManager(
Util.createHandlerForCurrentOrMainLooper(), Util.createHandlerForCurrentOrMainLooper(),
object : VideoRendererEventListener {}, object : VideoRendererEventListener {},
object : AudioRendererEventListener {}, object : AudioRendererEventListener {},
{ _: CueGroup? -> } { _: CueGroup? -> },
) { _: Metadata -> ) { _: Metadata ->
} }
val capabilities = ArrayList<RendererCapabilities>() val capabilities = ArrayList<RendererCapabilities>()
@ -131,9 +130,14 @@ class MediaSourceManager(
override fun onContinueLoadingRequested( override fun onContinueLoadingRequested(
mediaSource: PreloadMediaSource, mediaSource: PreloadMediaSource,
bufferedPositionUs: Long bufferedPositionUs: Long,
): Boolean { ): Boolean {
return bufferedPositionUs < targetPreloadPositionUs return bufferedPositionUs < targetPreloadPositionUs
} }
override fun onUsedByPlayer(mediaSource: PreloadMediaSource) {
// Implementation is no-op until the whole class is removed with the adoption of
// DefaultPreloadManager.
}
} }
} }

View File

@ -171,10 +171,6 @@ public final class DefaultPreloadManager extends BasePreloadManager<Integer> {
protected void preloadSourceInternal(MediaSource mediaSource, long startPositionsUs) { protected void preloadSourceInternal(MediaSource mediaSource, long startPositionsUs) {
checkArgument(mediaSource instanceof PreloadMediaSource); checkArgument(mediaSource instanceof PreloadMediaSource);
PreloadMediaSource preloadMediaSource = (PreloadMediaSource) mediaSource; PreloadMediaSource preloadMediaSource = (PreloadMediaSource) mediaSource;
if (preloadMediaSource.isUsedByPlayer()) {
onPreloadCompleted(preloadMediaSource);
return;
}
preloadMediaSource.preload(startPositionsUs); preloadMediaSource.preload(startPositionsUs);
} }
@ -227,6 +223,11 @@ public final class DefaultPreloadManager extends BasePreloadManager<Integer> {
&& status.getValue() > Util.usToMs(bufferedPositionUs))); && status.getValue() > Util.usToMs(bufferedPositionUs)));
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
onPreloadCompleted(mediaSource);
}
private boolean continueOrCompletePreloading( private boolean continueOrCompletePreloading(
MediaSource mediaSource, Predicate<Status> continueLoadingPredicate) { MediaSource mediaSource, Predicate<Status> continueLoadingPredicate) {
@Nullable @Nullable

View File

@ -86,6 +86,13 @@ public final class PreloadMediaSource extends WrappingMediaSource {
* data is buffered, or {@link C#TIME_END_OF_SOURCE} if the track is fully buffered. * data is buffered, or {@link C#TIME_END_OF_SOURCE} if the track is fully buffered.
*/ */
boolean onContinueLoadingRequested(PreloadMediaSource mediaSource, long bufferedPositionUs); boolean onContinueLoadingRequested(PreloadMediaSource mediaSource, long bufferedPositionUs);
/**
* Called from {@link PreloadMediaSource} when the player starts using this source.
*
* @param mediaSource The {@link PreloadMediaSource} that the player starts using.
*/
void onUsedByPlayer(PreloadMediaSource mediaSource);
} }
/** Factory for {@link PreloadMediaSource}. */ /** Factory for {@link PreloadMediaSource}. */
@ -197,6 +204,7 @@ public final class PreloadMediaSource extends WrappingMediaSource {
@Nullable private Timeline timeline; @Nullable private Timeline timeline;
@Nullable private Pair<PreloadMediaPeriod, MediaPeriodKey> preloadingMediaPeriodAndKey; @Nullable private Pair<PreloadMediaPeriod, MediaPeriodKey> preloadingMediaPeriodAndKey;
@Nullable private Pair<PreloadMediaPeriod, MediaPeriodId> playingPreloadedMediaPeriodAndId; @Nullable private Pair<PreloadMediaPeriod, MediaPeriodId> playingPreloadedMediaPeriodAndId;
private boolean onUsedByPlayerNotified;
private PreloadMediaSource( private PreloadMediaSource(
MediaSource mediaSource, MediaSource mediaSource,
@ -230,7 +238,9 @@ public final class PreloadMediaSource extends WrappingMediaSource {
() -> { () -> {
preloadCalled = true; preloadCalled = true;
this.startPositionUs = startPositionUs; this.startPositionUs = startPositionUs;
if (!isUsedByPlayer()) { if (isUsedByPlayer()) {
notifyOnUsedByPlayer();
} else {
setPlayerId(PlayerId.UNSET); // Set to PlayerId.UNSET as there is no ongoing playback. setPlayerId(PlayerId.UNSET); // Set to PlayerId.UNSET as there is no ongoing playback.
prepareSourceInternal(bandwidthMeter.getTransferListener()); prepareSourceInternal(bandwidthMeter.getTransferListener());
} }
@ -239,6 +249,9 @@ public final class PreloadMediaSource extends WrappingMediaSource {
@Override @Override
protected void prepareSourceInternal() { protected void prepareSourceInternal() {
if (isUsedByPlayer() && !onUsedByPlayerNotified) {
notifyOnUsedByPlayer();
}
if (timeline != null) { if (timeline != null) {
onChildSourceInfoRefreshed(timeline); onChildSourceInfoRefreshed(timeline);
} else if (!prepareChildSourceCalled) { } else if (!prepareChildSourceCalled) {
@ -318,10 +331,13 @@ public final class PreloadMediaSource extends WrappingMediaSource {
@Override @Override
protected void releaseSourceInternal() { protected void releaseSourceInternal() {
if (!preloadCalled && !isUsedByPlayer()) { if (!isUsedByPlayer()) {
timeline = null; onUsedByPlayerNotified = false;
prepareChildSourceCalled = false; if (!preloadCalled) {
super.releaseSourceInternal(); timeline = null;
prepareChildSourceCalled = false;
super.releaseSourceInternal();
}
} }
} }
@ -355,6 +371,9 @@ public final class PreloadMediaSource extends WrappingMediaSource {
@Override @Override
public void onPrepared(MediaPeriod mediaPeriod) { public void onPrepared(MediaPeriod mediaPeriod) {
if (isUsedByPlayer()) {
return;
}
prepared = true; prepared = true;
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod; PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
TrackGroupArray trackGroups = preloadMediaPeriod.getTrackGroups(); TrackGroupArray trackGroups = preloadMediaPeriod.getTrackGroups();
@ -379,6 +398,9 @@ public final class PreloadMediaSource extends WrappingMediaSource {
@Override @Override
public void onContinueLoadingRequested(MediaPeriod mediaPeriod) { public void onContinueLoadingRequested(MediaPeriod mediaPeriod) {
if (isUsedByPlayer()) {
return;
}
PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod; PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod;
if (!prepared if (!prepared
|| preloadControl.onContinueLoadingRequested( || preloadControl.onContinueLoadingRequested(
@ -389,10 +411,15 @@ public final class PreloadMediaSource extends WrappingMediaSource {
} }
} }
/* package */ boolean isUsedByPlayer() { private boolean isUsedByPlayer() {
return prepareSourceCalled(); return prepareSourceCalled();
} }
private void notifyOnUsedByPlayer() {
preloadControl.onUsedByPlayer(this);
onUsedByPlayerNotified = true;
}
private static boolean mediaPeriodIdEqualsWithoutWindowSequenceNumber( private static boolean mediaPeriodIdEqualsWithoutWindowSequenceNumber(
MediaPeriodId firstPeriodId, MediaPeriodId secondPeriodId) { MediaPeriodId firstPeriodId, MediaPeriodId secondPeriodId) {
return firstPeriodId.periodUid.equals(secondPeriodId.periodUid) return firstPeriodId.periodUid.equals(secondPeriodId.periodUid)

View File

@ -246,11 +246,10 @@ public class DefaultPreloadManagerTest {
FakeMediaSource wrappedMediaSource2 = fakeMediaSourceFactory.getLastCreatedSource(); FakeMediaSource wrappedMediaSource2 = fakeMediaSourceFactory.getLastCreatedSource();
wrappedMediaSource2.setAllowPreparation(false); wrappedMediaSource2.setAllowPreparation(false);
MediaSource.MediaSourceCaller externalCaller = (source, timeline) -> {};
PreloadMediaSource preloadMediaSource2 = PreloadMediaSource preloadMediaSource2 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem2); (PreloadMediaSource) preloadManager.getMediaSource(mediaItem2);
preloadMediaSource2.prepareSource( preloadMediaSource2.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET); (source, timeline) -> {}, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadManager.setCurrentPlayingIndex(2); preloadManager.setCurrentPlayingIndex(2);
preloadManager.invalidate(); preloadManager.invalidate();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
@ -261,6 +260,51 @@ public class DefaultPreloadManagerTest {
assertThat(targetPreloadStatusControlCallReference).containsExactly(2, 1, 0).inOrder(); assertThat(targetPreloadStatusControlCallReference).containsExactly(2, 1, 0).inOrder();
} }
@Test
public void invalidate_sourceHandedOverToPlayerDuringPreloading_continuesPreloadingNextSource() {
ArrayList<Integer> targetPreloadStatusControlCallReference = new ArrayList<>();
TargetPreloadStatusControl<Integer> targetPreloadStatusControl =
rankingData -> {
targetPreloadStatusControlCallReference.add(rankingData);
return new DefaultPreloadManager.Status(
DefaultPreloadManager.Status.STAGE_TIMELINE_REFRESHED);
};
FakeMediaSourceFactory fakeMediaSourceFactory = new FakeMediaSourceFactory();
DefaultPreloadManager preloadManager =
new DefaultPreloadManager(
targetPreloadStatusControl,
fakeMediaSourceFactory,
trackSelector,
bandwidthMeter,
rendererCapabilitiesListFactory,
allocator,
Util.getCurrentOrMainLooper());
MediaItem.Builder mediaItemBuilder = new MediaItem.Builder();
MediaItem mediaItem0 =
mediaItemBuilder.setMediaId("mediaId0").setUri("http://exoplayer.dev/video0").build();
MediaItem mediaItem1 =
mediaItemBuilder.setMediaId("mediaId1").setUri("http://exoplayer.dev/video1").build();
preloadManager.add(mediaItem0, /* rankingData= */ 0);
FakeMediaSource wrappedMediaSource0 = fakeMediaSourceFactory.getLastCreatedSource();
wrappedMediaSource0.setAllowPreparation(false);
preloadManager.add(mediaItem1, /* rankingData= */ 1);
FakeMediaSource wrappedMediaSource1 = fakeMediaSourceFactory.getLastCreatedSource();
wrappedMediaSource1.setAllowPreparation(false);
preloadManager.invalidate();
assertThat(targetPreloadStatusControlCallReference).containsExactly(0);
PreloadMediaSource preloadMediaSource0 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem0);
preloadMediaSource0.prepareSource(
(source, timeline) -> {}, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
shadowOf(Looper.getMainLooper()).idle();
// The preload of mediaItem0 should complete and the preload manager continues to preload
// mediaItem1, even when the preloadMediaSource0 hasn't finished preparation.
assertThat(targetPreloadStatusControlCallReference).containsExactly(0, 1).inOrder();
}
@Test @Test
public void invalidate_beforePreloadCompletedForLastInvalidate_preloadRespectsToLatestOrder() { public void invalidate_beforePreloadCompletedForLastInvalidate_preloadRespectsToLatestOrder() {
ArrayList<Integer> targetPreloadStatusControlCallReference = new ArrayList<>(); ArrayList<Integer> targetPreloadStatusControlCallReference = new ArrayList<>();

View File

@ -70,6 +70,7 @@ public class PreloadAndPlaybackCoordinationTest {
private final AtomicInteger preloadControlOnSourceInfoRefreshedCalledCounter; private final AtomicInteger preloadControlOnSourceInfoRefreshedCalledCounter;
private final AtomicInteger preloadControlOnPreparedCalledCounter; private final AtomicInteger preloadControlOnPreparedCalledCounter;
private final AtomicInteger preloadControlOnUsedByPlayerCounter;
private final AtomicBoolean playbackSourceCallerOnSourceInfoRefreshedCalled; private final AtomicBoolean playbackSourceCallerOnSourceInfoRefreshedCalled;
private final AtomicBoolean playbackPeriodCallbackOnPreparedCalled; private final AtomicBoolean playbackPeriodCallbackOnPreparedCalled;
private final AtomicReference<MediaPeriod> preloadMediaPeriodReference; private final AtomicReference<MediaPeriod> preloadMediaPeriodReference;
@ -94,6 +95,7 @@ public class PreloadAndPlaybackCoordinationTest {
}; };
preloadControlOnSourceInfoRefreshedCalledCounter = new AtomicInteger(); preloadControlOnSourceInfoRefreshedCalledCounter = new AtomicInteger();
preloadControlOnPreparedCalledCounter = new AtomicInteger(); preloadControlOnPreparedCalledCounter = new AtomicInteger();
preloadControlOnUsedByPlayerCounter = new AtomicInteger();
playbackSourceCallerOnSourceInfoRefreshedCalled = new AtomicBoolean(); playbackSourceCallerOnSourceInfoRefreshedCalled = new AtomicBoolean();
playbackPeriodCallbackOnPreparedCalled = new AtomicBoolean(); playbackPeriodCallbackOnPreparedCalled = new AtomicBoolean();
preloadMediaPeriodReference = new AtomicReference<>(); preloadMediaPeriodReference = new AtomicReference<>();
@ -117,6 +119,11 @@ public class PreloadAndPlaybackCoordinationTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return true; return true;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
preloadControlOnUsedByPlayerCounter.addAndGet(1);
}
}; };
PreloadMediaSource.Factory preloadMediaSourceFactory = PreloadMediaSource.Factory preloadMediaSourceFactory =
new PreloadMediaSource.Factory( new PreloadMediaSource.Factory(
@ -168,6 +175,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue(); assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue();
assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue(); assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue();
assertThat(preloadMediaPeriodReference.get()).isNotNull(); assertThat(preloadMediaPeriodReference.get()).isNotNull();
@ -181,6 +189,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
} }
@Test @Test
@ -192,6 +201,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(2);
assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue(); assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue();
assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue(); assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue();
assertThat(preloadMediaPeriodReference.get()).isNotNull(); assertThat(preloadMediaPeriodReference.get()).isNotNull();
@ -205,6 +215,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(2);
} }
@Test @Test
@ -220,6 +231,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue(); assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue();
assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue(); assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue();
assertThat(preloadMediaPeriodReference.get()).isNotNull(); assertThat(preloadMediaPeriodReference.get()).isNotNull();
@ -233,6 +245,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
} }
@Test @Test
@ -251,6 +264,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(0);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue(); assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue();
assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue(); assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue();
assertThat(preloadMediaPeriodReference.get()).isNotNull(); assertThat(preloadMediaPeriodReference.get()).isNotNull();
@ -265,6 +279,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(2); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(2);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
} }
@Test @Test
@ -277,6 +292,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(1);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue(); assertThat(playbackSourceCallerOnSourceInfoRefreshedCalled.get()).isTrue();
assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue(); assertThat(playbackPeriodCallbackOnPreparedCalled.get()).isTrue();
assertThat(preloadMediaPeriodReference.get()).isNotNull(); assertThat(preloadMediaPeriodReference.get()).isNotNull();
@ -290,6 +306,7 @@ public class PreloadAndPlaybackCoordinationTest {
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(2); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(2);
assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(2); assertThat(preloadControlOnPreparedCalledCounter.get()).isEqualTo(2);
assertThat(preloadControlOnUsedByPlayerCounter.get()).isEqualTo(1);
} }
private static RendererCapabilities[] getRendererCapabilities(RenderersFactory renderersFactory) { private static RendererCapabilities[] getRendererCapabilities(RenderersFactory renderersFactory) {

View File

@ -104,6 +104,7 @@ public final class PreloadMediaSourceTest {
AtomicBoolean onPreparedCalled = new AtomicBoolean(); AtomicBoolean onPreparedCalled = new AtomicBoolean();
AtomicBoolean onContinueLoadingStopped = new AtomicBoolean(); AtomicBoolean onContinueLoadingStopped = new AtomicBoolean();
AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>(); AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>();
AtomicBoolean onUsedByPlayerCalled = new AtomicBoolean();
PreloadMediaSource.PreloadControl preloadControl = PreloadMediaSource.PreloadControl preloadControl =
new PreloadMediaSource.PreloadControl() { new PreloadMediaSource.PreloadControl() {
@Override @Override
@ -128,6 +129,11 @@ public final class PreloadMediaSourceTest {
} }
return true; return true;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
onUsedByPlayerCalled.set(true);
}
}; };
ProgressiveMediaSource.Factory mediaSourceFactory = ProgressiveMediaSource.Factory mediaSourceFactory =
new ProgressiveMediaSource.Factory( new ProgressiveMediaSource.Factory(
@ -156,6 +162,7 @@ public final class PreloadMediaSourceTest {
assertThat(onTimelineRefreshedCalled.get()).isTrue(); assertThat(onTimelineRefreshedCalled.get()).isTrue();
assertThat(onPreparedCalled.get()).isTrue(); assertThat(onPreparedCalled.get()).isTrue();
assertThat(onUsedByPlayerCalled.get()).isFalse();
assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource);
} }
@ -165,6 +172,7 @@ public final class PreloadMediaSourceTest {
AtomicBoolean onPreparedCalled = new AtomicBoolean(); AtomicBoolean onPreparedCalled = new AtomicBoolean();
AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>(); AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>();
AtomicBoolean onContinueLoadingRequestedCalled = new AtomicBoolean(); AtomicBoolean onContinueLoadingRequestedCalled = new AtomicBoolean();
AtomicBoolean onUsedByPlayerCalled = new AtomicBoolean();
PreloadMediaSource.PreloadControl preloadControl = PreloadMediaSource.PreloadControl preloadControl =
new PreloadMediaSource.PreloadControl() { new PreloadMediaSource.PreloadControl() {
@Override @Override
@ -186,6 +194,11 @@ public final class PreloadMediaSourceTest {
onContinueLoadingRequestedCalled.set(true); onContinueLoadingRequestedCalled.set(true);
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
onUsedByPlayerCalled.set(true);
}
}; };
ProgressiveMediaSource.Factory mediaSourceFactory = ProgressiveMediaSource.Factory mediaSourceFactory =
new ProgressiveMediaSource.Factory( new ProgressiveMediaSource.Factory(
@ -215,6 +228,7 @@ public final class PreloadMediaSourceTest {
assertThat(onTimelineRefreshedCalled.get()).isTrue(); assertThat(onTimelineRefreshedCalled.get()).isTrue();
assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource);
assertThat(onContinueLoadingRequestedCalled.get()).isFalse(); assertThat(onContinueLoadingRequestedCalled.get()).isFalse();
assertThat(onUsedByPlayerCalled.get()).isFalse();
} }
@Test @Test
@ -223,6 +237,7 @@ public final class PreloadMediaSourceTest {
AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>(); AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>();
AtomicBoolean onPreparedCalled = new AtomicBoolean(); AtomicBoolean onPreparedCalled = new AtomicBoolean();
AtomicBoolean onContinueLoadingRequestedCalled = new AtomicBoolean(); AtomicBoolean onContinueLoadingRequestedCalled = new AtomicBoolean();
AtomicBoolean onUsedByPlayerCalled = new AtomicBoolean();
PreloadMediaSource.PreloadControl preloadControl = PreloadMediaSource.PreloadControl preloadControl =
new PreloadMediaSource.PreloadControl() { new PreloadMediaSource.PreloadControl() {
@Override @Override
@ -244,6 +259,11 @@ public final class PreloadMediaSourceTest {
onContinueLoadingRequestedCalled.set(true); onContinueLoadingRequestedCalled.set(true);
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
onUsedByPlayerCalled.set(true);
}
}; };
ProgressiveMediaSource.Factory mediaSourceFactory = ProgressiveMediaSource.Factory mediaSourceFactory =
new ProgressiveMediaSource.Factory( new ProgressiveMediaSource.Factory(
@ -272,12 +292,14 @@ public final class PreloadMediaSourceTest {
assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource);
assertThat(onPreparedCalled.get()).isFalse(); assertThat(onPreparedCalled.get()).isFalse();
assertThat(onContinueLoadingRequestedCalled.get()).isFalse(); assertThat(onContinueLoadingRequestedCalled.get()).isFalse();
assertThat(onUsedByPlayerCalled.get()).isFalse();
} }
@Test @Test
public void preload_whileSourceIsAccessedByExternalCaller_notProceedWithPreloading() { public void preload_whileSourceIsAccessedByExternalCaller_notProceedWithPreloading() {
AtomicBoolean onTimelineRefreshedCalled = new AtomicBoolean(false); AtomicBoolean onTimelineRefreshedCalled = new AtomicBoolean(false);
AtomicBoolean onPreparedCalled = new AtomicBoolean(false); AtomicBoolean onPreparedCalled = new AtomicBoolean(false);
AtomicBoolean onUsedByPlayerCalled = new AtomicBoolean();
PreloadMediaSource.PreloadControl preloadControl = PreloadMediaSource.PreloadControl preloadControl =
new PreloadMediaSource.PreloadControl() { new PreloadMediaSource.PreloadControl() {
@Override @Override
@ -297,6 +319,11 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return true; return true;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
onUsedByPlayerCalled.set(true);
}
}; };
TrackSelector trackSelector = new FakeTrackSelector(); TrackSelector trackSelector = new FakeTrackSelector();
trackSelector.init(() -> {}, bandwidthMeter); trackSelector.init(() -> {}, bandwidthMeter);
@ -332,6 +359,7 @@ public final class PreloadMediaSourceTest {
assertThat(externalCallerMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); assertThat(externalCallerMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource);
assertThat(onTimelineRefreshedCalled.get()).isFalse(); assertThat(onTimelineRefreshedCalled.get()).isFalse();
assertThat(onPreparedCalled.get()).isFalse(); assertThat(onPreparedCalled.get()).isFalse();
assertThat(onUsedByPlayerCalled.get()).isTrue();
} }
@Test @Test
@ -339,6 +367,7 @@ public final class PreloadMediaSourceTest {
prepareSource_beforeSourceInfoRefreshedForPreloading_onlyInvokeExternalCallerOnSourceInfoRefreshed() { prepareSource_beforeSourceInfoRefreshedForPreloading_onlyInvokeExternalCallerOnSourceInfoRefreshed() {
AtomicBoolean onTimelineRefreshedCalled = new AtomicBoolean(false); AtomicBoolean onTimelineRefreshedCalled = new AtomicBoolean(false);
AtomicBoolean onPreparedCalled = new AtomicBoolean(false); AtomicBoolean onPreparedCalled = new AtomicBoolean(false);
AtomicBoolean onUsedByPlayerCalled = new AtomicBoolean();
PreloadMediaSource.PreloadControl preloadControl = PreloadMediaSource.PreloadControl preloadControl =
new PreloadMediaSource.PreloadControl() { new PreloadMediaSource.PreloadControl() {
@Override @Override
@ -358,6 +387,11 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return true; return true;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
onUsedByPlayerCalled.set(true);
}
}; };
FakeMediaSourceFactory mediaSourceFactory = new FakeMediaSourceFactory(); FakeMediaSourceFactory mediaSourceFactory = new FakeMediaSourceFactory();
TrackSelector trackSelector = new FakeTrackSelector(); TrackSelector trackSelector = new FakeTrackSelector();
@ -396,12 +430,14 @@ public final class PreloadMediaSourceTest {
assertThat(externalCallerMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); assertThat(externalCallerMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource);
assertThat(onTimelineRefreshedCalled.get()).isFalse(); assertThat(onTimelineRefreshedCalled.get()).isFalse();
assertThat(onPreparedCalled.get()).isFalse(); assertThat(onPreparedCalled.get()).isFalse();
assertThat(onUsedByPlayerCalled.get()).isTrue();
} }
@Test @Test
public void prepareSource_afterPreload_immediatelyInvokeExternalCallerOnSourceInfoRefreshed() { public void prepareSource_afterPreload_immediatelyInvokeExternalCallerOnSourceInfoRefreshed() {
AtomicBoolean onTimelineRefreshedCalled = new AtomicBoolean(false); AtomicBoolean onTimelineRefreshedCalled = new AtomicBoolean(false);
AtomicBoolean onPreparedCalled = new AtomicBoolean(false); AtomicBoolean onPreparedCalled = new AtomicBoolean(false);
AtomicBoolean onUsedByPlayerCalled = new AtomicBoolean();
PreloadMediaSource.PreloadControl preloadControl = PreloadMediaSource.PreloadControl preloadControl =
new PreloadMediaSource.PreloadControl() { new PreloadMediaSource.PreloadControl() {
@Override @Override
@ -421,6 +457,11 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return true; return true;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {
onUsedByPlayerCalled.set(true);
}
}; };
FakeMediaSourceFactory mediaSourceFactory = new FakeMediaSourceFactory(); FakeMediaSourceFactory mediaSourceFactory = new FakeMediaSourceFactory();
TrackSelector trackSelector = new FakeTrackSelector(); TrackSelector trackSelector = new FakeTrackSelector();
@ -456,6 +497,7 @@ public final class PreloadMediaSourceTest {
assertThat(onTimelineRefreshedCalled.get()).isTrue(); assertThat(onTimelineRefreshedCalled.get()).isTrue();
assertThat(onPreparedCalled.get()).isTrue(); assertThat(onPreparedCalled.get()).isTrue();
assertThat(externalCallerMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); assertThat(externalCallerMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource);
assertThat(onUsedByPlayerCalled.get()).isTrue();
} }
@Test @Test
@ -480,6 +522,9 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {}
}; };
AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>(); AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>();
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
@ -587,6 +632,9 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {}
}; };
AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>(); AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>();
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
@ -692,6 +740,9 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {}
}; };
AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>(); AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>();
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
@ -769,6 +820,9 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return true; return true;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {}
}; };
AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>(); AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>();
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
@ -847,6 +901,9 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {}
}; };
AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>(); AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>();
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
@ -935,6 +992,9 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {}
}; };
AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>(); AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>();
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);
@ -1004,6 +1064,9 @@ public final class PreloadMediaSourceTest {
PreloadMediaSource mediaSource, long bufferedPositionUs) { PreloadMediaSource mediaSource, long bufferedPositionUs) {
return false; return false;
} }
@Override
public void onUsedByPlayer(PreloadMediaSource mediaSource) {}
}; };
AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>(); AtomicReference<MediaSource> internalSourceReference = new AtomicReference<>();
MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class); MediaSource.Factory mockMediaSourceFactory = mock(MediaSource.Factory.class);