mirror of
https://github.com/androidx/media.git
synced 2025-05-14 19:19:58 +08:00
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)
This commit is contained in:
parent
55633658c6
commit
6d2bf513fb
@ -8,6 +8,9 @@
|
||||
* Track Selection:
|
||||
* Extractors:
|
||||
* Audio:
|
||||
* Add `onAudioTrackInitialized` and `onAudioTrackReleased` callbacks to
|
||||
`AnalyticsListener`, `AudioRendererEventListener` and
|
||||
`AudioSink.Listener`.
|
||||
* Video:
|
||||
* Text:
|
||||
* Metadata:
|
||||
|
@ -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<Cue> cues) {
|
||||
|
@ -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.
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user