From 265dd079e99a8a1ca9b71a2255fc9c43d3f59198 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 17 Feb 2022 15:20:46 +0000 Subject: [PATCH] Move track type from TrackGroupInfo to TrackGroup The track type is derived solely from the content. It does not depend on any runtime properties such as the player's capabilities of user track selection. Hence it belongs in TrackGroup rather than TrackGroupInfo. Note that this avoids TrackSelectionOverride from having to re-derive the track type internally. PiperOrigin-RevId: 429303312 --- .../java/androidx/media3/cast/CastPlayer.java | 6 +-- .../androidx/media3/common/TrackGroup.java | 9 ++++- .../media3/common/TrackSelectionOverride.java | 2 +- .../androidx/media3/common/TracksInfo.java | 28 +++++--------- .../media3/common/TracksInfoTest.java | 38 ++++++++++++++----- .../trackselection/MappingTrackSelector.java | 12 ++---- .../MappingTrackSelectorTest.java | 13 +++++-- 7 files changed, 59 insertions(+), 49 deletions(-) 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