From 6d2bf513fbc8a01fae5ec233f506de7e47387804 Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 4 Oct 2023 01:47:28 -0700 Subject: [PATCH] Add onAudioTrackInitialized/Released events This is useful for analytics and understanding player behavior during transitions. #minor-release PiperOrigin-RevId: 570623227 (cherry picked from commit 8e2bf21011c63e2ca2fc58c4353cd66930b621e3) --- RELEASENOTES.md | 3 + .../media3/exoplayer/ExoPlayerImpl.java | 11 ++++ .../analytics/AnalyticsCollector.java | 16 +++++ .../analytics/AnalyticsListener.java | 31 ++++++++++ .../analytics/DefaultAnalyticsCollector.java | 19 ++++++ .../audio/AudioRendererEventListener.java | 30 +++++++++ .../media3/exoplayer/audio/AudioSink.java | 62 +++++++++++++++++++ .../exoplayer/audio/DecoderAudioRenderer.java | 10 +++ .../exoplayer/audio/DefaultAudioSink.java | 60 ++++++++++++------ .../audio/MediaCodecAudioRenderer.java | 10 +++ .../media3/exoplayer/util/EventLogger.java | 29 +++++++++ 11 files changed, 262 insertions(+), 19 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ae2ea8ffd5..2afe9d5d58 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -8,6 +8,9 @@ * Track Selection: * Extractors: * Audio: + * Add `onAudioTrackInitialized` and `onAudioTrackReleased` callbacks to + `AnalyticsListener`, `AudioRendererEventListener` and + `AudioSink.Listener`. * Video: * Text: * Metadata: diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java index 6d66bbb9c3..081b433c38 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java @@ -97,6 +97,7 @@ import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector; import androidx.media3.exoplayer.analytics.MediaMetricsListener; import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.exoplayer.audio.AudioRendererEventListener; +import androidx.media3.exoplayer.audio.AudioSink; import androidx.media3.exoplayer.metadata.MetadataOutput; import androidx.media3.exoplayer.source.MaskingMediaSource; import androidx.media3.exoplayer.source.MediaSource; @@ -3120,6 +3121,16 @@ import java.util.concurrent.TimeoutException; analyticsCollector.onAudioCodecError(audioCodecError); } + @Override + public void onAudioTrackInitialized(AudioSink.AudioTrackConfig audioTrackConfig) { + analyticsCollector.onAudioTrackInitialized(audioTrackConfig); + } + + @Override + public void onAudioTrackReleased(AudioSink.AudioTrackConfig audioTrackConfig) { + analyticsCollector.onAudioTrackReleased(audioTrackConfig); + } + // TextOutput implementation @Override public void onCues(List cues) { diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsCollector.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsCollector.java index 03751eed2f..b1939179b8 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsCollector.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsCollector.java @@ -179,6 +179,22 @@ public interface AnalyticsCollector */ void onAudioCodecError(Exception audioCodecError); + /** + * Called when an {@link AudioTrack} has been initialized. + * + * @param audioTrackConfig The {@link AudioSink.AudioTrackConfig} of the initialized {@link + * AudioTrack}. + */ + void onAudioTrackInitialized(AudioSink.AudioTrackConfig audioTrackConfig); + + /** + * Called when an {@link AudioTrack} has been released. + * + * @param audioTrackConfig The {@link AudioSink.AudioTrackConfig} of the released {@link + * AudioTrack}. + */ + void onAudioTrackReleased(AudioSink.AudioTrackConfig audioTrackConfig); + // Video events. /** diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsListener.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsListener.java index 41c3e9d12a..152a55fc98 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsListener.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/AnalyticsListener.java @@ -22,6 +22,7 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE_USE; +import android.media.AudioTrack; import android.media.MediaCodec; import android.media.MediaCodec.CodecException; import android.os.Looper; @@ -232,6 +233,8 @@ public interface AnalyticsListener { EVENT_PLAYER_RELEASED, EVENT_AUDIO_CODEC_ERROR, EVENT_VIDEO_CODEC_ERROR, + EVENT_AUDIO_TRACK_INITIALIZED, + EVENT_AUDIO_TRACK_RELEASED }) @interface EventFlags {} @@ -435,6 +438,12 @@ public interface AnalyticsListener { /** The video codec encountered an error. */ @UnstableApi int EVENT_VIDEO_CODEC_ERROR = 1030; + /** An audio track has been initialized. */ + @UnstableApi int EVENT_AUDIO_TRACK_INITIALIZED = 1031; + + /** An audio track has been released. */ + @UnstableApi int EVENT_AUDIO_TRACK_RELEASED = 1032; + /** Time information of an event. */ @UnstableApi final class EventTime { @@ -1113,6 +1122,28 @@ public interface AnalyticsListener { @UnstableApi default void onAudioCodecError(EventTime eventTime, Exception audioCodecError) {} + /** + * Called when an {@link AudioTrack} has been initialized. + * + * @param eventTime The event time. + * @param audioTrackConfig The {@link AudioSink.AudioTrackConfig} of the initialized {@link + * AudioTrack}. + */ + @UnstableApi + default void onAudioTrackInitialized( + EventTime eventTime, AudioSink.AudioTrackConfig audioTrackConfig) {} + + /** + * Called when an {@link AudioTrack} has been released. + * + * @param eventTime The event time. + * @param audioTrackConfig The {@link AudioSink.AudioTrackConfig} of the released {@link + * AudioTrack}. + */ + @UnstableApi + default void onAudioTrackReleased( + EventTime eventTime, AudioSink.AudioTrackConfig audioTrackConfig) {} + /** * Called when the volume changes. * diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/DefaultAnalyticsCollector.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/DefaultAnalyticsCollector.java index 70dc3b9fdd..240fb49055 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/DefaultAnalyticsCollector.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/analytics/DefaultAnalyticsCollector.java @@ -52,6 +52,7 @@ import androidx.media3.exoplayer.DecoderCounters; import androidx.media3.exoplayer.DecoderReuseEvaluation; import androidx.media3.exoplayer.ExoPlaybackException; import androidx.media3.exoplayer.analytics.AnalyticsListener.EventTime; +import androidx.media3.exoplayer.audio.AudioSink; import androidx.media3.exoplayer.drm.DrmSession; import androidx.media3.exoplayer.source.LoadEventInfo; import androidx.media3.exoplayer.source.MediaLoadData; @@ -263,6 +264,24 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector { listener -> listener.onAudioCodecError(eventTime, audioCodecError)); } + @Override + public void onAudioTrackInitialized(AudioSink.AudioTrackConfig audioTrackConfig) { + EventTime eventTime = generateReadingMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_AUDIO_TRACK_INITIALIZED, + listener -> listener.onAudioTrackInitialized(eventTime, audioTrackConfig)); + } + + @Override + public void onAudioTrackReleased(AudioSink.AudioTrackConfig audioTrackConfig) { + EventTime eventTime = generateReadingMediaPeriodEventTime(); + sendEvent( + eventTime, + AnalyticsListener.EVENT_AUDIO_TRACK_RELEASED, + listener -> listener.onAudioTrackReleased(eventTime, audioTrackConfig)); + } + @Override public final void onVolumeChanged(float volume) { EventTime eventTime = generateReadingMediaPeriodEventTime(); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioRendererEventListener.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioRendererEventListener.java index 2ffc957d43..7cc3ae748d 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioRendererEventListener.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioRendererEventListener.java @@ -150,6 +150,22 @@ public interface AudioRendererEventListener { */ default void onAudioSinkError(Exception audioSinkError) {} + /** + * Called when an {@link AudioTrack} has been initialized. + * + * @param audioTrackConfig The {@link AudioSink.AudioTrackConfig} of the initialized {@link + * AudioTrack}. + */ + default void onAudioTrackInitialized(AudioSink.AudioTrackConfig audioTrackConfig) {} + + /** + * Called when an {@link AudioTrack} has been released. + * + * @param audioTrackConfig The {@link AudioSink.AudioTrackConfig} of the released {@link + * AudioTrack}. + */ + default void onAudioTrackReleased(AudioSink.AudioTrackConfig audioTrackConfig) {} + /** Dispatches events to an {@link AudioRendererEventListener}. */ final class EventDispatcher { @@ -256,5 +272,19 @@ public interface AudioRendererEventListener { handler.post(() -> castNonNull(listener).onAudioCodecError(audioCodecError)); } } + + /** Invokes {@link AudioRendererEventListener#onAudioTrackInitialized}. */ + public void audioTrackInitialized(AudioSink.AudioTrackConfig audioTrackConfig) { + if (handler != null) { + handler.post(() -> castNonNull(listener).onAudioTrackInitialized(audioTrackConfig)); + } + } + + /** Invokes {@link AudioRendererEventListener#onAudioTrackReleased}. */ + public void audioTrackReleased(AudioSink.AudioTrackConfig audioTrackConfig) { + if (handler != null) { + handler.post(() -> castNonNull(listener).onAudioTrackReleased(audioTrackConfig)); + } + } } } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioSink.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioSink.java index 124fbaffef..a289965dba 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioSink.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioSink.java @@ -138,6 +138,68 @@ public interface AudioSink { /** Called when audio capabilities changed. */ default void onAudioCapabilitiesChanged() {} + + /** + * Called when an {@link AudioTrack} has been initialized. + * + * @param audioTrackConfig The {@link AudioTrackConfig} of the initialized {@link AudioTrack}. + */ + default void onAudioTrackInitialized(AudioTrackConfig audioTrackConfig) {} + + /** + * Called when an {@link AudioTrack} has been released. + * + * @param audioTrackConfig The {@link AudioTrackConfig} of the released {@link AudioTrack}. + */ + default void onAudioTrackReleased(AudioTrackConfig audioTrackConfig) {} + } + + /** Configuration parameters used for an {@link AudioTrack}. */ + final class AudioTrackConfig { + + /* The {@link C.Encoding} of the audio data. */ + public final @C.Encoding int encoding; + + /** The sample rate of the audio data. */ + public final int sampleRate; + + /** The channel configuration of the track. See {@code AudioTrack.CHANNEL_OUT_XXX} constants. */ + public final int channelConfig; + + /** Whether tunneling is enabled for this track. */ + public final boolean tunneling; + + /** Whether offload is enabled for this track. */ + public final boolean offload; + + /** The buffer size of the track in bytes. */ + public final int bufferSize; + + /** + * Creates the audio track configuration parameters. + * + * @param encoding The {@link C.Encoding} of the audio data + * @param sampleRate The sample rate of the audio data. + * @param channelConfig The channel configuration of the track. See {@code + * AudioTrack.CHANNEL_OUT_XXX} constants. + * @param tunneling Whether tunneling is enabled for this track. + * @param offload Whether offload is enabled for this track. + * @param bufferSize The buffer size of the track in bytes. + */ + public AudioTrackConfig( + @C.Encoding int encoding, + int sampleRate, + int channelConfig, + boolean tunneling, + boolean offload, + int bufferSize) { + this.encoding = encoding; + this.sampleRate = sampleRate; + this.channelConfig = channelConfig; + this.tunneling = tunneling; + this.offload = offload; + this.bufferSize = bufferSize; + } } /** Thrown when a failure occurs configuring the sink. */ diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java index ec3f5fae96..699c1ee8b2 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DecoderAudioRenderer.java @@ -856,6 +856,16 @@ public abstract class DecoderAudioRenderer< Log.e(TAG, "Audio sink error", audioSinkError); eventDispatcher.audioSinkError(audioSinkError); } + + @Override + public void onAudioTrackInitialized(AudioSink.AudioTrackConfig audioTrackConfig) { + eventDispatcher.audioTrackInitialized(audioTrackConfig); + } + + @Override + public void onAudioTrackReleased(AudioSink.AudioTrackConfig audioTrackConfig) { + eventDispatcher.audioTrackReleased(audioTrackConfig); + } } @RequiresApi(23) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java index 1850c70b17..5c070e9eeb 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java @@ -767,7 +767,8 @@ public final class DefaultAudioSink implements AudioSink { bufferSize, audioProcessingPipeline, enableAudioTrackPlaybackParams, - enableOffloadGapless); + enableOffloadGapless, + tunneling); if (isAudioTrackInitialized()) { this.pendingConfiguration = pendingConfiguration; } else { @@ -817,8 +818,12 @@ public final class DefaultAudioSink implements AudioSink { if (preferredDevice != null && Util.SDK_INT >= 23) { Api23.setPreferredDeviceOnAudioTrack(audioTrack, preferredDevice); } - startMediaTimeUsNeedsInit = true; + + if (listener != null) { + listener.onAudioTrackInitialized(configuration.buildAudioTrackConfig()); + } + return true; } @@ -1021,8 +1026,7 @@ public final class DefaultAudioSink implements AudioSink { private AudioTrack buildAudioTrack(Configuration configuration) throws InitializationException { try { - AudioTrack audioTrack = - configuration.buildAudioTrack(tunneling, audioAttributes, audioSessionId); + AudioTrack audioTrack = configuration.buildAudioTrack(audioAttributes, audioSessionId); if (audioOffloadListener != null) { audioOffloadListener.onOffloadedPlayback(isOffloadedPlayback(audioTrack)); } @@ -1427,12 +1431,13 @@ public final class DefaultAudioSink implements AudioSink { // we next create an audio track. audioSessionId = C.AUDIO_SESSION_ID_UNSET; } + AudioTrackConfig oldAudioTrackConfig = configuration.buildAudioTrackConfig(); if (pendingConfiguration != null) { configuration = pendingConfiguration; pendingConfiguration = null; } audioTrackPositionTracker.reset(); - releaseAudioTrackAsync(audioTrack, releasingConditionVariable); + releaseAudioTrackAsync(audioTrack, releasingConditionVariable, listener, oldAudioTrackConfig); audioTrack = null; } writeExceptionPendingExceptionHolder.clear(); @@ -1823,11 +1828,15 @@ public final class DefaultAudioSink implements AudioSink { } private static void releaseAudioTrackAsync( - AudioTrack audioTrack, ConditionVariable releasedConditionVariable) { + AudioTrack audioTrack, + ConditionVariable releasedConditionVariable, + @Nullable Listener listener, + AudioTrackConfig audioTrackConfig) { // AudioTrack.release can take some time, so we call it on a background thread. The background // thread is shared statically to avoid creating many threads when multiple players are released // at the same time. releasedConditionVariable.close(); + Handler audioTrackThreadHandler = new Handler(Looper.myLooper()); synchronized (releaseExecutorLock) { if (releaseExecutor == null) { releaseExecutor = Util.newSingleThreadExecutor("ExoPlayer:AudioTrackReleaseThread"); @@ -1839,6 +1848,9 @@ public final class DefaultAudioSink implements AudioSink { audioTrack.flush(); audioTrack.release(); } finally { + if (listener != null && audioTrackThreadHandler.getLooper().getThread().isAlive()) { + audioTrackThreadHandler.post(() -> listener.onAudioTrackReleased(audioTrackConfig)); + } releasedConditionVariable.open(); synchronized (releaseExecutorLock) { pendingReleaseCount--; @@ -2018,6 +2030,7 @@ public final class DefaultAudioSink implements AudioSink { public final AudioProcessingPipeline audioProcessingPipeline; public final boolean enableAudioTrackPlaybackParams; public final boolean enableOffloadGapless; + public final boolean tunneling; public Configuration( Format inputFormat, @@ -2030,7 +2043,8 @@ public final class DefaultAudioSink implements AudioSink { int bufferSize, AudioProcessingPipeline audioProcessingPipeline, boolean enableAudioTrackPlaybackParams, - boolean enableOffloadGapless) { + boolean enableOffloadGapless, + boolean tunneling) { this.inputFormat = inputFormat; this.inputPcmFrameSize = inputPcmFrameSize; this.outputMode = outputMode; @@ -2042,6 +2056,7 @@ public final class DefaultAudioSink implements AudioSink { this.audioProcessingPipeline = audioProcessingPipeline; this.enableAudioTrackPlaybackParams = enableAudioTrackPlaybackParams; this.enableOffloadGapless = enableOffloadGapless; + this.tunneling = tunneling; } public Configuration copyWithBufferSize(int bufferSize) { @@ -2056,7 +2071,8 @@ public final class DefaultAudioSink implements AudioSink { bufferSize, audioProcessingPipeline, enableAudioTrackPlaybackParams, - enableOffloadGapless); + enableOffloadGapless, + tunneling); } /** Returns if the configurations are sufficiently compatible to reuse the audio track. */ @@ -2078,12 +2094,21 @@ public final class DefaultAudioSink implements AudioSink { return Util.sampleCountToDurationUs(frameCount, outputSampleRate); } - public AudioTrack buildAudioTrack( - boolean tunneling, AudioAttributes audioAttributes, int audioSessionId) + public AudioTrackConfig buildAudioTrackConfig() { + return new AudioTrackConfig( + outputEncoding, + outputSampleRate, + outputChannelConfig, + tunneling, + outputMode == OUTPUT_MODE_OFFLOAD, + bufferSize); + } + + public AudioTrack buildAudioTrack(AudioAttributes audioAttributes, int audioSessionId) throws InitializationException { AudioTrack audioTrack; try { - audioTrack = createAudioTrack(tunneling, audioAttributes, audioSessionId); + audioTrack = createAudioTrack(audioAttributes, audioSessionId); } catch (UnsupportedOperationException | IllegalArgumentException e) { throw new InitializationException( AudioTrack.STATE_UNINITIALIZED, @@ -2115,20 +2140,18 @@ public final class DefaultAudioSink implements AudioSink { return audioTrack; } - private AudioTrack createAudioTrack( - boolean tunneling, AudioAttributes audioAttributes, int audioSessionId) { + private AudioTrack createAudioTrack(AudioAttributes audioAttributes, int audioSessionId) { if (Util.SDK_INT >= 29) { - return createAudioTrackV29(tunneling, audioAttributes, audioSessionId); + return createAudioTrackV29(audioAttributes, audioSessionId); } else if (Util.SDK_INT >= 21) { - return createAudioTrackV21(tunneling, audioAttributes, audioSessionId); + return createAudioTrackV21(audioAttributes, audioSessionId); } else { return createAudioTrackV9(audioAttributes, audioSessionId); } } @RequiresApi(29) - private AudioTrack createAudioTrackV29( - boolean tunneling, AudioAttributes audioAttributes, int audioSessionId) { + private AudioTrack createAudioTrackV29(AudioAttributes audioAttributes, int audioSessionId) { AudioFormat audioFormat = Util.getAudioFormat(outputSampleRate, outputChannelConfig, outputEncoding); android.media.AudioAttributes audioTrackAttributes = @@ -2144,8 +2167,7 @@ public final class DefaultAudioSink implements AudioSink { } @RequiresApi(21) - private AudioTrack createAudioTrackV21( - boolean tunneling, AudioAttributes audioAttributes, int audioSessionId) { + private AudioTrack createAudioTrackV21(AudioAttributes audioAttributes, int audioSessionId) { return new AudioTrack( getAudioTrackAttributesV21(audioAttributes, tunneling), Util.getAudioFormat(outputSampleRate, outputChannelConfig, outputEncoding), diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java index a226ce82b6..e5bb9f2f62 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java @@ -1022,6 +1022,16 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media public void onAudioCapabilitiesChanged() { MediaCodecAudioRenderer.this.onRendererCapabilitiesChanged(); } + + @Override + public void onAudioTrackInitialized(AudioSink.AudioTrackConfig audioTrackConfig) { + eventDispatcher.audioTrackInitialized(audioTrackConfig); + } + + @Override + public void onAudioTrackReleased(AudioSink.AudioTrackConfig audioTrackConfig) { + eventDispatcher.audioTrackReleased(audioTrackConfig); + } } @RequiresApi(23) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java index effe728080..70a295fa0f 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java @@ -38,6 +38,7 @@ import androidx.media3.common.util.UnstableApi; import androidx.media3.exoplayer.DecoderCounters; import androidx.media3.exoplayer.DecoderReuseEvaluation; import androidx.media3.exoplayer.analytics.AnalyticsListener; +import androidx.media3.exoplayer.audio.AudioSink; import androidx.media3.exoplayer.drm.DrmSession; import androidx.media3.exoplayer.source.LoadEventInfo; import androidx.media3.exoplayer.source.MediaLoadData; @@ -401,6 +402,20 @@ public class EventLogger implements AnalyticsListener { logd(eventTime, "volume", Float.toString(volume)); } + @UnstableApi + @Override + public void onAudioTrackInitialized( + EventTime eventTime, AudioSink.AudioTrackConfig audioTrackConfig) { + logd(eventTime, "audioTrackInit", getAudioTrackConfigString(audioTrackConfig)); + } + + @UnstableApi + @Override + public void onAudioTrackReleased( + EventTime eventTime, AudioSink.AudioTrackConfig audioTrackConfig) { + logd(eventTime, "audioTrackReleased", getAudioTrackConfigString(audioTrackConfig)); + } + @UnstableApi @Override public void onVideoEnabled(EventTime eventTime, DecoderCounters decoderCounters) { @@ -745,4 +760,18 @@ public class EventLogger implements AnalyticsListener { return "?"; } } + + private static String getAudioTrackConfigString(AudioSink.AudioTrackConfig audioTrackConfig) { + return audioTrackConfig.encoding + + "," + + audioTrackConfig.channelConfig + + "," + + audioTrackConfig.sampleRate + + "," + + audioTrackConfig.tunneling + + "," + + audioTrackConfig.offload + + "," + + audioTrackConfig.bufferSize; + } }