Add Offload gapless support
This it is enabled only on a list of
manually tested devices.
The list is empty in this CL.
*** Reason for rollforward ***
Fixed dependent cl was rolled forward.
*** Original change description ***
Rollback of 962e08d3be
*** Original commit ***
Add Offload gapless support
Confirmed to work on a Pixel 4 after enabling the feature:
`setprop vendor.audio.offload.gapless.enabled true`
***
***
PiperOrigin-RevId: 318433123
This commit is contained in:
parent
1c018e71d4
commit
a971d09a46
@ -432,7 +432,12 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
}
|
}
|
||||||
if (enableOffload
|
if (enableOffload
|
||||||
&& isOffloadedPlaybackSupported(
|
&& isOffloadedPlaybackSupported(
|
||||||
format.channelCount, format.sampleRate, encoding, audioAttributes)) {
|
format.channelCount,
|
||||||
|
format.sampleRate,
|
||||||
|
encoding,
|
||||||
|
audioAttributes,
|
||||||
|
format.encoderDelay,
|
||||||
|
format.encoderPadding)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return isPassthroughPlaybackSupported(encoding, format.channelCount);
|
return isPassthroughPlaybackSupported(encoding, format.channelCount);
|
||||||
@ -516,7 +521,13 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
boolean useOffload =
|
boolean useOffload =
|
||||||
enableOffload
|
enableOffload
|
||||||
&& !isInputPcm
|
&& !isInputPcm
|
||||||
&& isOffloadedPlaybackSupported(channelCount, sampleRate, encoding, audioAttributes);
|
&& isOffloadedPlaybackSupported(
|
||||||
|
channelCount,
|
||||||
|
sampleRate,
|
||||||
|
encoding,
|
||||||
|
audioAttributes,
|
||||||
|
trimStartFrames,
|
||||||
|
trimEndFrames);
|
||||||
|
|
||||||
Configuration pendingConfiguration =
|
Configuration pendingConfiguration =
|
||||||
new Configuration(
|
new Configuration(
|
||||||
@ -531,6 +542,8 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
processingEnabled,
|
processingEnabled,
|
||||||
canApplyPlaybackParameters,
|
canApplyPlaybackParameters,
|
||||||
availableAudioProcessors,
|
availableAudioProcessors,
|
||||||
|
trimStartFrames,
|
||||||
|
trimEndFrames,
|
||||||
useOffload);
|
useOffload);
|
||||||
if (isInitialized()) {
|
if (isInitialized()) {
|
||||||
this.pendingConfiguration = pendingConfiguration;
|
this.pendingConfiguration = pendingConfiguration;
|
||||||
@ -576,6 +589,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
.buildAudioTrack(tunneling, audioAttributes, audioSessionId);
|
.buildAudioTrack(tunneling, audioAttributes, audioSessionId);
|
||||||
if (isOffloadedPlayback(audioTrack)) {
|
if (isOffloadedPlayback(audioTrack)) {
|
||||||
registerStreamEventCallbackV29(audioTrack);
|
registerStreamEventCallbackV29(audioTrack);
|
||||||
|
audioTrack.setOffloadDelayPadding(configuration.trimStartFrames, configuration.trimEndFrames);
|
||||||
}
|
}
|
||||||
int audioSessionId = audioTrack.getAudioSessionId();
|
int audioSessionId = audioTrack.getAudioSessionId();
|
||||||
if (enablePreV21AudioSessionWorkaround) {
|
if (enablePreV21AudioSessionWorkaround) {
|
||||||
@ -653,6 +667,11 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
// The current audio track can be reused for the new configuration.
|
// The current audio track can be reused for the new configuration.
|
||||||
configuration = pendingConfiguration;
|
configuration = pendingConfiguration;
|
||||||
pendingConfiguration = null;
|
pendingConfiguration = null;
|
||||||
|
if (isOffloadedPlayback(audioTrack)) {
|
||||||
|
audioTrack.setOffloadEndOfStream();
|
||||||
|
audioTrack.setOffloadDelayPadding(
|
||||||
|
configuration.trimStartFrames, configuration.trimEndFrames);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Re-apply playback parameters.
|
// Re-apply playback parameters.
|
||||||
applyPlaybackSpeedAndSkipSilence(presentationTimeUs);
|
applyPlaybackSpeedAndSkipSilence(presentationTimeUs);
|
||||||
@ -1255,14 +1274,24 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRateHz,
|
int sampleRateHz,
|
||||||
@C.Encoding int encoding,
|
@C.Encoding int encoding,
|
||||||
AudioAttributes audioAttributes) {
|
AudioAttributes audioAttributes,
|
||||||
|
int trimStartFrames,
|
||||||
|
int trimEndFrames) {
|
||||||
if (Util.SDK_INT < 29) {
|
if (Util.SDK_INT < 29) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int channelMask = getChannelConfig(channelCount, /* isInputPcm= */ false);
|
int channelMask = getChannelConfig(channelCount, /* isInputPcm= */ false);
|
||||||
AudioFormat audioFormat = getAudioFormat(sampleRateHz, channelMask, encoding);
|
AudioFormat audioFormat = getAudioFormat(sampleRateHz, channelMask, encoding);
|
||||||
return AudioManager.isOffloadedPlaybackSupported(
|
if (!AudioManager.isOffloadedPlaybackSupported(
|
||||||
audioFormat, audioAttributes.getAudioAttributesV21());
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOffloadedPlayback(AudioTrack audioTrack) {
|
private static boolean isOffloadedPlayback(AudioTrack audioTrack) {
|
||||||
@ -1579,6 +1608,8 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
public final boolean processingEnabled;
|
public final boolean processingEnabled;
|
||||||
public final boolean canApplyPlaybackParameters;
|
public final boolean canApplyPlaybackParameters;
|
||||||
public final AudioProcessor[] availableAudioProcessors;
|
public final AudioProcessor[] availableAudioProcessors;
|
||||||
|
public int trimStartFrames;
|
||||||
|
public int trimEndFrames;
|
||||||
public final boolean useOffload;
|
public final boolean useOffload;
|
||||||
|
|
||||||
public Configuration(
|
public Configuration(
|
||||||
@ -1593,6 +1624,8 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
boolean processingEnabled,
|
boolean processingEnabled,
|
||||||
boolean canApplyPlaybackParameters,
|
boolean canApplyPlaybackParameters,
|
||||||
AudioProcessor[] availableAudioProcessors,
|
AudioProcessor[] availableAudioProcessors,
|
||||||
|
int trimStartFrames,
|
||||||
|
int trimEndFrames,
|
||||||
boolean useOffload) {
|
boolean useOffload) {
|
||||||
this.isInputPcm = isInputPcm;
|
this.isInputPcm = isInputPcm;
|
||||||
this.inputPcmFrameSize = inputPcmFrameSize;
|
this.inputPcmFrameSize = inputPcmFrameSize;
|
||||||
@ -1604,6 +1637,8 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
this.processingEnabled = processingEnabled;
|
this.processingEnabled = processingEnabled;
|
||||||
this.canApplyPlaybackParameters = canApplyPlaybackParameters;
|
this.canApplyPlaybackParameters = canApplyPlaybackParameters;
|
||||||
this.availableAudioProcessors = availableAudioProcessors;
|
this.availableAudioProcessors = availableAudioProcessors;
|
||||||
|
this.trimStartFrames = trimStartFrames;
|
||||||
|
this.trimEndFrames = trimEndFrames;
|
||||||
this.useOffload = useOffload;
|
this.useOffload = useOffload;
|
||||||
|
|
||||||
// Call computeBufferSize() last as it depends on the other configuration values.
|
// Call computeBufferSize() last as it depends on the other configuration values.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user