Pass player ID to methods of LoadControl

The old methods are deprecated and are called from the new
method for backwards compatibility of custom implementations.

'DefaultLoadControl' is unchanged, but `ExoPlayerImplInternal`
already calls the new methods passing in the `PlayerId`,

PiperOrigin-RevId: 613197190
This commit is contained in:
bachinger 2024-03-06 06:44:59 -08:00 committed by Copybara-Service
parent a90a7049e8
commit a0a40871b5
10 changed files with 322 additions and 78 deletions

View file

@ -14,6 +14,8 @@
`DefaultPreloadManager` which uses `PreloadMediaSource` to preload media
samples of the sources into memory, and uses an integer `rankingData`
that indicates the index of an item on the UI.
* Add `PlayerId` to most methods of `LoadControl` to enable `LoadControl`
implementations to support multiple players.
* Transformer:
* Add `audioConversionProcess` and `videoConversionProcess` to
`ExportResult` indicating how the respective track in the output file

View file

@ -54,6 +54,7 @@ import androidx.media3.datasource.DataSource;
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.audio.AudioSink;
import androidx.media3.exoplayer.audio.MediaCodecAudioRenderer;
import androidx.media3.exoplayer.image.ImageOutput;
@ -478,6 +479,7 @@ public interface ExoPlayer extends Player {
@Nullable /* package */ Looper playbackLooper;
/* package */ boolean buildCalled;
/* package */ boolean suppressPlaybackOnUnsuitableOutput;
/* package */ String playerName;
/**
* Creates a builder.
@ -678,6 +680,7 @@ public interface ExoPlayer extends Player {
releaseTimeoutMs = DEFAULT_RELEASE_TIMEOUT_MS;
detachSurfaceTimeoutMs = DEFAULT_DETACH_SURFACE_TIMEOUT_MS;
usePlatformDiagnostics = true;
playerName = "";
}
/**
@ -1187,6 +1190,24 @@ public interface ExoPlayer extends Player {
return this;
}
/**
* Sets the player name that is included in the {@link PlayerId} for informational purpose to
* recognize the player by its {@link PlayerId}.
*
* <p>The default is an empty string.
*
* @param playerName A name for the player in the {@link PlayerId}.
* @return This builder.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
@CanIgnoreReturnValue
@UnstableApi
public Builder setName(String playerName) {
checkState(!buildCalled);
this.playerName = playerName;
return this;
}
/**
* Builds an {@link ExoPlayer} instance.
*

View file

@ -347,9 +347,12 @@ import java.util.concurrent.TimeoutException;
analyticsCollector.setPlayer(this.wrappingPlayer, applicationLooper);
PlayerId playerId =
Util.SDK_INT < 31
? new PlayerId()
? new PlayerId(builder.playerName)
: Api31.registerMediaMetricsListener(
applicationContext, /* player= */ this, builder.usePlatformDiagnostics);
applicationContext,
/* player= */ this,
builder.usePlatformDiagnostics,
builder.playerName);
internalPlayer =
new ExoPlayerImplInternal(
renderers,
@ -3386,16 +3389,16 @@ import java.util.concurrent.TimeoutException;
@DoNotInline
public static PlayerId registerMediaMetricsListener(
Context context, ExoPlayerImpl player, boolean usePlatformDiagnostics) {
Context context, ExoPlayerImpl player, boolean usePlatformDiagnostics, String playerName) {
@Nullable MediaMetricsListener listener = MediaMetricsListener.create(context);
if (listener == null) {
Log.w(TAG, "MediaMetricsService unavailable.");
return new PlayerId(LogSessionId.LOG_SESSION_ID_NONE);
return new PlayerId(LogSessionId.LOG_SESSION_ID_NONE, playerName);
}
if (usePlatformDiagnostics) {
player.addAnalyticsListener(listener);
}
return new PlayerId(listener.getLogSessionId());
return new PlayerId(listener.getLogSessionId(), playerName);
}
}

View file

