Retry AudioTrack with smaller buffer if > 1M
Some phone with limited memory can't allocate bigger shared memory buffers. This might or might not be related to Binder's 1M transaction limit. Tested on Pixel 4 by setting the minimum buffer size to 1h. https://github.com/google/ExoPlayer/issues/9712 #minor-release PiperOrigin-RevId: 425324536
This commit is contained in:
parent
afc3a79e10
commit
40517200fc
@ -78,6 +78,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
@UnstableApi
|
@UnstableApi
|
||||||
public final class DefaultAudioSink implements AudioSink {
|
public final class DefaultAudioSink implements AudioSink {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If an attempt to instantiate an AudioTrack with a buffer size larger than this value fails, a
|
||||||
|
* second attempt is made using this buffer size.
|
||||||
|
*/
|
||||||
|
private static final int AUDIO_TRACK_SMALLER_BUFFER_RETRY_SIZE = 1_000_000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown when the audio track has provided a spurious timestamp, if {@link
|
* Thrown when the audio track has provided a spurious timestamp, if {@link
|
||||||
* #failOnSpuriousAudioTimestamp} is set.
|
* #failOnSpuriousAudioTimestamp} is set.
|
||||||
@ -833,7 +839,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
// initialization of the audio track to fail.
|
// initialization of the audio track to fail.
|
||||||
releasingConditionVariable.block();
|
releasingConditionVariable.block();
|
||||||
|
|
||||||
audioTrack = buildAudioTrack();
|
audioTrack = buildAudioTrackWithRetry();
|
||||||
if (isOffloadedPlayback(audioTrack)) {
|
if (isOffloadedPlayback(audioTrack)) {
|
||||||
registerStreamEventCallbackV29(audioTrack);
|
registerStreamEventCallbackV29(audioTrack);
|
||||||
if (offloadMode != OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED) {
|
if (offloadMode != OFFLOAD_MODE_ENABLED_GAPLESS_DISABLED) {
|
||||||
@ -1027,12 +1033,31 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AudioTrack buildAudioTrack() throws InitializationException {
|
private AudioTrack buildAudioTrackWithRetry() throws InitializationException {
|
||||||
try {
|
try {
|
||||||
return checkNotNull(configuration)
|
return buildAudioTrack(checkNotNull(configuration));
|
||||||
.buildAudioTrack(tunneling, audioAttributes, audioSessionId);
|
} catch (InitializationException initialFailure) {
|
||||||
} catch (InitializationException e) {
|
// Retry with a smaller buffer size.
|
||||||
|
if (configuration.bufferSize > AUDIO_TRACK_SMALLER_BUFFER_RETRY_SIZE) {
|
||||||
|
Configuration retryConfiguration =
|
||||||
|
configuration.copyWithBufferSize(AUDIO_TRACK_SMALLER_BUFFER_RETRY_SIZE);
|
||||||
|
try {
|
||||||
|
AudioTrack audioTrack = buildAudioTrack(retryConfiguration);
|
||||||
|
configuration = retryConfiguration;
|
||||||
|
return audioTrack;
|
||||||
|
} catch (InitializationException retryFailure) {
|
||||||
|
initialFailure.addSuppressed(retryFailure);
|
||||||
|
}
|
||||||
|
}
|
||||||
maybeDisableOffload();
|
maybeDisableOffload();
|
||||||
|
throw initialFailure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AudioTrack buildAudioTrack(Configuration configuration) throws InitializationException {
|
||||||
|
try {
|
||||||
|
return configuration.buildAudioTrack(tunneling, audioAttributes, audioSessionId);
|
||||||
|
} catch (InitializationException e) {
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onAudioSinkError(e);
|
listener.onAudioSinkError(e);
|
||||||
}
|
}
|
||||||
@ -2138,6 +2163,19 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
this.availableAudioProcessors = availableAudioProcessors;
|
this.availableAudioProcessors = availableAudioProcessors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Configuration copyWithBufferSize(int bufferSize) {
|
||||||
|
return new Configuration(
|
||||||
|
inputFormat,
|
||||||
|
inputPcmFrameSize,
|
||||||
|
outputMode,
|
||||||
|
outputPcmFrameSize,
|
||||||
|
outputSampleRate,
|
||||||
|
outputChannelConfig,
|
||||||
|
outputEncoding,
|
||||||
|
bufferSize,
|
||||||
|
availableAudioProcessors);
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns if the configurations are sufficiently compatible to reuse the audio track. */
|
/** Returns if the configurations are sufficiently compatible to reuse the audio track. */
|
||||||
public boolean canReuseAudioTrack(Configuration audioTrackConfiguration) {
|
public boolean canReuseAudioTrack(Configuration audioTrackConfiguration) {
|
||||||
return audioTrackConfiguration.outputMode == outputMode
|
return audioTrackConfiguration.outputMode == outputMode
|
||||||
|
Loading…
x
Reference in New Issue
Block a user