Expose AudioOffload track state.

Adds a new event to AudioOffloadListener to get the offload state of the track, which indicates when software decoding is taking place.

PiperOrigin-RevId: 465264362
This commit is contained in:
yschimke 2022-08-04 09:47:41 +00:00 committed by tonihei
parent a10af8ecda
commit 7893531888
3 changed files with 37 additions and 1 deletions

View File

@ -11,6 +11,10 @@
([#10057](https://github.com/google/ExoPlayer/issues/10057)).
* Limit parallel download removals to 1 to avoid excessive thread creation
([#10458](https://github.com/google/ExoPlayer/issues/10458)).
* Audio:
* Adds AudioOffloadListener.onExperimentalOffloadedPlayback for the
AudioTrack offload state.
([#134](https://github.com/androidx/media/issues/134)).
* Metadata:
* `MetadataRenderer` can now be configured to render metadata as soon as
they are available. Create an instance with

View File

@ -435,6 +435,16 @@ public interface ExoPlayer extends Player {
* <p>This method is experimental, and will be renamed or removed in a future release.
*/
default void onExperimentalSleepingForOffloadChanged(boolean sleepingForOffload) {}
/**
* Called when the value of {@link AudioTrack#isOffloadedPlayback} changes.
*
* <p>This should not be generally required to be acted upon. But when offload is critical for
* efficiency, or audio features (gapless, playback speed), this will let the app know.
*
* <p>This method is experimental, and will be renamed or removed in a future release.
*/
default void onExperimentalOffloadedPlayback(boolean offloadedPlayback) {}
}
/**

View File

@ -50,6 +50,7 @@ import androidx.media3.common.util.ConditionVariable;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlayer.AudioOffloadListener;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.audio.AudioProcessor.UnhandledAudioFormatException;
import androidx.media3.extractor.AacUtil;
@ -274,6 +275,7 @@ public final class DefaultAudioSink implements AudioSink {
private boolean enableAudioTrackPlaybackParams;
private int offloadMode;
AudioTrackBufferSizeProvider audioTrackBufferSizeProvider;
@Nullable AudioOffloadListener audioOffloadListener;
/** Creates a new builder. */
public Builder() {
@ -379,6 +381,19 @@ public final class DefaultAudioSink implements AudioSink {
return this;
}
/**
* Sets an optional {@link AudioOffloadListener} to receive events relevant to offloaded
* playback.
*
* <p>The default value is null.
*/
@CanIgnoreReturnValue
public Builder setExperimentalAudioOffloadListener(
@Nullable AudioOffloadListener audioOffloadListener) {
this.audioOffloadListener = audioOffloadListener;
return this;
}
/** Builds the {@link DefaultAudioSink}. Must only be called once per Builder instance. */
public DefaultAudioSink build() {
if (audioProcessorChain == null) {
@ -509,6 +524,7 @@ public final class DefaultAudioSink implements AudioSink {
initializationExceptionPendingExceptionHolder;
private final PendingExceptionHolder<WriteException> writeExceptionPendingExceptionHolder;
private final AudioTrackBufferSizeProvider audioTrackBufferSizeProvider;
@Nullable private final AudioOffloadListener audioOffloadListener;
@Nullable private PlayerId playerId;
@Nullable private Listener listener;
@ -669,6 +685,7 @@ public final class DefaultAudioSink implements AudioSink {
new PendingExceptionHolder<>(AUDIO_TRACK_RETRY_DURATION_MS);
writeExceptionPendingExceptionHolder =
new PendingExceptionHolder<>(AUDIO_TRACK_RETRY_DURATION_MS);
audioOffloadListener = builder.audioOffloadListener;
}
// AudioSink implementation.
@ -1096,7 +1113,12 @@ public final class DefaultAudioSink implements AudioSink {
private AudioTrack buildAudioTrack(Configuration configuration) throws InitializationException {
try {
return configuration.buildAudioTrack(tunneling, audioAttributes, audioSessionId);
AudioTrack audioTrack =
configuration.buildAudioTrack(tunneling, audioAttributes, audioSessionId);
if (audioOffloadListener != null) {
audioOffloadListener.onExperimentalOffloadedPlayback(isOffloadedPlayback(audioTrack));
}
return audioTrack;
} catch (InitializationException e) {
if (listener != null) {
listener.onAudioSinkError(e);