mirror of
https://github.com/androidx/media.git
synced 2025-05-11 01:31:40 +08:00
Add Offload gapless support
Confirmed to work on a Pixel 4 after enabling the feature: `setprop vendor.audio.offload.gapless.enabled true` PiperOrigin-RevId: 315889054
This commit is contained in:
parent
0b608dd19c
commit
962e08d3be
@ -434,7 +434,12 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
}
|
||||
if (enableOffload
|
||||
&& isOffloadedPlaybackSupported(
|
||||
format.channelCount, format.sampleRate, encoding, audioAttributes)) {
|
||||
format.channelCount,
|
||||
format.sampleRate,
|
||||
encoding,
|
||||
audioAttributes,
|
||||
format.encoderDelay,
|
||||
format.encoderPadding)) {
|
||||
return true;
|
||||
}
|
||||
return isPassthroughPlaybackSupported(encoding, format.channelCount);
|
||||
@ -518,7 +523,13 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
boolean useOffload =
|
||||
enableOffload
|
||||
&& !isInputPcm
|
||||
&& isOffloadedPlaybackSupported(channelCount, sampleRate, encoding, audioAttributes);
|
||||
&& isOffloadedPlaybackSupported(
|
||||
channelCount,
|
||||
sampleRate,
|
||||
encoding,
|
||||
audioAttributes,
|
||||
trimStartFrames,
|
||||
trimEndFrames);
|
||||
|
||||
Configuration pendingConfiguration =
|
||||
new Configuration(
|
||||
@ -533,6 +544,8 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
processingEnabled,
|
||||
canApplyPlaybackParameters,
|
||||
availableAudioProcessors,
|
||||
trimStartFrames,
|
||||
trimEndFrames,
|
||||
useOffload);
|
||||
if (isInitialized()) {
|
||||
this.pendingConfiguration = pendingConfiguration;
|
||||
@ -578,7 +591,8 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
.buildAudioTrack(tunneling, audioAttributes, audioSessionId);
|
||||
if (isOffloadedPlayback(audioTrack)) {
|
||||
// Receive stream event callbacks on the current (playback) thread.
|
||||
Assertions.checkNotNull(offloadStreamEventCallback).register(audioTrack);
|
||||
offloadStreamEventCallback.register(audioTrack);
|
||||
audioTrack.setOffloadDelayPadding(configuration.trimStartFrames, configuration.trimEndFrames);
|
||||
}
|
||||
int audioSessionId = audioTrack.getAudioSessionId();
|
||||
if (enablePreV21AudioSessionWorkaround) {
|
||||
@ -656,6 +670,11 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
// The current audio track can be reused for the new configuration.
|
||||
configuration = pendingConfiguration;
|
||||
pendingConfiguration = null;
|
||||
if (isOffloadedPlayback(audioTrack)) {
|
||||
audioTrack.setOffloadEndOfStream();
|
||||
audioTrack.setOffloadDelayPadding(
|
||||
configuration.trimStartFrames, configuration.trimEndFrames);
|
||||
}
|
||||
}
|
||||
// Re-apply playback parameters.
|
||||
applyPlaybackSpeedAndSkipSilence(presentationTimeUs);
|
||||
@ -1248,14 +1267,24 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
int channelCount,
|
||||
int sampleRateHz,
|
||||
@C.Encoding int encoding,
|
||||
AudioAttributes audioAttributes) {
|
||||
AudioAttributes audioAttributes,
|
||||
int trimStartFrames,
|
||||
int trimEndFrames) {
|
||||
if (Util.SDK_INT < 29) {
|
||||
return false;
|
||||
}
|
||||
int channelMask = getChannelConfig(channelCount, /* isInputPcm= */ false);
|
||||
AudioFormat audioFormat = getAudioFormat(sampleRateHz, channelMask, encoding);
|
||||
return AudioManager.isOffloadedPlaybackSupported(
|
||||
audioFormat, audioAttributes.getAudioAttributesV21());
|
||||
if (!AudioManager.isOffloadedPlaybackSupported(
|
||||
audioFormat, audioAttributes.getAudioAttributesV21())) {
|
||||
return false;
|
||||
}
|
||||
if (trimStartFrames > 0 || trimEndFrames > 0) {
|
||||
// TODO(internal b/158191844): Gapless offload is not supported by all devices and there is no
|
||||
// API to query its support.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@EnsuresNonNullIf(
|
||||
@ -1575,6 +1604,8 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
public final boolean processingEnabled;
|
||||
public final boolean canApplyPlaybackParameters;
|
||||
public final AudioProcessor[] availableAudioProcessors;
|
||||
public int trimStartFrames;
|
||||
public int trimEndFrames;
|
||||
public final boolean useOffload;
|
||||
|
||||
public Configuration(
|
||||
@ -1589,6 +1620,8 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
boolean processingEnabled,
|
||||
boolean canApplyPlaybackParameters,
|
||||
AudioProcessor[] availableAudioProcessors,
|
||||
int trimStartFrames,
|
||||
int trimEndFrames,
|
||||
boolean useOffload) {
|
||||
this.isInputPcm = isInputPcm;
|
||||
this.inputPcmFrameSize = inputPcmFrameSize;
|
||||
@ -1600,6 +1633,8 @@ public final class DefaultAudioSink implements AudioSink {
|
||||
this.processingEnabled = processingEnabled;
|
||||
this.canApplyPlaybackParameters = canApplyPlaybackParameters;
|
||||
this.availableAudioProcessors = availableAudioProcessors;
|
||||
this.trimStartFrames = trimStartFrames;
|
||||
this.trimEndFrames = trimEndFrames;
|
||||
this.useOffload = useOffload;
|
||||
|
||||
// Call computeBufferSize() last as it depends on the other configuration values.
|
||||
|
Loading…
x
Reference in New Issue
Block a user