@ -208,6 +208,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private final MediaSourceList mediaSourceList;
private final LivePlaybackSpeedControl livePlaybackSpeedControl;
private final long releaseTimeoutMs;
private final PlayerId playerId;
@SuppressWarnings("unused")
private SeekParameters seekParameters;
@ -266,11 +267,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
this.setForegroundModeTimeoutMs = releaseTimeoutMs;
this.pauseAtEndOfWindow = pauseAtEndOfWindow;
this.clock = clock;
this.playerId = playerId;
playbackMaybeBecameStuckAtMs = C.TIME_UNSET;
lastRebufferRealtimeMs = C.TIME_UNSET;
backBufferDurationUs = loadControl.getBackBufferDurationUs();
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe();
backBufferDurationUs = loadControl.getBackBufferDurationUs(playerId);
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe(playerId);
playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult);
playbackInfoUpdate = new PlaybackInfoUpdate(playbackInfo);
@ -772,7 +774,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* resetPosition= */ false,
/* releaseMediaSourceList= */ false,
/* resetError= */ true);
loadControl.onPrepared();
loadControl.onPrepared(playerId);
setState(playbackInfo.timeline.isEmpty() ? Player.STATE_ENDED : Player.STATE_BUFFERING);
mediaSourceList.prepare(bandwidthMeter.getTransferListener());
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
@ -1473,7 +1475,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* releaseMediaSourceList= */ true,
/* resetError= */ false);
playbackInfoUpdate.incrementPendingOperationAcks(acknowledgeStop ? 1 : 0);
loadControl.onStopped();
loadControl.onStopped(playerId);
setState(Player.STATE_IDLE);
}
@ -1485,7 +1487,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* releaseMediaSourceList= */ true,
/* resetError= */ false);
releaseRenderers();
loadControl.onReleased();
loadControl.onReleased(playerId);
setState(Player.STATE_IDLE);
} finally {
if (internalPlaybackThread != null) {
@ -1938,6 +1940,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return isBufferedToEnd
|| isAdPendingPreparation
|| loadControl.shouldStartPlayback(
playerId,
playbackInfo.timeline,
playingPeriodHolder.info.id,
getTotalBufferedDurationUs(),
@ -2522,7 +2525,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
- loadingPeriodHolder.info.startPositionUs;
boolean shouldContinueLoading =
loadControl.shouldContinueLoading(
playbackPositionUs, bufferedDurationUs, mediaClock.getPlaybackParameters().speed);
playerId,
playbackInfo.timeline,
loadingPeriodHolder.info.id,
playbackPositionUs,
bufferedDurationUs,
mediaClock.getPlaybackParameters().speed);
if (!shouldContinueLoading
&& bufferedDurationUs < PLAYBACK_BUFFER_EMPTY_THRESHOLD_US
&& (backBufferDurationUs > 0 || retainBackBufferFromKeyframe)) {
@ -2534,7 +2542,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
.discardBuffer(playbackInfo.positionUs, /* toKeyframe= */ false);
shouldContinueLoading =
loadControl.shouldContinueLoading(
playbackPositionUs, bufferedDurationUs, mediaClock.getPlaybackParameters().speed);
playerId,
playbackInfo.timeline,
loadingPeriodHolder.info.id,
playbackPositionUs,
bufferedDurationUs,
mediaClock.getPlaybackParameters().speed);
}
return shouldContinueLoading;
}
@ -2759,6 +2772,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
TrackGroupArray trackGroups,
TrackSelectorResult trackSelectorResult) {
loadControl.onTracksSelected(
playerId,
playbackInfo.timeline,
mediaPeriodId,
renderers,

View file

@ -19,6 +19,7 @@ import androidx.media3.common.C;
import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.source.MediaPeriod;
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
import androidx.media3.exoplayer.source.TrackGroupArray;
@ -37,15 +38,31 @@ public interface LoadControl {
@Deprecated
MediaPeriodId EMPTY_MEDIA_PERIOD_ID = new MediaPeriodId(/* periodUid= */ new Object());
/** Called by the player when prepared with a new source. */
void onPrepared();
/**
* Called by the player when prepared with a new source.
*
* @param playerId The {@linkplain PlayerId ID of the player} that prepared a new source.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onPrepared(PlayerId playerId) {
onPrepared();
}
/**
* @deprecated Use {@link #onPrepared(PlayerId)} instead.
*/
@Deprecated
default void onPrepared() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("onPrepared not implemented");
}
/**
* Called by the player when a track selection occurs.
*
* @param timeline The current {@link Timeline} in ExoPlayer. Can be {@link Timeline#EMPTY} only
* when the deprecated {@link #onTracksSelected(Renderer[], TrackGroupArray,
* ExoTrackSelection[])} was called.
* @param playerId The {@linkplain PlayerId ID of the player} that selected tracks.
* @param timeline The current {@link Timeline} in ExoPlayer.
* @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} for which the
* selection was made. Will be {@link #EMPTY_MEDIA_PERIOD_ID} when {@code timeline} is empty.
* @param renderers The renderers.
@ -53,6 +70,22 @@ public interface LoadControl {
* @param trackSelections The track selections that were made.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onTracksSelected(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodId,
Renderer[] renderers,
TrackGroupArray trackGroups,
ExoTrackSelection[] trackSelections) {
onTracksSelected(timeline, mediaPeriodId, renderers, trackGroups, trackSelections);
}
/**
* @deprecated Implement {@link #onTracksSelected(PlayerId, Timeline, MediaPeriodId, Renderer[],
* TrackGroupArray, ExoTrackSelection[])} instead.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
@Deprecated
default void onTracksSelected(
Timeline timeline,
MediaPeriodId mediaPeriodId,
@ -63,22 +96,57 @@ public interface LoadControl {
}
/**
* @deprecated Implement {@link #onTracksSelected(Timeline, MediaPeriodId, Renderer[],
* @deprecated Implement {@link #onTracksSelected(PlayerId, Timeline, MediaPeriodId, Renderer[],
* TrackGroupArray, ExoTrackSelection[])} instead.
*/
@SuppressWarnings("deprecation") // Intentionally referencing deprecated constant
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
@Deprecated
default void onTracksSelected(
Renderer[] renderers, TrackGroupArray trackGroups, ExoTrackSelection[] trackSelections) {
onTracksSelected(
Timeline.EMPTY, EMPTY_MEDIA_PERIOD_ID, renderers, trackGroups, trackSelections);
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("onTracksSelected not implemented");
}
/** Called by the player when stopped. */
void onStopped();
/**
* Called by the player when stopped.
*
* @param playerId The {@linkplain PlayerId ID of the player} that was stopped.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onStopped(PlayerId playerId) {
onStopped();
}
/** Called by the player when released. */
void onReleased();
/**
* @deprecated Implement {@link #onStopped(PlayerId)} instead.
*/
@Deprecated
default void onStopped() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("onStopped not implemented");
}
/**
* Called by the player when released.
*
* @param playerId The {@linkplain PlayerId ID of the player} that was released.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onReleased(PlayerId playerId) {
onReleased();
}
/**
* @deprecated Implement {@link #onReleased(PlayerId)} instead.
*/
@Deprecated
default void onReleased() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("onReleased not implemented");
}
/** Returns the {@link Allocator} that should be used to obtain media buffer allocations. */
Allocator getAllocator();
@ -93,10 +161,25 @@ public interface LoadControl {
* <p>Note: Implementations should return a single value. Dynamic changes to the back-buffer are
* not currently supported.
*
* @param playerId The {@linkplain PlayerId ID of the player} that requests the back buffer
* duration.
* @return The duration of media to retain in the buffer prior to the current playback position,
* in microseconds.
*/
long getBackBufferDurationUs();
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default long getBackBufferDurationUs(PlayerId playerId) {
return getBackBufferDurationUs();
}
/**
* @deprecated Implements {@link #getBackBufferDurationUs(PlayerId)} instead.
*/
@Deprecated
default long getBackBufferDurationUs() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("getBackBufferDurationUs not implemented");
}
/**
* Returns whether media should be retained from the keyframe before the current playback position
@ -111,17 +194,36 @@ public interface LoadControl {
* <p>Note: Implementations should return a single value. Dynamic changes to the back-buffer are
* not currently supported.
*
* @param playerId The {@linkplain PlayerId ID of the player} that requests whether to retain the
* back buffer from key frame.
* @return Whether media should be retained from the keyframe before the current playback position
* minus {@link #getBackBufferDurationUs()}, rather than any sample before or at that
* position.
*/
boolean retainBackBufferFromKeyframe();
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default boolean retainBackBufferFromKeyframe(PlayerId playerId) {
return retainBackBufferFromKeyframe();
}
/**
* @deprecated Implements {@link #retainBackBufferFromKeyframe(PlayerId)} instead.
*/
@Deprecated
default boolean retainBackBufferFromKeyframe() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("retainBackBufferFromKeyframe not implemented");
}
/**
* Called by the player to determine whether it should continue to load the source. If this method
* returns true, the {@link MediaPeriod} identified in the most recent {@link #onTracksSelected}
* call will continue being loaded.
*
* @param playerId The {@linkplain PlayerId ID of the player} that wants to continue loading.
* @param timeline The current {@link Timeline} in ExoPlayer.
* @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} that is
* currently loading.
* @param playbackPositionUs The current playback position in microseconds, relative to the start
* of the {@link Timeline.Period period} that will continue to be loaded if this method
* returns {@code true}. If playback of this period has not yet started, the value will be
@ -131,8 +233,28 @@ public interface LoadControl {
* @param playbackSpeed The current factor by which playback is sped up.
* @return Whether the loading should continue.
*/
boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed);
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default boolean shouldContinueLoading(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodId,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return shouldContinueLoading(playbackPositionUs, bufferedDurationUs, playbackSpeed);
}
/**
* @deprecated Implement {@link #shouldContinueLoading(PlayerId, Timeline, MediaPeriodId, long,
* long, float)} instead.
*/
@Deprecated
default boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("shouldContinueLoading not implemented");
}
/**
* Called repeatedly by the player when it's loading the source, has yet to start playback, and
@ -140,6 +262,7 @@ public interface LoadControl {
* determines whether playback is actually started. The load control may opt to return {@code
* false} until some condition has been met (e.g. a certain amount of media is buffered).
*
* @param playerId The {@linkplain PlayerId ID of the player} that wants to start playback.
* @param timeline The current {@link Timeline} in ExoPlayer. Can be {@link Timeline#EMPTY} only
* when the deprecated {@link #shouldStartPlayback(long, float, boolean, long)} was called.
* @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} for which
@ -156,29 +279,48 @@ public interface LoadControl {
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodId,
long bufferedDurationUs,
float playbackSpeed,
boolean rebuffering,
long targetLiveOffsetUs) {
return shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering, targetLiveOffsetUs);
}
/**
* @deprecated Implement {@link #shouldStartPlayback(Timeline, MediaPeriodId, long, float,
* boolean, long)} instead.
*/
@SuppressWarnings("deprecation") // Intentionally referencing deprecated constant
@Deprecated
default boolean shouldStartPlayback(
long bufferedDurationUs, float playbackSpeed, boolean rebuffering, long targetLiveOffsetUs) {
return shouldStartPlayback(
Timeline.EMPTY,
EMPTY_MEDIA_PERIOD_ID,
timeline,
mediaPeriodId,
bufferedDurationUs,
playbackSpeed,
rebuffering,
targetLiveOffsetUs);
}
/**
* @deprecated Implement {@link #shouldStartPlayback(PlayerId, Timeline, MediaPeriodId, long,
* float, boolean, long)} instead.
*/
@Deprecated
default boolean shouldStartPlayback(
Timeline timeline,
MediaPeriodId mediaPeriodId,
long bufferedDurationUs,
float playbackSpeed,
boolean rebuffering,
long targetLiveOffsetUs) {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("shouldStartPlayback not implemented");
}
/**
* @deprecated Implement {@link #shouldStartPlayback(PlayerId, Timeline, MediaPeriodId, long,
* float, boolean, long)} instead.
*/
@Deprecated
default boolean shouldStartPlayback(
long bufferedDurationUs, float playbackSpeed, boolean rebuffering, long targetLiveOffsetUs) {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("shouldStartPlayback not implemented");
}
}

