Create AudioOffloadPreferences class

Move audio offload mode related interfaces and definitions from `TrackSelectionParameters` to a new `AudioOffloadModePreferences` class.

PiperOrigin-RevId: 566905017
This commit is contained in:
michaelkatz 2023-09-20 03:00:26 -07:00 committed by Copybara-Service
parent 08c72b927d
commit 3cf9c08dca
8 changed files with 422 additions and 212 deletions

View File

@ -1076,13 +1076,10 @@ package androidx.media3.common {
method public static androidx.media3.common.TrackSelectionParameters fromBundle(android.os.Bundle);
method public static androidx.media3.common.TrackSelectionParameters getDefaults(android.content.Context);
method public android.os.Bundle toBundle();
field public final int audioOffloadModePreference;
field public final com.google.common.collect.ImmutableSet<java.lang.Integer> disabledTrackTypes;
field public final boolean forceHighestSupportedBitrate;
field public final boolean forceLowestBitrate;
field @androidx.media3.common.C.SelectionFlags public final int ignoredTextSelectionFlags;
field public final boolean isGaplessSupportRequired;
field public final boolean isSpeedChangeSupportRequired;
field public final int maxAudioBitrate;
field public final int maxAudioChannelCount;
field public final int maxVideoBitrate;
@ -1116,7 +1113,6 @@ package androidx.media3.common {
method public androidx.media3.common.TrackSelectionParameters.Builder clearOverridesOfType(@androidx.media3.common.C.TrackType int);
method public androidx.media3.common.TrackSelectionParameters.Builder clearVideoSizeConstraints();
method public androidx.media3.common.TrackSelectionParameters.Builder clearViewportSizeConstraints();
method public androidx.media3.common.TrackSelectionParameters.Builder setAudioOffloadPreference(int, boolean, boolean);
method public androidx.media3.common.TrackSelectionParameters.Builder setForceHighestSupportedBitrate(boolean);
method public androidx.media3.common.TrackSelectionParameters.Builder setForceLowestBitrate(boolean);
method public androidx.media3.common.TrackSelectionParameters.Builder setIgnoredTextSelectionFlags(@androidx.media3.common.C.SelectionFlags int);

View File

@ -19,6 +19,7 @@ import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.BundleableUtil.toBundleArrayList;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.content.Context;
import android.graphics.Point;
@ -38,7 +39,6 @@ import com.google.common.primitives.Ints;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashMap;
import java.util.HashSet;
@ -71,41 +71,6 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
*/
public class TrackSelectionParameters implements Bundleable {
/**
* The preference level for enabling audio offload on the audio sink. One of {@link
* #AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED}, {@link #AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED}, or
* {@link #AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED}.
*/
@UnstableApi
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED,
AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED,
})
public @interface AudioOffloadModePreference {}
/**
* The track selector will only select tracks that with the renderer capabilities provide an audio
* offload compatible playback scenario. If it is impossible to create an offload-compatible track
* selection, then no tracks will be selected.
*/
@UnstableApi public static final int AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED = 2;
/**
* The track selector will enable audio offload if the selected tracks and renderer capabilities
* are compatible.
*/
@UnstableApi public static final int AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED = 1;
/**
* The track selector will disable audio offload on the audio sink. Track selection will not take
* into consideration whether or not a track is offload compatible.
*/
@UnstableApi public static final int AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED = 0;
/**
* A builder for {@link TrackSelectionParameters}. See the {@link TrackSelectionParameters}
* documentation for explanations of the parameters that can be configured using this builder.
@ -131,9 +96,7 @@ public class TrackSelectionParameters implements Bundleable {
private int maxAudioChannelCount;
private int maxAudioBitrate;
private ImmutableList<String> preferredAudioMimeTypes;
private @AudioOffloadModePreference int audioOffloadModePreference;
private boolean isGaplessSupportRequired;
private boolean isSpeedChangeSupportRequired;
private AudioOffloadPreferences audioOffloadPreferences;
// Text
private ImmutableList<String> preferredTextLanguages;
private @C.RoleFlags int preferredTextRoleFlags;
@ -168,9 +131,7 @@ public class TrackSelectionParameters implements Bundleable {
maxAudioChannelCount = Integer.MAX_VALUE;
maxAudioBitrate = Integer.MAX_VALUE;
preferredAudioMimeTypes = ImmutableList.of();
audioOffloadModePreference = AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED;
isGaplessSupportRequired = false;
isSpeedChangeSupportRequired = false;
audioOffloadPreferences = AudioOffloadPreferences.DEFAULT;
// Text
preferredTextLanguages = ImmutableList.of();
preferredTextRoleFlags = 0;
@ -246,6 +207,7 @@ public class TrackSelectionParameters implements Bundleable {
preferredAudioMimeTypes =
ImmutableList.copyOf(
firstNonNull(bundle.getStringArray(FIELD_PREFERRED_AUDIO_MIME_TYPES), new String[0]));
audioOffloadPreferences = getAudioOffloadPreferencesFromBundle(bundle);
// Text
preferredTextLanguages =
normalizeLanguageCodes(
@ -261,17 +223,7 @@ public class TrackSelectionParameters implements Bundleable {
bundle.getBoolean(
FIELD_SELECT_UNDETERMINED_TEXT_LANGUAGE,
DEFAULT_WITHOUT_CONTEXT.selectUndeterminedTextLanguage);
audioOffloadModePreference =
bundle.getInt(
FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE,
DEFAULT_WITHOUT_CONTEXT.audioOffloadModePreference);
isGaplessSupportRequired =
bundle.getBoolean(
FIELD_IS_GAPLESS_SUPPORT_REQUIRED, DEFAULT_WITHOUT_CONTEXT.isGaplessSupportRequired);
isSpeedChangeSupportRequired =
bundle.getBoolean(
FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED,
DEFAULT_WITHOUT_CONTEXT.isSpeedChangeSupportRequired);
// General
forceLowestBitrate =
bundle.getBoolean(FIELD_FORCE_LOWEST_BITRATE, DEFAULT_WITHOUT_CONTEXT.forceLowestBitrate);
@ -298,11 +250,32 @@ public class TrackSelectionParameters implements Bundleable {
}
}
private static AudioOffloadPreferences getAudioOffloadPreferencesFromBundle(Bundle bundle) {
Bundle audioOffloadPreferencesBundle = bundle.getBundle(FIELD_AUDIO_OFFLOAD_PREFERENCES);
return (audioOffloadPreferencesBundle != null)
? AudioOffloadPreferences.fromBundle(audioOffloadPreferencesBundle)
: new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(
bundle.getInt(
FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE,
AudioOffloadPreferences.DEFAULT.audioOffloadMode))
.setIsGaplessSupportRequired(
bundle.getBoolean(
FIELD_IS_GAPLESS_SUPPORT_REQUIRED,
AudioOffloadPreferences.DEFAULT.isGaplessSupportRequired))
.setIsSpeedChangeSupportRequired(
bundle.getBoolean(
FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED,
AudioOffloadPreferences.DEFAULT.isSpeedChangeSupportRequired))
.build();
}
/** Overrides the value of the builder with the value of {@link TrackSelectionParameters}. */
@EnsuresNonNull({
"preferredVideoMimeTypes",
"preferredAudioLanguages",
"preferredAudioMimeTypes",
"audioOffloadPreferences",
"preferredTextLanguages",
"overrides",
"disabledTrackTypes",
@ -328,9 +301,7 @@ public class TrackSelectionParameters implements Bundleable {
maxAudioChannelCount = parameters.maxAudioChannelCount;
maxAudioBitrate = parameters.maxAudioBitrate;
preferredAudioMimeTypes = parameters.preferredAudioMimeTypes;
audioOffloadModePreference = parameters.audioOffloadModePreference;
isGaplessSupportRequired = parameters.isGaplessSupportRequired;
isSpeedChangeSupportRequired = parameters.isSpeedChangeSupportRequired;
audioOffloadPreferences = parameters.audioOffloadPreferences;
// Text
preferredTextLanguages = parameters.preferredTextLanguages;
preferredTextRoleFlags = parameters.preferredTextRoleFlags;
@ -625,21 +596,11 @@ public class TrackSelectionParameters implements Bundleable {
* Sets the audio offload mode preferences. This includes whether to enable/disable offload as
* well as to set requirements like if the device must support gapless transitions or speed
* change during offload.
*
* <p>If {@code isGaplessSupportRequired}, then audio offload will be enabled only if the device
* supports gapless transitions during offload or the selected audio is not gapless.
*
* <p>If {@code isSpeedChangeSupportRequired}, then audio offload will be enabled only if the
* device supports changing playback speed during offload.
*/
@UnstableApi
@CanIgnoreReturnValue
public Builder setAudioOffloadPreference(
@AudioOffloadModePreference int audioOffloadModePreference,
boolean isGaplessSupportRequired,
boolean isSpeedChangeSupportRequired) {
this.audioOffloadModePreference = audioOffloadModePreference;
this.isGaplessSupportRequired = isGaplessSupportRequired;
this.isSpeedChangeSupportRequired = isSpeedChangeSupportRequired;
public Builder setAudioOffloadPreferences(AudioOffloadPreferences audioOffloadPreferences) {
this.audioOffloadPreferences = audioOffloadPreferences;
return this;
}
@ -871,6 +832,199 @@ public class TrackSelectionParameters implements Bundleable {
}
}
/** Preferences and constraints for enabling audio offload. */
@UnstableApi
public static final class AudioOffloadPreferences implements Bundleable {
/**
* The preference level for enabling audio offload on the audio sink. One of {@link
* #AUDIO_OFFLOAD_MODE_REQUIRED}, {@link #AUDIO_OFFLOAD_MODE_ENABLED}, or {@link
* #AUDIO_OFFLOAD_MODE_DISABLED}.
*/
@Documented
@Retention(SOURCE)
@Target(TYPE_USE)
@IntDef({
AUDIO_OFFLOAD_MODE_REQUIRED,
AUDIO_OFFLOAD_MODE_ENABLED,
AUDIO_OFFLOAD_MODE_DISABLED,
})
public @interface AudioOffloadMode {}
/**
* The track selector will only select tracks that with the renderer capabilities provide an
* audio offload compatible playback scenario. If it is impossible to create an
* offload-compatible track selection, then no tracks will be selected.
*/
public static final int AUDIO_OFFLOAD_MODE_REQUIRED = 2;
/**
* The track selector will enable audio offload if the selected tracks and renderer capabilities
* are compatible.
*/
public static final int AUDIO_OFFLOAD_MODE_ENABLED = 1;
/**
* The track selector will disable audio offload on the audio sink. Track selection will not
* take into consideration whether or not a track is offload compatible.
*/
public static final int AUDIO_OFFLOAD_MODE_DISABLED = 0;
/**
* A builder for {@link AudioOffloadPreferences}. See the {@link AudioOffloadPreferences}
* documentation for explanations of the parameters that can be configured using this builder.
*/
public static final class Builder {
private @AudioOffloadMode int audioOffloadMode;
private boolean isGaplessSupportRequired;
private boolean isSpeedChangeSupportRequired;
public Builder() {
this.audioOffloadMode = AUDIO_OFFLOAD_MODE_DISABLED;
this.isGaplessSupportRequired = false;
this.isSpeedChangeSupportRequired = false;
}
/**
* Sets the audio offload mode preferences. For instance if the preferred mode is
* enabled/disabled or if offload is required for playback. Default value is {@link
* #AUDIO_OFFLOAD_MODE_DISABLED}.
*
* @param audioOffloadMode for enabling/disabling offload. One of {@link
* #AUDIO_OFFLOAD_MODE_REQUIRED}, {@link #AUDIO_OFFLOAD_MODE_ENABLED}, or {@link
* #AUDIO_OFFLOAD_MODE_DISABLED}.
* @return This builder.
*/
@CanIgnoreReturnValue
public Builder setAudioOffloadMode(@AudioOffloadMode int audioOffloadMode) {
this.audioOffloadMode = audioOffloadMode;
return this;
}
/**
* Sets a constraint on audio offload enablement. If {@code true} then audio offload will be
* enabled only if the device supports gapless transitions during offload or the selected
* audio is not gapless. Default value is {@code false}.
*
* @param isGaplessSupportRequired for playing gapless audio offloaded.
* @return This builder.
*/
@CanIgnoreReturnValue
public Builder setIsGaplessSupportRequired(boolean isGaplessSupportRequired) {
this.isGaplessSupportRequired = isGaplessSupportRequired;
return this;
}
/**
* Sets a constraint on audio offload enablement. If {@code true}, then audio offload will be
* enabled only if the device supports changing playback speed during offload. Default value
* is {@code false}.
*
* @param isSpeedChangeSupportRequired for playing audio offloaded.
* @return This builder.
*/
@CanIgnoreReturnValue
public Builder setIsSpeedChangeSupportRequired(boolean isSpeedChangeSupportRequired) {
this.isSpeedChangeSupportRequired = isSpeedChangeSupportRequired;
return this;
}
/** Builds a {@link TrackSelectionParameters} instance with the selected values. */
public AudioOffloadPreferences build() {
return new AudioOffloadPreferences(this);
}
}
/** Returns an instance configured with default values. */
public static final AudioOffloadPreferences DEFAULT =
new AudioOffloadPreferences.Builder().build();
/** The preferred offload mode setting for audio playback. */
public final @AudioOffloadMode int audioOffloadMode;
/**
* A constraint on enabling offload. If {@code true}, then audio offload will be enabled only if
* the device supports gapless transitions during offload or the selected audio is not gapless.
*/
public final boolean isGaplessSupportRequired;
/**
* A constraint on enabling offload. If {@code true}, then audio offload will be enabled only if
* the device supports changing playback speed during offload.
*/
public final boolean isSpeedChangeSupportRequired;
private AudioOffloadPreferences(Builder builder) {
this.audioOffloadMode = builder.audioOffloadMode;
this.isGaplessSupportRequired = builder.isGaplessSupportRequired;
this.isSpeedChangeSupportRequired = builder.isSpeedChangeSupportRequired;
}
/**
* Creates a new {@link AudioOffloadPreferences.Builder}, copying the initial values from this
* instance.
*/
public AudioOffloadPreferences.Builder buildUpon() {
return new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(audioOffloadMode)
.setIsGaplessSupportRequired(isGaplessSupportRequired)
.setIsSpeedChangeSupportRequired(isSpeedChangeSupportRequired);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
AudioOffloadPreferences other = (AudioOffloadPreferences) obj;
return audioOffloadMode == other.audioOffloadMode
&& isGaplessSupportRequired == other.isGaplessSupportRequired
&& isSpeedChangeSupportRequired == other.isSpeedChangeSupportRequired;
}
@Override
public int hashCode() {
int result = 1;
result = 31 * result + audioOffloadMode;
result = 31 * result + (isGaplessSupportRequired ? 1 : 0);
result = 31 * result + (isSpeedChangeSupportRequired ? 1 : 0);
return result;
}
// Bundleable implementation
private static final String FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE = Util.intToStringMaxRadix(1);
private static final String FIELD_IS_GAPLESS_SUPPORT_REQUIRED = Util.intToStringMaxRadix(2);
private static final String FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED =
Util.intToStringMaxRadix(3);
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putInt(FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE, audioOffloadMode);
bundle.putBoolean(FIELD_IS_GAPLESS_SUPPORT_REQUIRED, isGaplessSupportRequired);
bundle.putBoolean(FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED, isSpeedChangeSupportRequired);
return bundle;
}
/** Construct an instance from a {@link Bundle} produced by {@link #toBundle()}. */
public static AudioOffloadPreferences fromBundle(Bundle bundle) {
return new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(
bundle.getInt(FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE, DEFAULT.audioOffloadMode))
.setIsGaplessSupportRequired(
bundle.getBoolean(
FIELD_IS_GAPLESS_SUPPORT_REQUIRED, DEFAULT.isGaplessSupportRequired))
.setIsSpeedChangeSupportRequired(
bundle.getBoolean(
FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED, DEFAULT.isSpeedChangeSupportRequired))
.build();
}
}
/**
* An instance with default values, except those obtained from the {@link Context}.
*
@ -1015,23 +1169,10 @@ public class TrackSelectionParameters implements Bundleable {
public final ImmutableList<String> preferredAudioMimeTypes;
/**
* The preferred offload mode setting for audio playback. The default is {@link
* #AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED}.
* The preferred offload mode settings for audio playback. The default is {@link
* AudioOffloadPreferences#DEFAULT}.
*/
public final @AudioOffloadModePreference int audioOffloadModePreference;
/**
* A constraint on enabling offload. If {@code isGaplessSupportRequired}, then audio offload will
* be enabled only if the device supports gapless transitions during offload or the selected audio
* is not gapless.
*/
public final boolean isGaplessSupportRequired;
/**
* A constraint on enabling offload. If {@code isSpeedChangeSupportRequired}, then audio offload
* will be enabled only if the device supports changing playback speed during offload.
*/
public final boolean isSpeedChangeSupportRequired;
@UnstableApi public final AudioOffloadPreferences audioOffloadPreferences;
// Text
/**
@ -1108,9 +1249,7 @@ public class TrackSelectionParameters implements Bundleable {
this.maxAudioChannelCount = builder.maxAudioChannelCount;
this.maxAudioBitrate = builder.maxAudioBitrate;
this.preferredAudioMimeTypes = builder.preferredAudioMimeTypes;
this.audioOffloadModePreference = builder.audioOffloadModePreference;
this.isGaplessSupportRequired = builder.isGaplessSupportRequired;
this.isSpeedChangeSupportRequired = builder.isSpeedChangeSupportRequired;
this.audioOffloadPreferences = builder.audioOffloadPreferences;
// Text
this.preferredTextLanguages = builder.preferredTextLanguages;
this.preferredTextRoleFlags = builder.preferredTextRoleFlags;
@ -1158,9 +1297,7 @@ public class TrackSelectionParameters implements Bundleable {
&& maxAudioChannelCount == other.maxAudioChannelCount
&& maxAudioBitrate == other.maxAudioBitrate
&& preferredAudioMimeTypes.equals(other.preferredAudioMimeTypes)
&& audioOffloadModePreference == other.audioOffloadModePreference
&& isGaplessSupportRequired == other.isGaplessSupportRequired
&& isSpeedChangeSupportRequired == other.isSpeedChangeSupportRequired
&& audioOffloadPreferences.equals(other.audioOffloadPreferences)
// Text
&& preferredTextLanguages.equals(other.preferredTextLanguages)
&& preferredTextRoleFlags == other.preferredTextRoleFlags
@ -1196,9 +1333,7 @@ public class TrackSelectionParameters implements Bundleable {
result = 31 * result + maxAudioChannelCount;
result = 31 * result + maxAudioBitrate;
result = 31 * result + preferredAudioMimeTypes.hashCode();
result = 31 * result + audioOffloadModePreference;
result = 31 * result + (isGaplessSupportRequired ? 1 : 0);
result = 31 * result + (isSpeedChangeSupportRequired ? 1 : 0);
result = 31 * result + audioOffloadPreferences.hashCode();
// Text
result = 31 * result + preferredTextLanguages.hashCode();
result = 31 * result + preferredTextRoleFlags;
@ -1243,6 +1378,7 @@ public class TrackSelectionParameters implements Bundleable {
private static final String FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE = Util.intToStringMaxRadix(27);
private static final String FIELD_IS_GAPLESS_SUPPORT_REQUIRED = Util.intToStringMaxRadix(28);
private static final String FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED = Util.intToStringMaxRadix(29);
private static final String FIELD_AUDIO_OFFLOAD_PREFERENCES = Util.intToStringMaxRadix(30);
/**
* Defines a minimum field ID value for subclasses to use when implementing {@link #toBundle()}
@ -1287,9 +1423,13 @@ public class TrackSelectionParameters implements Bundleable {
bundle.putInt(FIELD_PREFERRED_TEXT_ROLE_FLAGS, preferredTextRoleFlags);
bundle.putInt(FIELD_IGNORED_TEXT_SELECTION_FLAGS, ignoredTextSelectionFlags);
bundle.putBoolean(FIELD_SELECT_UNDETERMINED_TEXT_LANGUAGE, selectUndeterminedTextLanguage);
bundle.putInt(FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE, audioOffloadModePreference);
bundle.putBoolean(FIELD_IS_GAPLESS_SUPPORT_REQUIRED, isGaplessSupportRequired);
bundle.putBoolean(FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED, isSpeedChangeSupportRequired);
bundle.putInt(FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE, audioOffloadPreferences.audioOffloadMode);
bundle.putBoolean(
FIELD_IS_GAPLESS_SUPPORT_REQUIRED, audioOffloadPreferences.isGaplessSupportRequired);
bundle.putBoolean(
FIELD_IS_SPEED_CHANGE_SUPPORT_REQUIRED,
audioOffloadPreferences.isSpeedChangeSupportRequired);
bundle.putBundle(FIELD_AUDIO_OFFLOAD_PREFERENCES, audioOffloadPreferences.toBundle());
// General
bundle.putBoolean(FIELD_FORCE_LOWEST_BITRATE, forceLowestBitrate);
bundle.putBoolean(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE, forceHighestSupportedBitrate);

View File

@ -15,9 +15,14 @@
*/
package androidx.media3.common;
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED;
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
import android.os.Bundle;
import androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences;
import androidx.media3.common.util.Util;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
@ -29,6 +34,9 @@ public final class TrackSelectionParametersTest {
private static final TrackGroup AAC_TRACK_GROUP =
new TrackGroup(new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_AAC).build());
private static final String BUNDLE_FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE =
Util.intToStringMaxRadix(27);
private static final String BUNDLE_FIELD_AUDIO_OFFLOAD_PREFERENCES = Util.intToStringMaxRadix(30);
@Test
public void defaultValue_withoutChange_isAsExpected() {
@ -52,10 +60,10 @@ public final class TrackSelectionParametersTest {
assertThat(parameters.preferredAudioRoleFlags).isEqualTo(0);
assertThat(parameters.maxAudioChannelCount).isEqualTo(Integer.MAX_VALUE);
assertThat(parameters.maxAudioBitrate).isEqualTo(Integer.MAX_VALUE);
assertThat(parameters.audioOffloadModePreference)
.isEqualTo(TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED);
assertThat(parameters.isGaplessSupportRequired).isFalse();
assertThat(parameters.isSpeedChangeSupportRequired).isFalse();
assertThat(parameters.audioOffloadPreferences.audioOffloadMode)
.isEqualTo(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED);
assertThat(parameters.audioOffloadPreferences.isGaplessSupportRequired).isFalse();
assertThat(parameters.audioOffloadPreferences.isSpeedChangeSupportRequired).isFalse();
// Text
assertThat(parameters.preferredAudioMimeTypes).isEmpty();
assertThat(parameters.preferredTextLanguages).isEmpty();
@ -100,10 +108,11 @@ public final class TrackSelectionParametersTest {
.setMaxAudioChannelCount(10)
.setMaxAudioBitrate(11)
.setPreferredAudioMimeTypes(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3)
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ true)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.setIsSpeedChangeSupportRequired(true)
.build())
// Text
.setPreferredTextLanguages("de", "en")
.setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION)
@ -148,10 +157,10 @@ public final class TrackSelectionParametersTest {
assertThat(parameters.preferredAudioMimeTypes)
.containsExactly(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3)
.inOrder();
assertThat(parameters.audioOffloadModePreference)
.isEqualTo(TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED);
assertThat(parameters.isGaplessSupportRequired).isFalse();
assertThat(parameters.isSpeedChangeSupportRequired).isTrue();
assertThat(parameters.audioOffloadPreferences.audioOffloadMode)
.isEqualTo(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED);
assertThat(parameters.audioOffloadPreferences.isGaplessSupportRequired).isFalse();
assertThat(parameters.audioOffloadPreferences.isSpeedChangeSupportRequired).isTrue();
// Text
assertThat(parameters.preferredTextLanguages).containsExactly("de", "en").inOrder();
assertThat(parameters.preferredTextRoleFlags).isEqualTo(C.ROLE_FLAG_CAPTION);
@ -220,6 +229,29 @@ public final class TrackSelectionParametersTest {
.containsExactly(override.mediaTrackGroup, override);
}
@Test
public void roundTripViaBundle_withLegacyPreferenceFields_yieldsEqualInstance() {
TrackSelectionParameters trackSelectionParameters =
new TrackSelectionParameters.Builder(getApplicationContext())
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(true)
.build())
.build();
Bundle bundle = trackSelectionParameters.toBundle();
// By removing AudioOffloadPreferences, bundle is a model of one initially created without
// AudioOffloadPreferences but containing AudioOffloadPreferences sub-fields(ex:
// isGaplessSupportRequired). Prod system should not be removing fields from the bundle.
bundle.remove(BUNDLE_FIELD_AUDIO_OFFLOAD_PREFERENCES);
TrackSelectionParameters trackSelectionParametersfromBundle =
TrackSelectionParameters.fromBundle(bundle);
assertThat(bundle.containsKey(BUNDLE_FIELD_AUDIO_OFFLOAD_MODE_PREFERENCE)).isTrue();
assertThat(trackSelectionParametersfromBundle).isEqualTo(trackSelectionParameters);
}
@Test
public void addOverride_onDifferentGroups_addsOverride() {
TrackSelectionOverride override1 =
@ -307,6 +339,29 @@ public final class TrackSelectionParametersTest {
.containsExactly(override1.mediaTrackGroup, override1);
}
@Test
public void audioOffloadPreferences_checkDefault_allFieldsAreDisabledOrFalse() {
AudioOffloadPreferences audioOffloadPreferences = AudioOffloadPreferences.DEFAULT;
assertThat(audioOffloadPreferences.audioOffloadMode).isEqualTo(AUDIO_OFFLOAD_MODE_DISABLED);
assertThat(audioOffloadPreferences.isGaplessSupportRequired).isFalse();
assertThat(audioOffloadPreferences.isSpeedChangeSupportRequired).isFalse();
}
@Test
public void audioOffloadPreferences_buildUponWithIndividualSetters_equalsToOriginal() {
AudioOffloadPreferences audioOffloadPreferences =
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(true)
.setIsSpeedChangeSupportRequired(false)
.build();
AudioOffloadPreferences copy = audioOffloadPreferences.buildUpon().build();
assertThat(copy).isEqualTo(audioOffloadPreferences);
}
private static TrackGroup newTrackGroupWithIds(int... ids) {
Format[] formats = new Format[ids.length];
for (int i = 0; i < ids.length; i++) {

View File

@ -1801,7 +1801,7 @@ public interface ExoPlayer extends Player {
*
* <ul>
* <li>Audio offload rendering is enabled through {@link
* TrackSelectionParameters.Builder#setAudioOffloadPreference}.
* TrackSelectionParameters.Builder#setAudioOffloadPreferences}.
* <li>An audio track is playing in a format that the device supports offloading (for example,
* MP3 or AAC).
* <li>The {@link AudioSink} is playing with an offload {@link AudioTrack}.

View File

@ -15,8 +15,8 @@
*/
package androidx.media3.exoplayer.trackselection;
import static androidx.media3.common.TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED;
import static androidx.media3.common.TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED;
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED;
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_REQUIRED;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.castNonNull;
import static androidx.media3.exoplayer.RendererCapabilities.AUDIO_OFFLOAD_GAPLESS_SUPPORTED;
@ -53,6 +53,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.BundleableUtil;
import androidx.media3.common.util.Log;
@ -463,12 +464,9 @@ public class DefaultTrackSelector extends MappingTrackSelector
@CanIgnoreReturnValue
@Override
public ParametersBuilder setAudioOffloadPreference(
@TrackSelectionParameters.AudioOffloadModePreference int audioOffloadModePreference,
boolean isGaplessSupportRequired,
boolean isSpeedChangeSupportRequired) {
delegate.setAudioOffloadPreference(
audioOffloadModePreference, isGaplessSupportRequired, isSpeedChangeSupportRequired);
public ParametersBuilder setAudioOffloadPreferences(
AudioOffloadPreferences audioOffloadPreferences) {
delegate.setAudioOffloadPreferences(audioOffloadPreferences);
return this;
}
@ -2507,7 +2505,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
}
// Configure audio renderer to use offload if appropriate.
if (parameters.audioOffloadModePreference != AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED) {
if (parameters.audioOffloadPreferences.audioOffloadMode != AUDIO_OFFLOAD_MODE_DISABLED) {
maybeConfigureRendererForOffload(
parameters,
mappedTrackInfo,
@ -2529,9 +2527,10 @@ public class DefaultTrackSelector extends MappingTrackSelector
* <p>The implementation should not account for overrides and disabled flags. Track selections
* generated by this method will be overridden to account for these properties.
*
* <p>If selection parameters include {@link Parameters#audioOffloadModePreference} with {@link
* TrackSelectionParameters#AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED}, then only audio tracks will
* be selected. If no audio track is supported in offload, then no track will be selected.
* <p>If selection parameters include {@link Parameters#audioOffloadPreferences} with {@link
* AudioOffloadPreferences#audioOffloadMode} set to {@link
* AudioOffloadPreferences#AUDIO_OFFLOAD_MODE_REQUIRED} then only audio tracks will be selected.
* If no audio track is supported in offload, then no track will be selected.
*
* @param mappedTrackInfo Mapped track information.
* @param rendererFormatSupports The {@link Capabilities} for each mapped track, indexed by
@ -2623,7 +2622,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
@AdaptiveSupport int[] mixedMimeTypeSupports,
Parameters params)
throws ExoPlaybackException {
if (params.audioOffloadModePreference == AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED) {
if (params.audioOffloadPreferences.audioOffloadMode == AUDIO_OFFLOAD_MODE_REQUIRED) {
return null;
}
return selectTracksForType(
@ -2741,7 +2740,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
Parameters params,
@Nullable String selectedAudioLanguage)
throws ExoPlaybackException {
if (params.audioOffloadModePreference == AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED) {
if (params.audioOffloadPreferences.audioOffloadMode == AUDIO_OFFLOAD_MODE_REQUIRED) {
return null;
}
return selectTracksForType(
@ -2772,7 +2771,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
protected ExoTrackSelection.Definition selectOtherTrack(
int trackType, TrackGroupArray groups, @Capabilities int[][] formatSupport, Parameters params)
throws ExoPlaybackException {
if (params.audioOffloadModePreference == AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED) {
if (params.audioOffloadPreferences.audioOffloadMode == AUDIO_OFFLOAD_MODE_REQUIRED) {
return null;
}
@Nullable TrackGroup selectedGroup = null;
@ -3077,7 +3076,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
// Check whether we can enable offload. To enable offload we require exactly one audio track
// and a renderer with support matching the requirements set by
// setAudioOffloadPreference. There also cannot be other non-audio renderers with their own
// selected tracks.
// selected tracks unless the selection parameters say audio-only is not required.
int audioRendererIndex = C.INDEX_UNSET;
int audioRenderersSupportingOffload = 0;
boolean hasNonAudioRendererWithSelectedTracks = false;
@ -3106,7 +3105,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
if (!hasNonAudioRendererWithSelectedTracks && audioRenderersSupportingOffload == 1) {
RendererConfiguration offloadRendererConfiguration =
new RendererConfiguration(
parameters.isGaplessSupportRequired
parameters.audioOffloadPreferences.isGaplessSupportRequired
? AudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_REQUIRED
: AudioSink.OFFLOAD_MODE_ENABLED_GAPLESS_NOT_REQUIRED,
/* tunneling= */ rendererConfigurations[audioRendererIndex] != null
@ -3128,14 +3127,14 @@ public class DefaultTrackSelector extends MappingTrackSelector
if (RendererCapabilities.getAudioOffloadSupport(formatSupport) == AUDIO_OFFLOAD_NOT_SUPPORTED) {
return false;
}
if (parameters.isSpeedChangeSupportRequired
if (parameters.audioOffloadPreferences.isSpeedChangeSupportRequired
&& (RendererCapabilities.getAudioOffloadSupport(formatSupport)
& AUDIO_OFFLOAD_SPEED_CHANGE_SUPPORTED)
== 0) {
return false;
}
// TODO(b/235883373): Add check for OPUS where gapless info is in initialization data
if (parameters.isGaplessSupportRequired) {
if (parameters.audioOffloadPreferences.isGaplessSupportRequired) {
boolean isGapless = format.encoderDelay != 0 || format.encoderPadding != 0;
boolean isGaplessSupported =
(RendererCapabilities.getAudioOffloadSupport(formatSupport)
@ -3751,7 +3750,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
if (!isWithinConstraints && !parameters.exceedAudioConstraintsIfNecessary) {
return SELECTION_ELIGIBILITY_NO;
}
if (params.audioOffloadModePreference == AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED
if (params.audioOffloadPreferences.audioOffloadMode == AUDIO_OFFLOAD_MODE_REQUIRED
&& !rendererSupportsOffload(params, rendererSupport, format)) {
return SELECTION_ELIGIBILITY_NO;
}
@ -3761,7 +3760,7 @@ public class DefaultTrackSelector extends MappingTrackSelector
&& !parameters.forceHighestSupportedBitrate
&& !parameters.forceLowestBitrate
&& (parameters.allowMultipleAdaptiveSelections || !hasMappedVideoTracks)
&& params.audioOffloadModePreference != AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED
&& params.audioOffloadPreferences.audioOffloadMode != AUDIO_OFFLOAD_MODE_REQUIRED
? SELECTION_ELIGIBILITY_ADAPTIVE
: SELECTION_ELIGIBILITY_FIXED;
}

View File

@ -122,7 +122,7 @@ import androidx.media3.common.Player.PositionInfo;
import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Window;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences;
import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize;
import androidx.media3.common.util.Assertions;
@ -10210,10 +10210,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
player.prepare();
player.play();
@ -10241,10 +10241,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ true);
@ -10266,10 +10266,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
player.prepare();
player.play();
@ -10292,10 +10292,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
player.prepare();
player.play();
@ -10305,10 +10305,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_DISABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED)
.build())
.build());
runUntilSleepingForOffload(player, /* expectedSleepForOffload= */ false);
@ -10328,10 +10328,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
player.prepare();
player.play();
@ -10359,10 +10359,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
player.prepare();
player.play();
@ -10393,10 +10393,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
player.prepare();
player.play();
@ -10428,10 +10428,10 @@ public final class ExoPlayerTest {
player
.getTrackSelectionParameters()
.buildUpon()
.setAudioOffloadPreference(
TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
.build())
.build());
player.prepare();
player.play();

View File

@ -15,13 +15,14 @@
*/
package androidx.media3.exoplayer.e2etest;
import static androidx.media3.common.TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED;
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.media3.common.Format;
import androidx.media3.common.MediaItem;
import androidx.media3.common.Player;
import androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.audio.AudioOffloadSupport;
@ -61,10 +62,12 @@ public class OggOpusPlaybackTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(false)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
ExoPlayer player =
new ExoPlayer.Builder(applicationContext, offloadRenderersFactory)

View File

@ -19,8 +19,8 @@ import static androidx.media3.common.C.FORMAT_EXCEEDS_CAPABILITIES;
import static androidx.media3.common.C.FORMAT_HANDLED;
import static androidx.media3.common.C.FORMAT_UNSUPPORTED_SUBTYPE;
import static androidx.media3.common.C.FORMAT_UNSUPPORTED_TYPE;
import static androidx.media3.common.TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED;
import static androidx.media3.common.TrackSelectionParameters.AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED;
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED;
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_REQUIRED;
import static androidx.media3.exoplayer.RendererCapabilities.ADAPTIVE_NOT_SEAMLESS;
import static androidx.media3.exoplayer.RendererCapabilities.AUDIO_OFFLOAD_GAPLESS_SUPPORTED;
import static androidx.media3.exoplayer.RendererCapabilities.AUDIO_OFFLOAD_SUPPORTED;
@ -51,6 +51,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.HandlerWrapper;
import androidx.media3.common.util.Util;
@ -2329,10 +2330,12 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ true,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(true)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
RendererCapabilities capabilitiesOffloadSupport =
new FakeRendererCapabilities(
@ -2365,10 +2368,12 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ true,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(true)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
RendererCapabilities capabilitiesOffloadSupport =
new FakeRendererCapabilities(
@ -2402,10 +2407,12 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED,
/* isGaplessSupportRequired= */ true,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_REQUIRED)
.setIsGaplessSupportRequired(true)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
RendererCapabilities capabilitiesOffloadSupport =
new FakeRendererCapabilities(
@ -2438,10 +2445,12 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(false)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
RendererCapabilities audioCapabilities =
new FakeRendererCapabilities(
@ -2475,10 +2484,12 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED,
/* isGaplessSupportRequired= */ false,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_REQUIRED)
.setIsGaplessSupportRequired(false)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
RendererCapabilities audioCapabilities =
new FakeRendererCapabilities(
@ -2517,10 +2528,12 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ true,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(true)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
// Offload playback without gapless transitions is supported
RendererCapabilities capabilitiesOffloadSupport =
@ -2559,12 +2572,14 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_ENABLED,
/* isGaplessSupportRequired= */ true,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_ENABLED)
.setIsGaplessSupportRequired(true)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
// Offload playback without gapless transitions is supported
// Offload playback with gapless transitions is supported
RendererCapabilities capabilitiesOffloadSupport =
new FakeRendererCapabilities(
C.TRACK_TYPE_AUDIO,
@ -2598,10 +2613,12 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAudioOffloadPreference(
AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED,
/* isGaplessSupportRequired= */ true,
/* isSpeedChangeSupportRequired= */ false)
.setAudioOffloadPreferences(
new AudioOffloadPreferences.Builder()
.setAudioOffloadMode(AUDIO_OFFLOAD_MODE_REQUIRED)
.setIsGaplessSupportRequired(true)
.setIsSpeedChangeSupportRequired(false)
.build())
.build());
// Offload playback without gapless transitions is supported
RendererCapabilities capabilitiesOffloadSupport =