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:
tonihei 2020-07-07 10:54:56 +01:00 committed by kim-vde
parent c06fa144e1
commit b259476ab9
3 changed files with 37 additions and 48 deletions

View file

@ -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`.

View file

@ -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));
}
/**

View file

@ -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));
}