Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b701a546 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "AAudio: Improve buffer size calculations" into main

parents ad8235ff 32d319ba
Loading
Loading
Loading
Loading
+24 −33
Original line number Diff line number Diff line
@@ -239,31 +239,35 @@ error:
}

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 @@ void AudioStreamInternal::processTimestamp(uint64_t position, int64_t time) {
}

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();

    // 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 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();
        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)