diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index c1b7e9d6aa..b029419701 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -55,6 +55,10 @@
* Track selection:
* Allow parallel adaptation for video and audio
([#5111](https://github.com/google/ExoPlayer/issues/5111)).
+ * Simplified enabling tunneling with `DefaultTrackSelector`.
+ `ParametersBuilder.setTunnelingAudioSessionId` has been replaced with
+ `ParametersBuilder.setTunnelingEnabled`. The player's audio session ID
+ will be used, and so a tunneling specified ID is no longer needed.
* Add option to specify multiple preferred audio or text languages.
* Add option to specify preferred MIME type(s) for video and audio
([#8320](https://github.com/google/ExoPlayer/issues/8320)).
@@ -87,6 +91,18 @@
`DecoderReuseEvaluation` indicates whether it was possible to re-use an
existing decoder instance for the new format, and if not then the
reasons why.
+* Audio:
+ * Fix handling of audio session IDs
+ ([#8190](https://github.com/google/ExoPlayer/issues/8190)).
+ `SimpleExoPlayer` now generates an audio session ID on construction,
+ which can be immediately queried by calling
+ `SimpleExoPlayer.getAudioSessionId`. The audio session ID will only
+ change if application code calls `SimpleExoPlayer.setAudioSessionId`.
+* Text:
+ * Gracefully handle null-terminated subtitle content in Matroska
+ containers.
+ * Fix CEA-708 anchor positioning
+ ([#1807](https://github.com/google/ExoPlayer/issues/1807)).
* Metadata retriever:
* Parse Google Photos HEIC motion photos metadata.
* Data sources:
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Player.java b/library/core/src/main/java/com/google/android/exoplayer2/Player.java
index 1abe7d4e5d..961d930f02 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/Player.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/Player.java
@@ -89,7 +89,7 @@ public interface Player {
* default audio attributes will be used. They are suitable for general media playback.
*
*
Setting the audio attributes during playback may introduce a short gap in audio output as
- * the audio track is recreated. A new audio session id will also be generated.
+ * the audio track is recreated.
*
*
If tunneling is enabled by the track selector, the specified audio attributes will be
* ignored, but they will take effect if audio is later played without tunneling.
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java b/library/core/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java
index bc8c6ff633..e36cb0c71d 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java
@@ -22,24 +22,16 @@ import androidx.annotation.Nullable;
*/
public final class RendererConfiguration {
- /**
- * The default configuration.
- */
+ /** The default configuration. */
public static final RendererConfiguration DEFAULT =
- new RendererConfiguration(C.AUDIO_SESSION_ID_UNSET);
+ new RendererConfiguration(/* tunneling= */ false);
- /**
- * The audio session id to use for tunneling, or {@link C#AUDIO_SESSION_ID_UNSET} if tunneling
- * should not be enabled.
- */
- public final int tunnelingAudioSessionId;
+ /** Whether to enable tunneling. */
+ public final boolean tunneling;
- /**
- * @param tunnelingAudioSessionId The audio session id to use for tunneling, or
- * {@link C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
- */
- public RendererConfiguration(int tunnelingAudioSessionId) {
- this.tunnelingAudioSessionId = tunnelingAudioSessionId;
+ /** @param tunneling Whether to enable tunneling. */
+ public RendererConfiguration(boolean tunneling) {
+ this.tunneling = tunneling;
}
@Override
@@ -51,12 +43,11 @@ public final class RendererConfiguration {
return false;
}
RendererConfiguration other = (RendererConfiguration) obj;
- return tunnelingAudioSessionId == other.tunnelingAudioSessionId;
+ return tunneling == other.tunneling;
}
@Override
public int hashCode() {
- return tunnelingAudioSessionId;
+ return tunneling ? 0 : 1;
}
-
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
index 53babe2709..2516d8f488 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
@@ -18,6 +18,8 @@ package com.google.android.exoplayer2;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
+import android.media.AudioFormat;
+import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.PlaybackParams;
import android.os.Handler;
@@ -568,6 +570,7 @@ public class SimpleExoPlayer extends BasePlayer
protected final Renderer[] renderers;
+ private final Context applicationContext;
private final ExoPlayerImpl player;
private final ComponentListener componentListener;
private final CopyOnWriteArraySet
@@ -588,7 +591,7 @@ public class SimpleExoPlayer extends BasePlayer
@Nullable private Format videoFormat;
@Nullable private Format audioFormat;
-
+ @Nullable private AudioTrack keepSessionIdAudioTrack;
@Nullable private VideoDecoderOutputBufferRenderer videoDecoderOutputBufferRenderer;
@Nullable private Surface surface;
private boolean ownsSurface;
@@ -640,6 +643,7 @@ public class SimpleExoPlayer extends BasePlayer
/** @param builder The {@link Builder} to obtain all construction parameters. */
protected SimpleExoPlayer(Builder builder) {
+ applicationContext = builder.context.getApplicationContext();
analyticsCollector = builder.analyticsCollector;
priorityTaskManager = builder.priorityTaskManager;
audioAttributes = builder.audioAttributes;
@@ -665,7 +669,11 @@ public class SimpleExoPlayer extends BasePlayer
// Set initial values.
audioVolume = 1;
- audioSessionId = C.AUDIO_SESSION_ID_UNSET;
+ if (Util.SDK_INT < 21) {
+ audioSessionId = initializeKeepSessionIdAudioTrack(C.AUDIO_SESSION_ID_UNSET);
+ } else {
+ audioSessionId = C.generateAudioSessionIdV21(applicationContext);
+ }
currentCues = Collections.emptyList();
throwsWhenUsingWrongThread = true;
@@ -706,6 +714,8 @@ public class SimpleExoPlayer extends BasePlayer
wifiLockManager.setEnabled(builder.wakeMode == C.WAKE_MODE_NETWORK);
deviceInfo = createDeviceInfo(streamVolumeManager);
+ sendRendererMessage(C.TRACK_TYPE_AUDIO, Renderer.MSG_SET_AUDIO_SESSION_ID, audioSessionId);
+ sendRendererMessage(C.TRACK_TYPE_VIDEO, Renderer.MSG_SET_AUDIO_SESSION_ID, audioSessionId);
sendRendererMessage(C.TRACK_TYPE_AUDIO, Renderer.MSG_SET_AUDIO_ATTRIBUTES, audioAttributes);
sendRendererMessage(C.TRACK_TYPE_VIDEO, Renderer.MSG_SET_SCALING_MODE, videoScalingMode);
sendRendererMessage(
@@ -960,11 +970,22 @@ public class SimpleExoPlayer extends BasePlayer
if (this.audioSessionId == audioSessionId) {
return;
}
+ if (audioSessionId == C.AUDIO_SESSION_ID_UNSET) {
+ if (Util.SDK_INT < 21) {
+ audioSessionId = initializeKeepSessionIdAudioTrack(C.AUDIO_SESSION_ID_UNSET);
+ } else {
+ audioSessionId = C.generateAudioSessionIdV21(applicationContext);
+ }
+ } else if (Util.SDK_INT < 21) {
+ // We need to re-initialize keepSessionIdAudioTrack to make sure the session is kept alive for
+ // as long as the player is using it.
+ initializeKeepSessionIdAudioTrack(audioSessionId);
+ }
this.audioSessionId = audioSessionId;
sendRendererMessage(C.TRACK_TYPE_AUDIO, Renderer.MSG_SET_AUDIO_SESSION_ID, audioSessionId);
sendRendererMessage(C.TRACK_TYPE_VIDEO, Renderer.MSG_SET_AUDIO_SESSION_ID, audioSessionId);
- if (audioSessionId != C.AUDIO_SESSION_ID_UNSET) {
- notifyAudioSessionIdSet();
+ for (AudioListener audioListener : audioListeners) {
+ audioListener.onAudioSessionId(audioSessionId);
}
}
@@ -1024,7 +1045,7 @@ public class SimpleExoPlayer extends BasePlayer
* Sets the stream type for audio playback, used by the underlying audio track.
*
* Setting the stream type during playback may introduce a short gap in audio output as the
- * audio track is recreated. A new audio session id will also be generated.
+ * audio track is recreated.
*
*
Calling this method overwrites any attributes set previously by calling {@link
* #setAudioAttributes(AudioAttributes)}.
@@ -1760,6 +1781,10 @@ public class SimpleExoPlayer extends BasePlayer
@Override
public void release() {
verifyApplicationThread();
+ if (Util.SDK_INT < 21 && keepSessionIdAudioTrack != null) {
+ keepSessionIdAudioTrack.release();
+ keepSessionIdAudioTrack = null;
+ }
audioBecomingNoisyManager.setEnabled(false);
streamVolumeManager.release();
wakeLockManager.setStayAwake(false);
@@ -2100,19 +2125,6 @@ public class SimpleExoPlayer extends BasePlayer
sendRendererMessage(C.TRACK_TYPE_AUDIO, Renderer.MSG_SET_VOLUME, scaledVolume);
}
- private void notifyAudioSessionIdSet() {
- for (AudioListener audioListener : audioListeners) {
- // Prevent duplicate notification if a listener is both a AudioRendererEventListener and
- // a AudioListener, as they have the same method signature.
- if (!audioDebugListeners.contains(audioListener)) {
- audioListener.onAudioSessionId(audioSessionId);
- }
- }
- for (AudioRendererEventListener audioDebugListener : audioDebugListeners) {
- audioDebugListener.onAudioSessionId(audioSessionId);
- }
- }
-
@SuppressWarnings("SuspiciousMethodCalls")
private void notifySkipSilenceEnabledChanged() {
for (AudioListener listener : audioListeners) {
@@ -2181,6 +2193,40 @@ public class SimpleExoPlayer extends BasePlayer
}
}
+ /**
+ * Initializes {@link #keepSessionIdAudioTrack} to keep an audio session ID alive. If the audio
+ * session ID is {@link C#AUDIO_SESSION_ID_UNSET} then a new audio session ID is generated.
+ *
+ *
Use of this method is only required on API level 21 and earlier.
+ *
+ * @param audioSessionId The audio session ID, or {@link C#AUDIO_SESSION_ID_UNSET} to generate a
+ * new one.
+ * @return The audio session ID.
+ */
+ private int initializeKeepSessionIdAudioTrack(int audioSessionId) {
+ if (keepSessionIdAudioTrack != null
+ && keepSessionIdAudioTrack.getAudioSessionId() != audioSessionId) {
+ keepSessionIdAudioTrack.release();
+ keepSessionIdAudioTrack = null;
+ }
+ if (keepSessionIdAudioTrack == null) {
+ int sampleRate = 4000; // Minimum sample rate supported by the platform.
+ int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
+ @C.PcmEncoding int encoding = C.ENCODING_PCM_16BIT;
+ int bufferSize = 2; // Use a two byte buffer, as it is not actually used for playback.
+ keepSessionIdAudioTrack =
+ new AudioTrack(
+ C.STREAM_TYPE_DEFAULT,
+ sampleRate,
+ channelConfig,
+ encoding,
+ bufferSize,
+ AudioTrack.MODE_STATIC,
+ audioSessionId);
+ }
+ return keepSessionIdAudioTrack.getAudioSessionId();
+ }
+
private static DeviceInfo createDeviceInfo(StreamVolumeManager streamVolumeManager) {
return new DeviceInfo(
DeviceInfo.PLAYBACK_TYPE_LOCAL,
@@ -2303,15 +2349,6 @@ public class SimpleExoPlayer extends BasePlayer
}
}
- @Override
- public void onAudioSessionId(int sessionId) {
- if (audioSessionId == sessionId) {
- return;
- }
- audioSessionId = sessionId;
- notifyAudioSessionIdSet();
- }
-
@Override
public void onAudioDecoderInitialized(
String decoderName, long initializedTimestampMs, long initializationDurationMs) {
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java
index 48d0e03144..82ca6f4b9a 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java
@@ -44,13 +44,6 @@ public interface AudioRendererEventListener {
*/
default void onAudioEnabled(DecoderCounters counters) {}
- /**
- * Called when the audio session is set.
- *
- * @param audioSessionId The audio session id.
- */
- default void onAudioSessionId(int audioSessionId) {}
-
/**
* Called when a decoder is created.
*
@@ -224,13 +217,6 @@ public interface AudioRendererEventListener {
}
}
- /** Invokes {@link AudioRendererEventListener#onAudioSessionId(int)}. */
- public void audioSessionId(int audioSessionId) {
- if (handler != null) {
- handler.post(() -> castNonNull(listener).onAudioSessionId(audioSessionId));
- }
- }
-
/** Invokes {@link AudioRendererEventListener#onSkipSilenceEnabledChanged(boolean)}. */
public void skipSilenceEnabledChanged(boolean skipSilenceEnabled) {
if (handler != null) {
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java
index 1cbfde0bca..463461916f 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java
@@ -49,9 +49,9 @@ import java.nio.ByteBuffer;
*
*
The implementation may be backed by a platform {@link AudioTrack}. In this case, {@link
* #setAudioSessionId(int)}, {@link #setAudioAttributes(AudioAttributes)}, {@link
- * #enableTunnelingV21(int)} and/or {@link #disableTunneling()} may be called before writing data to
- * the sink. These methods may also be called after writing data to the sink, in which case it will
- * be reinitialized as required. For implementations that are not based on platform {@link
+ * #enableTunnelingV21()} and {@link #disableTunneling()} may be called before writing data to the
+ * sink. These methods may also be called after writing data to the sink, in which case it will be
+ * reinitialized as required. For implementations that are not based on platform {@link
* AudioTrack}s, calling methods relating to audio sessions, audio attributes, and tunneling may
* have no effect.
*/
@@ -62,13 +62,6 @@ public interface AudioSink {
*/
interface Listener {
- /**
- * Called if the audio sink has started rendering audio to a new platform audio session.
- *
- * @param audioSessionId The newly generated audio session's identifier.
- */
- void onAudioSessionId(int audioSessionId);
-
/**
* Called when the audio sink handles a buffer whose timestamp is discontinuous with the last
* buffer handled since it was reset.
@@ -392,14 +385,13 @@ public interface AudioSink {
void setAuxEffectInfo(AuxEffectInfo auxEffectInfo);
/**
- * Enables tunneling, if possible. The sink is reset if tunneling was previously disabled or if
- * the audio session id has changed. Enabling tunneling is only possible if the sink is based on a
- * platform {@link AudioTrack}, and requires platform API version 21 onwards.
+ * Enables tunneling, if possible. The sink is reset if tunneling was previously disabled.
+ * Enabling tunneling is only possible if the sink is based on a platform {@link AudioTrack}, and
+ * requires platform API version 21 onwards.
*
- * @param tunnelingAudioSessionId The audio session id to use.
* @throws IllegalStateException Thrown if enabling tunneling on platform API version < 21.
*/
- void enableTunnelingV21(int tunnelingAudioSessionId);
+ void enableTunnelingV21();
/**
* Disables tunneling. If tunneling was previously enabled then the sink is reset and any audio
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java
index ac5ff75d08..12962a786a 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java
@@ -512,9 +512,8 @@ public abstract class DecoderAudioRenderer<
throws ExoPlaybackException {
decoderCounters = new DecoderCounters();
eventDispatcher.enabled(decoderCounters);
- int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
- if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
- audioSink.enableTunnelingV21(tunnelingAudioSessionId);
+ if (getConfiguration().tunneling) {
+ audioSink.enableTunnelingV21();
} else {
audioSink.disableTunneling();
}
@@ -714,11 +713,6 @@ public abstract class DecoderAudioRenderer<
private final class AudioSinkListener implements AudioSink.Listener {
- @Override
- public void onAudioSessionId(int audioSessionId) {
- eventDispatcher.audioSessionId(audioSessionId);
- }
-
@Override
public void onPositionDiscontinuity() {
DecoderAudioRenderer.this.onPositionDiscontinuity();
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java
index 2acaa42e5b..7bd7d1a7eb 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java
@@ -261,15 +261,6 @@ public final class DefaultAudioSink implements AudioSink {
private static final String TAG = "DefaultAudioSink";
- /**
- * Whether to enable a workaround for an issue where an audio effect does not keep its session
- * active across releasing/initializing a new audio track, on platform builds where
- * {@link Util#SDK_INT} < 21.
- *
- * The flag must be set before creating a player.
- */
- public static boolean enablePreV21AudioSessionWorkaround = false;
-
/**
* Whether to throw an {@link InvalidAudioTrackTimestampException} when a spurious timestamp is
* reported from {@link AudioTrack#getTimestamp}.
@@ -297,11 +288,6 @@ public final class DefaultAudioSink implements AudioSink {
private final PendingExceptionHolder writeExceptionPendingExceptionHolder;
@Nullable private Listener listener;
- /**
- * Used to keep the audio session active on pre-V21 builds (see {@link #initializeAudioTrack()}).
- */
- @Nullable private AudioTrack keepSessionIdAudioTrack;
-
@Nullable private Configuration pendingConfiguration;
@MonotonicNonNull private Configuration configuration;
@Nullable private AudioTrack audioTrack;
@@ -336,6 +322,7 @@ public final class DefaultAudioSink implements AudioSink {
private boolean stoppedAudioTrack;
private boolean playing;
+ private boolean externalAudioSessionIdProvided;
private int audioSessionId;
private AuxEffectInfo auxEffectInfo;
private boolean tunneling;
@@ -646,27 +633,7 @@ public final class DefaultAudioSink implements AudioSink {
audioTrack.setOffloadDelayPadding(
configuration.inputFormat.encoderDelay, configuration.inputFormat.encoderPadding);
}
- int audioSessionId = audioTrack.getAudioSessionId();
- if (enablePreV21AudioSessionWorkaround) {
- if (Util.SDK_INT < 21) {
- // The workaround creates an audio track with a two byte buffer on the same session, and
- // does not release it until this object is released, which keeps the session active.
- if (keepSessionIdAudioTrack != null
- && audioSessionId != keepSessionIdAudioTrack.getAudioSessionId()) {
- releaseKeepSessionIdAudioTrack();
- }
- if (keepSessionIdAudioTrack == null) {
- keepSessionIdAudioTrack = initializeKeepSessionIdAudioTrack(audioSessionId);
- }
- }
- }
- if (this.audioSessionId != audioSessionId) {
- this.audioSessionId = audioSessionId;
- if (listener != null) {
- listener.onAudioSessionId(audioSessionId);
- }
- }
-
+ audioSessionId = audioTrack.getAudioSessionId();
audioTrackPositionTracker.setAudioTrack(
audioTrack,
/* isPassthrough= */ configuration.outputMode == OUTPUT_MODE_PASSTHROUGH,
@@ -1115,13 +1082,13 @@ public final class DefaultAudioSink implements AudioSink {
return;
}
flush();
- audioSessionId = C.AUDIO_SESSION_ID_UNSET;
}
@Override
public void setAudioSessionId(int audioSessionId) {
if (this.audioSessionId != audioSessionId) {
this.audioSessionId = audioSessionId;
+ externalAudioSessionIdProvided = audioSessionId != C.AUDIO_SESSION_ID_UNSET;
flush();
}
}
@@ -1145,11 +1112,11 @@ public final class DefaultAudioSink implements AudioSink {
}
@Override
- public void enableTunnelingV21(int tunnelingAudioSessionId) {
+ public void enableTunnelingV21() {
Assertions.checkState(Util.SDK_INT >= 21);
- if (!tunneling || audioSessionId != tunnelingAudioSessionId) {
+ Assertions.checkState(externalAudioSessionIdProvided);
+ if (!tunneling) {
tunneling = true;
- audioSessionId = tunnelingAudioSessionId;
flush();
}
}
@@ -1158,7 +1125,6 @@ public final class DefaultAudioSink implements AudioSink {
public void disableTunneling() {
if (tunneling) {
tunneling = false;
- audioSessionId = C.AUDIO_SESSION_ID_UNSET;
flush();
}
}
@@ -1203,6 +1169,14 @@ public final class DefaultAudioSink implements AudioSink {
// AudioTrack.release can take some time, so we call it on a background thread.
final AudioTrack toRelease = audioTrack;
audioTrack = null;
+ if (Util.SDK_INT < 21 && !externalAudioSessionIdProvided) {
+ // Prior to API level 21, audio sessions are not kept alive once there are no components
+ // associated with them. If we generated the session ID internally, the only component
+ // associated with the session is the audio track that's being released, and therefore
+ // the session will not be kept alive. As a result, we need to generate a new session when
+ // we next create an audio track.
+ audioSessionId = C.AUDIO_SESSION_ID_UNSET;
+ }
if (pendingConfiguration != null) {
configuration = pendingConfiguration;
pendingConfiguration = null;
@@ -1261,14 +1235,12 @@ public final class DefaultAudioSink implements AudioSink {
@Override
public void reset() {
flush();
- releaseKeepSessionIdAudioTrack();
for (AudioProcessor audioProcessor : toIntPcmAvailableAudioProcessors) {
audioProcessor.reset();
}
for (AudioProcessor audioProcessor : toFloatPcmAvailableAudioProcessors) {
audioProcessor.reset();
}
- audioSessionId = C.AUDIO_SESSION_ID_UNSET;
playing = false;
offloadDisabledUntilNextConfiguration = false;
}
@@ -1303,23 +1275,6 @@ public final class DefaultAudioSink implements AudioSink {
flushAudioProcessors();
}
- /** Releases {@link #keepSessionIdAudioTrack} asynchronously, if it is non-{@code null}. */
- private void releaseKeepSessionIdAudioTrack() {
- if (keepSessionIdAudioTrack == null) {
- return;
- }
-
- // AudioTrack.release can take some time, so we call it on a background thread.
- final AudioTrack toRelease = keepSessionIdAudioTrack;
- keepSessionIdAudioTrack = null;
- new Thread() {
- @Override
- public void run() {
- toRelease.release();
- }
- }.start();
- }
-
@RequiresApi(23)
private void setAudioTrackPlaybackParametersV23(PlaybackParameters audioTrackPlaybackParameters) {
if (isAudioTrackInitialized()) {
@@ -1587,21 +1542,6 @@ public final class DefaultAudioSink implements AudioSink {
return Util.SDK_INT >= 30 && Util.MODEL.startsWith("Pixel");
}
- private static AudioTrack initializeKeepSessionIdAudioTrack(int audioSessionId) {
- int sampleRate = 4000; // Equal to private AudioTrack.MIN_SAMPLE_RATE.
- int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
- @C.PcmEncoding int encoding = C.ENCODING_PCM_16BIT;
- int bufferSize = 2; // Use a two byte buffer, as it is not actually used for playback.
- return new AudioTrack(
- C.STREAM_TYPE_DEFAULT,
- sampleRate,
- channelConfig,
- encoding,
- bufferSize,
- AudioTrack.MODE_STATIC,
- audioSessionId);
- }
-
private static int getMaximumEncodedRateBytesPerSecond(@C.Encoding int encoding) {
switch (encoding) {
case C.ENCODING_MP3:
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java
index 7460d12457..1e60dc3ed1 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java
@@ -124,8 +124,8 @@ public class ForwardingAudioSink implements AudioSink {
}
@Override
- public void enableTunnelingV21(int tunnelingAudioSessionId) {
- sink.enableTunnelingV21(tunnelingAudioSessionId);
+ public void enableTunnelingV21() {
+ sink.enableTunnelingV21();
}
@Override
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
index 990369c783..5786af503d 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
@@ -486,9 +486,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
throws ExoPlaybackException {
super.onEnabled(joining, mayRenderStartOfStream);
eventDispatcher.enabled(decoderCounters);
- int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
- if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
- audioSink.enableTunnelingV21(tunnelingAudioSessionId);
+ if (getConfiguration().tunneling) {
+ audioSink.enableTunnelingV21();
} else {
audioSink.disableTunneling();
}
@@ -813,11 +812,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
private final class AudioSinkListener implements AudioSink.Listener {
- @Override
- public void onAudioSessionId(int audioSessionId) {
- eventDispatcher.audioSessionId(audioSessionId);
- }
-
@Override
public void onPositionDiscontinuity() {
MediaCodecAudioRenderer.this.onPositionDiscontinuity();
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
index d477bc1fed..85be24aafa 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
@@ -159,7 +159,7 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
*
* Tunneled playback can be enabled in cases where the combination of renderers and selected tracks
* support it. Tunneled playback is enabled by passing an audio session ID to {@link
- * ParametersBuilder#setTunnelingAudioSessionId(int)}.
+ * ParametersBuilder#setTunnelingEnabled(boolean)}.
*/
public class DefaultTrackSelector extends MappingTrackSelector {
@@ -197,7 +197,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private boolean forceLowestBitrate;
private boolean forceHighestSupportedBitrate;
private boolean exceedRendererCapabilitiesIfNecessary;
- private int tunnelingAudioSessionId;
+ private boolean tunnelingEnabled;
private boolean allowMultipleAdaptiveSelections;
private final SparseArray