diff --git a/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java b/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java index 071f38c59a..d60a7452f7 100644 --- a/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java +++ b/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java @@ -1038,11 +1038,7 @@ public final class CastPlayer extends BasePlayer { final boolean[] trackSelected = new boolean[] {selected}; trackGroupInfos[i] = new TracksInfo.TrackGroupInfo( - trackType, - trackGroups[i], - /* adaptiveSupported= */ false, - trackSupport, - trackSelected); + trackGroups[i], /* adaptiveSupported= */ false, trackSupport, trackSelected); } TrackGroupArray newTrackGroups = new TrackGroupArray(trackGroups); TrackSelectionArray newTrackSelections = new TrackSelectionArray(trackSelections); diff --git a/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java b/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java index ad0bb81c23..8631aac4ab 100644 --- a/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java +++ b/libraries/common/src/main/java/androidx/media3/common/TrackGroup.java @@ -43,6 +43,8 @@ public final class TrackGroup implements Bundleable { public final int length; /** An identifier for the track group. */ public final String id; + /** The type of tracks in the group. */ + public final @C.TrackType int type; private final Format[] formats; @@ -71,6 +73,11 @@ public final class TrackGroup implements Bundleable { this.id = id; this.formats = formats; this.length = formats.length; + @C.TrackType int type = MimeTypes.getTrackType(formats[0].sampleMimeType); + if (type == C.TRACK_TYPE_UNKNOWN) { + type = MimeTypes.getTrackType(formats[0].containerMimeType); + } + this.type = type; verifyCorrectness(); } @@ -134,7 +141,7 @@ public final class TrackGroup implements Bundleable { return false; } TrackGroup other = (TrackGroup) obj; - return length == other.length && id.equals(other.id) && Arrays.equals(formats, other.formats); + return id.equals(other.id) && Arrays.equals(formats, other.formats); } // Bundleable implementation. diff --git a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java index 77b9c2bbf1..791f4f7082 100644 --- a/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java +++ b/libraries/common/src/main/java/androidx/media3/common/TrackSelectionOverride.java @@ -88,7 +88,7 @@ public final class TrackSelectionOverride implements Bundleable { /** Returns the {@link C.TrackType} of the overridden track group. */ public @C.TrackType int getTrackType() { - return MimeTypes.getTrackType(trackGroup.getFormat(0).sampleMimeType); + return trackGroup.type; } @Override diff --git a/libraries/common/src/main/java/androidx/media3/common/TracksInfo.java b/libraries/common/src/main/java/androidx/media3/common/TracksInfo.java index bf98c0f5ef..9dd0885788 100644 --- a/libraries/common/src/main/java/androidx/media3/common/TracksInfo.java +++ b/libraries/common/src/main/java/androidx/media3/common/TracksInfo.java @@ -49,7 +49,6 @@ public final class TracksInfo implements Bundleable { /** The number of tracks in the group. */ public final int length; - private final @C.TrackType int trackType; private final TrackGroup trackGroup; private final boolean adaptiveSupported; private final @C.FormatSupport int[] trackSupport; @@ -58,23 +57,20 @@ public final class TracksInfo implements Bundleable { /** * Constructs a TrackGroupInfo. * - * @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 adaptiveSupported Whether adaptive selections containing more than one track in the + * {@code trackGroup} 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}. + * @param tracksSelected Whether each track in the {@code trackGroup} is selected. */ @UnstableApi public TrackGroupInfo( - @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.trackType = trackType; this.trackGroup = trackGroup; this.adaptiveSupported = adaptiveSupported && length > 1; this.trackSupport = trackSupport.clone(); @@ -191,7 +187,7 @@ public final class TracksInfo implements Bundleable { /** Returns the {@link C.TrackType} of the group. */ public @C.TrackType int getTrackType() { - return trackType; + return trackGroup.type; } @Override @@ -203,7 +199,7 @@ public final class TracksInfo implements Bundleable { return false; } TrackGroupInfo that = (TrackGroupInfo) other; - return trackType == that.trackType + return adaptiveSupported == that.adaptiveSupported && trackGroup.equals(that.trackGroup) && Arrays.equals(trackSupport, that.trackSupport) && Arrays.equals(trackSelected, that.trackSelected); @@ -212,8 +208,8 @@ public final class TracksInfo implements Bundleable { @Override public int hashCode() { int result = trackGroup.hashCode(); + result = 31 * result + (adaptiveSupported ? 1 : 0); result = 31 * result + Arrays.hashCode(trackSupport); - result = 31 * result + trackType; result = 31 * result + Arrays.hashCode(trackSelected); return result; } @@ -225,7 +221,6 @@ public final class TracksInfo implements Bundleable { @IntDef({ FIELD_TRACK_GROUP, FIELD_TRACK_SUPPORT, - FIELD_TRACK_TYPE, FIELD_TRACK_SELECTED, FIELD_ADAPTIVE_SUPPORTED, }) @@ -233,7 +228,6 @@ public final class TracksInfo implements Bundleable { 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; private static final int FIELD_ADAPTIVE_SUPPORTED = 4; @@ -242,7 +236,6 @@ public final class TracksInfo implements Bundleable { 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); bundle.putBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), adaptiveSupported); return bundle; @@ -259,16 +252,13 @@ public final class TracksInfo implements Bundleable { final @C.FormatSupport int[] trackSupport = MoreObjects.firstNonNull( bundle.getIntArray(keyForField(FIELD_TRACK_SUPPORT)), new int[trackGroup.length]); - @C.TrackType - int trackType = bundle.getInt(keyForField(FIELD_TRACK_TYPE), C.TRACK_TYPE_UNKNOWN); boolean[] selected = MoreObjects.firstNonNull( bundle.getBooleanArray(keyForField(FIELD_TRACK_SELECTED)), new boolean[trackGroup.length]); boolean adaptiveSupported = bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false); - return new TrackGroupInfo( - trackType, trackGroup, adaptiveSupported, trackSupport, selected); + return new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected); }; private static String keyForField(@FieldNumber int field) { @@ -300,7 +290,7 @@ public final class TracksInfo implements Bundleable { /** 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) { + if (trackGroupInfos.get(i).getTrackType() == trackType) { return true; } } @@ -330,7 +320,7 @@ public final class TracksInfo implements Bundleable { @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).getTrackType() == trackType) { if (trackGroupInfos.get(i).isSupported(allowExceedsCapabilities)) { return true; } else { diff --git a/libraries/common/src/test/java/androidx/media3/common/TracksInfoTest.java b/libraries/common/src/test/java/androidx/media3/common/TracksInfoTest.java index b2eb0c80fe..c3f4182e29 100644 --- a/libraries/common/src/test/java/androidx/media3/common/TracksInfoTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/TracksInfoTest.java @@ -15,6 +15,8 @@ */ package androidx.media3.common; +import static androidx.media3.common.MimeTypes.AUDIO_AAC; +import static androidx.media3.common.MimeTypes.VIDEO_H264; import static com.google.common.truth.Truth.assertThat; import androidx.media3.common.TracksInfo.TrackGroupInfo; @@ -40,14 +42,14 @@ public class TracksInfoTest { new TracksInfo( ImmutableList.of( new TrackGroupInfo( - C.TRACK_TYPE_AUDIO, - new TrackGroup(new Format.Builder().build()), + new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()), /* adaptiveSupported= */ false, new int[] {C.FORMAT_EXCEEDS_CAPABILITIES}, /* tracksSelected= */ new boolean[] {true}), new TrackGroupInfo( - C.TRACK_TYPE_VIDEO, - new TrackGroup(new Format.Builder().build(), new Format.Builder().build()), + new TrackGroup( + new Format.Builder().setSampleMimeType(VIDEO_H264).build(), + new Format.Builder().setSampleMimeType(VIDEO_H264).build()), /* adaptiveSupported= */ true, new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_UNSUPPORTED_TYPE}, /* tracksSelected= */ new boolean[] {false, true}))); @@ -59,7 +61,12 @@ public class TracksInfoTest { public void tracksInfoGetters_withoutTrack_returnExpectedValues() { TracksInfo tracksInfo = new TracksInfo(ImmutableList.of()); + assertThat(tracksInfo.hasTracksOfType(C.TRACK_TYPE_AUDIO)).isFalse(); assertThat(tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)).isTrue(); + assertThat( + tracksInfo.isTypeSupportedOrEmpty( + C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) + .isTrue(); assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse(); ImmutableList trackGroupInfos = tracksInfo.getTrackGroupInfos(); assertThat(trackGroupInfos).isEmpty(); @@ -77,15 +84,15 @@ public class TracksInfoTest { public void tracksInfoGetters_ofComplexTracksInfo_returnExpectedValues() { TrackGroupInfo trackGroupInfo0 = new TrackGroupInfo( - C.TRACK_TYPE_AUDIO, - new TrackGroup(new Format.Builder().build()), + new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()), /* adaptiveSupported= */ false, new int[] {C.FORMAT_EXCEEDS_CAPABILITIES}, /* tracksSelected= */ new boolean[] {false}); TrackGroupInfo trackGroupInfo1 = new TrackGroupInfo( - C.TRACK_TYPE_VIDEO, - new TrackGroup(new Format.Builder().build(), new Format.Builder().build()), + new TrackGroup( + new Format.Builder().setSampleMimeType(VIDEO_H264).build(), + new Format.Builder().setSampleMimeType(VIDEO_H264).build()), /* adaptiveSupported= */ true, new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_HANDLED}, /* tracksSelected= */ new boolean[] {false, true}); @@ -97,6 +104,18 @@ public class TracksInfoTest { 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.isTypeSupportedOrEmpty( + C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) + .isTrue(); + assertThat( + tracksInfo.isTypeSupportedOrEmpty( + C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) + .isTrue(); + assertThat( + tracksInfo.isTypeSupportedOrEmpty( + C.TRACK_TYPE_TEXT, /* allowExceedsCapabilities= */ true)) + .isTrue(); assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse(); assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)).isTrue(); ImmutableList trackGroupInfos = tracksInfo.getTrackGroupInfos(); @@ -124,8 +143,7 @@ public class TracksInfoTest { public void trackGroupInfo_withSingleTrack_isNotAdaptive() { TrackGroupInfo trackGroupInfo0 = new TrackGroupInfo( - C.TRACK_TYPE_AUDIO, - new TrackGroup(new Format.Builder().build()), + new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()), /* adaptiveSupported= */ true, new int[] {C.FORMAT_EXCEEDS_CAPABILITIES}, /* tracksSelected= */ new boolean[] {false}); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java index 11f381e734..5f031720de 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java @@ -29,7 +29,6 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.media3.common.C; import androidx.media3.common.C.FormatSupport; -import androidx.media3.common.MimeTypes; import androidx.media3.common.Timeline; import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroupArray; @@ -373,8 +372,7 @@ public abstract class MappingTrackSelector extends TrackSelector { for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { TrackGroup group = trackGroups.get(groupIndex); // Associate the group to a preferred renderer. - boolean preferUnassociatedRenderer = - MimeTypes.getTrackType(group.getFormat(0).sampleMimeType) == C.TRACK_TYPE_METADATA; + boolean preferUnassociatedRenderer = group.type == C.TRACK_TYPE_METADATA; int rendererIndex = findRenderer( rendererCapabilities, group, rendererTrackGroupCounts, preferUnassociatedRenderer); @@ -588,10 +586,8 @@ public abstract class MappingTrackSelector extends TrackSelector { && trackSelection.indexOf(trackIndex) != C.INDEX_UNSET; selected[trackIndex] = isTrackSelected; } - @C.TrackType int trackGroupType = mappedTrackInfo.getRendererType(rendererIndex); builder.add( - new TracksInfo.TrackGroupInfo( - trackGroupType, trackGroup, adaptiveSupported, trackSupport, selected)); + new TracksInfo.TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected)); } } TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups(); @@ -600,12 +596,10 @@ public abstract class MappingTrackSelector extends TrackSelector { @C.FormatSupport int[] trackSupport = new int[trackGroup.length]; Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE); // A track group only contains tracks of the same type, thus only consider the first track. - @C.TrackType - int trackGroupType = MimeTypes.getTrackType(trackGroup.getFormat(0).sampleMimeType); boolean[] selected = new boolean[trackGroup.length]; // Initialized to false. builder.add( new TracksInfo.TrackGroupInfo( - trackGroupType, trackGroup, /* adaptiveSupported= */ false, trackSupport, selected)); + trackGroup, /* adaptiveSupported= */ false, trackSupport, selected)); } return new TracksInfo(builder.build()); } diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/MappingTrackSelectorTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/MappingTrackSelectorTest.java index 32023b11e2..6badef1484 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/MappingTrackSelectorTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/trackselection/MappingTrackSelectorTest.java @@ -15,6 +15,8 @@ */ package androidx.media3.exoplayer.trackselection; +import static androidx.media3.common.MimeTypes.AUDIO_AAC; +import static androidx.media3.common.MimeTypes.VIDEO_H264; import static com.google.common.truth.Truth.assertThat; import android.util.Pair; @@ -53,7 +55,7 @@ public final class MappingTrackSelectorTest { new FakeRendererCapabilities(C.TRACK_TYPE_METADATA); private static final TrackGroup VIDEO_TRACK_GROUP = buildTrackGroup(MimeTypes.VIDEO_H264); - private static final TrackGroup AUDIO_TRACK_GROUP = buildTrackGroup(MimeTypes.AUDIO_AAC); + private static final TrackGroup AUDIO_TRACK_GROUP = buildTrackGroup(AUDIO_AAC); private static final TrackGroup METADATA_TRACK_GROUP = buildTrackGroup(MimeTypes.APPLICATION_ID3); private static final Timeline TIMELINE = new FakeTimeline(); @@ -146,10 +148,13 @@ public final class MappingTrackSelectorTest { new int[] {C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_VIDEO}, new TrackGroupArray[] { new TrackGroupArray( - new TrackGroup("0", new Format.Builder().build()), - new TrackGroup("1", new Format.Builder().build())), + new TrackGroup("0", new Format.Builder().setSampleMimeType(AUDIO_AAC).build()), + new TrackGroup("1", new Format.Builder().setSampleMimeType(AUDIO_AAC).build())), new TrackGroupArray( - new TrackGroup("2", new Format.Builder().build(), new Format.Builder().build())) + new TrackGroup( + "2", + new Format.Builder().setSampleMimeType(VIDEO_H264).build(), + new Format.Builder().setSampleMimeType(VIDEO_H264).build())) }, new int[] { RendererCapabilities.ADAPTIVE_SEAMLESS, RendererCapabilities.ADAPTIVE_NOT_SUPPORTED