mirror of
https://github.com/androidx/media.git
synced 2025-05-14 19:19:58 +08:00
Add option to set preferred audio role flags in DefaultTrackSelector
We already have the eequivalent option for text tracks. PiperOrigin-RevId: 351999287
This commit is contained in:
parent
d2950c2e97
commit
68fd23a967
@ -141,6 +141,7 @@
|
|||||||
* Add option to specify multiple preferred audio or text languages.
|
* Add option to specify multiple preferred audio or text languages.
|
||||||
* Add option to specify preferred MIME type(s) for video and audio
|
* Add option to specify preferred MIME type(s) for video and audio
|
||||||
([#8320](https://github.com/google/ExoPlayer/issues/8320)).
|
([#8320](https://github.com/google/ExoPlayer/issues/8320)).
|
||||||
|
* Add option to specify preferred audio role flags.
|
||||||
* Forward `Timeline` and `MediaPeriodId` to `TrackSelection.Factory`.
|
* Forward `Timeline` and `MediaPeriodId` to `TrackSelection.Factory`.
|
||||||
* DASH:
|
* DASH:
|
||||||
* Support low-latency DASH playback (`availabilityTimeOffset` and
|
* Support low-latency DASH playback (`availabilityTimeOffset` and
|
||||||
|
@ -489,6 +489,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParametersBuilder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFlags) {
|
||||||
|
super.setPreferredAudioRoleFlags(preferredAudioRoleFlags);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum allowed audio channel count.
|
* Sets the maximum allowed audio channel count.
|
||||||
*
|
*
|
||||||
@ -843,6 +849,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
preferredVideoMimeTypes,
|
preferredVideoMimeTypes,
|
||||||
// Audio
|
// Audio
|
||||||
preferredAudioLanguages,
|
preferredAudioLanguages,
|
||||||
|
preferredAudioRoleFlags,
|
||||||
maxAudioChannelCount,
|
maxAudioChannelCount,
|
||||||
maxAudioBitrate,
|
maxAudioBitrate,
|
||||||
exceedAudioConstraintsIfNecessary,
|
exceedAudioConstraintsIfNecessary,
|
||||||
@ -1112,6 +1119,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
ImmutableList<String> preferredVideoMimeTypes,
|
ImmutableList<String> preferredVideoMimeTypes,
|
||||||
// Audio
|
// Audio
|
||||||
ImmutableList<String> preferredAudioLanguages,
|
ImmutableList<String> preferredAudioLanguages,
|
||||||
|
@C.RoleFlags int preferredAudioRoleFlags,
|
||||||
int maxAudioChannelCount,
|
int maxAudioChannelCount,
|
||||||
int maxAudioBitrate,
|
int maxAudioBitrate,
|
||||||
boolean exceedAudioConstraintsIfNecessary,
|
boolean exceedAudioConstraintsIfNecessary,
|
||||||
@ -1135,6 +1143,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
SparseBooleanArray rendererDisabledFlags) {
|
SparseBooleanArray rendererDisabledFlags) {
|
||||||
super(
|
super(
|
||||||
preferredAudioLanguages,
|
preferredAudioLanguages,
|
||||||
|
preferredAudioRoleFlags,
|
||||||
preferredTextLanguages,
|
preferredTextLanguages,
|
||||||
preferredTextRoleFlags,
|
preferredTextRoleFlags,
|
||||||
selectUndeterminedTextLanguage,
|
selectUndeterminedTextLanguage,
|
||||||
@ -2724,6 +2733,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
private final boolean isWithinRendererCapabilities;
|
private final boolean isWithinRendererCapabilities;
|
||||||
private final int preferredLanguageScore;
|
private final int preferredLanguageScore;
|
||||||
private final int preferredLanguageIndex;
|
private final int preferredLanguageIndex;
|
||||||
|
private final int preferredRoleFlagsScore;
|
||||||
private final int localeLanguageMatchIndex;
|
private final int localeLanguageMatchIndex;
|
||||||
private final int localeLanguageScore;
|
private final int localeLanguageScore;
|
||||||
private final boolean isDefaultSelectionFlag;
|
private final boolean isDefaultSelectionFlag;
|
||||||
@ -2753,6 +2763,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
}
|
}
|
||||||
preferredLanguageIndex = bestLanguageIndex;
|
preferredLanguageIndex = bestLanguageIndex;
|
||||||
preferredLanguageScore = bestLanguageScore;
|
preferredLanguageScore = bestLanguageScore;
|
||||||
|
preferredRoleFlagsScore =
|
||||||
|
Integer.bitCount(format.roleFlags & parameters.preferredAudioRoleFlags);
|
||||||
isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
|
isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
|
||||||
channelCount = format.channelCount;
|
channelCount = format.channelCount;
|
||||||
sampleRate = format.sampleRate;
|
sampleRate = format.sampleRate;
|
||||||
@ -2809,6 +2821,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
other.preferredLanguageIndex,
|
other.preferredLanguageIndex,
|
||||||
Ordering.natural().reverse())
|
Ordering.natural().reverse())
|
||||||
.compare(this.preferredLanguageScore, other.preferredLanguageScore)
|
.compare(this.preferredLanguageScore, other.preferredLanguageScore)
|
||||||
|
.compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore)
|
||||||
.compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints)
|
.compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints)
|
||||||
.compare(
|
.compare(
|
||||||
this.preferredMimeTypeMatchIndex,
|
this.preferredMimeTypeMatchIndex,
|
||||||
|
@ -40,6 +40,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/* package */ ImmutableList<String> preferredAudioLanguages;
|
/* package */ ImmutableList<String> preferredAudioLanguages;
|
||||||
|
@C.RoleFlags /* package */ int preferredAudioRoleFlags;
|
||||||
/* package */ ImmutableList<String> preferredTextLanguages;
|
/* package */ ImmutableList<String> preferredTextLanguages;
|
||||||
@C.RoleFlags /* package */ int preferredTextRoleFlags;
|
@C.RoleFlags /* package */ int preferredTextRoleFlags;
|
||||||
/* package */ boolean selectUndeterminedTextLanguage;
|
/* package */ boolean selectUndeterminedTextLanguage;
|
||||||
@ -63,6 +64,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public Builder() {
|
public Builder() {
|
||||||
preferredAudioLanguages = ImmutableList.of();
|
preferredAudioLanguages = ImmutableList.of();
|
||||||
|
preferredAudioRoleFlags = 0;
|
||||||
preferredTextLanguages = ImmutableList.of();
|
preferredTextLanguages = ImmutableList.of();
|
||||||
preferredTextRoleFlags = 0;
|
preferredTextRoleFlags = 0;
|
||||||
selectUndeterminedTextLanguage = false;
|
selectUndeterminedTextLanguage = false;
|
||||||
@ -75,6 +77,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
/* package */ Builder(TrackSelectionParameters initialValues) {
|
/* package */ Builder(TrackSelectionParameters initialValues) {
|
||||||
preferredAudioLanguages = initialValues.preferredAudioLanguages;
|
preferredAudioLanguages = initialValues.preferredAudioLanguages;
|
||||||
|
preferredAudioRoleFlags = initialValues.preferredAudioRoleFlags;
|
||||||
preferredTextLanguages = initialValues.preferredTextLanguages;
|
preferredTextLanguages = initialValues.preferredTextLanguages;
|
||||||
preferredTextRoleFlags = initialValues.preferredTextRoleFlags;
|
preferredTextRoleFlags = initialValues.preferredTextRoleFlags;
|
||||||
selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage;
|
selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage;
|
||||||
@ -111,6 +114,17 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the preferred {@link C.RoleFlags} for audio tracks.
|
||||||
|
*
|
||||||
|
* @param preferredAudioRoleFlags Preferred audio role flags.
|
||||||
|
* @return This builder.
|
||||||
|
*/
|
||||||
|
public Builder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFlags) {
|
||||||
|
this.preferredAudioRoleFlags = preferredAudioRoleFlags;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the preferred language and role flags for text tracks based on the accessibility
|
* Sets the preferred language and role flags for text tracks based on the accessibility
|
||||||
* settings of {@link CaptioningManager}.
|
* settings of {@link CaptioningManager}.
|
||||||
@ -201,6 +215,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
return new TrackSelectionParameters(
|
return new TrackSelectionParameters(
|
||||||
// Audio
|
// Audio
|
||||||
preferredAudioLanguages,
|
preferredAudioLanguages,
|
||||||
|
preferredAudioRoleFlags,
|
||||||
// Text
|
// Text
|
||||||
preferredTextLanguages,
|
preferredTextLanguages,
|
||||||
preferredTextRoleFlags,
|
preferredTextRoleFlags,
|
||||||
@ -262,6 +277,11 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
* default. The default value is an empty list.
|
* default. The default value is an empty list.
|
||||||
*/
|
*/
|
||||||
public final ImmutableList<String> preferredAudioLanguages;
|
public final ImmutableList<String> preferredAudioLanguages;
|
||||||
|
/**
|
||||||
|
* The preferred {@link C.RoleFlags} for audio tracks. {@code 0} selects the default track if
|
||||||
|
* there is one, or the first track if there's no default. The default value is {@code 0}.
|
||||||
|
*/
|
||||||
|
@C.RoleFlags public final int preferredAudioRoleFlags;
|
||||||
/**
|
/**
|
||||||
* The preferred languages for text tracks as IETF BCP 47 conformant tags in order of preference.
|
* The preferred languages for text tracks as IETF BCP 47 conformant tags in order of preference.
|
||||||
* An empty list selects the default track if there is one, or no track otherwise. The default
|
* An empty list selects the default track if there is one, or no track otherwise. The default
|
||||||
@ -290,12 +310,14 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
|
|
||||||
/* package */ TrackSelectionParameters(
|
/* package */ TrackSelectionParameters(
|
||||||
ImmutableList<String> preferredAudioLanguages,
|
ImmutableList<String> preferredAudioLanguages,
|
||||||
|
@C.RoleFlags int preferredAudioRoleFlags,
|
||||||
ImmutableList<String> preferredTextLanguages,
|
ImmutableList<String> preferredTextLanguages,
|
||||||
@C.RoleFlags int preferredTextRoleFlags,
|
@C.RoleFlags int preferredTextRoleFlags,
|
||||||
boolean selectUndeterminedTextLanguage,
|
boolean selectUndeterminedTextLanguage,
|
||||||
@C.SelectionFlags int disabledTextTrackSelectionFlags) {
|
@C.SelectionFlags int disabledTextTrackSelectionFlags) {
|
||||||
// Audio
|
// Audio
|
||||||
this.preferredAudioLanguages = preferredAudioLanguages;
|
this.preferredAudioLanguages = preferredAudioLanguages;
|
||||||
|
this.preferredAudioRoleFlags = preferredAudioRoleFlags;
|
||||||
// Text
|
// Text
|
||||||
this.preferredTextLanguages = preferredTextLanguages;
|
this.preferredTextLanguages = preferredTextLanguages;
|
||||||
this.preferredTextRoleFlags = preferredTextRoleFlags;
|
this.preferredTextRoleFlags = preferredTextRoleFlags;
|
||||||
@ -307,6 +329,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
ArrayList<String> preferredAudioLanguages = new ArrayList<>();
|
ArrayList<String> preferredAudioLanguages = new ArrayList<>();
|
||||||
in.readList(preferredAudioLanguages, /* loader= */ null);
|
in.readList(preferredAudioLanguages, /* loader= */ null);
|
||||||
this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages);
|
this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages);
|
||||||
|
this.preferredAudioRoleFlags = in.readInt();
|
||||||
ArrayList<String> preferredTextLanguages = new ArrayList<>();
|
ArrayList<String> preferredTextLanguages = new ArrayList<>();
|
||||||
in.readList(preferredTextLanguages, /* loader= */ null);
|
in.readList(preferredTextLanguages, /* loader= */ null);
|
||||||
this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages);
|
this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages);
|
||||||
@ -331,6 +354,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
}
|
}
|
||||||
TrackSelectionParameters other = (TrackSelectionParameters) obj;
|
TrackSelectionParameters other = (TrackSelectionParameters) obj;
|
||||||
return preferredAudioLanguages.equals(other.preferredAudioLanguages)
|
return preferredAudioLanguages.equals(other.preferredAudioLanguages)
|
||||||
|
&& preferredAudioRoleFlags == other.preferredAudioRoleFlags
|
||||||
&& preferredTextLanguages.equals(other.preferredTextLanguages)
|
&& preferredTextLanguages.equals(other.preferredTextLanguages)
|
||||||
&& preferredTextRoleFlags == other.preferredTextRoleFlags
|
&& preferredTextRoleFlags == other.preferredTextRoleFlags
|
||||||
&& selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage
|
&& selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage
|
||||||
@ -341,6 +365,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = 31 * result + preferredAudioLanguages.hashCode();
|
result = 31 * result + preferredAudioLanguages.hashCode();
|
||||||
|
result = 31 * result + preferredAudioRoleFlags;
|
||||||
result = 31 * result + preferredTextLanguages.hashCode();
|
result = 31 * result + preferredTextLanguages.hashCode();
|
||||||
result = 31 * result + preferredTextRoleFlags;
|
result = 31 * result + preferredTextRoleFlags;
|
||||||
result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0);
|
result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0);
|
||||||
@ -358,6 +383,7 @@ public class TrackSelectionParameters implements Parcelable {
|
|||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeList(preferredAudioLanguages);
|
dest.writeList(preferredAudioLanguages);
|
||||||
|
dest.writeInt(preferredAudioRoleFlags);
|
||||||
dest.writeList(preferredTextLanguages);
|
dest.writeList(preferredTextLanguages);
|
||||||
dest.writeInt(preferredTextRoleFlags);
|
dest.writeInt(preferredTextRoleFlags);
|
||||||
Util.writeBoolean(dest, selectUndeterminedTextLanguage);
|
Util.writeBoolean(dest, selectUndeterminedTextLanguage);
|
||||||
|
@ -383,6 +383,75 @@ public final class DefaultTrackSelectorTest {
|
|||||||
assertFixedSelection(result.selections.get(0), trackGroups, enAudioFormat);
|
assertFixedSelection(result.selections.get(0), trackGroups, enAudioFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio track with the highest number of matching role
|
||||||
|
* flags given by {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void selectTracks_withPreferredAudioRoleFlags_selectPreferredTrack() throws Exception {
|
||||||
|
Format.Builder formatBuilder = AUDIO_FORMAT.buildUpon();
|
||||||
|
Format noRoleFlags = formatBuilder.build();
|
||||||
|
Format lessRoleFlags = formatBuilder.setRoleFlags(C.ROLE_FLAG_CAPTION).build();
|
||||||
|
Format moreRoleFlags =
|
||||||
|
formatBuilder
|
||||||
|
.setRoleFlags(C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_COMMENTARY | C.ROLE_FLAG_DUB)
|
||||||
|
.build();
|
||||||
|
TrackGroupArray trackGroups = wrapFormats(noRoleFlags, moreRoleFlags, lessRoleFlags);
|
||||||
|
|
||||||
|
trackSelector.setParameters(
|
||||||
|
defaultParameters
|
||||||
|
.buildUpon()
|
||||||
|
.setPreferredAudioRoleFlags(C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_COMMENTARY));
|
||||||
|
TrackSelectorResult result =
|
||||||
|
trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
trackGroups,
|
||||||
|
periodId,
|
||||||
|
TIMELINE);
|
||||||
|
assertFixedSelection(result.selections.get(0), trackGroups, moreRoleFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector with select default audio track if no role flag preference is
|
||||||
|
* specified by {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void selectTracks_withoutPreferredAudioRoleFlags_selectsDefaultTrack() throws Exception {
|
||||||
|
Format firstFormat = AUDIO_FORMAT;
|
||||||
|
Format defaultFormat =
|
||||||
|
AUDIO_FORMAT.buildUpon().setSelectionFlags(C.SELECTION_FLAG_DEFAULT).build();
|
||||||
|
Format roleFlagFormat = AUDIO_FORMAT.buildUpon().setRoleFlags(C.ROLE_FLAG_CAPTION).build();
|
||||||
|
TrackGroupArray trackGroups = wrapFormats(firstFormat, defaultFormat, roleFlagFormat);
|
||||||
|
|
||||||
|
TrackSelectorResult result =
|
||||||
|
trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
trackGroups,
|
||||||
|
periodId,
|
||||||
|
TIMELINE);
|
||||||
|
assertFixedSelection(result.selections.get(0), trackGroups, defaultFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector with select the first audio track if no role flag preference is
|
||||||
|
* specified by {@link Parameters} and no default track exists.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void selectTracks_withoutPreferredAudioRoleFlagsOrDefaultTrack_selectsFirstTrack()
|
||||||
|
throws Exception {
|
||||||
|
Format firstFormat = AUDIO_FORMAT;
|
||||||
|
Format roleFlagFormat = AUDIO_FORMAT.buildUpon().setRoleFlags(C.ROLE_FLAG_CAPTION).build();
|
||||||
|
TrackGroupArray trackGroups = wrapFormats(firstFormat, roleFlagFormat);
|
||||||
|
|
||||||
|
TrackSelectorResult result =
|
||||||
|
trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
trackGroups,
|
||||||
|
periodId,
|
||||||
|
TIMELINE);
|
||||||
|
assertFixedSelection(result.selections.get(0), trackGroups, firstFormat);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that track selector will prefer selecting audio track with language that match preferred
|
* Tests that track selector will prefer selecting audio track with language that match preferred
|
||||||
* language given by {@link Parameters} over track with {@link C#SELECTION_FLAG_DEFAULT}.
|
* language given by {@link Parameters} over track with {@link C#SELECTION_FLAG_DEFAULT}.
|
||||||
@ -1667,6 +1736,7 @@ public final class DefaultTrackSelectorTest {
|
|||||||
/* preferredVideoMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264),
|
/* preferredVideoMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264),
|
||||||
// Audio
|
// Audio
|
||||||
/* preferredAudioLanguages= */ ImmutableList.of("zh", "jp"),
|
/* preferredAudioLanguages= */ ImmutableList.of("zh", "jp"),
|
||||||
|
/* preferredAudioRoleFlags= */ C.ROLE_FLAG_COMMENTARY,
|
||||||
/* maxAudioChannelCount= */ 10,
|
/* maxAudioChannelCount= */ 10,
|
||||||
/* maxAudioBitrate= */ 11,
|
/* maxAudioBitrate= */ 11,
|
||||||
/* exceedAudioConstraintsIfNecessary= */ false,
|
/* exceedAudioConstraintsIfNecessary= */ false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user