Add fail-early checks for TrackSelectorResult correctness
The two arrays need to have the same length and the selection must match in their nullness (unless for TYPE_NONE renderers). Clarify this more clearly in the docs and add new asssertions for it. This avoids that the player is failing in obscure ways much later. Issue: androidx/media#1473 #cherrypick PiperOrigin-RevId: 646086833
This commit is contained in:
parent
bb568b5150
commit
71ef848ec3
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.exoplayer;
|
package androidx.media3.exoplayer;
|
||||||
|
|
||||||
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.exoplayer.MediaPeriodQueue.areDurationsCompatible;
|
import static androidx.media3.exoplayer.MediaPeriodQueue.areDurationsCompatible;
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
|
|
||||||
@ -22,7 +23,6 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.util.Assertions;
|
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
import androidx.media3.common.util.NullableType;
|
import androidx.media3.common.util.NullableType;
|
||||||
import androidx.media3.exoplayer.source.ClippingMediaPeriod;
|
import androidx.media3.exoplayer.source.ClippingMediaPeriod;
|
||||||
@ -212,7 +212,7 @@ import androidx.media3.exoplayer.upstream.Allocator;
|
|||||||
* @param rendererPositionUs The playing position in renderer time, in microseconds.
|
* @param rendererPositionUs The playing position in renderer time, in microseconds.
|
||||||
*/
|
*/
|
||||||
public void reevaluateBuffer(long rendererPositionUs) {
|
public void reevaluateBuffer(long rendererPositionUs) {
|
||||||
Assertions.checkState(isLoadingMediaPeriod());
|
checkState(isLoadingMediaPeriod());
|
||||||
if (prepared) {
|
if (prepared) {
|
||||||
mediaPeriod.reevaluateBuffer(toPeriodTime(rendererPositionUs));
|
mediaPeriod.reevaluateBuffer(toPeriodTime(rendererPositionUs));
|
||||||
}
|
}
|
||||||
@ -230,7 +230,7 @@ import androidx.media3.exoplayer.upstream.Allocator;
|
|||||||
*/
|
*/
|
||||||
public void continueLoading(
|
public void continueLoading(
|
||||||
long rendererPositionUs, float playbackSpeed, long lastRebufferRealtimeMs) {
|
long rendererPositionUs, float playbackSpeed, long lastRebufferRealtimeMs) {
|
||||||
Assertions.checkState(isLoadingMediaPeriod());
|
checkState(isLoadingMediaPeriod());
|
||||||
long loadingPeriodPositionUs = toPeriodTime(rendererPositionUs);
|
long loadingPeriodPositionUs = toPeriodTime(rendererPositionUs);
|
||||||
mediaPeriod.continueLoading(
|
mediaPeriod.continueLoading(
|
||||||
new LoadingInfo.Builder()
|
new LoadingInfo.Builder()
|
||||||
@ -255,6 +255,15 @@ import androidx.media3.exoplayer.upstream.Allocator;
|
|||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
TrackSelectorResult selectorResult =
|
TrackSelectorResult selectorResult =
|
||||||
trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
|
trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
|
||||||
|
for (int i = 0; i < selectorResult.length; i++) {
|
||||||
|
if (selectorResult.isRendererEnabled(i)) {
|
||||||
|
checkState(
|
||||||
|
selectorResult.selections[i] != null
|
||||||
|
|| rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE);
|
||||||
|
} else {
|
||||||
|
checkState(selectorResult.selections[i] == null);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (ExoTrackSelection trackSelection : selectorResult.selections) {
|
for (ExoTrackSelection trackSelection : selectorResult.selections) {
|
||||||
if (trackSelection != null) {
|
if (trackSelection != null) {
|
||||||
trackSelection.onPlaybackSpeed(playbackSpeed);
|
trackSelection.onPlaybackSpeed(playbackSpeed);
|
||||||
@ -324,13 +333,13 @@ import androidx.media3.exoplayer.upstream.Allocator;
|
|||||||
hasEnabledTracks = false;
|
hasEnabledTracks = false;
|
||||||
for (int i = 0; i < sampleStreams.length; i++) {
|
for (int i = 0; i < sampleStreams.length; i++) {
|
||||||
if (sampleStreams[i] != null) {
|
if (sampleStreams[i] != null) {
|
||||||
Assertions.checkState(newTrackSelectorResult.isRendererEnabled(i));
|
checkState(newTrackSelectorResult.isRendererEnabled(i));
|
||||||
// hasEnabledTracks should be true only when non-empty streams exists.
|
// hasEnabledTracks should be true only when non-empty streams exists.
|
||||||
if (rendererCapabilities[i].getTrackType() != C.TRACK_TYPE_NONE) {
|
if (rendererCapabilities[i].getTrackType() != C.TRACK_TYPE_NONE) {
|
||||||
hasEnabledTracks = true;
|
hasEnabledTracks = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Assertions.checkState(newTrackSelectorResult.selections[i] == null);
|
checkState(newTrackSelectorResult.selections[i] == null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return positionUs;
|
return positionUs;
|
||||||
|
@ -450,7 +450,7 @@ public abstract class MappingTrackSelector extends TrackSelector {
|
|||||||
* @param timeline The {@link Timeline} holding the period for which tracks are to be selected.
|
* @param timeline The {@link Timeline} holding the period for which tracks are to be selected.
|
||||||
* @return A pair consisting of the track selections and configurations for each renderer. A null
|
* @return A pair consisting of the track selections and configurations for each renderer. A null
|
||||||
* configuration indicates the renderer should be disabled, in which case the track selection
|
* configuration indicates the renderer should be disabled, in which case the track selection
|
||||||
* will also be null. A track selection may also be null for a non-disabled renderer if {@link
|
* must also be null. A track selection may also be null for a non-disabled renderer if {@link
|
||||||
* RendererCapabilities#getTrackType()} is {@link C#TRACK_TYPE_NONE}.
|
* RendererCapabilities#getTrackType()} is {@link C#TRACK_TYPE_NONE}.
|
||||||
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
||||||
*/
|
*/
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.exoplayer.trackselection;
|
package androidx.media3.exoplayer.trackselection;
|
||||||
|
|
||||||
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Tracks;
|
import androidx.media3.common.Tracks;
|
||||||
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.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
import androidx.media3.exoplayer.RendererConfiguration;
|
import androidx.media3.exoplayer.RendererConfiguration;
|
||||||
|
|
||||||
/** The result of a {@link TrackSelector} operation. */
|
/** The result of a {@link TrackSelector} operation. */
|
||||||
@ -69,6 +73,9 @@ public final class TrackSelectorResult {
|
|||||||
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
|
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
|
||||||
* indicates the corresponding renderer should be disabled.
|
* indicates the corresponding renderer should be disabled.
|
||||||
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
|
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
|
||||||
|
* If the renderer is disabled with a null {@link RendererConfiguration}, then it must have a
|
||||||
|
* null selection too. It can also have a null selection if it has a {@linkplain
|
||||||
|
* RendererCapabilities#getTrackType() track type} of {@link C#TRACK_TYPE_NONE}.
|
||||||
* @param tracks Description of the available tracks and which one were selected.
|
* @param tracks Description of the available tracks and which one were selected.
|
||||||
* @param info An opaque object that will be returned to {@link
|
* @param info An opaque object that will be returned to {@link
|
||||||
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
||||||
@ -79,6 +86,7 @@ public final class TrackSelectorResult {
|
|||||||
@NullableType ExoTrackSelection[] selections,
|
@NullableType ExoTrackSelection[] selections,
|
||||||
Tracks tracks,
|
Tracks tracks,
|
||||||
@Nullable Object info) {
|
@Nullable Object info) {
|
||||||
|
checkArgument(rendererConfigurations.length == selections.length);
|
||||||
this.rendererConfigurations = rendererConfigurations;
|
this.rendererConfigurations = rendererConfigurations;
|
||||||
this.selections = selections.clone();
|
this.selections = selections.clone();
|
||||||
this.tracks = tracks;
|
this.tracks = tracks;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user