Make usage of live minDurationForQualityIncrease more consistent
We have two ways to choose the minDurationForQualityIncreaseMs value in AdaptiveTrackSelection: use the configured value for non-live or when enough buffered data is available, or use a fraction of the available duration to allow switching when playing close to the live edge. The decision point when to use which value isn't quite consistent because we compare against availableDurationUs before making the adjustments. This means there is range of values where no up-switching is possible despite perfect buffering. Fix this by choosing the minimum of both values. Issue: google/ExoPlayer#9784 #minor-release PiperOrigin-RevId: 428474332
This commit is contained in:
parent
6197a712ff
commit
6048ca2faa
@ -16,6 +16,7 @@
|
|||||||
package androidx.media3.exoplayer.trackselection;
|
package androidx.media3.exoplayer.trackselection;
|
||||||
|
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
|
import static java.lang.Math.min;
|
||||||
|
|
||||||
import androidx.annotation.CallSuper;
|
import androidx.annotation.CallSuper;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -605,10 +606,8 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long minDurationForQualityIncreaseUs(long availableDurationUs, long chunkDurationUs) {
|
private long minDurationForQualityIncreaseUs(long availableDurationUs, long chunkDurationUs) {
|
||||||
boolean isAvailableDurationTooShort =
|
if (availableDurationUs == C.TIME_UNSET) {
|
||||||
availableDurationUs != C.TIME_UNSET
|
// We are not in a live stream. Use the configured value.
|
||||||
&& availableDurationUs <= minDurationForQualityIncreaseUs;
|
|
||||||
if (!isAvailableDurationTooShort) {
|
|
||||||
return minDurationForQualityIncreaseUs;
|
return minDurationForQualityIncreaseUs;
|
||||||
}
|
}
|
||||||
if (chunkDurationUs != C.TIME_UNSET) {
|
if (chunkDurationUs != C.TIME_UNSET) {
|
||||||
@ -619,7 +618,9 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
|||||||
// actually achievable.
|
// actually achievable.
|
||||||
availableDurationUs -= chunkDurationUs;
|
availableDurationUs -= chunkDurationUs;
|
||||||
}
|
}
|
||||||
return (long) (availableDurationUs * bufferedFractionToLiveEdgeForQualityIncrease);
|
long adjustedMinDurationForQualityIncreaseUs =
|
||||||
|
(long) (availableDurationUs * bufferedFractionToLiveEdgeForQualityIncrease);
|
||||||
|
return min(adjustedMinDurationForQualityIncreaseUs, minDurationForQualityIncreaseUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,7 +175,9 @@ public final class AdaptiveTrackSelectionTest {
|
|||||||
when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L, 2000L);
|
when(mockBandwidthMeter.getBitrateEstimate()).thenReturn(1000L, 2000L);
|
||||||
AdaptiveTrackSelection adaptiveTrackSelection =
|
AdaptiveTrackSelection adaptiveTrackSelection =
|
||||||
prepareAdaptiveTrackSelectionWithBufferedFractionToLiveEdgeForQualiyIncrease(
|
prepareAdaptiveTrackSelectionWithBufferedFractionToLiveEdgeForQualiyIncrease(
|
||||||
trackGroup, /* bufferedFractionToLiveEdgeForQualityIncrease= */ 0.75f);
|
trackGroup,
|
||||||
|
/* bufferedFractionToLiveEdgeForQualityIncrease= */ 0.75f,
|
||||||
|
/* minDurationForQualityIncreaseMs= */ 5000);
|
||||||
|
|
||||||
// Not buffered close to live edge yet.
|
// Not buffered close to live edge yet.
|
||||||
adaptiveTrackSelection.updateSelectedTrack(
|
adaptiveTrackSelection.updateSelectedTrack(
|
||||||
@ -188,6 +190,8 @@ public final class AdaptiveTrackSelectionTest {
|
|||||||
assertThat(adaptiveTrackSelection.getSelectedFormat()).isEqualTo(format2);
|
assertThat(adaptiveTrackSelection.getSelectedFormat()).isEqualTo(format2);
|
||||||
|
|
||||||
// Buffered all possible chunks (except for newly added chunk of 2 seconds).
|
// Buffered all possible chunks (except for newly added chunk of 2 seconds).
|
||||||
|
// Intentionally choose a situation where availableDurationUs > minDurationForQualityIncreaseMs
|
||||||
|
// to ensure the live calculation is used regardless.
|
||||||
adaptiveTrackSelection.updateSelectedTrack(
|
adaptiveTrackSelection.updateSelectedTrack(
|
||||||
/* playbackPositionUs= */ 0,
|
/* playbackPositionUs= */ 0,
|
||||||
/* bufferedDurationUs= */ 3_600_000,
|
/* bufferedDurationUs= */ 3_600_000,
|
||||||
@ -768,14 +772,16 @@ public final class AdaptiveTrackSelectionTest {
|
|||||||
|
|
||||||
private AdaptiveTrackSelection
|
private AdaptiveTrackSelection
|
||||||
prepareAdaptiveTrackSelectionWithBufferedFractionToLiveEdgeForQualiyIncrease(
|
prepareAdaptiveTrackSelectionWithBufferedFractionToLiveEdgeForQualiyIncrease(
|
||||||
TrackGroup trackGroup, float bufferedFractionToLiveEdgeForQualityIncrease) {
|
TrackGroup trackGroup,
|
||||||
|
float bufferedFractionToLiveEdgeForQualityIncrease,
|
||||||
|
long minDurationForQualityIncreaseMs) {
|
||||||
return prepareTrackSelection(
|
return prepareTrackSelection(
|
||||||
new AdaptiveTrackSelection(
|
new AdaptiveTrackSelection(
|
||||||
trackGroup,
|
trackGroup,
|
||||||
selectedAllTracksInGroup(trackGroup),
|
selectedAllTracksInGroup(trackGroup),
|
||||||
TrackSelection.TYPE_UNSET,
|
TrackSelection.TYPE_UNSET,
|
||||||
mockBandwidthMeter,
|
mockBandwidthMeter,
|
||||||
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS,
|
minDurationForQualityIncreaseMs,
|
||||||
AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
|
AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
|
||||||
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
|
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
|
||||||
AdaptiveTrackSelection.DEFAULT_MAX_WIDTH_TO_DISCARD,
|
AdaptiveTrackSelection.DEFAULT_MAX_WIDTH_TO_DISCARD,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user