View file

@ -23,6 +23,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlayer.Builder;
import java.util.Objects;
/** Identifier for a player instance. */
@UnstableApi
@ -32,28 +34,69 @@ public final class PlayerId {
* A player identifier with unset default values that can be used as a placeholder or for testing.
*/
public static final PlayerId UNSET =
Util.SDK_INT < 31 ? new PlayerId() : new PlayerId(LogSessionIdApi31.UNSET);
Util.SDK_INT < 31
? new PlayerId(/* playerName= */ "")
: new PlayerId(LogSessionIdApi31.UNSET, /* playerName= */ "");
/**
* A name to identify the player. Use {@link Builder#setName(String)} to set the name, otherwise
* an empty string is used as the default.
*/
public final String name;
@Nullable private final LogSessionIdApi31 logSessionIdApi31;
/** Creates an instance for API &lt; 31. */
public PlayerId() {
/**
* An object used for equals/hashCode below API 31 or when the MediaMetricsService is unavailable.
*/
@Nullable private final Object equalityToken;
/**
* Creates an instance for API &lt; 31.
*
* @param playerName The name of the player, for informational purpose only.
*/
public PlayerId(String playerName) {
checkState(Util.SDK_INT < 31);
this.name = playerName;
this.logSessionIdApi31 = null;
equalityToken = new Object();
}
/**
* Creates an instance for API &ge; 31.
*
* @param logSessionId The {@link LogSessionId} used for this player.
* @param playerName The name of the player, for informational purpose only.
*/
@RequiresApi(31)
public PlayerId(LogSessionId logSessionId) {
this(new LogSessionIdApi31(logSessionId));
public PlayerId(LogSessionId logSessionId, String playerName) {
this(new LogSessionIdApi31(logSessionId), playerName);
}
private PlayerId(LogSessionIdApi31 logSessionIdApi31) {
private PlayerId(LogSessionIdApi31 logSessionIdApi31, String playerName) {
this.logSessionIdApi31 = logSessionIdApi31;
this.name = playerName;
equalityToken = new Object();
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof PlayerId)) {
return false;
}
PlayerId playerId = (PlayerId) o;
return Objects.equals(name, playerId.name)
&& Objects.equals(logSessionIdApi31, playerId.logSessionIdApi31)
&& Objects.equals(equalityToken, playerId.equalityToken);
}
@Override
public int hashCode() {
return Objects.hash(name, logSessionIdApi31, equalityToken);
}
/** Returns the {@link LogSessionId} for this player instance. */

View file

@ -137,6 +137,7 @@ import androidx.media3.common.util.Util;
import androidx.media3.datasource.TransferListener;
import androidx.media3.decoder.DecoderInputBuffer;
import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.audio.AudioRendererEventListener;
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
import androidx.media3.exoplayer.drm.DrmSessionManager;
@ -5931,12 +5932,20 @@ public final class ExoPlayerTest {
new DefaultLoadControl() {
@Override
public boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) {
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return false;
}
@Override
public boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long bufferedDurationUs,
float playbackSpeed,
boolean rebuffering,
@ -5978,12 +5987,20 @@ public final class ExoPlayerTest {
new DefaultLoadControl() {
@Override
public boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) {
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return bufferedDurationUs < maxBufferUs;
}
@Override
public boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long bufferedDurationUs,
float playbackSpeed,
boolean rebuffering,
@ -6058,12 +6075,20 @@ public final class ExoPlayerTest {
new DefaultLoadControl() {
@Override
public boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) {
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return true;
}
@Override
public boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long bufferedDurationUs,
float playbackSpeed,
boolean rebuffering,
@ -12947,7 +12972,7 @@ public final class ExoPlayerTest {
spy(
new DefaultLoadControl() {
@Override
public void onReleased() {
public void onReleased(PlayerId playerId) {
// Emulate a failure during player release.
throw new RuntimeException();
}
@ -12958,13 +12983,13 @@ public final class ExoPlayerTest {
.build();
player.addListener(listener);
// Ensure load control has not thrown the exception yet.
verify(loadControl, never()).onReleased();
verify(loadControl, never()).onReleased(any());
player.release();
ShadowLooper.idleMainLooper();
// Verify load control threw the exception.
verify(loadControl).onReleased();
verify(loadControl).onReleased(any());
verify(listener, never()).onPlayerError(any());
}

View file

@ -62,7 +62,6 @@ import org.mockito.Mock;
@RunWith(AndroidJUnit4.class)
public class DefaultPreloadManagerTest {
@Mock private TargetPreloadStatusControl<Integer> mockTargetPreloadStatusControl;
private PlayerId playerId;
private TrackSelector trackSelector;
private Allocator allocator;
private BandwidthMeter bandwidthMeter;
@ -70,7 +69,6 @@ public class DefaultPreloadManagerTest {
@Before
public void setUp() {
playerId = new PlayerId();
trackSelector = new DefaultTrackSelector(ApplicationProvider.getApplicationContext());
allocator = new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
bandwidthMeter =
@ -252,7 +250,7 @@ public class DefaultPreloadManagerTest {
PreloadMediaSource preloadMediaSource2 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem2);
preloadMediaSource2.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadManager.setCurrentPlayingIndex(2);
preloadManager.invalidate();
shadowOf(Looper.getMainLooper()).idle();
@ -303,7 +301,7 @@ public class DefaultPreloadManagerTest {
PreloadMediaSource preloadMediaSource0 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem0);
preloadMediaSource0.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadManager.setCurrentPlayingIndex(0);
preloadManager.invalidate();
shadowOf(Looper.getMainLooper()).idle();
@ -314,7 +312,7 @@ public class DefaultPreloadManagerTest {
PreloadMediaSource preloadMediaSource2 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem2);
preloadMediaSource2.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadManager.setCurrentPlayingIndex(2);
preloadManager.invalidate();
shadowOf(Looper.getMainLooper()).idle();

View file

@ -63,7 +63,6 @@ import org.robolectric.shadows.ShadowLooper;
@RunWith(AndroidJUnit4.class)
public class PreloadAndPlaybackCoordinationTest {
private final PlayerId playerId;
private final BandwidthMeter bandwidthMeter;
private final PreloadMediaSource preloadMediaSource;
private final FakeMediaSource wrappedMediaSource;
@ -76,7 +75,6 @@ public class PreloadAndPlaybackCoordinationTest {
private final AtomicReference<MediaPeriod> preloadMediaPeriodReference;
public PreloadAndPlaybackCoordinationTest() {
playerId = new PlayerId();
Context context = ApplicationProvider.getApplicationContext();
bandwidthMeter = new DefaultBandwidthMeter.Builder(context).build();
FakeMediaSourceFactory mediaSourceFactory = new FakeMediaSourceFactory();
@ -165,7 +163,7 @@ public class PreloadAndPlaybackCoordinationTest {
@Test
public void playbackWithoutPreload_reusableForPreloadAfterRelease() {
preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId);
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
ShadowLooper.idleMainLooper();
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0);
@ -188,7 +186,7 @@ public class PreloadAndPlaybackCoordinationTest {
@Test
public void playbackBeforePreload_reusableForPreloadAfterRelease() {
preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId);
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper();
@ -216,7 +214,7 @@ public class PreloadAndPlaybackCoordinationTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper();
preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId);
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
wrappedMediaSource.setAllowPreparation(true);
ShadowLooper.idleMainLooper();
@ -245,7 +243,7 @@ public class PreloadAndPlaybackCoordinationTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper();
preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId);
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
FakeMediaPeriod lastCreatedActiveMediaPeriod =
(FakeMediaPeriod) wrappedMediaSource.getLastCreatedActiveMediaPeriod();
lastCreatedActiveMediaPeriod.setPreparationComplete();
@ -274,7 +272,7 @@ public class PreloadAndPlaybackCoordinationTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper();
preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId);
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
ShadowLooper.idleMainLooper();
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1);

View file

@ -80,7 +80,6 @@ public final class PreloadMediaSourceTest {
private Allocator allocator;
private BandwidthMeter bandwidthMeter;
private RenderersFactory renderersFactory;
private PlayerId playerId;
@Before
public void setUp() {
@ -97,7 +96,6 @@ public final class PreloadMediaSourceTest {
SystemClock.DEFAULT.createHandler(handler.getLooper(), /* callback= */ null),
audioListener)
};
playerId = new PlayerId();
}
@Test
@ -326,7 +324,7 @@ public final class PreloadMediaSourceTest {
}
};
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.preload(/* startPositionUs= */ 0L);
shadowOf(Looper.getMainLooper()).idle();
@ -391,7 +389,7 @@ public final class PreloadMediaSourceTest {
}
};
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
wrappedMediaSource.setAllowPreparation(true);
shadowOf(Looper.getMainLooper()).idle();
@ -453,7 +451,7 @@ public final class PreloadMediaSourceTest {
}
};
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
assertThat(onTimelineRefreshedCalled.get()).isTrue();
assertThat(onPreparedCalled.get()).isTrue();
@ -551,7 +549,7 @@ public final class PreloadMediaSourceTest {
}
};
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
Pair<Object, Long> periodPosition =
externalCallerSourceInfoTimelineReference
.get()
@ -658,7 +656,7 @@ public final class PreloadMediaSourceTest {
}
};
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
// Create a period from different position.
Pair<Object, Long> periodPosition =
externalCallerSourceInfoTimelineReference
@ -740,7 +738,7 @@ public final class PreloadMediaSourceTest {
}
};
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.releaseSource(externalCaller);
@ -819,7 +817,7 @@ public final class PreloadMediaSourceTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L);
shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadMediaSource.releaseSource(externalCaller);
assertThat(onTimelineRefreshedCalled.get()).isTrue();
@ -903,9 +901,9 @@ public final class PreloadMediaSourceTest {
}
};
preloadMediaSource.prepareSource(
externalCaller1, bandwidthMeter.getTransferListener(), playerId);
externalCaller1, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadMediaSource.prepareSource(
externalCaller2, bandwidthMeter.getTransferListener(), playerId);
externalCaller2, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
// Only releaseSource by externalCaller1.
preloadMediaSource.releaseSource(externalCaller1);
@ -1054,7 +1052,7 @@ public final class PreloadMediaSourceTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L);
shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId);
externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.releasePreloadMediaSource();
shadowOf(Looper.getMainLooper()).idle();