/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.exoplayer2; import static com.google.android.exoplayer2.util.Assertions.checkArgument; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.BundleableUtil.fromBundleNullableList; import static com.google.android.exoplayer2.util.BundleableUtil.fromNullableBundle; import static com.google.android.exoplayer2.util.BundleableUtil.toBundleArrayList; 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; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.List; /** Immutable information ({@link TrackGroupInfo}) about 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. */ public static final class TrackGroupInfo implements Bundleable { private final TrackGroup trackGroup; @C.FormatSupport private final int[] trackSupport; private final @C.TrackType int trackType; private final boolean[] trackSelected; /** * Constructs a TrackGroupInfo. * * @param trackGroup The {@link TrackGroup} described. * @param trackSupport The {@link C.FormatSupport} of each track in the {@code trackGroup}. * @param trackType The {@link C.TrackType} of the tracks in the {@code trackGroup}. * @param tracksSelected Whether a track is selected for each track in {@code trackGroup}. */ public TrackGroupInfo( TrackGroup trackGroup, @C.FormatSupport int[] trackSupport, @C.TrackType int trackType, boolean[] tracksSelected) { int length = trackGroup.length; checkArgument(length == trackSupport.length && length == tracksSelected.length); this.trackGroup = trackGroup; this.trackSupport = trackSupport.clone(); this.trackType = trackType; this.trackSelected = tracksSelected.clone(); } /** Returns the {@link TrackGroup} described by this {@code TrackGroupInfo}. */ public TrackGroup getTrackGroup() { return trackGroup; } /** * Returns the level of support for a track in a {@link TrackGroup}. * * @param trackIndex The index of the track in the {@link TrackGroup}. * @return The {@link C.FormatSupport} of the track. */ @C.FormatSupport public int getTrackSupport(int trackIndex) { return trackSupport[trackIndex]; } /** * Returns if a track in a {@link TrackGroup} is supported for playback. * * @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; } /** Returns if at least one track in a {@link TrackGroup} is selected for playback. */ public boolean isSelected() { return Booleans.contains(trackSelected, true); } /** Returns if at least one track in a {@link TrackGroup} is supported. */ public boolean isSupported() { for (int i = 0; i < trackSupport.length; i++) { if (isTrackSupported(i)) { return true; } } return false; } /** * Returns if a track in a {@link TrackGroup} 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}. * *
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}.
*
* @param trackIndex The index of the track in the {@link TrackGroup}.
* @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.
*/
public @C.TrackType int getTrackType() {
return trackType;
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (other == null || getClass() != other.getClass()) {
return false;
}
TrackGroupInfo that = (TrackGroupInfo) other;
return trackType == that.trackType
&& trackGroup.equals(that.trackGroup)
&& Arrays.equals(trackSupport, that.trackSupport)
&& Arrays.equals(trackSelected, that.trackSelected);
}
@Override
public int hashCode() {
int result = trackGroup.hashCode();
result = 31 * result + Arrays.hashCode(trackSupport);
result = 31 * result + trackType;
result = 31 * result + Arrays.hashCode(trackSelected);
return result;
}
// Bundleable implementation.
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({
FIELD_TRACK_GROUP,
FIELD_TRACK_SUPPORT,
FIELD_TRACK_TYPE,
FIELD_TRACK_SELECTED,
})
private @interface FieldNumber {}
private static final int FIELD_TRACK_GROUP = 0;
private static final int FIELD_TRACK_SUPPORT = 1;
private static final int FIELD_TRACK_TYPE = 2;
private static final int FIELD_TRACK_SELECTED = 3;
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putBundle(keyForField(FIELD_TRACK_GROUP), trackGroup.toBundle());
bundle.putIntArray(keyForField(FIELD_TRACK_SUPPORT), trackSupport);
bundle.putInt(keyForField(FIELD_TRACK_TYPE), trackType);
bundle.putBooleanArray(keyForField(FIELD_TRACK_SELECTED), trackSelected);
return bundle;
}
/** Object that can restores a {@code TracksInfo} from a {@link Bundle}. */
public static final Creator