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
This commit is contained in:
olly 2022-02-17 15:20:46 +00:00 committed by Ian Baker
parent 6b606b9987
commit 265dd079e9
7 changed files with 59 additions and 49 deletions

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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 {

View File

@ -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<TrackGroupInfo> 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<TrackGroupInfo> 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});

View File

@ -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());
}

View File

@ -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