Add TracksInfo methods for track selection UI
We need TracksInfo.hasTracksOfType to determine which tabs to display in TrackSelectionDialog. We need TrackGroupInfo.isAdaptiveSupported to determine whether to allow multiple selection (check boxes) or not (radio buttons). PiperOrigin-RevId: 428793739
This commit is contained in:
parent
3cd23de1cb
commit
9137947797
@ -1037,7 +1037,12 @@ public final class CastPlayer extends BasePlayer {
|
||||
int[] trackSupport = new int[] {supported ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_TYPE};
|
||||
final boolean[] trackSelected = new boolean[] {selected};
|
||||
trackGroupInfos[i] =
|
||||
new TracksInfo.TrackGroupInfo(trackGroups[i], trackSupport, trackType, trackSelected);
|
||||
new TracksInfo.TrackGroupInfo(
|
||||
trackType,
|
||||
trackGroups[i],
|
||||
/* adaptiveSupported= */ false,
|
||||
trackSupport,
|
||||
trackSelected);
|
||||
}
|
||||
TrackGroupArray newTrackGroups = new TrackGroupArray(trackGroups);
|
||||
TrackSelectionArray newTrackSelections = new TrackSelectionArray(trackSelections);
|
||||
|
@ -49,30 +49,35 @@ public final class TracksInfo implements Bundleable {
|
||||
/** The number of tracks in the group. */
|
||||
public final int length;
|
||||
|
||||
private final TrackGroup trackGroup;
|
||||
private final @C.FormatSupport int[] trackSupport;
|
||||
private final @C.TrackType int trackType;
|
||||
private final TrackGroup trackGroup;
|
||||
private final boolean adaptiveSupported;
|
||||
private final @C.FormatSupport int[] trackSupport;
|
||||
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 trackGroup The {@link TrackGroup} described.
|
||||
* @param adaptiveSupported Whether adaptive selections containing more than one track are
|
||||
* supported.
|
||||
* @param trackSupport The {@link C.FormatSupport} of each track in the {@code trackGroup}.
|
||||
* @param tracksSelected Whether a track is selected for each track in {@code trackGroup}.
|
||||
*/
|
||||
@UnstableApi
|
||||
public TrackGroupInfo(
|
||||
TrackGroup trackGroup,
|
||||
@C.FormatSupport int[] trackSupport,
|
||||
@C.TrackType int trackType,
|
||||
TrackGroup trackGroup,
|
||||
boolean adaptiveSupported,
|
||||
@C.FormatSupport int[] trackSupport,
|
||||
boolean[] tracksSelected) {
|
||||
length = trackGroup.length;
|
||||
checkArgument(length == trackSupport.length && length == tracksSelected.length);
|
||||
this.trackGroup = trackGroup;
|
||||
this.trackSupport = trackSupport.clone();
|
||||
this.trackType = trackType;
|
||||
this.trackGroup = trackGroup;
|
||||
this.adaptiveSupported = adaptiveSupported && length > 1;
|
||||
this.trackSupport = trackSupport.clone();
|
||||
this.trackSelected = tracksSelected.clone();
|
||||
}
|
||||
|
||||
@ -135,6 +140,11 @@ public final class TracksInfo implements Bundleable {
|
||||
return Booleans.contains(trackSelected, true);
|
||||
}
|
||||
|
||||
/** Returns whether adaptive selections containing more than one track are supported. */
|
||||
public boolean isAdaptiveSupported() {
|
||||
return adaptiveSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)}.
|
||||
@ -217,6 +227,7 @@ public final class TracksInfo implements Bundleable {
|
||||
FIELD_TRACK_SUPPORT,
|
||||
FIELD_TRACK_TYPE,
|
||||
FIELD_TRACK_SELECTED,
|
||||
FIELD_ADAPTIVE_SUPPORTED,
|
||||
})
|
||||
private @interface FieldNumber {}
|
||||
|
||||
@ -224,6 +235,7 @@ public final class TracksInfo implements Bundleable {
|
||||
private static final int FIELD_TRACK_SUPPORT = 1;
|
||||
private static final int FIELD_TRACK_TYPE = 2;
|
||||
private static final int FIELD_TRACK_SELECTED = 3;
|
||||
private static final int FIELD_ADAPTIVE_SUPPORTED = 4;
|
||||
|
||||
@Override
|
||||
public Bundle toBundle() {
|
||||
@ -232,6 +244,7 @@ public final class TracksInfo implements Bundleable {
|
||||
bundle.putIntArray(keyForField(FIELD_TRACK_SUPPORT), trackSupport);
|
||||
bundle.putInt(keyForField(FIELD_TRACK_TYPE), trackType);
|
||||
bundle.putBooleanArray(keyForField(FIELD_TRACK_SELECTED), trackSelected);
|
||||
bundle.putBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), adaptiveSupported);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@ -252,7 +265,10 @@ public final class TracksInfo implements Bundleable {
|
||||
MoreObjects.firstNonNull(
|
||||
bundle.getBooleanArray(keyForField(FIELD_TRACK_SELECTED)),
|
||||
new boolean[trackGroup.length]);
|
||||
return new TrackGroupInfo(trackGroup, trackSupport, trackType, selected);
|
||||
boolean adaptiveSupported =
|
||||
bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false);
|
||||
return new TrackGroupInfo(
|
||||
trackType, trackGroup, adaptiveSupported, trackSupport, selected);
|
||||
};
|
||||
|
||||
private static String keyForField(@FieldNumber int field) {
|
||||
@ -281,6 +297,16 @@ public final class TracksInfo implements Bundleable {
|
||||
return trackGroupInfos;
|
||||
}
|
||||
|
||||
/** Returns true if there are tracks of type {@code trackType}, and false otherwise. */
|
||||
public boolean hasTracksOfType(@C.TrackType int trackType) {
|
||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
||||
if (trackGroupInfos.get(i).trackType == trackType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if at least one track of type {@code trackType} is {@link
|
||||
* TrackGroupInfo#isTrackSupported(int) supported} or if there are no tracks of this type.
|
||||
|
@ -17,6 +17,7 @@ package androidx.media3.common;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.junit.Test;
|
||||
@ -38,16 +39,18 @@ public class TracksInfoTest {
|
||||
TracksInfo before =
|
||||
new TracksInfo(
|
||||
ImmutableList.of(
|
||||
new TracksInfo.TrackGroupInfo(
|
||||
new TrackGroup(new Format.Builder().build()),
|
||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||
new TrackGroupInfo(
|
||||
C.TRACK_TYPE_AUDIO,
|
||||
new boolean[] {true}),
|
||||
new TracksInfo.TrackGroupInfo(
|
||||
new TrackGroup(new Format.Builder().build(), new Format.Builder().build()),
|
||||
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_UNSUPPORTED_TYPE},
|
||||
new TrackGroup(new Format.Builder().build()),
|
||||
/* adaptiveSupported= */ false,
|
||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||
/* tracksSelected= */ new boolean[] {true}),
|
||||
new TrackGroupInfo(
|
||||
C.TRACK_TYPE_VIDEO,
|
||||
new boolean[] {false, true})));
|
||||
new TrackGroup(new Format.Builder().build(), new Format.Builder().build()),
|
||||
/* adaptiveSupported= */ true,
|
||||
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_UNSUPPORTED_TYPE},
|
||||
/* tracksSelected= */ new boolean[] {false, true})));
|
||||
TracksInfo after = TracksInfo.CREATOR.fromBundle(before.toBundle());
|
||||
assertThat(after).isEqualTo(before);
|
||||
}
|
||||
@ -58,7 +61,7 @@ public class TracksInfoTest {
|
||||
|
||||
assertThat(tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)).isTrue();
|
||||
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
||||
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
||||
assertThat(trackGroupInfos).isEmpty();
|
||||
}
|
||||
|
||||
@ -72,26 +75,31 @@ public class TracksInfoTest {
|
||||
|
||||
@Test
|
||||
public void tracksInfoGetters_ofComplexTracksInfo_returnExpectedValues() {
|
||||
TracksInfo.TrackGroupInfo trackGroupInfo0 =
|
||||
new TracksInfo.TrackGroupInfo(
|
||||
new TrackGroup(new Format.Builder().build()),
|
||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||
TrackGroupInfo trackGroupInfo0 =
|
||||
new TrackGroupInfo(
|
||||
C.TRACK_TYPE_AUDIO,
|
||||
new TrackGroup(new Format.Builder().build()),
|
||||
/* adaptiveSupported= */ false,
|
||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||
/* tracksSelected= */ new boolean[] {false});
|
||||
TracksInfo.TrackGroupInfo trackGroupInfo1 =
|
||||
new TracksInfo.TrackGroupInfo(
|
||||
new TrackGroup(new Format.Builder().build(), new Format.Builder().build()),
|
||||
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_HANDLED},
|
||||
TrackGroupInfo trackGroupInfo1 =
|
||||
new TrackGroupInfo(
|
||||
C.TRACK_TYPE_VIDEO,
|
||||
new TrackGroup(new Format.Builder().build(), new Format.Builder().build()),
|
||||
/* adaptiveSupported= */ true,
|
||||
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_HANDLED},
|
||||
/* tracksSelected= */ new boolean[] {false, true});
|
||||
TracksInfo tracksInfo = new TracksInfo(ImmutableList.of(trackGroupInfo0, trackGroupInfo1));
|
||||
|
||||
assertThat(tracksInfo.hasTracksOfType(C.TRACK_TYPE_AUDIO)).isTrue();
|
||||
assertThat(tracksInfo.hasTracksOfType(C.TRACK_TYPE_VIDEO)).isTrue();
|
||||
assertThat(tracksInfo.hasTracksOfType(C.TRACK_TYPE_TEXT)).isFalse();
|
||||
assertThat(tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||
assertThat(tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_VIDEO)).isTrue();
|
||||
assertThat(tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_TEXT)).isTrue();
|
||||
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)).isTrue();
|
||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
||||
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
||||
assertThat(trackGroupInfos).hasSize(2);
|
||||
assertThat(trackGroupInfos.get(0)).isSameInstanceAs(trackGroupInfo0);
|
||||
assertThat(trackGroupInfos.get(1)).isSameInstanceAs(trackGroupInfo1);
|
||||
@ -107,4 +115,20 @@ public class TracksInfoTest {
|
||||
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(C.TRACK_TYPE_AUDIO);
|
||||
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(C.TRACK_TYPE_VIDEO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@link TrackGroupInfo#isAdaptiveSupported} returns false if the group only contains
|
||||
* a single track, even if true is passed to the constructor.
|
||||
*/
|
||||
@Test
|
||||
public void trackGroupInfo_withSingleTrack_isNotAdaptive() {
|
||||
TrackGroupInfo trackGroupInfo0 =
|
||||
new TrackGroupInfo(
|
||||
C.TRACK_TYPE_AUDIO,
|
||||
new TrackGroup(new Format.Builder().build()),
|
||||
/* adaptiveSupported= */ true,
|
||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||
/* tracksSelected= */ new boolean[] {false});
|
||||
assertThat(trackGroupInfo0.isAdaptiveSupported()).isFalse();
|
||||
}
|
||||
}
|
||||
|
@ -573,6 +573,10 @@ public abstract class MappingTrackSelector extends TrackSelector {
|
||||
@Nullable TrackSelection trackSelection = selections[rendererIndex];
|
||||
for (int groupIndex = 0; groupIndex < trackGroupArray.length; groupIndex++) {
|
||||
TrackGroup trackGroup = trackGroupArray.get(groupIndex);
|
||||
boolean adaptiveSupported =
|
||||
mappedTrackInfo.getAdaptiveSupport(
|
||||
rendererIndex, groupIndex, /* includeCapabilitiesExceededTracks= */ false)
|
||||
!= RendererCapabilities.ADAPTIVE_NOT_SUPPORTED;
|
||||
@C.FormatSupport int[] trackSupport = new int[trackGroup.length];
|
||||
boolean[] selected = new boolean[trackGroup.length];
|
||||
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||
@ -586,7 +590,8 @@ public abstract class MappingTrackSelector extends TrackSelector {
|
||||
}
|
||||
@C.TrackType int trackGroupType = mappedTrackInfo.getRendererType(rendererIndex);
|
||||
builder.add(
|
||||
new TracksInfo.TrackGroupInfo(trackGroup, trackSupport, trackGroupType, selected));
|
||||
new TracksInfo.TrackGroupInfo(
|
||||
trackGroupType, trackGroup, adaptiveSupported, trackSupport, selected));
|
||||
}
|
||||
}
|
||||
TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
|
||||
@ -599,7 +604,8 @@ public abstract class MappingTrackSelector extends TrackSelector {
|
||||
int trackGroupType = MimeTypes.getTrackType(trackGroup.getFormat(0).sampleMimeType);
|
||||
boolean[] selected = new boolean[trackGroup.length]; // Initialized to false.
|
||||
builder.add(
|
||||
new TracksInfo.TrackGroupInfo(trackGroup, trackSupport, trackGroupType, selected));
|
||||
new TracksInfo.TrackGroupInfo(
|
||||
trackGroupType, trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
|
||||
}
|
||||
return new TracksInfo(builder.build());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user