Loading media/libmedia/AudioRecord.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -722,9 +722,12 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) // Manage overrun callback if (mActive && (cblk->framesAvailable() == 0)) { LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); AutoMutex _l(cblk->lock); if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { mCbf(EVENT_OVERRUN, mUserData, 0); cblk->flags |= CBLK_UNDERRUN_ON; cblk->lock.unlock(); mCbf(EVENT_OVERRUN, mUserData, 0); cblk->lock.lock(); } } Loading media/libmedia/AudioTrack.cpp +22 −8 Original line number Diff line number Diff line Loading @@ -329,6 +329,7 @@ void AudioTrack::start() if (mActive == 0) { mActive = 1; mNewPosition = cblk->server + mUpdatePeriod; cblk->lock.lock(); cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; cblk->waitTimeMs = 0; cblk->flags &= ~CBLK_DISABLED_ON; Loading @@ -339,7 +340,6 @@ void AudioTrack::start() } LOGV("start %p before lock cblk %p", this, mCblk); cblk->lock.lock(); if (!(cblk->flags & CBLK_INVALID_MSK)) { cblk->lock.unlock(); status = mAudioTrack->start(); Loading Loading @@ -892,10 +892,15 @@ create_new_track: } // restart track if it was disabled by audioflinger due to previous underrun if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) { AutoMutex _l(cblk->lock); if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) { cblk->flags &= ~CBLK_DISABLED_ON; cblk->lock.unlock(); LOGW("obtainBuffer() track %p disabled, restarting", this); mAudioTrack->start(); cblk->lock.lock(); } } cblk->waitTimeMs = 0; Loading Loading @@ -957,9 +962,10 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) ssize_t written = 0; const int8_t *src = (const int8_t *)buffer; Buffer audioBuffer; size_t frameSz = (size_t)frameSize(); do { audioBuffer.frameCount = userSize/frameSize(); audioBuffer.frameCount = userSize/frameSz; // Calling obtainBuffer() with a negative wait count causes // an (almost) infinite wait time. Loading Loading @@ -991,7 +997,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) written += toWrite; releaseBuffer(&audioBuffer); } while (userSize); } while (userSize >= frameSz); return written; } Loading @@ -1015,12 +1021,15 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Manage underrun callback if (mActive && (cblk->framesReady() == 0)) { LOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); AutoMutex _l(cblk->lock); if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { cblk->flags |= CBLK_UNDERRUN_ON; cblk->lock.unlock(); mCbf(EVENT_UNDERRUN, mUserData, 0); if (cblk->server == cblk->frameCount) { mCbf(EVENT_BUFFER_END, mUserData, 0); } cblk->flags |= CBLK_UNDERRUN_ON; cblk->lock.lock(); if (mSharedBuffer != 0) return false; } } Loading Loading @@ -1279,7 +1288,12 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) this->user = u; // Clear flow control error condition as new data has been written/read to/from buffer. if (flags & CBLK_UNDERRUN_MSK) { AutoMutex _l(lock); if (flags & CBLK_UNDERRUN_MSK) { flags &= ~CBLK_UNDERRUN_MSK; } } return u; } Loading services/audioflinger/AudioFlinger.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -1738,7 +1738,10 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this); tracksToRemove->add(track); // indicate to client process that the track was disabled because of underrun { AutoMutex _l(cblk->lock); cblk->flags |= CBLK_DISABLED_ON; } } else if (mixerStatus != MIXER_TRACKS_READY) { mixerStatus = MIXER_TRACKS_ENABLED; } Loading Loading @@ -1787,10 +1790,9 @@ void AudioFlinger::MixerThread::invalidateTracks(int streamType) for (size_t i = 0; i < size; i++) { sp<Track> t = mTracks[i]; if (t->type() == streamType) { t->mCblk->lock.lock(); AutoMutex _lcblk(t->mCblk->lock); t->mCblk->flags |= CBLK_INVALID_ON; t->mCblk->cv.signal(); t->mCblk->lock.unlock(); } } } Loading Loading @@ -2948,6 +2950,7 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { if (mCblk->framesReady() >= mCblk->frameCount || (mCblk->flags & CBLK_FORCEREADY_MSK)) { AutoMutex _l(mCblk->lock); mFillingUpStatus = FS_FILLED; mCblk->flags &= ~CBLK_FORCEREADY_MSK; return true; Loading Loading @@ -3063,19 +3066,18 @@ void AudioFlinger::PlaybackThread::Track::flush() // STOPPED state mState = STOPPED; mCblk->lock.lock(); // NOTE: reset() will reset cblk->user and cblk->server with // the risk that at the same time, the AudioMixer is trying to read // data. In this case, getNextBuffer() would return a NULL pointer // as audio buffer => the AudioMixer code MUST always test that pointer // returned by getNextBuffer() is not NULL! reset(); mCblk->lock.unlock(); } } void AudioFlinger::PlaybackThread::Track::reset() { AutoMutex _l(mCblk->lock); // Do not reset twice to avoid discarding data written just after a flush and before // the audioflinger thread detects the track is stopped. if (!mResetDone) { Loading Loading @@ -3209,12 +3211,15 @@ void AudioFlinger::RecordThread::RecordTrack::stop() if (thread != 0) { RecordThread *recordThread = (RecordThread *)thread.get(); recordThread->stop(this); { AutoMutex _l(mCblk->lock); TrackBase::reset(); // Force overerrun condition to avoid false overrun callback until first data is // read from buffer mCblk->flags |= CBLK_UNDERRUN_ON; } } } void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) { Loading Loading
media/libmedia/AudioRecord.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -722,9 +722,12 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) // Manage overrun callback if (mActive && (cblk->framesAvailable() == 0)) { LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); AutoMutex _l(cblk->lock); if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { mCbf(EVENT_OVERRUN, mUserData, 0); cblk->flags |= CBLK_UNDERRUN_ON; cblk->lock.unlock(); mCbf(EVENT_OVERRUN, mUserData, 0); cblk->lock.lock(); } } Loading
media/libmedia/AudioTrack.cpp +22 −8 Original line number Diff line number Diff line Loading @@ -329,6 +329,7 @@ void AudioTrack::start() if (mActive == 0) { mActive = 1; mNewPosition = cblk->server + mUpdatePeriod; cblk->lock.lock(); cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; cblk->waitTimeMs = 0; cblk->flags &= ~CBLK_DISABLED_ON; Loading @@ -339,7 +340,6 @@ void AudioTrack::start() } LOGV("start %p before lock cblk %p", this, mCblk); cblk->lock.lock(); if (!(cblk->flags & CBLK_INVALID_MSK)) { cblk->lock.unlock(); status = mAudioTrack->start(); Loading Loading @@ -892,10 +892,15 @@ create_new_track: } // restart track if it was disabled by audioflinger due to previous underrun if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) { AutoMutex _l(cblk->lock); if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) { cblk->flags &= ~CBLK_DISABLED_ON; cblk->lock.unlock(); LOGW("obtainBuffer() track %p disabled, restarting", this); mAudioTrack->start(); cblk->lock.lock(); } } cblk->waitTimeMs = 0; Loading Loading @@ -957,9 +962,10 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) ssize_t written = 0; const int8_t *src = (const int8_t *)buffer; Buffer audioBuffer; size_t frameSz = (size_t)frameSize(); do { audioBuffer.frameCount = userSize/frameSize(); audioBuffer.frameCount = userSize/frameSz; // Calling obtainBuffer() with a negative wait count causes // an (almost) infinite wait time. Loading Loading @@ -991,7 +997,7 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) written += toWrite; releaseBuffer(&audioBuffer); } while (userSize); } while (userSize >= frameSz); return written; } Loading @@ -1015,12 +1021,15 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Manage underrun callback if (mActive && (cblk->framesReady() == 0)) { LOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); AutoMutex _l(cblk->lock); if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) { cblk->flags |= CBLK_UNDERRUN_ON; cblk->lock.unlock(); mCbf(EVENT_UNDERRUN, mUserData, 0); if (cblk->server == cblk->frameCount) { mCbf(EVENT_BUFFER_END, mUserData, 0); } cblk->flags |= CBLK_UNDERRUN_ON; cblk->lock.lock(); if (mSharedBuffer != 0) return false; } } Loading Loading @@ -1279,7 +1288,12 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) this->user = u; // Clear flow control error condition as new data has been written/read to/from buffer. if (flags & CBLK_UNDERRUN_MSK) { AutoMutex _l(lock); if (flags & CBLK_UNDERRUN_MSK) { flags &= ~CBLK_UNDERRUN_MSK; } } return u; } Loading
services/audioflinger/AudioFlinger.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -1738,7 +1738,10 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this); tracksToRemove->add(track); // indicate to client process that the track was disabled because of underrun { AutoMutex _l(cblk->lock); cblk->flags |= CBLK_DISABLED_ON; } } else if (mixerStatus != MIXER_TRACKS_READY) { mixerStatus = MIXER_TRACKS_ENABLED; } Loading Loading @@ -1787,10 +1790,9 @@ void AudioFlinger::MixerThread::invalidateTracks(int streamType) for (size_t i = 0; i < size; i++) { sp<Track> t = mTracks[i]; if (t->type() == streamType) { t->mCblk->lock.lock(); AutoMutex _lcblk(t->mCblk->lock); t->mCblk->flags |= CBLK_INVALID_ON; t->mCblk->cv.signal(); t->mCblk->lock.unlock(); } } } Loading Loading @@ -2948,6 +2950,7 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { if (mCblk->framesReady() >= mCblk->frameCount || (mCblk->flags & CBLK_FORCEREADY_MSK)) { AutoMutex _l(mCblk->lock); mFillingUpStatus = FS_FILLED; mCblk->flags &= ~CBLK_FORCEREADY_MSK; return true; Loading Loading @@ -3063,19 +3066,18 @@ void AudioFlinger::PlaybackThread::Track::flush() // STOPPED state mState = STOPPED; mCblk->lock.lock(); // NOTE: reset() will reset cblk->user and cblk->server with // the risk that at the same time, the AudioMixer is trying to read // data. In this case, getNextBuffer() would return a NULL pointer // as audio buffer => the AudioMixer code MUST always test that pointer // returned by getNextBuffer() is not NULL! reset(); mCblk->lock.unlock(); } } void AudioFlinger::PlaybackThread::Track::reset() { AutoMutex _l(mCblk->lock); // Do not reset twice to avoid discarding data written just after a flush and before // the audioflinger thread detects the track is stopped. if (!mResetDone) { Loading Loading @@ -3209,12 +3211,15 @@ void AudioFlinger::RecordThread::RecordTrack::stop() if (thread != 0) { RecordThread *recordThread = (RecordThread *)thread.get(); recordThread->stop(this); { AutoMutex _l(mCblk->lock); TrackBase::reset(); // Force overerrun condition to avoid false overrun callback until first data is // read from buffer mCblk->flags |= CBLK_UNDERRUN_ON; } } } void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) { Loading