Loading services/audioflinger/RecordTracks.h +0 −8 Original line number Diff line number Diff line Loading @@ -67,14 +67,6 @@ private: bool mOverflow; // overflow on most recent attempt to fill client buffer size_t mRsmpInUnrel; // unreleased frames remaining from // most recent getNextBuffer // for debug only // rolling counter that is never cleared int32_t mRsmpInFront; // next available frame AudioBufferProvider::Buffer mSink; // references client's buffer sink in shared memory // sync event triggering actual audio capture. Frames read before this event will Loading services/audioflinger/Threads.cpp +56 −28 Original line number Diff line number Diff line Loading @@ -5593,6 +5593,7 @@ reacquire_wakelock: continue; } // TODO: This code probably should be moved to RecordTrack. // TODO: Update the activeTrack buffer converter in case of reconfigure. enum { Loading @@ -5609,24 +5610,14 @@ reacquire_wakelock: size_t framesOut = activeTrack->mSink.frameCount; LOG_ALWAYS_FATAL_IF((status == OK) != (framesOut > 0)); int32_t front = activeTrack->mRsmpInFront; ssize_t filled = rear - front; // check available frames and handle overrun conditions // if the record track isn't draining fast enough. bool hasOverrun; size_t framesIn; if (filled < 0) { // should not happen, but treat like a massive overrun and re-sync framesIn = 0; activeTrack->mRsmpInFront = rear; overrun = OVERRUN_TRUE; } else if ((size_t) filled <= mRsmpInFrames) { framesIn = (size_t) filled; } else { // client is not keeping up with server, but give it latest data framesIn = mRsmpInFrames; activeTrack->mRsmpInFront = front = rear - framesIn; activeTrack->mResamplerBufferProvider->sync(&framesIn, &hasOverrun); if (hasOverrun) { overrun = OVERRUN_TRUE; } if (framesOut == 0 || framesIn == 0) { break; } Loading Loading @@ -5942,8 +5933,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // was initialized to some value closer to the thread's mRsmpInFront, then the track could // see previously buffered data before it called start(), but with greater risk of overrun. recordTrack->mRsmpInFront = mRsmpInRear; recordTrack->mRsmpInUnrel = 0; recordTrack->mResamplerBufferProvider->reset(); // clear any converter state as new data will be discontinuous recordTrack->mRecordBufferConverter->reset(); recordTrack->mState = TrackBase::STARTING_2; Loading Loading @@ -6121,12 +6111,52 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args write(fd, result.string(), result.size()); } void AudioFlinger::RecordThread::ResamplerBufferProvider::reset() { sp<ThreadBase> threadBase = mRecordTrack->mThread.promote(); RecordThread *recordThread = (RecordThread *) threadBase.get(); mRsmpInFront = recordThread->mRsmpInRear; mRsmpInUnrel = 0; } void AudioFlinger::RecordThread::ResamplerBufferProvider::sync( size_t *framesAvailable, bool *hasOverrun) { sp<ThreadBase> threadBase = mRecordTrack->mThread.promote(); RecordThread *recordThread = (RecordThread *) threadBase.get(); const int32_t rear = recordThread->mRsmpInRear; const int32_t front = mRsmpInFront; const ssize_t filled = rear - front; size_t framesIn; bool overrun = false; if (filled < 0) { // should not happen, but treat like a massive overrun and re-sync framesIn = 0; mRsmpInFront = rear; overrun = true; } else if ((size_t) filled <= recordThread->mRsmpInFrames) { framesIn = (size_t) filled; } else { // client is not keeping up with server, but give it latest data framesIn = recordThread->mRsmpInFrames; mRsmpInFront = /* front = */ rear - framesIn; overrun = true; } if (framesAvailable != NULL) { *framesAvailable = framesIn; } if (hasOverrun != NULL) { *hasOverrun = overrun; } } // AudioBufferProvider interface status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( AudioBufferProvider::Buffer* buffer, int64_t pts __unused) { RecordTrack *activeTrack = mRecordTrack; sp<ThreadBase> threadBase = activeTrack->mThread.promote(); sp<ThreadBase> threadBase = mRecordTrack->mThread.promote(); if (threadBase == 0) { buffer->frameCount = 0; buffer->raw = NULL; Loading @@ -6134,7 +6164,7 @@ status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( } RecordThread *recordThread = (RecordThread *) threadBase.get(); int32_t rear = recordThread->mRsmpInRear; int32_t front = activeTrack->mRsmpInFront; int32_t front = mRsmpInFront; ssize_t filled = rear - front; // FIXME should not be P2 (don't want to increase latency) // FIXME if client not keeping up, discard Loading @@ -6151,17 +6181,16 @@ status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( part1 = ask; } if (part1 == 0) { // Higher-level should keep mRsmpInBuffer full, and not call resampler if empty LOG_ALWAYS_FATAL("RecordThread::getNextBuffer() starved"); // out of data is fine since the resampler will return a short-count. buffer->raw = NULL; buffer->frameCount = 0; activeTrack->mRsmpInUnrel = 0; mRsmpInUnrel = 0; return NOT_ENOUGH_DATA; } buffer->raw = recordThread->mRsmpInBuffer + front * recordThread->mChannelCount; buffer->frameCount = part1; activeTrack->mRsmpInUnrel = part1; mRsmpInUnrel = part1; return NO_ERROR; } Loading @@ -6169,14 +6198,13 @@ status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer( AudioBufferProvider::Buffer* buffer) { RecordTrack *activeTrack = mRecordTrack; size_t stepCount = buffer->frameCount; if (stepCount == 0) { return; } ALOG_ASSERT(stepCount <= activeTrack->mRsmpInUnrel); activeTrack->mRsmpInUnrel -= stepCount; activeTrack->mRsmpInFront += stepCount; ALOG_ASSERT(stepCount <= mRsmpInUnrel); mRsmpInUnrel -= stepCount; mRsmpInFront += stepCount; buffer->raw = NULL; buffer->frameCount = 0; } Loading services/audioflinger/Threads.h +31 −2 Original line number Diff line number Diff line Loading @@ -1036,17 +1036,46 @@ class RecordThread : public ThreadBase public: class RecordTrack; /* The ResamplerBufferProvider is used to retrieve recorded input data from the * RecordThread. It maintains local state on the relative position of the read * position of the RecordTrack compared with the RecordThread. */ class ResamplerBufferProvider : public AudioBufferProvider // derives from AudioBufferProvider interface for use by resampler { public: ResamplerBufferProvider(RecordTrack* recordTrack) : mRecordTrack(recordTrack) { } ResamplerBufferProvider(RecordTrack* recordTrack) : mRecordTrack(recordTrack), mRsmpInUnrel(0), mRsmpInFront(0) { } virtual ~ResamplerBufferProvider() { } // called to set the ResamplerBufferProvider to head of the RecordThread data buffer, // skipping any previous data read from the hal. virtual void reset(); /* Synchronizes RecordTrack position with the RecordThread. * Calculates available frames and handle overruns if the RecordThread * has advanced faster than the ResamplerBufferProvider has retrieved data. * TODO: why not do this for every getNextBuffer? * * Parameters * framesAvailable: pointer to optional output size_t to store record track * frames available. * hasOverrun: pointer to optional boolean, returns true if track has overrun. */ virtual void sync(size_t *framesAvailable = NULL, bool *hasOverrun = NULL); // AudioBufferProvider interface virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); private: RecordTrack * const mRecordTrack; size_t mRsmpInUnrel; // unreleased frames remaining from // most recent getNextBuffer // for debug only int32_t mRsmpInFront; // next available frame // rolling counter that is never cleared }; /* The RecordBufferConverter is used for format, channel, and sample rate Loading services/audioflinger/Tracks.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -1991,8 +1991,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE), type), mOverflow(false), // See real initialization of mRsmpInFront at RecordThread::start() mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) mFramesToDrop(0) { if (mCblk == NULL) { return; Loading Loading
services/audioflinger/RecordTracks.h +0 −8 Original line number Diff line number Diff line Loading @@ -67,14 +67,6 @@ private: bool mOverflow; // overflow on most recent attempt to fill client buffer size_t mRsmpInUnrel; // unreleased frames remaining from // most recent getNextBuffer // for debug only // rolling counter that is never cleared int32_t mRsmpInFront; // next available frame AudioBufferProvider::Buffer mSink; // references client's buffer sink in shared memory // sync event triggering actual audio capture. Frames read before this event will Loading
services/audioflinger/Threads.cpp +56 −28 Original line number Diff line number Diff line Loading @@ -5593,6 +5593,7 @@ reacquire_wakelock: continue; } // TODO: This code probably should be moved to RecordTrack. // TODO: Update the activeTrack buffer converter in case of reconfigure. enum { Loading @@ -5609,24 +5610,14 @@ reacquire_wakelock: size_t framesOut = activeTrack->mSink.frameCount; LOG_ALWAYS_FATAL_IF((status == OK) != (framesOut > 0)); int32_t front = activeTrack->mRsmpInFront; ssize_t filled = rear - front; // check available frames and handle overrun conditions // if the record track isn't draining fast enough. bool hasOverrun; size_t framesIn; if (filled < 0) { // should not happen, but treat like a massive overrun and re-sync framesIn = 0; activeTrack->mRsmpInFront = rear; overrun = OVERRUN_TRUE; } else if ((size_t) filled <= mRsmpInFrames) { framesIn = (size_t) filled; } else { // client is not keeping up with server, but give it latest data framesIn = mRsmpInFrames; activeTrack->mRsmpInFront = front = rear - framesIn; activeTrack->mResamplerBufferProvider->sync(&framesIn, &hasOverrun); if (hasOverrun) { overrun = OVERRUN_TRUE; } if (framesOut == 0 || framesIn == 0) { break; } Loading Loading @@ -5942,8 +5933,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // was initialized to some value closer to the thread's mRsmpInFront, then the track could // see previously buffered data before it called start(), but with greater risk of overrun. recordTrack->mRsmpInFront = mRsmpInRear; recordTrack->mRsmpInUnrel = 0; recordTrack->mResamplerBufferProvider->reset(); // clear any converter state as new data will be discontinuous recordTrack->mRecordBufferConverter->reset(); recordTrack->mState = TrackBase::STARTING_2; Loading Loading @@ -6121,12 +6111,52 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args write(fd, result.string(), result.size()); } void AudioFlinger::RecordThread::ResamplerBufferProvider::reset() { sp<ThreadBase> threadBase = mRecordTrack->mThread.promote(); RecordThread *recordThread = (RecordThread *) threadBase.get(); mRsmpInFront = recordThread->mRsmpInRear; mRsmpInUnrel = 0; } void AudioFlinger::RecordThread::ResamplerBufferProvider::sync( size_t *framesAvailable, bool *hasOverrun) { sp<ThreadBase> threadBase = mRecordTrack->mThread.promote(); RecordThread *recordThread = (RecordThread *) threadBase.get(); const int32_t rear = recordThread->mRsmpInRear; const int32_t front = mRsmpInFront; const ssize_t filled = rear - front; size_t framesIn; bool overrun = false; if (filled < 0) { // should not happen, but treat like a massive overrun and re-sync framesIn = 0; mRsmpInFront = rear; overrun = true; } else if ((size_t) filled <= recordThread->mRsmpInFrames) { framesIn = (size_t) filled; } else { // client is not keeping up with server, but give it latest data framesIn = recordThread->mRsmpInFrames; mRsmpInFront = /* front = */ rear - framesIn; overrun = true; } if (framesAvailable != NULL) { *framesAvailable = framesIn; } if (hasOverrun != NULL) { *hasOverrun = overrun; } } // AudioBufferProvider interface status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( AudioBufferProvider::Buffer* buffer, int64_t pts __unused) { RecordTrack *activeTrack = mRecordTrack; sp<ThreadBase> threadBase = activeTrack->mThread.promote(); sp<ThreadBase> threadBase = mRecordTrack->mThread.promote(); if (threadBase == 0) { buffer->frameCount = 0; buffer->raw = NULL; Loading @@ -6134,7 +6164,7 @@ status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( } RecordThread *recordThread = (RecordThread *) threadBase.get(); int32_t rear = recordThread->mRsmpInRear; int32_t front = activeTrack->mRsmpInFront; int32_t front = mRsmpInFront; ssize_t filled = rear - front; // FIXME should not be P2 (don't want to increase latency) // FIXME if client not keeping up, discard Loading @@ -6151,17 +6181,16 @@ status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( part1 = ask; } if (part1 == 0) { // Higher-level should keep mRsmpInBuffer full, and not call resampler if empty LOG_ALWAYS_FATAL("RecordThread::getNextBuffer() starved"); // out of data is fine since the resampler will return a short-count. buffer->raw = NULL; buffer->frameCount = 0; activeTrack->mRsmpInUnrel = 0; mRsmpInUnrel = 0; return NOT_ENOUGH_DATA; } buffer->raw = recordThread->mRsmpInBuffer + front * recordThread->mChannelCount; buffer->frameCount = part1; activeTrack->mRsmpInUnrel = part1; mRsmpInUnrel = part1; return NO_ERROR; } Loading @@ -6169,14 +6198,13 @@ status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer( void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer( AudioBufferProvider::Buffer* buffer) { RecordTrack *activeTrack = mRecordTrack; size_t stepCount = buffer->frameCount; if (stepCount == 0) { return; } ALOG_ASSERT(stepCount <= activeTrack->mRsmpInUnrel); activeTrack->mRsmpInUnrel -= stepCount; activeTrack->mRsmpInFront += stepCount; ALOG_ASSERT(stepCount <= mRsmpInUnrel); mRsmpInUnrel -= stepCount; mRsmpInFront += stepCount; buffer->raw = NULL; buffer->frameCount = 0; } Loading
services/audioflinger/Threads.h +31 −2 Original line number Diff line number Diff line Loading @@ -1036,17 +1036,46 @@ class RecordThread : public ThreadBase public: class RecordTrack; /* The ResamplerBufferProvider is used to retrieve recorded input data from the * RecordThread. It maintains local state on the relative position of the read * position of the RecordTrack compared with the RecordThread. */ class ResamplerBufferProvider : public AudioBufferProvider // derives from AudioBufferProvider interface for use by resampler { public: ResamplerBufferProvider(RecordTrack* recordTrack) : mRecordTrack(recordTrack) { } ResamplerBufferProvider(RecordTrack* recordTrack) : mRecordTrack(recordTrack), mRsmpInUnrel(0), mRsmpInFront(0) { } virtual ~ResamplerBufferProvider() { } // called to set the ResamplerBufferProvider to head of the RecordThread data buffer, // skipping any previous data read from the hal. virtual void reset(); /* Synchronizes RecordTrack position with the RecordThread. * Calculates available frames and handle overruns if the RecordThread * has advanced faster than the ResamplerBufferProvider has retrieved data. * TODO: why not do this for every getNextBuffer? * * Parameters * framesAvailable: pointer to optional output size_t to store record track * frames available. * hasOverrun: pointer to optional boolean, returns true if track has overrun. */ virtual void sync(size_t *framesAvailable = NULL, bool *hasOverrun = NULL); // AudioBufferProvider interface virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); private: RecordTrack * const mRecordTrack; size_t mRsmpInUnrel; // unreleased frames remaining from // most recent getNextBuffer // for debug only int32_t mRsmpInFront; // next available frame // rolling counter that is never cleared }; /* The RecordBufferConverter is used for format, channel, and sample rate Loading
services/audioflinger/Tracks.cpp +1 −2 Original line number Diff line number Diff line Loading @@ -1991,8 +1991,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( ((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE), type), mOverflow(false), // See real initialization of mRsmpInFront at RecordThread::start() mRsmpInUnrel(0), mRsmpInFront(0), mFramesToDrop(0), mResamplerBufferProvider(NULL) mFramesToDrop(0) { if (mCblk == NULL) { return; Loading