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

Commit 11454092 authored by Glenn Kasten's avatar Glenn Kasten Committed by Android Git Automerger
Browse files

am 18f86140: Merge "Fix underruns when fast track denied due to SRC" into klp-dev

* commit '18f86140':
  Fix underruns when fast track denied due to SRC
parents 440b5a49 18f86140
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -383,8 +383,6 @@ public:
protected:
    size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
    int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
private:
    bool        mDeferWake;     // whether another releaseBuffer() is expected soon
};

// Proxy used by AudioFlinger for servicing AudioTrack
+35 −32
Original line number Diff line number Diff line
@@ -815,12 +815,29 @@ status_t AudioTrack::createTrack_l(
        return NO_INIT;
    }

    // Not all of these values are needed under all conditions, but it is easier to get them all

    uint32_t afLatency;
    if ((status = AudioSystem::getLatency(output, streamType, &afLatency)) != NO_ERROR) {
    status = AudioSystem::getLatency(output, streamType, &afLatency);
    if (status != NO_ERROR) {
        ALOGE("getLatency(%d) failed status %d", output, status);
        return NO_INIT;
    }

    size_t afFrameCount;
    status = AudioSystem::getFrameCount(output, streamType, &afFrameCount);
    if (status != NO_ERROR) {
        ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status);
        return NO_INIT;
    }

    uint32_t afSampleRate;
    status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate);
    if (status != NO_ERROR) {
        ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType, status);
        return NO_INIT;
    }

    // Client decides whether the track is TIMED (see below), but can only express a preference
    // for FAST.  Server will perform additional tests.
    if ((flags & AUDIO_OUTPUT_FLAG_FAST) && !(
@@ -836,6 +853,14 @@ status_t AudioTrack::createTrack_l(
    }
    ALOGV("createTrack_l() output %d afLatency %d", output, afLatency);

    // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where
    //  n = 1   fast track; nBuffering is ignored
    //  n = 2   normal track, no sample rate conversion
    //  n = 3   normal track, with sample rate conversion
    //          (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering)
    //  n > 3   very high latency or very small notification interval; nBuffering is ignored
    const uint32_t nBuffering = (sampleRate == afSampleRate) ? 2 : 3;

    mNotificationFramesAct = mNotificationFramesReq;

    if (!audio_is_linear_pcm(format)) {
@@ -844,13 +869,6 @@ status_t AudioTrack::createTrack_l(
            // Same comment as below about ignoring frameCount parameter for set()
            frameCount = sharedBuffer->size();
        } else if (frameCount == 0) {
            size_t afFrameCount;
            status = AudioSystem::getFrameCount(output, streamType, &afFrameCount);
            if (status != NO_ERROR) {
                ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType,
                        status);
                return NO_INIT;
            }
            frameCount = afFrameCount;
        }
        if (mNotificationFramesAct != frameCount) {
@@ -880,26 +898,13 @@ status_t AudioTrack::createTrack_l(
    } else if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) {

        // FIXME move these calculations and associated checks to server
        uint32_t afSampleRate;
        status = AudioSystem::getSamplingRate(output, streamType, &afSampleRate);
        if (status != NO_ERROR) {
            ALOGE("getSamplingRate(output=%d, streamType=%d) status %d", output, streamType,
                    status);
            return NO_INIT;
        }
        size_t afFrameCount;
        status = AudioSystem::getFrameCount(output, streamType, &afFrameCount);
        if (status != NO_ERROR) {
            ALOGE("getFrameCount(output=%d, streamType=%d) status %d", output, streamType, status);
            return NO_INIT;
        }

        // Ensure that buffer depth covers at least audio hardware latency
        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
        ALOGV("afFrameCount=%d, minBufCount=%d, afSampleRate=%u, afLatency=%d",
                afFrameCount, minBufCount, afSampleRate, afLatency);
        if (minBufCount <= 2) {
            minBufCount = sampleRate == afSampleRate ? 2 : 3;
        if (minBufCount <= nBuffering) {
            minBufCount = nBuffering;
        }

        size_t minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
@@ -909,18 +914,16 @@ status_t AudioTrack::createTrack_l(

        if (frameCount == 0) {
            frameCount = minFrameCount;
        }
        // Make sure that application is notified with sufficient margin
        // before underrun
        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) {
            mNotificationFramesAct = frameCount/2;
        }
        if (frameCount < minFrameCount) {
        } else if (frameCount < minFrameCount) {
            // not ALOGW because it happens all the time when playing key clicks over A2DP
            ALOGV("Minimum buffer size corrected from %d to %d",
                     frameCount, minFrameCount);
            frameCount = minFrameCount;
        }
        // Make sure that application is notified with sufficient margin before underrun
        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
            mNotificationFramesAct = frameCount/nBuffering;
        }

    } else {
        // For fast tracks, the frame count calculations and checks are done by server
@@ -1001,8 +1004,8 @@ status_t AudioTrack::createTrack_l(
            flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST);
            mFlags = flags;
            if (sharedBuffer == 0) {
                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) {
                    mNotificationFramesAct = frameCount/2;
                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
                    mNotificationFramesAct = frameCount/nBuffering;
                }
            }
        }
+2 −5
Original line number Diff line number Diff line
@@ -481,7 +481,7 @@ size_t StaticAudioTrackClientProxy::getBufferPosition()
ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
        size_t frameSize, bool isOut, bool clientInServer)
    : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
      mAvailToClient(0), mFlush(0), mDeferWake(false)
      mAvailToClient(0), mFlush(0)
{
}

@@ -559,9 +559,6 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer)
            &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL;
    buffer->mNonContig = availToServer - part1;
    mUnreleased = part1;
    // optimization to avoid waking up the client too early
    // FIXME need to test for recording
    mDeferWake = part1 < ask && availToServer >= ask;
    return part1 > 0 ? NO_ERROR : WOULD_BLOCK;
    }
no_init:
@@ -607,7 +604,7 @@ void ServerProxy::releaseBuffer(Buffer* buffer)
        minimum = half;
    }
    // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time
    if (!mIsOut || (!mDeferWake && mAvailToClient + stepCount >= minimum)) {
    if (!mIsOut || (mAvailToClient + stepCount >= minimum)) {
        ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum);
        int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
        if (!(old & CBLK_FUTEX_WAKE)) {