Merge "AAudio: Improve buffer size calculations" into main
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 9b1ad72..8d9bf20 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -239,31 +239,35 @@
}
aaudio_result_t AudioStreamInternal::configureDataInformation(int32_t callbackFrames) {
- int32_t deviceFramesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
+ int32_t originalFramesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
+ int32_t deviceFramesPerBurst = originalFramesPerBurst;
// Scale up the burst size to meet the minimum equivalent in microseconds.
// This is to avoid waking the CPU too often when the HW burst is very small
// or at high sample rates. The actual number of frames that we call back to
// the app with will be 0 < N <= framesPerBurst so round up the division.
- int32_t framesPerBurst = (static_cast<int64_t>(deviceFramesPerBurst) * getSampleRate() +
- getDeviceSampleRate() - 1) / getDeviceSampleRate();
int32_t burstMicros = 0;
const int32_t burstMinMicros = android::AudioSystem::getAAudioHardwareBurstMinUsec();
do {
if (burstMicros > 0) { // skip first loop
deviceFramesPerBurst *= 2;
- framesPerBurst *= 2;
}
- burstMicros = framesPerBurst * static_cast<int64_t>(1000000) / getSampleRate();
+ burstMicros = deviceFramesPerBurst * static_cast<int64_t>(1000000) / getDeviceSampleRate();
} while (burstMicros < burstMinMicros);
ALOGD("%s() original HW burst = %d, minMicros = %d => SW burst = %d\n",
- __func__, deviceFramesPerBurst, burstMinMicros, framesPerBurst);
+ __func__, originalFramesPerBurst, burstMinMicros, deviceFramesPerBurst);
// Validate final burst size.
- if (framesPerBurst < MIN_FRAMES_PER_BURST || framesPerBurst > MAX_FRAMES_PER_BURST) {
- ALOGE("%s - framesPerBurst out of range = %d", __func__, framesPerBurst);
+ if (deviceFramesPerBurst < MIN_FRAMES_PER_BURST
+ || deviceFramesPerBurst > MAX_FRAMES_PER_BURST) {
+ ALOGE("%s - deviceFramesPerBurst out of range = %d", __func__, deviceFramesPerBurst);
return AAUDIO_ERROR_OUT_OF_RANGE;
}
+
+ // Calculate the application framesPerBurst from the deviceFramesPerBurst
+ int32_t framesPerBurst = (static_cast<int64_t>(deviceFramesPerBurst) * getSampleRate() +
+ getDeviceSampleRate() - 1) / getDeviceSampleRate();
+
setDeviceFramesPerBurst(deviceFramesPerBurst);
setFramesPerBurst(framesPerBurst); // only save good value
@@ -894,43 +898,30 @@
}
aaudio_result_t AudioStreamInternal::setBufferSize(int32_t requestedFrames) {
- int32_t adjustedFrames = requestedFrames;
const int32_t maximumSize = getBufferCapacity() - getFramesPerBurst();
- // Minimum size should be a multiple number of bursts.
- const int32_t minimumSize = 1 * getFramesPerBurst();
+ int32_t adjustedFrames = std::min(requestedFrames, maximumSize);
+ // Buffer sizes should always be a multiple of framesPerBurst.
+ int32_t numBursts = (static_cast<int64_t>(adjustedFrames) + getFramesPerBurst() - 1) /
+ getFramesPerBurst();
- // Clip to minimum size so that rounding up will work better.
- adjustedFrames = std::max(minimumSize, adjustedFrames);
-
- // Prevent arithmetic overflow by clipping before we round.
- if (adjustedFrames >= maximumSize) {
- adjustedFrames = maximumSize;
- } else {
- // Round to the next highest burst size.
- int32_t numBursts = (static_cast<int64_t>(adjustedFrames) + getFramesPerBurst() - 1) /
- getFramesPerBurst();
- adjustedFrames = numBursts * getFramesPerBurst();
- // Clip just in case maximumSize is not a multiple of getFramesPerBurst().
- adjustedFrames = std::min(maximumSize, adjustedFrames);
+ // Use at least one burst
+ if (numBursts == 0) {
+ numBursts = 1;
}
if (mAudioEndpoint) {
// Clip against the actual size from the endpoint.
int32_t actualFramesDevice = 0;
- int32_t maximumFramesDevice = (static_cast<int64_t>(maximumSize) * getDeviceSampleRate()
- + getSampleRate() - 1) / getSampleRate();
+ int32_t maximumFramesDevice = getDeviceBufferCapacity() - getDeviceFramesPerBurst();
// Set to maximum size so we can write extra data when ready in order to reduce glitches.
// The amount we keep in the buffer is controlled by mBufferSizeInFrames.
mAudioEndpoint->setBufferSizeInFrames(maximumFramesDevice, &actualFramesDevice);
- int32_t actualFrames = (static_cast<int64_t>(actualFramesDevice) * getSampleRate() +
- getDeviceSampleRate() - 1) / getDeviceSampleRate();
- // actualFrames should be <= actual maximum size of endpoint
- adjustedFrames = std::min(actualFrames, adjustedFrames);
+ int32_t actualNumBursts = actualFramesDevice / getDeviceFramesPerBurst();
+ numBursts = std::min(numBursts, actualNumBursts);
}
- const int32_t bufferSizeInFrames = adjustedFrames;
- const int32_t deviceBufferSizeInFrames = static_cast<int64_t>(bufferSizeInFrames) *
- getDeviceSampleRate() / getSampleRate();
+ const int32_t bufferSizeInFrames = numBursts * getFramesPerBurst();
+ const int32_t deviceBufferSizeInFrames = numBursts * getDeviceFramesPerBurst();
if (deviceBufferSizeInFrames != mDeviceBufferSizeInFrames) {
android::mediametrics::LogItem(mMetricsId)