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

Commit a1472d98 authored by Marco Nelissen's avatar Marco Nelissen
Browse files

Make AudioTrack/AudioRecord handle more than 2^32 frames

b/6160363
Change-Id: I471815012c6a113ec2c4dd7676e8fa288a70bc76
parent 40a1da57
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -577,7 +577,7 @@ create_new_record:
    uint32_t u = cblk->user;
    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;

    if (u + framesReq > bufferEnd) {
    if (framesReq > bufferEnd - u) {
        framesReq = bufferEnd - u;
    }

+27 −8
Original line number Diff line number Diff line
@@ -952,7 +952,7 @@ create_new_track:
    uint32_t u = cblk->user;
    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;

    if (u + framesReq > bufferEnd) {
    if (framesReq > bufferEnd - u) {
        framesReq = bufferEnd - u;
    }

@@ -1382,8 +1382,9 @@ audio_track_cblk_t::audio_track_cblk_t()

uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
{
    uint32_t u = user;
    ALOGV("stepuser %08x %08x %d", user, server, frameCount);

    uint32_t u = user;
    u += frameCount;
    // Ensure that user is never ahead of server for AudioRecord
    if (flags & CBLK_DIRECTION_MSK) {
@@ -1392,12 +1393,19 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
        }
    } else if (u > server) {
        ALOGW("stepServer occurred after track reset");
        ALOGW("stepUser occurred after track reset");
        u = server;
    }

    if (u >= userBase + this->frameCount) {
        userBase += this->frameCount;
    uint32_t fc = this->frameCount;
    if (u >= fc) {
        // common case, user didn't just wrap
        if (u - fc >= userBase ) {
            userBase += fc;
        }
    } else if (u >= userBase + fc) {
        // user just wrapped
        userBase += fc;
    }

    user = u;
@@ -1412,12 +1420,15 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)

bool audio_track_cblk_t::stepServer(uint32_t frameCount)
{
    ALOGV("stepserver %08x %08x %d", user, server, frameCount);

    if (!tryLock()) {
        ALOGW("stepServer() could not lock cblk");
        return false;
    }

    uint32_t s = server;
    bool flushed = (s == user);

    s += frameCount;
    if (flags & CBLK_DIRECTION_MSK) {
@@ -1430,7 +1441,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
        // while the mixer is processing a block: in this case,
        // stepServer() is called After the flush() has reset u & s and
        // we have s > u
        if (s > user) {
        if (flushed) {
            ALOGW("stepServer occurred after track reset");
            s = user;
        }
@@ -1444,8 +1455,16 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
            loopStart = UINT_MAX;
        }
    }
    if (s >= serverBase + this->frameCount) {
        serverBase += this->frameCount;

    uint32_t fc = this->frameCount;
    if (s >= fc) {
        // common case, server didn't just wrap
        if (s - fc >= serverBase ) {
            serverBase += fc;
        }
    } else if (s >= serverBase + fc) {
        // server just wrapped
        serverBase += fc;
    }

    server = s;
+14 −4
Original line number Diff line number Diff line
@@ -3409,6 +3409,11 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase(
                // clear all buffers
                mCblk->frameCount = frameCount;
                mCblk->sampleRate = sampleRate;
// uncomment the following lines to quickly test 32-bit wraparound
//                mCblk->user = 0xffff0000;
//                mCblk->server = 0xffff0000;
//                mCblk->userBase = 0xffff0000;
//                mCblk->serverBase = 0xffff0000;
                mChannelCount = channelCount;
                mChannelMask = channelMask;
                if (sharedBuffer == 0) {
@@ -3434,6 +3439,11 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase(
        // clear all buffers
        mCblk->frameCount = frameCount;
        mCblk->sampleRate = sampleRate;
// uncomment the following lines to quickly test 32-bit wraparound
//        mCblk->user = 0xffff0000;
//        mCblk->server = 0xffff0000;
//        mCblk->userBase = 0xffff0000;
//        mCblk->serverBase = 0xffff0000;
        mChannelCount = channelCount;
        mChannelMask = channelMask;
        mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
@@ -3513,7 +3523,7 @@ void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t f
    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
        ((unsigned long)bufferStart & (unsigned long)(frameSize - 1))) {
        ALOGE("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
                server %d, serverBase %d, user %d, userBase %d",
                server %u, serverBase %u, user %u, userBase %u",
                bufferStart, bufferEnd, mBuffer, mBufferEnd,
                cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
        return NULL;
@@ -3656,7 +3666,7 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
        if (framesReq > framesReady) {
            framesReq = framesReady;
        }
        if (s + framesReq > bufferEnd) {
        if (framesReq > bufferEnd - s) {
            framesReq = bufferEnd - s;
        }

@@ -4323,7 +4333,7 @@ status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvi
        if (framesReq > framesAvail) {
            framesReq = framesAvail;
        }
        if (s + framesReq > bufferEnd) {
        if (framesReq > bufferEnd - s) {
            framesReq = bufferEnd - s;
        }

@@ -4596,7 +4606,7 @@ status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProv
    uint32_t u = cblk->user;
    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;

    if (u + framesReq > bufferEnd) {
    if (framesReq > bufferEnd - u) {
        framesReq = bufferEnd - u;
    }