mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add TestPlayerRunHelper run(player).untilFullyBuffered
This simplifies some common test setup steps that rely on a fully buffered player before making further test progress. PiperOrigin-RevId: 693651493
This commit is contained in:
parent
08470140ac
commit
5336d71c22
@ -50,10 +50,11 @@ import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_VIDEO_
|
||||
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_VIDEO_SIZE_CHANGED;
|
||||
import static androidx.media3.test.utils.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
|
||||
import static androidx.media3.test.utils.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.play;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.playUntilPosition;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.run;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilError;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilIsLoading;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPendingCommandsAreFullyHandled;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPlaybackState;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilTimelineChanged;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@ -477,11 +478,10 @@ public final class DefaultAnalyticsCollectorTest {
|
||||
player.setMediaSources(ImmutableList.of(mediaSource1, mediaSource2));
|
||||
player.prepare();
|
||||
// Wait until second period has fully loaded to assert loading events.
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.seekTo(/* mediaItemIndex= */ 1, /* positionMs= */ 0);
|
||||
player.play();
|
||||
runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
|
||||
populateEventIds(listener.lastReportedTimeline);
|
||||
assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED))
|
||||
@ -975,16 +975,15 @@ public final class DefaultAnalyticsCollectorTest {
|
||||
|
||||
player.setMediaSource(fakeMediaSource);
|
||||
player.prepare();
|
||||
runUntilPlaybackState(player, Player.STATE_READY);
|
||||
run(player).untilState(Player.STATE_READY);
|
||||
player.addMediaSource(fakeMediaSource);
|
||||
// Wait until second period has fully loaded to assert loading events.
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.removeMediaItem(/* index= */ 0);
|
||||
runUntilPlaybackState(player, Player.STATE_BUFFERING);
|
||||
runUntilPlaybackState(player, Player.STATE_READY);
|
||||
run(player).untilState(Player.STATE_BUFFERING);
|
||||
run(player).untilState(Player.STATE_READY);
|
||||
player.play();
|
||||
runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
|
||||
// Populate event ids with second to last timeline that still contained both periods.
|
||||
populateEventIds(listener.reportedTimelines.get(listener.reportedTimelines.size() - 2));
|
||||
@ -1140,18 +1139,17 @@ public final class DefaultAnalyticsCollectorTest {
|
||||
player.setMediaSource(fakeMediaSource);
|
||||
player.prepare();
|
||||
// Ensure everything is preloaded.
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
runUntilPlaybackState(player, Player.STATE_READY);
|
||||
run(player).untilFullyBuffered();
|
||||
run(player).untilState(Player.STATE_READY);
|
||||
// Wait in each content part to ensure previously triggered events get a chance to be delivered.
|
||||
playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ 3_000);
|
||||
runUntilPendingCommandsAreFullyHandled(player);
|
||||
playUntilPosition(player, /* mediaItemIndex= */ 0, /* positionMs= */ 8_000);
|
||||
runUntilPendingCommandsAreFullyHandled(player);
|
||||
play(player).untilPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 3_000);
|
||||
run(player).untilPendingCommandsAreFullyHandled();
|
||||
play(player).untilPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 8_000);
|
||||
run(player).untilPendingCommandsAreFullyHandled();
|
||||
player.play();
|
||||
runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
// Wait for final timeline change that marks post-roll played.
|
||||
runUntilTimelineChanged(player);
|
||||
run(player).untilTimelineChanges();
|
||||
|
||||
Object periodUid = listener.lastReportedTimeline.getUidOfPeriod(/* periodIndex= */ 0);
|
||||
EventWindowAndPeriodId prerollAd =
|
||||
@ -1343,14 +1341,13 @@ public final class DefaultAnalyticsCollectorTest {
|
||||
player.setMediaSource(fakeMediaSource);
|
||||
player.prepare();
|
||||
// Ensure everything is preloaded.
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
// Seek behind the midroll.
|
||||
player.seekTo(/* positionMs= */ 6_000);
|
||||
// Wait until loading started again to assert loading events.
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
run(player).untilLoadingIs(true);
|
||||
player.play();
|
||||
runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
|
||||
Object periodUid = listener.lastReportedTimeline.getUidOfPeriod(/* periodIndex= */ 0);
|
||||
EventWindowAndPeriodId midrollAd =
|
||||
@ -1516,11 +1513,9 @@ public final class DefaultAnalyticsCollectorTest {
|
||||
// Wait for the media to be fully buffered before unblocking the DRM key request. This
|
||||
// ensures both periods report the same load event (because period1's DRM session is
|
||||
// already preacquired by the time the key load completes).
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
mediaDrmCallback.keyCondition.open();
|
||||
runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
|
||||
populateEventIds(listener.lastReportedTimeline);
|
||||
assertThat(listener.getEvents(EVENT_DRM_SESSION_MANAGER_ERROR)).isEmpty();
|
||||
@ -1590,9 +1585,9 @@ public final class DefaultAnalyticsCollectorTest {
|
||||
player.play();
|
||||
player.setMediaSource(mediaSource);
|
||||
player.prepare();
|
||||
runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
mediaDrmCallback.keyCondition.open();
|
||||
runUntilError(player);
|
||||
run(player).untilPlayerError();
|
||||
|
||||
populateEventIds(listener.lastReportedTimeline);
|
||||
assertThat(listener.getEvents(EVENT_DRM_SESSION_MANAGER_ERROR)).containsExactly(period0);
|
||||
|
@ -108,13 +108,7 @@ public final class MergingPlaylistPlaybackTest {
|
||||
player.prepare();
|
||||
// Load all content prior to play to reduce flaky-ness resulting from the playback advancement
|
||||
// speed and handling of discontinuities.
|
||||
long durationToBufferMs =
|
||||
(firstItemVideoClipped || firstItemAudioClipped ? 300L : 1024L)
|
||||
+ (secondItemVideoClipped || secondItemAudioClipped ? 300L : 1024L);
|
||||
run(player)
|
||||
.untilBackgroundThreadCondition(
|
||||
() -> player.getTotalBufferedDuration() >= durationToBufferMs);
|
||||
run(player).untilPendingCommandsAreFullyHandled();
|
||||
run(player).untilFullyBuffered();
|
||||
// Reset the listener to avoid verifying the onIsLoadingChanged events from prepare().
|
||||
reset(listener);
|
||||
player.play();
|
||||
@ -160,12 +154,8 @@ public final class MergingPlaylistPlaybackTest {
|
||||
player.prepare();
|
||||
// Load all content prior to play to reduce flaky-ness resulting from the playback advancement
|
||||
// speed and handling of discontinuities.
|
||||
long durationToBufferMs = (firstItemVideoClipped || firstItemAudioClipped ? 300L : 1024L) * 5;
|
||||
run(player)
|
||||
.untilBackgroundThreadCondition(
|
||||
() -> player.getTotalBufferedDuration() >= durationToBufferMs);
|
||||
run(player).untilFullyBuffered();
|
||||
// Reset the listener to avoid verifying the onIsLoadingChanged events from prepare().
|
||||
run(player).untilPendingCommandsAreFullyHandled();
|
||||
reset(listener);
|
||||
player.play();
|
||||
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package androidx.media3.exoplayer.e2etest;
|
||||
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.run;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.robolectric.annotation.GraphicsMode.Mode.NATIVE;
|
||||
|
||||
@ -86,11 +87,9 @@ public final class PlaylistPlaybackTest {
|
||||
|
||||
player.addMediaItem(MediaItem.fromUri("asset:///media/mka/bear-opus.mka"));
|
||||
player.prepare();
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.addMediaItem(MediaItem.fromUri("asset:///media/wav/sample.wav"));
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
// Wait until second period has fully loaded to start the playback.
|
||||
player.play();
|
||||
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
@ -115,8 +114,7 @@ public final class PlaylistPlaybackTest {
|
||||
|
||||
player.addMediaItem(MediaItem.fromUri("asset:///media/mp4/preroll-5s.mp4"));
|
||||
player.prepare();
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
MediaItem mediaItemWithSubtitle =
|
||||
new MediaItem.Builder()
|
||||
.setUri("asset:///media/mp4/preroll-5s.mp4")
|
||||
@ -130,8 +128,7 @@ public final class PlaylistPlaybackTest {
|
||||
.build()))
|
||||
.build();
|
||||
player.addMediaItem(mediaItemWithSubtitle);
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ true);
|
||||
TestPlayerRunHelper.runUntilIsLoading(player, /* expectedIsLoading= */ false);
|
||||
run(player).untilFullyBuffered();
|
||||
// Wait until second period has fully loaded to start the playback.
|
||||
player.play();
|
||||
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED);
|
||||
|
@ -98,7 +98,7 @@ public class SubtitlePlaybackTest {
|
||||
player.setMediaItem(mediaItem);
|
||||
player.prepare();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_READY);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -160,7 +160,7 @@ public class SubtitlePlaybackTest {
|
||||
player.setMediaItem(mediaItem);
|
||||
player.prepare();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_READY);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
|
@ -96,7 +96,7 @@ public class WebvttPlaybackTest {
|
||||
player.setMediaItem(mediaItem);
|
||||
player.prepare();
|
||||
run(player).untilState(Player.STATE_READY);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -139,7 +139,7 @@ public class WebvttPlaybackTest {
|
||||
player.setMediaItem(mediaItem);
|
||||
player.prepare();
|
||||
run(player).untilState(Player.STATE_READY);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
|
||||
|
@ -22,7 +22,7 @@ import static androidx.media3.test.utils.FakeSampleStream.FakeSampleStreamItem.E
|
||||
import static androidx.media3.test.utils.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||
import static androidx.media3.test.utils.robolectric.RobolectricUtil.runMainLooperUntil;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.playUntilPosition;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilIsLoading;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.run;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPendingCommandsAreFullyHandled;
|
||||
import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUntilPlaybackState;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@ -521,8 +521,7 @@ public final class ServerSideAdInsertionMediaSourceTest {
|
||||
|
||||
// Add ad at the current playback position during playback.
|
||||
runUntilPlaybackState(player, Player.STATE_READY);
|
||||
runUntilIsLoading(player, false);
|
||||
runMainLooperUntil(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilFullyBuffered();
|
||||
AdPlaybackState secondAdPlaybackState =
|
||||
addAdGroupToAdPlaybackState(
|
||||
firstAdPlaybackState,
|
||||
|
@ -95,8 +95,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/standalone-webvtt/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -136,10 +135,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/standalone-webvtt/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -178,10 +174,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/standalone-webvtt/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -218,8 +211,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/standalone-ttml/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -250,8 +242,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/webvtt-in-mp4/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -281,8 +272,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/ttml-in-mp4/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -322,10 +312,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/ttml-in-mp4/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -364,10 +351,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/ttml-in-mp4/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -411,8 +395,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/cea608/manifest.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -452,8 +435,7 @@ public final class DashPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/dash/cea608/manifest.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -690,8 +672,7 @@ public final class DashPlaybackTest {
|
||||
MediaItem.fromUri("asset:///media/dash/multi-period-with-offset/sample.mpd"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered to avoid flakiness from loading second period too late.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
|
@ -85,8 +85,7 @@ public final class HlsPlaybackTest {
|
||||
MediaItem.fromUri("asset:///media/hls/standalone-webvtt/multivariant_playlist.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -124,10 +123,7 @@ public final class HlsPlaybackTest {
|
||||
MediaItem.fromUri("asset:///media/hls/standalone-webvtt/multivariant_playlist.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -164,10 +160,7 @@ public final class HlsPlaybackTest {
|
||||
MediaItem.fromUri("asset:///media/hls/standalone-webvtt/multivariant_playlist.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -198,8 +191,7 @@ public final class HlsPlaybackTest {
|
||||
MediaItem.fromUri("asset:///media/hls/ttml-in-mp4/multivariant_playlist.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -236,10 +228,7 @@ public final class HlsPlaybackTest {
|
||||
MediaItem.fromUri("asset:///media/hls/ttml-in-mp4/multivariant_playlist.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -275,10 +264,7 @@ public final class HlsPlaybackTest {
|
||||
MediaItem.fromUri("asset:///media/hls/ttml-in-mp4/multivariant_playlist.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player)
|
||||
.ignoringNonFatalErrors()
|
||||
.untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).ignoringNonFatalErrors().untilLoadingIs(false);
|
||||
run(player).ignoringNonFatalErrors().untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).ignoringNonFatalErrors().untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -318,8 +304,7 @@ public final class HlsPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/hls/cea608/manifest.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
@ -355,8 +340,7 @@ public final class HlsPlaybackTest {
|
||||
player.setMediaItem(MediaItem.fromUri("asset:///media/hls/cea608/manifest.m3u8"));
|
||||
player.prepare();
|
||||
// Ensure media is fully buffered so that the first subtitle is ready at the start of playback.
|
||||
run(player).untilBackgroundThreadCondition(() -> player.getBufferedPercentage() == 100);
|
||||
run(player).untilLoadingIs(false);
|
||||
run(player).untilFullyBuffered();
|
||||
player.play();
|
||||
run(player).untilState(Player.STATE_ENDED);
|
||||
player.release();
|
||||
|
@ -22,6 +22,7 @@ import static androidx.media3.test.utils.robolectric.RobolectricUtil.runMainLoop
|
||||
|
||||
import android.os.Looper;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.PlaybackException;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.Timeline;
|
||||
@ -504,6 +505,31 @@ public final class TestPlayerRunHelper {
|
||||
runUntil(conditionTrue::get);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs tasks of the main {@link Looper} until the player has fully buffered its entire playlist
|
||||
* and stopped reporting {@link Player#isLoading()}.
|
||||
*
|
||||
* <p>Note that this method won't succeed if the player is configured with a {@link
|
||||
* androidx.media3.exoplayer.LoadControl} that prevents loading the playlist fully before
|
||||
* playback resumes.
|
||||
*
|
||||
* <p>If a {@link Player.RepeatMode} setting results in an endless playlist, this method only
|
||||
* waits until all items have been buffered at least once.
|
||||
*
|
||||
* @throws PlaybackException If a playback error occurs.
|
||||
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public void untilFullyBuffered() throws PlaybackException, TimeoutException {
|
||||
untilBackgroundThreadCondition(
|
||||
() -> {
|
||||
long remainingDurationMs = getRemainingPlaybackDuration(player);
|
||||
return remainingDurationMs != C.TIME_UNSET
|
||||
&& player.getTotalBufferedDuration() >= remainingDurationMs
|
||||
&& !player.isLoading();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExoPlayerRunResult ignoringNonFatalErrors() {
|
||||
checkState(!hasBeenUsed);
|
||||
@ -854,6 +880,41 @@ public final class TestPlayerRunHelper {
|
||||
"Playback thread is not alive, has the player been released?");
|
||||
}
|
||||
|
||||
private static long getRemainingPlaybackDuration(Player player) {
|
||||
if (player.getCurrentTimeline().isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
int currentMediaItemIndex = player.getCurrentMediaItemIndex();
|
||||
long currentMediaItemDurationMs = getMediaItemDurationMs(player, currentMediaItemIndex);
|
||||
if (currentMediaItemDurationMs == C.TIME_UNSET) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
long totalDurationMs = currentMediaItemDurationMs - player.getCurrentPosition();
|
||||
int mediaItemIndex = currentMediaItemIndex;
|
||||
while ((mediaItemIndex = getNextMediaItemIndex(player, mediaItemIndex)) != C.INDEX_UNSET
|
||||
&& mediaItemIndex != currentMediaItemIndex) {
|
||||
currentMediaItemDurationMs = getMediaItemDurationMs(player, mediaItemIndex);
|
||||
if (currentMediaItemDurationMs == C.TIME_UNSET) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
totalDurationMs += currentMediaItemDurationMs;
|
||||
}
|
||||
return totalDurationMs;
|
||||
}
|
||||
|
||||
private static long getMediaItemDurationMs(Player player, int mediaItemIndex) {
|
||||
return player
|
||||
.getCurrentTimeline()
|
||||
.getWindow(mediaItemIndex, new Timeline.Window())
|
||||
.getDurationMs();
|
||||
}
|
||||
|
||||
private static int getNextMediaItemIndex(Player player, int mediaItemIndex) {
|
||||
return player
|
||||
.getCurrentTimeline()
|
||||
.getNextWindowIndex(mediaItemIndex, player.getRepeatMode(), player.getShuffleModeEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Player.Listener} and {@link AnalyticsListener} that records errors.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user