diff --git a/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java b/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java index 32fb65c2fa..8d78ca1112 100644 --- a/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java +++ b/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java @@ -223,10 +223,12 @@ import java.util.ArrayList; if (currentPlayer != localPlayer || tracksInfo == lastSeenTrackGroupInfo) { return; } - if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_VIDEO)) { + if (!tracksInfo.isTypeSupportedOrEmpty( + C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) { listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO); } - if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)) { + if (!tracksInfo.isTypeSupportedOrEmpty( + C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) { listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO); } lastSeenTrackGroupInfo = tracksInfo; diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index d0aa4d58af..eaff9a185a 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -441,10 +441,12 @@ public class PlayerActivity extends AppCompatActivity if (tracksInfo == lastSeenTracksInfo) { return; } - if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_VIDEO)) { + if (!tracksInfo.isTypeSupportedOrEmpty( + C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) { showToast(R.string.error_unsupported_video); } - if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)) { + if (!tracksInfo.isTypeSupportedOrEmpty( + C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) { showToast(R.string.error_unsupported_audio); } lastSeenTracksInfo = tracksInfo; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/TracksInfo.java b/library/common/src/main/java/com/google/android/exoplayer2/TracksInfo.java index 328f8a4080..5a46825692 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/TracksInfo.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/TracksInfo.java @@ -25,7 +25,6 @@ import android.os.Bundle; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.TrackGroup; -import com.google.android.exoplayer2.trackselection.TrackSelectionParameters; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; import com.google.common.primitives.Booleans; @@ -35,11 +34,12 @@ import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.List; -/** Immutable information ({@link TrackGroupInfo}) about tracks. */ +/** Information about groups of tracks. */ public final class TracksInfo implements Bundleable { /** - * Information about tracks in a {@link TrackGroup}: their {@link C.TrackType}, if their format is - * supported by the player and if they are selected for playback. + * Information about a single group of tracks, including the underlying {@link TrackGroup}, the + * {@link C.TrackType type} of tracks it contains, and the level to which each track is supported + * by the player. */ public static final class TrackGroupInfo implements Bundleable { private final TrackGroup trackGroup; @@ -74,7 +74,7 @@ public final class TracksInfo implements Bundleable { } /** - * Returns the level of support for a track in a {@link TrackGroup}. + * Returns the level of support for a specified track. * * @param trackIndex The index of the track in the {@link TrackGroup}. * @return The {@link C.FormatSupport} of the track. @@ -85,24 +85,58 @@ public final class TracksInfo implements Bundleable { } /** - * Returns if a track in a {@link TrackGroup} is supported for playback. + * Returns whether a specified track is supported for playback, without exceeding the advertised + * capabilities of the device. Equivalent to {@code isTrackSupported(trackIndex, false)}. * * @param trackIndex The index of the track in the {@link TrackGroup}. * @return True if the track's format can be played, false otherwise. */ public boolean isTrackSupported(int trackIndex) { - return trackSupport[trackIndex] == C.FORMAT_HANDLED; + return isTrackSupported(trackIndex, /* allowExceedsCapabilities= */ false); } - /** Returns if at least one track in a {@link TrackGroup} is selected for playback. */ + /** + * Returns whether a specified track is supported for playback. + * + * @param trackIndex The index of the track in the {@link TrackGroup}. + * @param allowExceedsCapabilities Whether to consider the track as supported if it has a + * supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised + * capabilities of the device. For example, a video track for which there's a corresponding + * decoder whose maximum advertised resolution is exceeded by the resolution of the track. + * Such tracks may be playable in some cases. + * @return True if the track's format can be played, false otherwise. + */ + public boolean isTrackSupported(int trackIndex, boolean allowExceedsCapabilities) { + return trackSupport[trackIndex] == C.FORMAT_HANDLED + || (allowExceedsCapabilities + && trackSupport[trackIndex] == C.FORMAT_EXCEEDS_CAPABILITIES); + } + + /** Returns whether at least one track in the group is selected for playback. */ public boolean isSelected() { return Booleans.contains(trackSelected, true); } - /** Returns if at least one track in a {@link TrackGroup} is supported. */ + /** + * Returns whether at least one track in the group is supported for playback, without exceeding + * the advertised capabilities of the device. Equivalent to {@code isSupported(false)}. + */ public boolean isSupported() { + return isSupported(/* allowExceedsCapabilities= */ false); + } + + /** + * Returns whether at least one track in the group is supported for playback. + * + * @param allowExceedsCapabilities Whether to consider a track as supported if it has a + * supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised + * capabilities of the device. For example, a video track for which there's a corresponding + * decoder whose maximum advertised resolution is exceeded by the resolution of the track. + * Such tracks may be playable in some cases. + */ + public boolean isSupported(boolean allowExceedsCapabilities) { for (int i = 0; i < trackSupport.length; i++) { - if (isTrackSupported(i)) { + if (isTrackSupported(i, allowExceedsCapabilities)) { return true; } } @@ -110,27 +144,24 @@ public final class TracksInfo implements Bundleable { } /** - * Returns if a track in a {@link TrackGroup} is selected for playback. + * Returns whether a specified track is selected for playback. * - *

Multiple tracks of a track group may be selected. This is common in adaptive streaming, - * where multiple tracks of different quality are selected and the player switches between them - * depending on the network and the {@link TrackSelectionParameters}. + *

Note that multiple tracks in the group may be selected. This is common in adaptive + * streaming, where tracks of different qualities are selected and the player switches between + * them during playback (e.g., based on the available network bandwidth). * - *

While this class doesn't provide which selected track is currently playing, some player - * implementations have ways of getting such information. For example ExoPlayer provides this - * information in {@code ExoTrackSelection.getSelectedFormat}. + *

This class doesn't provide a way to determine which of the selected tracks is currently + * playing, however some player implementations have ways of getting such information. For + * example, ExoPlayer provides this information via {@code ExoTrackSelection.getSelectedFormat}. * * @param trackIndex The index of the track in the {@link TrackGroup}. - * @return true if the track is selected, false otherwise. + * @return True if the track is selected, false otherwise. */ public boolean isTrackSelected(int trackIndex) { return trackSelected[trackIndex]; } - /** - * Returns the {@link C.TrackType} of the tracks in the {@link TrackGroup}. Tracks in a group - * are all of the same type. - */ + /** Returns the {@link C.TrackType} of the group. */ public @C.TrackType int getTrackType() { return trackType; } @@ -212,28 +243,49 @@ public final class TracksInfo implements Bundleable { private final ImmutableList trackGroupInfos; - /** An empty {@code TrackInfo} containing no {@link TrackGroupInfo}. */ + /** An {@code TrackInfo} that contains no tracks. */ public static final TracksInfo EMPTY = new TracksInfo(ImmutableList.of()); - /** Constructs {@code TracksInfo} from the provided {@link TrackGroupInfo}. */ + /** + * Constructs an instance. + * + * @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} describing the groups of + * tracks. + */ public TracksInfo(List trackGroupInfos) { this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos); } - /** Returns the {@link TrackGroupInfo TrackGroupInfos}, describing each {@link TrackGroup}. */ + /** Returns the {@link TrackGroupInfo TrackGroupInfos} describing the groups of tracks. */ public ImmutableList getTrackGroupInfos() { return trackGroupInfos; } /** * Returns true if at least one track of type {@code trackType} is {@link - * TrackGroupInfo#isTrackSupported(int) supported}, or there are no tracks of this type. + * TrackGroupInfo#isTrackSupported(int) supported} or if there are no tracks of this type. */ public boolean isTypeSupportedOrEmpty(@C.TrackType int trackType) { + return isTypeSupportedOrEmpty(trackType, /* allowExceedsCapabilities= */ false); + } + + /** + * Returns true if at least one track of type {@code trackType} is {@link + * TrackGroupInfo#isTrackSupported(int, boolean) supported} or if there are no tracks of this + * type. + * + * @param allowExceedsCapabilities Whether to consider the track as supported if it has a + * supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised + * capabilities of the device. For example, a video track for which there's a corresponding + * decoder whose maximum advertised resolution is exceeded by the resolution of the track. + * Such tracks may be playable in some cases. + */ + public boolean isTypeSupportedOrEmpty( + @C.TrackType int trackType, boolean allowExceedsCapabilities) { boolean supported = true; for (int i = 0; i < trackGroupInfos.size(); i++) { if (trackGroupInfos.get(i).trackType == trackType) { - if (trackGroupInfos.get(i).isSupported()) { + if (trackGroupInfos.get(i).isSupported(allowExceedsCapabilities)) { return true; } else { supported = false;