Enhance continueLoading() API to allow passing more information
Modifies the `SequenceableLoader.continueLoading(long)` method in the `SequenceableLoader` interface to `SequenceableLoader.continueLoading(LoadingInfo)`. `LoadingInfo` contains additional parameters, including `playbackSpeed` and `lastRebufferRealtimeMs` in addition to the existing `playbackPositionUs`. The additional parameters will allow us to pass these information to Common Media Client Data (CMCD) logging. By using the `LoadingInfo` object, we ensure future flexibility to add more fields without causing any breaking changes to the API. PiperOrigin-RevId: 555123961
This commit is contained in:
parent
2da3cc71e5
commit
481ea4a274
@ -43,6 +43,12 @@
|
||||
`MimeTypes.APPLICATION_MEDIA3_CUES`.
|
||||
* Add `PngExtractor` that sends and reads a whole png file into the the
|
||||
`TrackOutput` as one sample.
|
||||
* Enhance `SequenceableLoader.continueLoading(long)` method in the
|
||||
`SequenceableLoader` interface to
|
||||
`SequenceableLoader.continueLoading(LoadingInfo loadingInfo)`.
|
||||
`LoadingInfo` contains additional parameters, including `playbackSpeed`
|
||||
and `lastRebufferRealtimeMs` in addition to the existing
|
||||
`playbackPositionUs`.
|
||||
* Transformer:
|
||||
* Parse EXIF rotation data for image inputs.
|
||||
* Remove `TransformationRequest.HdrMode` annotation type and its
|
||||
|
@ -218,6 +218,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
private boolean pauseAtEndOfWindow;
|
||||
private boolean pendingPauseAtEndOfPeriod;
|
||||
private boolean isRebuffering;
|
||||
private long lastRebufferRealtimeMs;
|
||||
private boolean shouldContinueLoading;
|
||||
private @Player.RepeatMode int repeatMode;
|
||||
private boolean shuffleModeEnabled;
|
||||
@ -267,6 +268,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
this.clock = clock;
|
||||
|
||||
playbackMaybeBecameStuckAtMs = C.TIME_UNSET;
|
||||
lastRebufferRealtimeMs = C.TIME_UNSET;
|
||||
backBufferDurationUs = loadControl.getBackBufferDurationUs();
|
||||
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe();
|
||||
|
||||
@ -852,7 +854,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
playbackInfoUpdate.incrementPendingOperationAcks(operationAck ? 1 : 0);
|
||||
playbackInfoUpdate.setPlayWhenReadyChangeReason(reason);
|
||||
playbackInfo = playbackInfo.copyWithPlayWhenReady(playWhenReady, playbackSuppressionReason);
|
||||
isRebuffering = false;
|
||||
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ false);
|
||||
notifyTrackSelectionPlayWhenReadyChanged(playWhenReady);
|
||||
if (!shouldPlayWhenReady()) {
|
||||
stopRenderers();
|
||||
@ -931,7 +933,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
}
|
||||
|
||||
private void startRenderers() throws ExoPlaybackException {
|
||||
isRebuffering = false;
|
||||
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ false);
|
||||
mediaClock.start();
|
||||
for (Renderer renderer : renderers) {
|
||||
if (isRendererEnabled(renderer)) {
|
||||
@ -1120,7 +1122,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
}
|
||||
} else if (playbackInfo.playbackState == Player.STATE_READY
|
||||
&& !(enabledRendererCount == 0 ? isTimelineReady() : renderersAllowPlayback)) {
|
||||
isRebuffering = shouldPlayWhenReady();
|
||||
updateRebufferingState(
|
||||
/* isRebuffering= */ shouldPlayWhenReady(), /* resetLastRebufferRealtimeMs= */ false);
|
||||
setState(Player.STATE_BUFFERING);
|
||||
if (isRebuffering) {
|
||||
notifyTrackSelectionRebuffer();
|
||||
@ -1334,7 +1337,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
boolean forceBufferingState)
|
||||
throws ExoPlaybackException {
|
||||
stopRenderers();
|
||||
isRebuffering = false;
|
||||
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ true);
|
||||
if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
|
||||
setState(Player.STATE_BUFFERING);
|
||||
}
|
||||
@ -1475,7 +1478,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
boolean resetError) {
|
||||
handler.removeMessages(MSG_DO_SOME_WORK);
|
||||
pendingRecoverableRendererError = null;
|
||||
isRebuffering = false;
|
||||
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ true);
|
||||
mediaClock.stop();
|
||||
rendererPositionUs = MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US;
|
||||
for (Renderer renderer : renderers) {
|
||||
@ -2436,7 +2439,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
private void maybeContinueLoading() {
|
||||
shouldContinueLoading = shouldContinueLoading();
|
||||
if (shouldContinueLoading) {
|
||||
queue.getLoadingPeriod().continueLoading(rendererPositionUs);
|
||||
queue
|
||||
.getLoadingPeriod()
|
||||
.continueLoading(
|
||||
rendererPositionUs, mediaClock.getPlaybackParameters().speed, lastRebufferRealtimeMs);
|
||||
}
|
||||
updateIsLoading();
|
||||
}
|
||||
@ -2907,6 +2913,23 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
return timeline.isEmpty() || timeline.getPeriodByUid(periodId.periodUid, period).isPlaceholder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the {@link #isRebuffering} state and the timestamp of the last rebuffering event.
|
||||
*
|
||||
* @param isRebuffering A boolean indicating whether the media playback is currently rebuffering.
|
||||
* @param resetLastRebufferRealtimeMs A boolean indicating whether {@link #lastRebufferRealtimeMs}
|
||||
* should be reset.<br>
|
||||
* If set to {@code true}, the method resets the {@link #lastRebufferRealtimeMs} to {@link
|
||||
* C#TIME_UNSET}.<br>
|
||||
* If set to {@code false}, the method updates the {@link #lastRebufferRealtimeMs} with the
|
||||
* current value of {@link Clock#elapsedRealtime()}.
|
||||
*/
|
||||
private void updateRebufferingState(boolean isRebuffering, boolean resetLastRebufferRealtimeMs) {
|
||||
this.isRebuffering = isRebuffering;
|
||||
this.lastRebufferRealtimeMs =
|
||||
resetLastRebufferRealtimeMs ? C.TIME_UNSET : clock.elapsedRealtime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates pending message to a new timeline.
|
||||
*
|
||||
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package androidx.media3.exoplayer;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
|
||||
/** Information about the player state when loading is started or continued. */
|
||||
@UnstableApi
|
||||
public final class LoadingInfo {
|
||||
|
||||
/** A builder for {@link LoadingInfo} instances. */
|
||||
public static final class Builder {
|
||||
private long playbackPositionUs;
|
||||
private float playbackSpeed;
|
||||
private long lastRebufferRealtimeMs;
|
||||
|
||||
/** Creates a new instance with default values. */
|
||||
public Builder() {
|
||||
this.playbackPositionUs = C.TIME_UNSET;
|
||||
this.playbackSpeed = C.RATE_UNSET;
|
||||
this.lastRebufferRealtimeMs = C.TIME_UNSET;
|
||||
}
|
||||
|
||||
private Builder(LoadingInfo loadingInfo) {
|
||||
this.playbackPositionUs = loadingInfo.playbackPositionUs;
|
||||
this.playbackSpeed = loadingInfo.playbackSpeed;
|
||||
this.lastRebufferRealtimeMs = loadingInfo.lastRebufferRealtimeMs;
|
||||
}
|
||||
|
||||
/** Sets {@link LoadingInfo#playbackPositionUs}. The default is {@link C#TIME_UNSET} */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setPlaybackPositionUs(long playbackPositionUs) {
|
||||
this.playbackPositionUs = playbackPositionUs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link LoadingInfo#playbackSpeed}. The default is {@link C#RATE_UNSET}
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code playbackSpeed} is not equal to {@link
|
||||
* C#RATE_UNSET} and is non-positive.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setPlaybackSpeed(float playbackSpeed) {
|
||||
checkArgument(playbackSpeed > 0 || playbackSpeed == C.RATE_UNSET);
|
||||
this.playbackSpeed = playbackSpeed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link LoadingInfo#lastRebufferRealtimeMs}. The default is {@link C#TIME_UNSET}
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code lastRebufferRealtimeMs} is not equal to {@link
|
||||
* C#TIME_UNSET} and is negative.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setLastRebufferRealtimeMs(long lastRebufferRealtimeMs) {
|
||||
checkArgument(lastRebufferRealtimeMs >= 0 || lastRebufferRealtimeMs == C.TIME_UNSET);
|
||||
this.lastRebufferRealtimeMs = lastRebufferRealtimeMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns a new {@link LoadingInfo} instance with the current builder values. */
|
||||
public LoadingInfo build() {
|
||||
return new LoadingInfo(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The current playback position in microseconds, or {@link C#TIME_UNSET} if unset. If playback of
|
||||
* the period to which this loading info belongs has not yet started, the value will be the
|
||||
* starting position in the period minus the duration of any media in previous periods still to be
|
||||
* played.
|
||||
*/
|
||||
public final long playbackPositionUs;
|
||||
|
||||
/**
|
||||
* The playback speed indicating the current rate of playback, or {@link C#RATE_UNSET} if playback
|
||||
* speed is not known when the load is started or continued.
|
||||
*/
|
||||
public final float playbackSpeed;
|
||||
|
||||
/**
|
||||
* Sets the time at which the last rebuffering occurred, in milliseconds since boot including time
|
||||
* spent in sleep.
|
||||
*
|
||||
* <p>The time base used is the same as that measured by {@link SystemClock#elapsedRealtime}.
|
||||
*
|
||||
* <p><b>Note:</b> If rebuffer events are not known when the load is started or continued, or if
|
||||
* no rebuffering has occurred, or if there have been any user interactions such as seeking or
|
||||
* stopping the player, the value will be set to {@link C#TIME_UNSET}.
|
||||
*/
|
||||
public final long lastRebufferRealtimeMs;
|
||||
|
||||
private LoadingInfo(Builder builder) {
|
||||
this.playbackPositionUs = builder.playbackPositionUs;
|
||||
this.playbackSpeed = builder.playbackSpeed;
|
||||
this.lastRebufferRealtimeMs = builder.lastRebufferRealtimeMs;
|
||||
}
|
||||
|
||||
/** Creates a new {@link Builder}, copying the initial values from this instance. */
|
||||
public LoadingInfo.Builder buildUpon() {
|
||||
return new LoadingInfo.Builder(this);
|
||||
}
|
||||
}
|
@ -222,11 +222,21 @@ import androidx.media3.exoplayer.upstream.Allocator;
|
||||
* this is the loading media period.
|
||||
*
|
||||
* @param rendererPositionUs The load position in renderer time, in microseconds.
|
||||
* @param playbackSpeed The playback speed indicating the current rate of playback.
|
||||
* @param lastRebufferRealtimeMs The time at which the last rebuffering occurred, in milliseconds
|
||||
* since boot including time spent in sleep. The time base used is the same as that measured
|
||||
* by {@link android.os.SystemClock#elapsedRealtime}.
|
||||
*/
|
||||
public void continueLoading(long rendererPositionUs) {
|
||||
public void continueLoading(
|
||||
long rendererPositionUs, float playbackSpeed, long lastRebufferRealtimeMs) {
|
||||
Assertions.checkState(isLoadingMediaPeriod());
|
||||
long loadingPeriodPositionUs = toPeriodTime(rendererPositionUs);
|
||||
mediaPeriod.continueLoading(loadingPeriodPositionUs);
|
||||
mediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder()
|
||||
.setPlaybackPositionUs(loadingPeriodPositionUs)
|
||||
.setPlaybackSpeed(playbackSpeed)
|
||||
.setLastRebufferRealtimeMs(lastRebufferRealtimeMs)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,7 +164,8 @@ public final class MetadataRetriever {
|
||||
}
|
||||
return true;
|
||||
case MESSAGE_CONTINUE_LOADING:
|
||||
checkNotNull(mediaPeriod).continueLoading(/* positionUs= */ 0);
|
||||
checkNotNull(mediaPeriod)
|
||||
.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
return true;
|
||||
case MESSAGE_RELEASE:
|
||||
if (mediaPeriod != null) {
|
||||
|
@ -39,6 +39,7 @@ import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.Renderer;
|
||||
import androidx.media3.exoplayer.RendererCapabilities;
|
||||
import androidx.media3.exoplayer.RenderersFactory;
|
||||
@ -896,7 +897,7 @@ public final class DownloadHelper {
|
||||
case MESSAGE_CONTINUE_LOADING:
|
||||
MediaPeriod mediaPeriod = (MediaPeriod) msg.obj;
|
||||
if (pendingMediaPeriods.contains(mediaPeriod)) {
|
||||
mediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
mediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
return true;
|
||||
case MESSAGE_RELEASE:
|
||||
|
@ -25,6 +25,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.source.ClippingMediaSource.IllegalClippingException;
|
||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||
@ -222,8 +223,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return mediaPeriod.continueLoading(positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return mediaPeriod.continueLoading(loadingInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,6 +19,7 @@ import static java.lang.Math.min;
|
||||
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
|
||||
/** A {@link SequenceableLoader} that encapsulates multiple other {@link SequenceableLoader}s. */
|
||||
@UnstableApi
|
||||
@ -62,7 +63,7 @@ public class CompositeSequenceableLoader implements SequenceableLoader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
boolean madeProgress = false;
|
||||
boolean madeProgressThisIteration;
|
||||
do {
|
||||
@ -75,9 +76,9 @@ public class CompositeSequenceableLoader implements SequenceableLoader {
|
||||
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
|
||||
boolean isLoaderBehind =
|
||||
loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE
|
||||
&& loaderNextLoadPositionUs <= positionUs;
|
||||
&& loaderNextLoadPositionUs <= loadingInfo.playbackPositionUs;
|
||||
if (loaderNextLoadPositionUs == nextLoadPositionUs || isLoaderBehind) {
|
||||
madeProgressThisIteration |= loader.continueLoading(positionUs);
|
||||
madeProgressThisIteration |= loader.continueLoading(loadingInfo);
|
||||
}
|
||||
}
|
||||
madeProgress |= madeProgressThisIteration;
|
||||
|
@ -23,6 +23,7 @@ import androidx.media3.common.StreamKey;
|
||||
import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||
import androidx.media3.exoplayer.upstream.Allocator;
|
||||
@ -155,8 +156,8 @@ public class FilteringMediaSource extends WrappingMediaSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return mediaPeriod.continueLoading(positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return mediaPeriod.continueLoading(loadingInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
|
||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||
@ -224,8 +225,8 @@ public final class MaskingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return mediaPeriod != null && mediaPeriod.continueLoading(positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return mediaPeriod != null && mediaPeriod.continueLoading(loadingInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,6 +22,7 @@ import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.source.MediaSource.MediaSourceCaller;
|
||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||
@ -231,14 +232,12 @@ public interface MediaPeriod extends SequenceableLoader {
|
||||
* called when the period is permitted to continue loading data. A period may do this both during
|
||||
* and after preparation.
|
||||
*
|
||||
* @param positionUs The current playback position in microseconds. If playback of this period has
|
||||
* not yet started, the value will be the starting position in this period minus the duration
|
||||
* of any media in previous periods still to be played.
|
||||
* @param loadingInfo The {@link LoadingInfo} when attempting to continue loading.
|
||||
* @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a
|
||||
* different value than prior to the call. False otherwise.
|
||||
*/
|
||||
@Override
|
||||
boolean continueLoading(long positionUs);
|
||||
boolean continueLoading(LoadingInfo loadingInfo);
|
||||
|
||||
/** Returns whether the media period is currently loading. */
|
||||
@Override
|
||||
|
@ -26,6 +26,7 @@ import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.source.chunk.Chunk;
|
||||
import androidx.media3.exoplayer.source.chunk.MediaChunk;
|
||||
@ -192,16 +193,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
if (!childrenPendingPreparation.isEmpty()) {
|
||||
// Preparation is still going on.
|
||||
int childrenPendingPreparationSize = childrenPendingPreparation.size();
|
||||
for (int i = 0; i < childrenPendingPreparationSize; i++) {
|
||||
childrenPendingPreparation.get(i).continueLoading(positionUs);
|
||||
childrenPendingPreparation.get(i).continueLoading(loadingInfo);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return compositeSequenceableLoader.continueLoading(positionUs);
|
||||
return compositeSequenceableLoader.continueLoading(loadingInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,8 +407,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return mediaPeriod.continueLoading(positionUs - timeOffsetUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return mediaPeriod.continueLoading(
|
||||
loadingInfo
|
||||
.buildUpon()
|
||||
.setPlaybackPositionUs(loadingInfo.playbackPositionUs - timeOffsetUs)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,6 +40,7 @@ import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.StatsDataSource;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
@ -343,7 +344,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long playbackPositionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
if (loadingFinished
|
||||
|| loader.hasFatalError()
|
||||
|| pendingDeferredRetry
|
||||
|
@ -17,6 +17,7 @@ package androidx.media3.exoplayer.source;
|
||||
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
|
||||
// TODO: Clarify the requirements for implementing this interface [Internal ref: b/36250203].
|
||||
/** A loader that can proceed in approximate synchronization with other loaders. */
|
||||
@ -27,8 +28,8 @@ public interface SequenceableLoader {
|
||||
interface Callback<T extends SequenceableLoader> {
|
||||
|
||||
/**
|
||||
* Called by the loader to indicate that it wishes for its {@link #continueLoading(long)} method
|
||||
* to be called when it can continue to load data. Called on the playback thread.
|
||||
* Called by the loader to indicate that it wishes for its {@link #continueLoading(LoadingInfo)}
|
||||
* method to be called when it can continue to load data. Called on the playback thread.
|
||||
*/
|
||||
void onContinueLoadingRequested(T source);
|
||||
}
|
||||
@ -47,13 +48,11 @@ public interface SequenceableLoader {
|
||||
/**
|
||||
* Attempts to continue loading.
|
||||
*
|
||||
* @param positionUs The current playback position in microseconds. If playback of the period to
|
||||
* which this loader belongs has not yet started, the value will be the starting position in
|
||||
* the period minus the duration of any media in previous periods still to be played.
|
||||
* @param loadingInfo The {@link LoadingInfo} when attempting to continue loading.
|
||||
* @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a
|
||||
* different value than prior to the call. False otherwise.
|
||||
*/
|
||||
boolean continueLoading(long positionUs);
|
||||
boolean continueLoading(LoadingInfo loadingInfo);
|
||||
|
||||
/** Returns whether the loader is currently loading. */
|
||||
boolean isLoading();
|
||||
|
@ -34,6 +34,7 @@ import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||
import androidx.media3.exoplayer.upstream.Allocator;
|
||||
@ -257,7 +258,7 @@ public final class SilenceMediaSource extends BaseMediaSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import androidx.media3.datasource.StatsDataSource;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.source.MediaSourceEventListener.EventDispatcher;
|
||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||
@ -145,7 +146,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.drm.DrmSession;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
@ -741,7 +742,7 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
||||
return actualMediaPeriod.getStreamKeys(trackSelections);
|
||||
}
|
||||
|
||||
public boolean continueLoading(MediaPeriodImpl mediaPeriod, long positionUs) {
|
||||
public boolean continueLoading(MediaPeriodImpl mediaPeriod, LoadingInfo loadingInfo) {
|
||||
@Nullable MediaPeriodImpl loadingPeriod = this.loadingPeriod;
|
||||
if (loadingPeriod != null && !mediaPeriod.equals(loadingPeriod)) {
|
||||
for (Pair<LoadEventInfo, MediaLoadData> loadData : activeLoads.values()) {
|
||||
@ -754,8 +755,9 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
||||
}
|
||||
this.loadingPeriod = mediaPeriod;
|
||||
long actualPlaybackPositionUs =
|
||||
getStreamPositionUsWithNotYetStartedHandling(mediaPeriod, positionUs);
|
||||
return actualMediaPeriod.continueLoading(actualPlaybackPositionUs);
|
||||
getStreamPositionUsWithNotYetStartedHandling(mediaPeriod, loadingInfo.playbackPositionUs);
|
||||
return actualMediaPeriod.continueLoading(
|
||||
loadingInfo.buildUpon().setPlaybackPositionUs(actualPlaybackPositionUs).build());
|
||||
}
|
||||
|
||||
public boolean isLoading(MediaPeriodImpl mediaPeriod) {
|
||||
@ -1209,8 +1211,8 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return sharedPeriod.continueLoading(/* mediaPeriod= */ this, positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return sharedPeriod.continueLoading(/* mediaPeriod= */ this, loadingInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,6 +28,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.drm.DrmSession;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
@ -561,7 +562,7 @@ public class ChunkSampleStream<T extends ChunkSource>
|
||||
// SequenceableLoader implementation
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
||||
return false;
|
||||
}
|
||||
@ -576,7 +577,8 @@ public class ChunkSampleStream<T extends ChunkSource>
|
||||
chunkQueue = readOnlyMediaChunks;
|
||||
loadPositionUs = getLastMediaChunk().endTimeUs;
|
||||
}
|
||||
chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
|
||||
chunkSource.getNextChunk(
|
||||
loadingInfo.playbackPositionUs, loadPositionUs, chunkQueue, nextChunkHolder);
|
||||
boolean endOfStream = nextChunkHolder.endOfStream;
|
||||
@Nullable Chunk loadable = nextChunkHolder.chunk;
|
||||
nextChunkHolder.clear();
|
||||
|
@ -8679,7 +8679,7 @@ public final class ExoPlayerTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
allocations.add(allocator.allocate());
|
||||
callback.onContinueLoadingRequested(this);
|
||||
return true;
|
||||
@ -8744,8 +8744,8 @@ public final class ExoPlayerTest {
|
||||
private final Loader loader = new Loader("ExoPlayerTest");
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
super.continueLoading(positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
super.continueLoading(loadingInfo);
|
||||
if (!loader.isLoading()) {
|
||||
loader.startLoading(
|
||||
loadable, new FakeLoaderCallback(), /* defaultMinRetryCount= */ 1);
|
||||
|
@ -25,6 +25,7 @@ import androidx.media3.common.Format;
|
||||
import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||
@ -116,7 +117,8 @@ public class ClippingMediaPeriodTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
clippingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
clippingMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.source;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -130,9 +131,9 @@ public final class CompositeSequenceableLoaderTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} only allows the loader
|
||||
* with minimum next load position to continue loading if next load positions are not behind
|
||||
* current playback position.
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} only allows the
|
||||
* loader with minimum next load position to continue loading if next load positions are not
|
||||
* behind current playback position.
|
||||
*/
|
||||
@Test
|
||||
public void continueLoadingOnlyAllowFurthestBehindLoaderToLoadIfNotBehindPlaybackPosition() {
|
||||
@ -142,15 +143,16 @@ public final class CompositeSequenceableLoaderTest {
|
||||
new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001);
|
||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
||||
compositeSequenceableLoader.continueLoading(100);
|
||||
compositeSequenceableLoader.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(100).build());
|
||||
|
||||
assertThat(loader1.numInvocations).isEqualTo(1);
|
||||
assertThat(loader2.numInvocations).isEqualTo(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} allows all loaders with
|
||||
* next load position behind current playback position to continue loading.
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} allows all loaders
|
||||
* with next load position behind current playback position to continue loading.
|
||||
*/
|
||||
@Test
|
||||
public void continueLoadingReturnAllowAllLoadersBehindPlaybackPositionToLoad() {
|
||||
@ -162,7 +164,8 @@ public final class CompositeSequenceableLoaderTest {
|
||||
new FakeSequenceableLoader(/* bufferedPositionUs */ 1002, /* nextLoadPositionUs */ 2002);
|
||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3});
|
||||
compositeSequenceableLoader.continueLoading(3000);
|
||||
compositeSequenceableLoader.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(3000).build());
|
||||
|
||||
assertThat(loader1.numInvocations).isEqualTo(1);
|
||||
assertThat(loader2.numInvocations).isEqualTo(1);
|
||||
@ -170,8 +173,8 @@ public final class CompositeSequenceableLoaderTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} does not allow loader with
|
||||
* next load position at end-of-source to continue loading.
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} does not allow
|
||||
* loader with next load position at end-of-source to continue loading.
|
||||
*/
|
||||
@Test
|
||||
public void continueLoadingOnlyNotAllowEndOfSourceLoaderToLoad() {
|
||||
@ -183,16 +186,17 @@ public final class CompositeSequenceableLoaderTest {
|
||||
/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
|
||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
||||
compositeSequenceableLoader.continueLoading(3000);
|
||||
compositeSequenceableLoader.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(3000).build());
|
||||
|
||||
assertThat(loader1.numInvocations).isEqualTo(0);
|
||||
assertThat(loader2.numInvocations).isEqualTo(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} returns true if the loader
|
||||
* with minimum next load position can make progress if next load positions are not behind current
|
||||
* playback position.
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} returns true if the
|
||||
* loader with minimum next load position can make progress if next load positions are not behind
|
||||
* current playback position.
|
||||
*/
|
||||
@Test
|
||||
public void continueLoadingReturnTrueIfFurthestBehindLoaderCanMakeProgress() {
|
||||
@ -205,13 +209,16 @@ public final class CompositeSequenceableLoaderTest {
|
||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
||||
|
||||
assertThat(compositeSequenceableLoader.continueLoading(100)).isTrue();
|
||||
assertThat(
|
||||
compositeSequenceableLoader.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(100).build()))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} returns true if any loader
|
||||
* that are behind current playback position can make progress, even if it is not the one with
|
||||
* minimum next load position.
|
||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} returns true if any
|
||||
* loader that are behind current playback position can make progress, even if it is not the one
|
||||
* with minimum next load position.
|
||||
*/
|
||||
@Test
|
||||
public void continueLoadingReturnTrueIfLoaderBehindPlaybackPositionCanMakeProgress() {
|
||||
@ -225,7 +232,10 @@ public final class CompositeSequenceableLoaderTest {
|
||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
||||
|
||||
assertThat(compositeSequenceableLoader.continueLoading(3000)).isTrue();
|
||||
assertThat(
|
||||
compositeSequenceableLoader.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(3000).build()))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
private static class FakeSequenceableLoader implements SequenceableLoader {
|
||||
@ -251,7 +261,7 @@ public final class CompositeSequenceableLoaderTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
numInvocations++;
|
||||
boolean loaded = nextChunkDurationUs != 0;
|
||||
// The current chunk has been loaded, advance to next chunk.
|
||||
|
@ -41,6 +41,7 @@ import androidx.media3.common.Timeline;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.util.EventLogger;
|
||||
import androidx.media3.test.utils.FakeMediaSource;
|
||||
@ -736,7 +737,7 @@ public final class ConcatenatingMediaSource2Test {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
mediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
mediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
|
@ -26,6 +26,7 @@ import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
|
||||
@ -88,7 +89,7 @@ public final class MergingMediaPeriodTest {
|
||||
streams,
|
||||
/* streamResetFlags= */ new boolean[] {false, false, false, false},
|
||||
/* positionUs= */ 0);
|
||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
mergingMediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
|
||||
assertThat(streams[0]).isNull();
|
||||
assertThat(streams[3]).isNull();
|
||||
@ -133,7 +134,7 @@ public final class MergingMediaPeriodTest {
|
||||
streams,
|
||||
/* streamResetFlags= */ new boolean[] {false, false},
|
||||
/* positionUs= */ 0);
|
||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
mergingMediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
FormatHolder formatHolder = new FormatHolder();
|
||||
DecoderInputBuffer inputBuffer =
|
||||
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
||||
@ -219,7 +220,7 @@ public final class MergingMediaPeriodTest {
|
||||
streams,
|
||||
/* streamResetFlags= */ new boolean[2],
|
||||
/* positionUs= */ 0);
|
||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
mergingMediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
|
||||
FormatHolder formatHolder = new FormatHolder();
|
||||
DecoderInputBuffer inputBuffer =
|
||||
@ -266,7 +267,8 @@ public final class MergingMediaPeriodTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
mergingMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
|
@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import android.net.Uri;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.datasource.AssetDataSource;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
@ -87,7 +88,7 @@ public final class ProgressiveMediaPeriodTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
source.continueLoading(/* positionUs= */ 0);
|
||||
source.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
|
@ -54,6 +54,7 @@ import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
@ -805,7 +806,8 @@ public final class ServerSideAdInsertionMediaSourceTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
serverSideAdInsertionMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
serverSideAdInsertionMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
|
@ -51,6 +51,7 @@ import androidx.media3.common.VideoSize;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.decoder.CryptoInfo;
|
||||
import androidx.media3.exoplayer.DecoderCounters;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.Renderer;
|
||||
import androidx.media3.exoplayer.RendererCapabilities;
|
||||
import androidx.media3.exoplayer.RendererCapabilities.Capabilities;
|
||||
@ -352,7 +353,8 @@ public class MediaCodecVideoRendererTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
clippingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
clippingMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 100);
|
||||
@ -456,7 +458,8 @@ public class MediaCodecVideoRendererTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
clippingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
||||
clippingMediaPeriod.continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 100);
|
||||
|
@ -30,6 +30,7 @@ import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.dash.PlayerEmsgHandler.PlayerEmsgCallback;
|
||||
@ -316,8 +317,8 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return compositeSequenceableLoader.continueLoading(positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return compositeSequenceableLoader.continueLoading(loadingInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +31,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.drm.DrmSession;
|
||||
@ -391,7 +392,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsPlaylistTracker.Pla
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
if (trackGroups == null) {
|
||||
// Preparation is still going on.
|
||||
for (HlsSampleStreamWrapper wrapper : sampleStreamWrappers) {
|
||||
@ -399,7 +400,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsPlaylistTracker.Pla
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return compositeSequenceableLoader.continueLoading(positionUs);
|
||||
return compositeSequenceableLoader.continueLoading(loadingInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.HttpDataSource;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.drm.DrmSession;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
@ -109,8 +110,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
void onPrepared();
|
||||
|
||||
/**
|
||||
* Called to schedule a {@link #continueLoading(long)} call when the playlist referred by the
|
||||
* given url changes.
|
||||
* Called to schedule a {@link #continueLoading(LoadingInfo)} call when the playlist referred by
|
||||
* the given url changes.
|
||||
*/
|
||||
void onPlaylistRefreshRequired(Uri playlistUrl);
|
||||
}
|
||||
@ -258,7 +259,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
public void continuePreparing() {
|
||||
if (!prepared) {
|
||||
continueLoading(lastSeekPositionUs);
|
||||
continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(lastSeekPositionUs).build());
|
||||
}
|
||||
}
|
||||
|
||||
@ -737,7 +738,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
||||
return false;
|
||||
}
|
||||
@ -760,7 +761,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
}
|
||||
nextChunkHolder.clear();
|
||||
chunkSource.getNextChunk(
|
||||
positionUs,
|
||||
loadingInfo.playbackPositionUs,
|
||||
loadPositionUs,
|
||||
chunkQueue,
|
||||
/* allowEndOfStream= */ prepared || !chunkQueue.isEmpty(),
|
||||
@ -862,7 +863,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
loadable.startTimeUs,
|
||||
loadable.endTimeUs);
|
||||
if (!prepared) {
|
||||
continueLoading(lastSeekPositionUs);
|
||||
continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(lastSeekPositionUs).build());
|
||||
} else {
|
||||
callback.onContinueLoadingRequested(this);
|
||||
}
|
||||
@ -991,7 +992,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
if (exclusionSucceeded) {
|
||||
if (!prepared) {
|
||||
continueLoading(lastSeekPositionUs);
|
||||
continueLoading(
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(lastSeekPositionUs).build());
|
||||
} else {
|
||||
callback.onContinueLoadingRequested(this);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.decoder.DecoderInputBuffer;
|
||||
import androidx.media3.exoplayer.FormatHolder;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.rtsp.RtspClient.PlaybackEventListener;
|
||||
import androidx.media3.exoplayer.rtsp.RtspClient.SessionInfoListener;
|
||||
@ -373,7 +374,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return isLoading();
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import android.net.Uri;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.source.MediaPeriod;
|
||||
import androidx.media3.exoplayer.upstream.DefaultAllocator;
|
||||
import androidx.media3.test.utils.robolectric.RobolectricUtil;
|
||||
@ -97,7 +98,7 @@ public final class RtspMediaPeriodTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
source.continueLoading(/* positionUs= */ 0);
|
||||
source.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
@ -182,7 +183,7 @@ public final class RtspMediaPeriodTest {
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
source.continueLoading(/* positionUs= */ 0);
|
||||
source.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
|
@ -22,6 +22,7 @@ import androidx.media3.common.StreamKey;
|
||||
import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
@ -185,8 +186,8 @@ import java.util.List;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
return compositeSequenceableLoader.continueLoading(positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
return compositeSequenceableLoader.continueLoading(loadingInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,6 +29,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
@ -236,8 +237,8 @@ public class FakeAdaptiveMediaPeriod
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
sequenceableLoader.continueLoading(positionUs);
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
sequenceableLoader.continueLoading(loadingInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ import androidx.media3.common.util.NullableType;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||
@ -361,9 +362,9 @@ public class FakeMediaPeriod implements MediaPeriod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean continueLoading(long positionUs) {
|
||||
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||
for (FakeSampleStream sampleStream : sampleStreams) {
|
||||
sampleStream.writeData(positionUs);
|
||||
sampleStream.writeData(loadingInfo.playbackPositionUs);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user