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

Commit 18f86140 authored by Glenn Kasten's avatar Glenn Kasten Committed by Android (Google) Code Review
Browse files

Merge "Fix underruns when fast track denied due to SRC" into klp-dev

parents bc910e5c ce8828a0
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)) {