mirror of
https://github.com/samsonjs/media.git
synced 2026-03-31 10:25:48 +00:00
Remove wait time parameter for evaluateQueueSize calls.
The wait time parameter is an implementation detail where we can just provide a default. In addition, we should also force the evaluation when the last chunk in the queue changed to ensure it is always evaluated before starting to load a new chunk. Issue: #7582 PiperOrigin-RevId: 319949251
This commit is contained in:
parent
c06fa144e1
commit
b259476ab9
3 changed files with 37 additions and 48 deletions
|
|
@ -94,6 +94,8 @@
|
|||
* Remove throws clause from Renderer.stop.
|
||||
* Don't clear `exception` in `SimpleDecoder#flush()`
|
||||
([#7590](https://github.com/google/ExoPlayer/issues/7590)).
|
||||
* Remove `AdaptiveTrackSelection.minTimeBetweenBufferReevaluationMs`
|
||||
parameter ([#7582](https://github.com/google/ExoPlayer/issues/7582)).
|
||||
* Video: Pass frame rate hint to `Surface.setFrameRate` on Android R devices.
|
||||
* Track selection:
|
||||
* Add `Player.getTrackSelector`.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.trackselection;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
|
|
@ -26,6 +27,7 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
|||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Clock;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
|
|
@ -45,7 +47,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
private final int minDurationToRetainAfterDiscardMs;
|
||||
private final float bandwidthFraction;
|
||||
private final float bufferedFractionToLiveEdgeForQualityIncrease;
|
||||
private final long minTimeBetweenBufferReevaluationMs;
|
||||
private final Clock clock;
|
||||
|
||||
/** Creates an adaptive track selection factory with default parameters. */
|
||||
|
|
@ -56,7 +57,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
|
||||
DEFAULT_BANDWIDTH_FRACTION,
|
||||
DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
|
||||
Clock.DEFAULT);
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +74,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
|
||||
DEFAULT_BANDWIDTH_FRACTION,
|
||||
DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
|
||||
Clock.DEFAULT);
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +103,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
minDurationToRetainAfterDiscardMs,
|
||||
bandwidthFraction,
|
||||
DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
|
||||
Clock.DEFAULT);
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +125,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
minDurationToRetainAfterDiscardMs,
|
||||
bandwidthFraction,
|
||||
DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
|
||||
Clock.DEFAULT);
|
||||
}
|
||||
|
||||
|
|
@ -151,10 +148,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
* applied when the playback position is closer to the live edge than {@code
|
||||
* minDurationForQualityIncreaseMs}, which would otherwise prevent switching to a higher
|
||||
* quality from happening.
|
||||
* @param minTimeBetweenBufferReevaluationMs The track selection may periodically reevaluate its
|
||||
* buffer and discard some chunks of lower quality to improve the playback quality if
|
||||
* network conditions have changed. This is the minimum duration between 2 consecutive
|
||||
* buffer reevaluation calls.
|
||||
* @param clock A {@link Clock}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
|
|
@ -164,7 +157,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
int minDurationToRetainAfterDiscardMs,
|
||||
float bandwidthFraction,
|
||||
float bufferedFractionToLiveEdgeForQualityIncrease,
|
||||
long minTimeBetweenBufferReevaluationMs,
|
||||
Clock clock) {
|
||||
this(
|
||||
/* bandwidthMeter= */ null,
|
||||
|
|
@ -173,12 +165,11 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
minDurationToRetainAfterDiscardMs,
|
||||
bandwidthFraction,
|
||||
bufferedFractionToLiveEdgeForQualityIncrease,
|
||||
minTimeBetweenBufferReevaluationMs,
|
||||
clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #Factory(int, int, int, float, float, long, Clock)} instead. Custom
|
||||
* @deprecated Use {@link #Factory(int, int, int, float, float, Clock)} instead. Custom
|
||||
* bandwidth meter should be directly passed to the player in {@link
|
||||
* SimpleExoPlayer.Builder}.
|
||||
*/
|
||||
|
|
@ -190,7 +181,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
int minDurationToRetainAfterDiscardMs,
|
||||
float bandwidthFraction,
|
||||
float bufferedFractionToLiveEdgeForQualityIncrease,
|
||||
long minTimeBetweenBufferReevaluationMs,
|
||||
Clock clock) {
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
this.minDurationForQualityIncreaseMs = minDurationForQualityIncreaseMs;
|
||||
|
|
@ -199,7 +189,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
this.bandwidthFraction = bandwidthFraction;
|
||||
this.bufferedFractionToLiveEdgeForQualityIncrease =
|
||||
bufferedFractionToLiveEdgeForQualityIncrease;
|
||||
this.minTimeBetweenBufferReevaluationMs = minTimeBetweenBufferReevaluationMs;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
|
|
@ -278,7 +267,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
maxDurationForQualityDecreaseMs,
|
||||
minDurationToRetainAfterDiscardMs,
|
||||
bufferedFractionToLiveEdgeForQualityIncrease,
|
||||
minTimeBetweenBufferReevaluationMs,
|
||||
clock);
|
||||
}
|
||||
}
|
||||
|
|
@ -288,20 +276,21 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
public static final int DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS = 25_000;
|
||||
public static final float DEFAULT_BANDWIDTH_FRACTION = 0.7f;
|
||||
public static final float DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE = 0.75f;
|
||||
public static final long DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS = 2000;
|
||||
|
||||
private static final long MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS = 1000;
|
||||
|
||||
private final BandwidthProvider bandwidthProvider;
|
||||
private final long minDurationForQualityIncreaseUs;
|
||||
private final long maxDurationForQualityDecreaseUs;
|
||||
private final long minDurationToRetainAfterDiscardUs;
|
||||
private final float bufferedFractionToLiveEdgeForQualityIncrease;
|
||||
private final long minTimeBetweenBufferReevaluationMs;
|
||||
private final Clock clock;
|
||||
|
||||
private float playbackSpeed;
|
||||
private int selectedIndex;
|
||||
private int reason;
|
||||
private long lastBufferEvaluationMs;
|
||||
@Nullable private MediaChunk lastBufferEvaluationMediaChunk;
|
||||
|
||||
/**
|
||||
* @param group The {@link TrackGroup}.
|
||||
|
|
@ -321,7 +310,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
|
||||
DEFAULT_BANDWIDTH_FRACTION,
|
||||
DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
|
||||
Clock.DEFAULT);
|
||||
}
|
||||
|
||||
|
|
@ -349,10 +337,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
* when the playback position is closer to the live edge than {@code
|
||||
* minDurationForQualityIncreaseMs}, which would otherwise prevent switching to a higher
|
||||
* quality from happening.
|
||||
* @param minTimeBetweenBufferReevaluationMs The track selection may periodically reevaluate its
|
||||
* buffer and discard some chunks of lower quality to improve the playback quality if network
|
||||
* condition has changed. This is the minimum duration between 2 consecutive buffer
|
||||
* reevaluation calls.
|
||||
*/
|
||||
public AdaptiveTrackSelection(
|
||||
TrackGroup group,
|
||||
|
|
@ -364,7 +348,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
long minDurationToRetainAfterDiscardMs,
|
||||
float bandwidthFraction,
|
||||
float bufferedFractionToLiveEdgeForQualityIncrease,
|
||||
long minTimeBetweenBufferReevaluationMs,
|
||||
Clock clock) {
|
||||
this(
|
||||
group,
|
||||
|
|
@ -374,7 +357,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
maxDurationForQualityDecreaseMs,
|
||||
minDurationToRetainAfterDiscardMs,
|
||||
bufferedFractionToLiveEdgeForQualityIncrease,
|
||||
minTimeBetweenBufferReevaluationMs,
|
||||
clock);
|
||||
}
|
||||
|
||||
|
|
@ -386,7 +368,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
long maxDurationForQualityDecreaseMs,
|
||||
long minDurationToRetainAfterDiscardMs,
|
||||
float bufferedFractionToLiveEdgeForQualityIncrease,
|
||||
long minTimeBetweenBufferReevaluationMs,
|
||||
Clock clock) {
|
||||
super(group, tracks);
|
||||
this.bandwidthProvider = bandwidthProvider;
|
||||
|
|
@ -395,7 +376,6 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
this.minDurationToRetainAfterDiscardUs = minDurationToRetainAfterDiscardMs * 1000L;
|
||||
this.bufferedFractionToLiveEdgeForQualityIncrease =
|
||||
bufferedFractionToLiveEdgeForQualityIncrease;
|
||||
this.minTimeBetweenBufferReevaluationMs = minTimeBetweenBufferReevaluationMs;
|
||||
this.clock = clock;
|
||||
playbackSpeed = 1f;
|
||||
reason = C.SELECTION_REASON_UNKNOWN;
|
||||
|
|
@ -413,9 +393,18 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
.experimental_setBandwidthAllocationCheckpoints(allocationCheckpoints);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void enable() {
|
||||
lastBufferEvaluationMs = C.TIME_UNSET;
|
||||
lastBufferEvaluationMediaChunk = null;
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void disable() {
|
||||
// Avoid keeping a reference to a MediaChunk in case it prevents garbage collection.
|
||||
lastBufferEvaluationMediaChunk = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -487,15 +476,15 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
@Override
|
||||
public int evaluateQueueSize(long playbackPositionUs, List<? extends MediaChunk> queue) {
|
||||
long nowMs = clock.elapsedRealtime();
|
||||
if (!shouldEvaluateQueueSize(nowMs)) {
|
||||
if (!shouldEvaluateQueueSize(nowMs, queue)) {
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
lastBufferEvaluationMs = nowMs;
|
||||
lastBufferEvaluationMediaChunk = queue.isEmpty() ? null : Iterables.getLast(queue);
|
||||
|
||||
if (queue.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int queueSize = queue.size();
|
||||
MediaChunk lastChunk = queue.get(queueSize - 1);
|
||||
long playoutBufferedDurationBeforeLastChunkUs =
|
||||
|
|
@ -548,11 +537,13 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||
* performed.
|
||||
*
|
||||
* @param nowMs The current value of {@link Clock#elapsedRealtime()}.
|
||||
* @param queue The queue of buffered {@link MediaChunk MediaChunks}. Must not be modified.
|
||||
* @return Whether an evaluation should be performed.
|
||||
*/
|
||||
protected boolean shouldEvaluateQueueSize(long nowMs) {
|
||||
protected boolean shouldEvaluateQueueSize(long nowMs, List<? extends MediaChunk> queue) {
|
||||
return lastBufferEvaluationMs == C.TIME_UNSET
|
||||
|| nowMs - lastBufferEvaluationMs >= minTimeBetweenBufferReevaluationMs;
|
||||
|| nowMs - lastBufferEvaluationMs >= MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS
|
||||
|| (!queue.isEmpty() && !Iterables.getLast(queue).equals(lastBufferEvaluationMediaChunk));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -272,20 +272,23 @@ public final class AdaptiveTrackSelectionTest {
|
|||
when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(500L);
|
||||
adaptiveTrackSelection =
|
||||
adaptiveTrackSelectionWithMinTimeBetweenBufferReevaluationMs(
|
||||
trackGroup,
|
||||
/* durationToRetainAfterDiscardMs= */ 15_000,
|
||||
/* minTimeBetweenBufferReevaluationMs= */ 2000);
|
||||
trackGroup, /* durationToRetainAfterDiscardMs= */ 15_000);
|
||||
|
||||
int initialQueueSize = adaptiveTrackSelection.evaluateQueueSize(0, queue);
|
||||
|
||||
fakeClock.advanceTime(1999);
|
||||
fakeClock.advanceTime(999);
|
||||
when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L);
|
||||
|
||||
// When bandwidth estimation is updated, we can discard chunks at the end of the queue now.
|
||||
// However, since min duration between buffer reevaluation = 2000, we will not reevaluate
|
||||
// queue size if time now is only 1999 ms after last buffer reevaluation.
|
||||
int newSize = adaptiveTrackSelection.evaluateQueueSize(0, queue);
|
||||
// When the bandwidth estimation is updated, we should be able to discard chunks from the end of
|
||||
// the queue. However, since the duration since the last evaluation (999ms) is less than 1000ms,
|
||||
// we will not reevaluate the queue size and should not discard chunks.
|
||||
int newSize = adaptiveTrackSelection.evaluateQueueSize(/* playbackPositionUs= */ 0, queue);
|
||||
assertThat(newSize).isEqualTo(initialQueueSize);
|
||||
|
||||
// Sanity check for the comment above.
|
||||
fakeClock.advanceTime(1);
|
||||
newSize = adaptiveTrackSelection.evaluateQueueSize(/* playbackPositionUs= */ 0, queue);
|
||||
assertThat(newSize).isLessThan(initialQueueSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -309,9 +312,7 @@ public final class AdaptiveTrackSelectionTest {
|
|||
when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(500L);
|
||||
adaptiveTrackSelection =
|
||||
adaptiveTrackSelectionWithMinTimeBetweenBufferReevaluationMs(
|
||||
trackGroup,
|
||||
/* durationToRetainAfterDiscardMs= */ 15_000,
|
||||
/* minTimeBetweenBufferReevaluationMs= */ 2000);
|
||||
trackGroup, /* durationToRetainAfterDiscardMs= */ 15_000);
|
||||
|
||||
int initialQueueSize = adaptiveTrackSelection.evaluateQueueSize(0, queue);
|
||||
assertThat(initialQueueSize).isEqualTo(3);
|
||||
|
|
@ -345,7 +346,6 @@ public final class AdaptiveTrackSelectionTest {
|
|||
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
|
||||
/* bandwidthFraction= */ 1.0f,
|
||||
AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
|
||||
fakeClock));
|
||||
}
|
||||
|
||||
|
|
@ -362,14 +362,11 @@ public final class AdaptiveTrackSelectionTest {
|
|||
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
|
||||
/* bandwidthFraction= */ 1.0f,
|
||||
AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
AdaptiveTrackSelection.DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS,
|
||||
fakeClock));
|
||||
}
|
||||
|
||||
private AdaptiveTrackSelection adaptiveTrackSelectionWithMinTimeBetweenBufferReevaluationMs(
|
||||
TrackGroup trackGroup,
|
||||
long durationToRetainAfterDiscardMs,
|
||||
long minTimeBetweenBufferReevaluationMs) {
|
||||
TrackGroup trackGroup, long durationToRetainAfterDiscardMs) {
|
||||
return prepareTrackSelection(
|
||||
new AdaptiveTrackSelection(
|
||||
trackGroup,
|
||||
|
|
@ -381,7 +378,6 @@ public final class AdaptiveTrackSelectionTest {
|
|||
durationToRetainAfterDiscardMs,
|
||||
/* bandwidthFraction= */ 1.0f,
|
||||
AdaptiveTrackSelection.DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE,
|
||||
minTimeBetweenBufferReevaluationMs,
|
||||
fakeClock));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue