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`.
|
`MimeTypes.APPLICATION_MEDIA3_CUES`.
|
||||||
* Add `PngExtractor` that sends and reads a whole png file into the the
|
* Add `PngExtractor` that sends and reads a whole png file into the the
|
||||||
`TrackOutput` as one sample.
|
`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:
|
* Transformer:
|
||||||
* Parse EXIF rotation data for image inputs.
|
* Parse EXIF rotation data for image inputs.
|
||||||
* Remove `TransformationRequest.HdrMode` annotation type and its
|
* Remove `TransformationRequest.HdrMode` annotation type and its
|
||||||
|
@ -218,6 +218,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private boolean pauseAtEndOfWindow;
|
private boolean pauseAtEndOfWindow;
|
||||||
private boolean pendingPauseAtEndOfPeriod;
|
private boolean pendingPauseAtEndOfPeriod;
|
||||||
private boolean isRebuffering;
|
private boolean isRebuffering;
|
||||||
|
private long lastRebufferRealtimeMs;
|
||||||
private boolean shouldContinueLoading;
|
private boolean shouldContinueLoading;
|
||||||
private @Player.RepeatMode int repeatMode;
|
private @Player.RepeatMode int repeatMode;
|
||||||
private boolean shuffleModeEnabled;
|
private boolean shuffleModeEnabled;
|
||||||
@ -267,6 +268,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
|
|
||||||
playbackMaybeBecameStuckAtMs = C.TIME_UNSET;
|
playbackMaybeBecameStuckAtMs = C.TIME_UNSET;
|
||||||
|
lastRebufferRealtimeMs = C.TIME_UNSET;
|
||||||
backBufferDurationUs = loadControl.getBackBufferDurationUs();
|
backBufferDurationUs = loadControl.getBackBufferDurationUs();
|
||||||
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe();
|
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe();
|
||||||
|
|
||||||
@ -852,7 +854,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
playbackInfoUpdate.incrementPendingOperationAcks(operationAck ? 1 : 0);
|
playbackInfoUpdate.incrementPendingOperationAcks(operationAck ? 1 : 0);
|
||||||
playbackInfoUpdate.setPlayWhenReadyChangeReason(reason);
|
playbackInfoUpdate.setPlayWhenReadyChangeReason(reason);
|
||||||
playbackInfo = playbackInfo.copyWithPlayWhenReady(playWhenReady, playbackSuppressionReason);
|
playbackInfo = playbackInfo.copyWithPlayWhenReady(playWhenReady, playbackSuppressionReason);
|
||||||
isRebuffering = false;
|
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ false);
|
||||||
notifyTrackSelectionPlayWhenReadyChanged(playWhenReady);
|
notifyTrackSelectionPlayWhenReadyChanged(playWhenReady);
|
||||||
if (!shouldPlayWhenReady()) {
|
if (!shouldPlayWhenReady()) {
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
@ -931,7 +933,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startRenderers() throws ExoPlaybackException {
|
private void startRenderers() throws ExoPlaybackException {
|
||||||
isRebuffering = false;
|
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ false);
|
||||||
mediaClock.start();
|
mediaClock.start();
|
||||||
for (Renderer renderer : renderers) {
|
for (Renderer renderer : renderers) {
|
||||||
if (isRendererEnabled(renderer)) {
|
if (isRendererEnabled(renderer)) {
|
||||||
@ -1120,7 +1122,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
} else if (playbackInfo.playbackState == Player.STATE_READY
|
} else if (playbackInfo.playbackState == Player.STATE_READY
|
||||||
&& !(enabledRendererCount == 0 ? isTimelineReady() : renderersAllowPlayback)) {
|
&& !(enabledRendererCount == 0 ? isTimelineReady() : renderersAllowPlayback)) {
|
||||||
isRebuffering = shouldPlayWhenReady();
|
updateRebufferingState(
|
||||||
|
/* isRebuffering= */ shouldPlayWhenReady(), /* resetLastRebufferRealtimeMs= */ false);
|
||||||
setState(Player.STATE_BUFFERING);
|
setState(Player.STATE_BUFFERING);
|
||||||
if (isRebuffering) {
|
if (isRebuffering) {
|
||||||
notifyTrackSelectionRebuffer();
|
notifyTrackSelectionRebuffer();
|
||||||
@ -1334,7 +1337,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
boolean forceBufferingState)
|
boolean forceBufferingState)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
isRebuffering = false;
|
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ true);
|
||||||
if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
|
if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
|
||||||
setState(Player.STATE_BUFFERING);
|
setState(Player.STATE_BUFFERING);
|
||||||
}
|
}
|
||||||
@ -1475,7 +1478,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
boolean resetError) {
|
boolean resetError) {
|
||||||
handler.removeMessages(MSG_DO_SOME_WORK);
|
handler.removeMessages(MSG_DO_SOME_WORK);
|
||||||
pendingRecoverableRendererError = null;
|
pendingRecoverableRendererError = null;
|
||||||
isRebuffering = false;
|
updateRebufferingState(/* isRebuffering= */ false, /* resetLastRebufferRealtimeMs= */ true);
|
||||||
mediaClock.stop();
|
mediaClock.stop();
|
||||||
rendererPositionUs = MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US;
|
rendererPositionUs = MediaPeriodQueue.INITIAL_RENDERER_POSITION_OFFSET_US;
|
||||||
for (Renderer renderer : renderers) {
|
for (Renderer renderer : renderers) {
|
||||||
@ -2436,7 +2439,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private void maybeContinueLoading() {
|
private void maybeContinueLoading() {
|
||||||
shouldContinueLoading = shouldContinueLoading();
|
shouldContinueLoading = shouldContinueLoading();
|
||||||
if (shouldContinueLoading) {
|
if (shouldContinueLoading) {
|
||||||
queue.getLoadingPeriod().continueLoading(rendererPositionUs);
|
queue
|
||||||
|
.getLoadingPeriod()
|
||||||
|
.continueLoading(
|
||||||
|
rendererPositionUs, mediaClock.getPlaybackParameters().speed, lastRebufferRealtimeMs);
|
||||||
}
|
}
|
||||||
updateIsLoading();
|
updateIsLoading();
|
||||||
}
|
}
|
||||||
@ -2907,6 +2913,23 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
return timeline.isEmpty() || timeline.getPeriodByUid(periodId.periodUid, period).isPlaceholder;
|
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.
|
* 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.
|
* this is the loading media period.
|
||||||
*
|
*
|
||||||
* @param rendererPositionUs The load position in renderer time, in microseconds.
|
* @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());
|
Assertions.checkState(isLoadingMediaPeriod());
|
||||||
long loadingPeriodPositionUs = toPeriodTime(rendererPositionUs);
|
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;
|
return true;
|
||||||
case MESSAGE_CONTINUE_LOADING:
|
case MESSAGE_CONTINUE_LOADING:
|
||||||
checkNotNull(mediaPeriod).continueLoading(/* positionUs= */ 0);
|
checkNotNull(mediaPeriod)
|
||||||
|
.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
return true;
|
return true;
|
||||||
case MESSAGE_RELEASE:
|
case MESSAGE_RELEASE:
|
||||||
if (mediaPeriod != null) {
|
if (mediaPeriod != null) {
|
||||||
|
@ -39,6 +39,7 @@ import androidx.media3.common.util.Util;
|
|||||||
import androidx.media3.datasource.DataSource;
|
import androidx.media3.datasource.DataSource;
|
||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.Renderer;
|
import androidx.media3.exoplayer.Renderer;
|
||||||
import androidx.media3.exoplayer.RendererCapabilities;
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
import androidx.media3.exoplayer.RenderersFactory;
|
import androidx.media3.exoplayer.RenderersFactory;
|
||||||
@ -896,7 +897,7 @@ public final class DownloadHelper {
|
|||||||
case MESSAGE_CONTINUE_LOADING:
|
case MESSAGE_CONTINUE_LOADING:
|
||||||
MediaPeriod mediaPeriod = (MediaPeriod) msg.obj;
|
MediaPeriod mediaPeriod = (MediaPeriod) msg.obj;
|
||||||
if (pendingMediaPeriods.contains(mediaPeriod)) {
|
if (pendingMediaPeriods.contains(mediaPeriod)) {
|
||||||
mediaPeriod.continueLoading(/* positionUs= */ 0);
|
mediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case MESSAGE_RELEASE:
|
case MESSAGE_RELEASE:
|
||||||
|
@ -25,6 +25,7 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.source.ClippingMediaSource.IllegalClippingException;
|
import androidx.media3.exoplayer.source.ClippingMediaSource.IllegalClippingException;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
@ -222,8 +223,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return mediaPeriod.continueLoading(positionUs);
|
return mediaPeriod.continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,7 @@ import static java.lang.Math.min;
|
|||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
|
|
||||||
/** A {@link SequenceableLoader} that encapsulates multiple other {@link SequenceableLoader}s. */
|
/** A {@link SequenceableLoader} that encapsulates multiple other {@link SequenceableLoader}s. */
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@ -62,7 +63,7 @@ public class CompositeSequenceableLoader implements SequenceableLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
boolean madeProgress = false;
|
boolean madeProgress = false;
|
||||||
boolean madeProgressThisIteration;
|
boolean madeProgressThisIteration;
|
||||||
do {
|
do {
|
||||||
@ -75,9 +76,9 @@ public class CompositeSequenceableLoader implements SequenceableLoader {
|
|||||||
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
|
long loaderNextLoadPositionUs = loader.getNextLoadPositionUs();
|
||||||
boolean isLoaderBehind =
|
boolean isLoaderBehind =
|
||||||
loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE
|
loaderNextLoadPositionUs != C.TIME_END_OF_SOURCE
|
||||||
&& loaderNextLoadPositionUs <= positionUs;
|
&& loaderNextLoadPositionUs <= loadingInfo.playbackPositionUs;
|
||||||
if (loaderNextLoadPositionUs == nextLoadPositionUs || isLoaderBehind) {
|
if (loaderNextLoadPositionUs == nextLoadPositionUs || isLoaderBehind) {
|
||||||
madeProgressThisIteration |= loader.continueLoading(positionUs);
|
madeProgressThisIteration |= loader.continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
madeProgress |= madeProgressThisIteration;
|
madeProgress |= madeProgressThisIteration;
|
||||||
|
@ -23,6 +23,7 @@ import androidx.media3.common.StreamKey;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
import androidx.media3.exoplayer.upstream.Allocator;
|
import androidx.media3.exoplayer.upstream.Allocator;
|
||||||
@ -155,8 +156,8 @@ public class FilteringMediaSource extends WrappingMediaSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return mediaPeriod.continueLoading(positionUs);
|
return mediaPeriod.continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
|
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
@ -224,8 +225,8 @@ public final class MaskingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return mediaPeriod != null && mediaPeriod.continueLoading(positionUs);
|
return mediaPeriod != null && mediaPeriod.continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,6 +22,7 @@ import androidx.media3.common.TrackGroup;
|
|||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.source.MediaSource.MediaSourceCaller;
|
import androidx.media3.exoplayer.source.MediaSource.MediaSourceCaller;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
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
|
* called when the period is permitted to continue loading data. A period may do this both during
|
||||||
* and after preparation.
|
* and after preparation.
|
||||||
*
|
*
|
||||||
* @param positionUs The current playback position in microseconds. If playback of this period has
|
* @param loadingInfo The {@link LoadingInfo} when attempting to continue loading.
|
||||||
* 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.
|
|
||||||
* @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a
|
* @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a
|
||||||
* different value than prior to the call. False otherwise.
|
* different value than prior to the call. False otherwise.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
boolean continueLoading(long positionUs);
|
boolean continueLoading(LoadingInfo loadingInfo);
|
||||||
|
|
||||||
/** Returns whether the media period is currently loading. */
|
/** Returns whether the media period is currently loading. */
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,6 +26,7 @@ import androidx.media3.common.util.Assertions;
|
|||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.source.chunk.Chunk;
|
import androidx.media3.exoplayer.source.chunk.Chunk;
|
||||||
import androidx.media3.exoplayer.source.chunk.MediaChunk;
|
import androidx.media3.exoplayer.source.chunk.MediaChunk;
|
||||||
@ -192,16 +193,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
if (!childrenPendingPreparation.isEmpty()) {
|
if (!childrenPendingPreparation.isEmpty()) {
|
||||||
// Preparation is still going on.
|
// Preparation is still going on.
|
||||||
int childrenPendingPreparationSize = childrenPendingPreparation.size();
|
int childrenPendingPreparationSize = childrenPendingPreparation.size();
|
||||||
for (int i = 0; i < childrenPendingPreparationSize; i++) {
|
for (int i = 0; i < childrenPendingPreparationSize; i++) {
|
||||||
childrenPendingPreparation.get(i).continueLoading(positionUs);
|
childrenPendingPreparation.get(i).continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return compositeSequenceableLoader.continueLoading(positionUs);
|
return compositeSequenceableLoader.continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,8 +407,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return mediaPeriod.continueLoading(positionUs - timeOffsetUs);
|
return mediaPeriod.continueLoading(
|
||||||
|
loadingInfo
|
||||||
|
.buildUpon()
|
||||||
|
.setPlaybackPositionUs(loadingInfo.playbackPositionUs - timeOffsetUs)
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -40,6 +40,7 @@ import androidx.media3.datasource.DataSpec;
|
|||||||
import androidx.media3.datasource.StatsDataSource;
|
import androidx.media3.datasource.StatsDataSource;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
@ -343,7 +344,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long playbackPositionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
if (loadingFinished
|
if (loadingFinished
|
||||||
|| loader.hasFatalError()
|
|| loader.hasFatalError()
|
||||||
|| pendingDeferredRetry
|
|| pendingDeferredRetry
|
||||||
|
@ -17,6 +17,7 @@ package androidx.media3.exoplayer.source;
|
|||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
|
|
||||||
// TODO: Clarify the requirements for implementing this interface [Internal ref: b/36250203].
|
// TODO: Clarify the requirements for implementing this interface [Internal ref: b/36250203].
|
||||||
/** A loader that can proceed in approximate synchronization with other loaders. */
|
/** A loader that can proceed in approximate synchronization with other loaders. */
|
||||||
@ -27,8 +28,8 @@ public interface SequenceableLoader {
|
|||||||
interface Callback<T extends SequenceableLoader> {
|
interface Callback<T extends SequenceableLoader> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the loader to indicate that it wishes for its {@link #continueLoading(long)} method
|
* Called by the loader to indicate that it wishes for its {@link #continueLoading(LoadingInfo)}
|
||||||
* to be called when it can continue to load data. Called on the playback thread.
|
* method to be called when it can continue to load data. Called on the playback thread.
|
||||||
*/
|
*/
|
||||||
void onContinueLoadingRequested(T source);
|
void onContinueLoadingRequested(T source);
|
||||||
}
|
}
|
||||||
@ -47,13 +48,11 @@ public interface SequenceableLoader {
|
|||||||
/**
|
/**
|
||||||
* Attempts to continue loading.
|
* Attempts to continue loading.
|
||||||
*
|
*
|
||||||
* @param positionUs The current playback position in microseconds. If playback of the period to
|
* @param loadingInfo The {@link LoadingInfo} when attempting to continue loading.
|
||||||
* 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.
|
|
||||||
* @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a
|
* @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return a
|
||||||
* different value than prior to the call. False otherwise.
|
* different value than prior to the call. False otherwise.
|
||||||
*/
|
*/
|
||||||
boolean continueLoading(long positionUs);
|
boolean continueLoading(LoadingInfo loadingInfo);
|
||||||
|
|
||||||
/** Returns whether the loader is currently loading. */
|
/** Returns whether the loader is currently loading. */
|
||||||
boolean isLoading();
|
boolean isLoading();
|
||||||
|
@ -34,6 +34,7 @@ import androidx.media3.common.util.Util;
|
|||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
import androidx.media3.exoplayer.upstream.Allocator;
|
import androidx.media3.exoplayer.upstream.Allocator;
|
||||||
@ -257,7 +258,7 @@ public final class SilenceMediaSource extends BaseMediaSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import androidx.media3.datasource.StatsDataSource;
|
|||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.source.MediaSourceEventListener.EventDispatcher;
|
import androidx.media3.exoplayer.source.MediaSourceEventListener.EventDispatcher;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
@ -145,7 +146,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import androidx.media3.common.util.Util;
|
|||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.drm.DrmSession;
|
import androidx.media3.exoplayer.drm.DrmSession;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
@ -741,7 +742,7 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
|||||||
return actualMediaPeriod.getStreamKeys(trackSelections);
|
return actualMediaPeriod.getStreamKeys(trackSelections);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean continueLoading(MediaPeriodImpl mediaPeriod, long positionUs) {
|
public boolean continueLoading(MediaPeriodImpl mediaPeriod, LoadingInfo loadingInfo) {
|
||||||
@Nullable MediaPeriodImpl loadingPeriod = this.loadingPeriod;
|
@Nullable MediaPeriodImpl loadingPeriod = this.loadingPeriod;
|
||||||
if (loadingPeriod != null && !mediaPeriod.equals(loadingPeriod)) {
|
if (loadingPeriod != null && !mediaPeriod.equals(loadingPeriod)) {
|
||||||
for (Pair<LoadEventInfo, MediaLoadData> loadData : activeLoads.values()) {
|
for (Pair<LoadEventInfo, MediaLoadData> loadData : activeLoads.values()) {
|
||||||
@ -754,8 +755,9 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
|||||||
}
|
}
|
||||||
this.loadingPeriod = mediaPeriod;
|
this.loadingPeriod = mediaPeriod;
|
||||||
long actualPlaybackPositionUs =
|
long actualPlaybackPositionUs =
|
||||||
getStreamPositionUsWithNotYetStartedHandling(mediaPeriod, positionUs);
|
getStreamPositionUsWithNotYetStartedHandling(mediaPeriod, loadingInfo.playbackPositionUs);
|
||||||
return actualMediaPeriod.continueLoading(actualPlaybackPositionUs);
|
return actualMediaPeriod.continueLoading(
|
||||||
|
loadingInfo.buildUpon().setPlaybackPositionUs(actualPlaybackPositionUs).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLoading(MediaPeriodImpl mediaPeriod) {
|
public boolean isLoading(MediaPeriodImpl mediaPeriod) {
|
||||||
@ -1209,8 +1211,8 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return sharedPeriod.continueLoading(/* mediaPeriod= */ this, positionUs);
|
return sharedPeriod.continueLoading(/* mediaPeriod= */ this, loadingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -28,6 +28,7 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.drm.DrmSession;
|
import androidx.media3.exoplayer.drm.DrmSession;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
@ -561,7 +562,7 @@ public class ChunkSampleStream<T extends ChunkSource>
|
|||||||
// SequenceableLoader implementation
|
// SequenceableLoader implementation
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -576,7 +577,8 @@ public class ChunkSampleStream<T extends ChunkSource>
|
|||||||
chunkQueue = readOnlyMediaChunks;
|
chunkQueue = readOnlyMediaChunks;
|
||||||
loadPositionUs = getLastMediaChunk().endTimeUs;
|
loadPositionUs = getLastMediaChunk().endTimeUs;
|
||||||
}
|
}
|
||||||
chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
|
chunkSource.getNextChunk(
|
||||||
|
loadingInfo.playbackPositionUs, loadPositionUs, chunkQueue, nextChunkHolder);
|
||||||
boolean endOfStream = nextChunkHolder.endOfStream;
|
boolean endOfStream = nextChunkHolder.endOfStream;
|
||||||
@Nullable Chunk loadable = nextChunkHolder.chunk;
|
@Nullable Chunk loadable = nextChunkHolder.chunk;
|
||||||
nextChunkHolder.clear();
|
nextChunkHolder.clear();
|
||||||
|
@ -8679,7 +8679,7 @@ public final class ExoPlayerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
allocations.add(allocator.allocate());
|
allocations.add(allocator.allocate());
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
return true;
|
return true;
|
||||||
@ -8744,8 +8744,8 @@ public final class ExoPlayerTest {
|
|||||||
private final Loader loader = new Loader("ExoPlayerTest");
|
private final Loader loader = new Loader("ExoPlayerTest");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
super.continueLoading(positionUs);
|
super.continueLoading(loadingInfo);
|
||||||
if (!loader.isLoading()) {
|
if (!loader.isLoading()) {
|
||||||
loader.startLoading(
|
loader.startLoading(
|
||||||
loadable, new FakeLoaderCallback(), /* defaultMinRetryCount= */ 1);
|
loadable, new FakeLoaderCallback(), /* defaultMinRetryCount= */ 1);
|
||||||
|
@ -25,6 +25,7 @@ import androidx.media3.common.Format;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
@ -116,7 +117,8 @@ public class ClippingMediaPeriodTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
clippingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
clippingMediaPeriod.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.source;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -130,9 +131,9 @@ public final class CompositeSequenceableLoaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} only allows the loader
|
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} only allows the
|
||||||
* with minimum next load position to continue loading if next load positions are not behind
|
* loader with minimum next load position to continue loading if next load positions are not
|
||||||
* current playback position.
|
* behind current playback position.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void continueLoadingOnlyAllowFurthestBehindLoaderToLoadIfNotBehindPlaybackPosition() {
|
public void continueLoadingOnlyAllowFurthestBehindLoaderToLoadIfNotBehindPlaybackPosition() {
|
||||||
@ -142,15 +143,16 @@ public final class CompositeSequenceableLoaderTest {
|
|||||||
new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001);
|
new FakeSequenceableLoader(/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ 2001);
|
||||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
||||||
compositeSequenceableLoader.continueLoading(100);
|
compositeSequenceableLoader.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(100).build());
|
||||||
|
|
||||||
assertThat(loader1.numInvocations).isEqualTo(1);
|
assertThat(loader1.numInvocations).isEqualTo(1);
|
||||||
assertThat(loader2.numInvocations).isEqualTo(0);
|
assertThat(loader2.numInvocations).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} allows all loaders with
|
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} allows all loaders
|
||||||
* next load position behind current playback position to continue loading.
|
* with next load position behind current playback position to continue loading.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void continueLoadingReturnAllowAllLoadersBehindPlaybackPositionToLoad() {
|
public void continueLoadingReturnAllowAllLoadersBehindPlaybackPositionToLoad() {
|
||||||
@ -162,7 +164,8 @@ public final class CompositeSequenceableLoaderTest {
|
|||||||
new FakeSequenceableLoader(/* bufferedPositionUs */ 1002, /* nextLoadPositionUs */ 2002);
|
new FakeSequenceableLoader(/* bufferedPositionUs */ 1002, /* nextLoadPositionUs */ 2002);
|
||||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3});
|
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2, loader3});
|
||||||
compositeSequenceableLoader.continueLoading(3000);
|
compositeSequenceableLoader.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(3000).build());
|
||||||
|
|
||||||
assertThat(loader1.numInvocations).isEqualTo(1);
|
assertThat(loader1.numInvocations).isEqualTo(1);
|
||||||
assertThat(loader2.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
|
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} does not allow
|
||||||
* next load position at end-of-source to continue loading.
|
* loader with next load position at end-of-source to continue loading.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void continueLoadingOnlyNotAllowEndOfSourceLoaderToLoad() {
|
public void continueLoadingOnlyNotAllowEndOfSourceLoaderToLoad() {
|
||||||
@ -183,16 +186,17 @@ public final class CompositeSequenceableLoaderTest {
|
|||||||
/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
|
/* bufferedPositionUs */ 1001, /* nextLoadPositionUs */ C.TIME_END_OF_SOURCE);
|
||||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
||||||
compositeSequenceableLoader.continueLoading(3000);
|
compositeSequenceableLoader.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(3000).build());
|
||||||
|
|
||||||
assertThat(loader1.numInvocations).isEqualTo(0);
|
assertThat(loader1.numInvocations).isEqualTo(0);
|
||||||
assertThat(loader2.numInvocations).isEqualTo(0);
|
assertThat(loader2.numInvocations).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that {@link CompositeSequenceableLoader#continueLoading(long)} returns true if the loader
|
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} returns true if the
|
||||||
* with minimum next load position can make progress if next load positions are not behind current
|
* loader with minimum next load position can make progress if next load positions are not behind
|
||||||
* playback position.
|
* current playback position.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void continueLoadingReturnTrueIfFurthestBehindLoaderCanMakeProgress() {
|
public void continueLoadingReturnTrueIfFurthestBehindLoaderCanMakeProgress() {
|
||||||
@ -205,13 +209,16 @@ public final class CompositeSequenceableLoaderTest {
|
|||||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
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
|
* Tests that {@link CompositeSequenceableLoader#continueLoading(LoadingInfo)} returns true if any
|
||||||
* that are behind current playback position can make progress, even if it is not the one with
|
* loader that are behind current playback position can make progress, even if it is not the one
|
||||||
* minimum next load position.
|
* with minimum next load position.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void continueLoadingReturnTrueIfLoaderBehindPlaybackPositionCanMakeProgress() {
|
public void continueLoadingReturnTrueIfLoaderBehindPlaybackPositionCanMakeProgress() {
|
||||||
@ -225,7 +232,10 @@ public final class CompositeSequenceableLoaderTest {
|
|||||||
CompositeSequenceableLoader compositeSequenceableLoader =
|
CompositeSequenceableLoader compositeSequenceableLoader =
|
||||||
new CompositeSequenceableLoader(new SequenceableLoader[] {loader1, loader2});
|
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 {
|
private static class FakeSequenceableLoader implements SequenceableLoader {
|
||||||
@ -251,7 +261,7 @@ public final class CompositeSequenceableLoaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
numInvocations++;
|
numInvocations++;
|
||||||
boolean loaded = nextChunkDurationUs != 0;
|
boolean loaded = nextChunkDurationUs != 0;
|
||||||
// The current chunk has been loaded, advance to next chunk.
|
// 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.common.util.Util;
|
||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||||
import androidx.media3.exoplayer.util.EventLogger;
|
import androidx.media3.exoplayer.util.EventLogger;
|
||||||
import androidx.media3.test.utils.FakeMediaSource;
|
import androidx.media3.test.utils.FakeMediaSource;
|
||||||
@ -736,7 +737,7 @@ public final class ConcatenatingMediaSource2Test {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
mediaPeriod.continueLoading(/* positionUs= */ 0);
|
mediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
|
@ -26,6 +26,7 @@ import androidx.media3.common.TrackGroup;
|
|||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
|
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
|
||||||
@ -88,7 +89,7 @@ public final class MergingMediaPeriodTest {
|
|||||||
streams,
|
streams,
|
||||||
/* streamResetFlags= */ new boolean[] {false, false, false, false},
|
/* streamResetFlags= */ new boolean[] {false, false, false, false},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
mergingMediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
|
|
||||||
assertThat(streams[0]).isNull();
|
assertThat(streams[0]).isNull();
|
||||||
assertThat(streams[3]).isNull();
|
assertThat(streams[3]).isNull();
|
||||||
@ -133,7 +134,7 @@ public final class MergingMediaPeriodTest {
|
|||||||
streams,
|
streams,
|
||||||
/* streamResetFlags= */ new boolean[] {false, false},
|
/* streamResetFlags= */ new boolean[] {false, false},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
mergingMediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
FormatHolder formatHolder = new FormatHolder();
|
FormatHolder formatHolder = new FormatHolder();
|
||||||
DecoderInputBuffer inputBuffer =
|
DecoderInputBuffer inputBuffer =
|
||||||
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
|
||||||
@ -219,7 +220,7 @@ public final class MergingMediaPeriodTest {
|
|||||||
streams,
|
streams,
|
||||||
/* streamResetFlags= */ new boolean[2],
|
/* streamResetFlags= */ new boolean[2],
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
mergingMediaPeriod.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
|
|
||||||
FormatHolder formatHolder = new FormatHolder();
|
FormatHolder formatHolder = new FormatHolder();
|
||||||
DecoderInputBuffer inputBuffer =
|
DecoderInputBuffer inputBuffer =
|
||||||
@ -266,7 +267,8 @@ public final class MergingMediaPeriodTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
mergingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
mergingMediaPeriod.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
|
@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.datasource.AssetDataSource;
|
import androidx.media3.datasource.AssetDataSource;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
@ -87,7 +88,7 @@ public final class ProgressiveMediaPeriodTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
source.continueLoading(/* positionUs= */ 0);
|
source.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
|
@ -54,6 +54,7 @@ import androidx.media3.datasource.TransferListener;
|
|||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
||||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
@ -805,7 +806,8 @@ public final class ServerSideAdInsertionMediaSourceTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
serverSideAdInsertionMediaPeriod.continueLoading(/* positionUs= */ 0);
|
serverSideAdInsertionMediaPeriod.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
|
@ -51,6 +51,7 @@ import androidx.media3.common.VideoSize;
|
|||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
import androidx.media3.decoder.CryptoInfo;
|
import androidx.media3.decoder.CryptoInfo;
|
||||||
import androidx.media3.exoplayer.DecoderCounters;
|
import androidx.media3.exoplayer.DecoderCounters;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.Renderer;
|
import androidx.media3.exoplayer.Renderer;
|
||||||
import androidx.media3.exoplayer.RendererCapabilities;
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
import androidx.media3.exoplayer.RendererCapabilities.Capabilities;
|
import androidx.media3.exoplayer.RendererCapabilities.Capabilities;
|
||||||
@ -352,7 +353,8 @@ public class MediaCodecVideoRendererTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
clippingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
clippingMediaPeriod.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 100);
|
/* positionUs= */ 100);
|
||||||
@ -456,7 +458,8 @@ public class MediaCodecVideoRendererTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
clippingMediaPeriod.continueLoading(/* positionUs= */ 0);
|
clippingMediaPeriod.continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 100);
|
/* positionUs= */ 100);
|
||||||
|
@ -30,6 +30,7 @@ import androidx.media3.common.TrackGroup;
|
|||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||||
import androidx.media3.exoplayer.dash.PlayerEmsgHandler.PlayerEmsgCallback;
|
import androidx.media3.exoplayer.dash.PlayerEmsgHandler.PlayerEmsgCallback;
|
||||||
@ -316,8 +317,8 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return compositeSequenceableLoader.continueLoading(positionUs);
|
return compositeSequenceableLoader.continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,6 +31,7 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.datasource.DataSource;
|
import androidx.media3.datasource.DataSource;
|
||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||||
import androidx.media3.exoplayer.drm.DrmSession;
|
import androidx.media3.exoplayer.drm.DrmSession;
|
||||||
@ -391,7 +392,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsPlaylistTracker.Pla
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
if (trackGroups == null) {
|
if (trackGroups == null) {
|
||||||
// Preparation is still going on.
|
// Preparation is still going on.
|
||||||
for (HlsSampleStreamWrapper wrapper : sampleStreamWrappers) {
|
for (HlsSampleStreamWrapper wrapper : sampleStreamWrappers) {
|
||||||
@ -399,7 +400,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsPlaylistTracker.Pla
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} 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.datasource.HttpDataSource;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.drm.DrmSession;
|
import androidx.media3.exoplayer.drm.DrmSession;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
@ -109,8 +110,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
void onPrepared();
|
void onPrepared();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to schedule a {@link #continueLoading(long)} call when the playlist referred by the
|
* Called to schedule a {@link #continueLoading(LoadingInfo)} call when the playlist referred by
|
||||||
* given url changes.
|
* the given url changes.
|
||||||
*/
|
*/
|
||||||
void onPlaylistRefreshRequired(Uri playlistUrl);
|
void onPlaylistRefreshRequired(Uri playlistUrl);
|
||||||
}
|
}
|
||||||
@ -258,7 +259,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
|
|
||||||
public void continuePreparing() {
|
public void continuePreparing() {
|
||||||
if (!prepared) {
|
if (!prepared) {
|
||||||
continueLoading(lastSeekPositionUs);
|
continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(lastSeekPositionUs).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,7 +738,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
if (loadingFinished || loader.isLoading() || loader.hasFatalError()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -760,7 +761,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
nextChunkHolder.clear();
|
nextChunkHolder.clear();
|
||||||
chunkSource.getNextChunk(
|
chunkSource.getNextChunk(
|
||||||
positionUs,
|
loadingInfo.playbackPositionUs,
|
||||||
loadPositionUs,
|
loadPositionUs,
|
||||||
chunkQueue,
|
chunkQueue,
|
||||||
/* allowEndOfStream= */ prepared || !chunkQueue.isEmpty(),
|
/* allowEndOfStream= */ prepared || !chunkQueue.isEmpty(),
|
||||||
@ -862,7 +863,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
loadable.startTimeUs,
|
loadable.startTimeUs,
|
||||||
loadable.endTimeUs);
|
loadable.endTimeUs);
|
||||||
if (!prepared) {
|
if (!prepared) {
|
||||||
continueLoading(lastSeekPositionUs);
|
continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(lastSeekPositionUs).build());
|
||||||
} else {
|
} else {
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
@ -991,7 +992,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
|
|
||||||
if (exclusionSucceeded) {
|
if (exclusionSucceeded) {
|
||||||
if (!prepared) {
|
if (!prepared) {
|
||||||
continueLoading(lastSeekPositionUs);
|
continueLoading(
|
||||||
|
new LoadingInfo.Builder().setPlaybackPositionUs(lastSeekPositionUs).build());
|
||||||
} else {
|
} else {
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.decoder.DecoderInputBuffer;
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.rtsp.RtspClient.PlaybackEventListener;
|
import androidx.media3.exoplayer.rtsp.RtspClient.PlaybackEventListener;
|
||||||
import androidx.media3.exoplayer.rtsp.RtspClient.SessionInfoListener;
|
import androidx.media3.exoplayer.rtsp.RtspClient.SessionInfoListener;
|
||||||
@ -373,7 +374,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return isLoading();
|
return isLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.source.MediaPeriod;
|
import androidx.media3.exoplayer.source.MediaPeriod;
|
||||||
import androidx.media3.exoplayer.upstream.DefaultAllocator;
|
import androidx.media3.exoplayer.upstream.DefaultAllocator;
|
||||||
import androidx.media3.test.utils.robolectric.RobolectricUtil;
|
import androidx.media3.test.utils.robolectric.RobolectricUtil;
|
||||||
@ -97,7 +98,7 @@ public final class RtspMediaPeriodTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
source.continueLoading(/* positionUs= */ 0);
|
source.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
@ -182,7 +183,7 @@ public final class RtspMediaPeriodTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||||
source.continueLoading(/* positionUs= */ 0);
|
source.continueLoading(new LoadingInfo.Builder().setPlaybackPositionUs(0).build());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* positionUs= */ 0);
|
/* positionUs= */ 0);
|
||||||
|
@ -22,6 +22,7 @@ import androidx.media3.common.StreamKey;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
@ -185,8 +186,8 @@ import java.util.List;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
return compositeSequenceableLoader.continueLoading(positionUs);
|
return compositeSequenceableLoader.continueLoading(loadingInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,6 +29,7 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.datasource.DataSpec;
|
import androidx.media3.datasource.DataSpec;
|
||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
@ -236,8 +237,8 @@ public class FakeAdaptiveMediaPeriod
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
sequenceableLoader.continueLoading(positionUs);
|
sequenceableLoader.continueLoading(loadingInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import androidx.media3.common.util.NullableType;
|
|||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.datasource.DataSpec;
|
import androidx.media3.datasource.DataSpec;
|
||||||
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.SeekParameters;
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
import androidx.media3.exoplayer.drm.DrmSessionEventListener;
|
||||||
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
import androidx.media3.exoplayer.drm.DrmSessionManager;
|
||||||
@ -361,9 +362,9 @@ public class FakeMediaPeriod implements MediaPeriod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean continueLoading(long positionUs) {
|
public boolean continueLoading(LoadingInfo loadingInfo) {
|
||||||
for (FakeSampleStream sampleStream : sampleStreams) {
|
for (FakeSampleStream sampleStream : sampleStreams) {
|
||||||
sampleStream.writeData(positionUs);
|
sampleStream.writeData(loadingInfo.playbackPositionUs);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user