diff options
author | Glenn Kasten <gkasten@google.com> | 2012-11-06 16:15:41 -0800 |
---|---|---|
committer | Glenn Kasten <gkasten@google.com> | 2012-11-07 08:32:40 -0800 |
commit | ba85098eb31bd2637db49816f0591361211024f2 (patch) | |
tree | ac7f6e3c4d620dbbc87991dbb41944c53245c72a | |
parent | 891b11da870ad3f860c1d2610ef4d8836ed6c590 (diff) | |
download | frameworks_av-ba85098eb31bd2637db49816f0591361211024f2.zip frameworks_av-ba85098eb31bd2637db49816f0591361211024f2.tar.gz frameworks_av-ba85098eb31bd2637db49816f0591361211024f2.tar.bz2 |
Remove CBLK_DIRECTION from control block flags
This is part of a series to clean up the control block.
Change-Id: I0265fece3247356b585d4d48fbda6f37aea8a851
-rw-r--r-- | include/private/media/AudioTrackShared.h | 38 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 9 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 37 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 25 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 6 |
5 files changed, 71 insertions, 44 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 141078f..46788c4 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -34,13 +34,12 @@ namespace android { #define RESTORE_TIMEOUT_MS 5000 // Maximum waiting time for a track to be restored #define CBLK_UNDERRUN 0x01 // set: underrun (out) or overrrun (in), clear: no underrun or overrun -#define CBLK_DIRECTION 0x02 // set: cblk is for an AudioTrack, clear: for AudioRecord -#define CBLK_FORCEREADY 0x04 // set: track is considered ready immediately by AudioFlinger, +#define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger, // clear: track is ready when buffer full -#define CBLK_INVALID 0x08 // track buffer invalidated by AudioFlinger, need to re-create -#define CBLK_DISABLED 0x10 // track disabled by AudioFlinger due to underrun, need to re-start -#define CBLK_RESTORING 0x20 // track is being restored after invalidation by AudioFlinger -#define CBLK_RESTORED 0x40 // track has been restored after invalidation by AudioFlinger +#define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create +#define CBLK_DISABLED 0x08 // track disabled by AudioFlinger due to underrun, need to re-start +#define CBLK_RESTORING 0x10 // track is being restored after invalidation by AudioFlinger +#define CBLK_RESTORED 0x20 // track has been restored after invalidation by AudioFlinger // Important: do not add any virtual methods, including ~ struct audio_track_cblk_t @@ -102,13 +101,22 @@ public: // Since the control block is always located in shared memory, this constructor // is only used for placement new(). It is never used for regular new() or stack. audio_track_cblk_t(); - uint32_t stepUser(uint32_t frameCount); // called by client only, where - // client includes regular AudioTrack and AudioFlinger::PlaybackThread::OutputTrack - bool stepServer(uint32_t frameCount); // called by server only + + // called by client only, where client includes regular + // AudioTrack and AudioFlinger::PlaybackThread::OutputTrack + uint32_t stepUserIn(uint32_t frameCount) { return stepUser(frameCount, false); } + uint32_t stepUserOut(uint32_t frameCount) { return stepUser(frameCount, true); } + + bool stepServer(uint32_t frameCount, bool isOut); + void* buffer(uint32_t offset) const; - uint32_t framesAvailable(); - uint32_t framesAvailable_l(); - uint32_t framesReady(); // called by server only + uint32_t framesAvailableIn() { return framesAvailable(false); } + uint32_t framesAvailableOut() { return framesAvailable(true); } + uint32_t framesAvailableIn_l() { return framesAvailable_l(false); } + uint32_t framesAvailableOut_l() { return framesAvailable_l(true); } + uint32_t framesReadyIn() { return framesReady(false); } + uint32_t framesReadyOut() { return framesReady(true); } + bool tryLock(); // No barriers on the following operations, so the ordering of loads/stores @@ -134,6 +142,12 @@ public: return mVolumeLR; } +private: + // isOut == true means AudioTrack, isOut == false means AudioRecord + uint32_t stepUser(uint32_t frameCount, bool isOut); + uint32_t framesAvailable(bool isOut); + uint32_t framesAvailable_l(bool isOut); + uint32_t framesReady(bool isOut); }; diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 3c28ca7..ae1842e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -466,7 +466,6 @@ status_t AudioRecord::openRecord_l( mCblkMemory = cblk; mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - android_atomic_and(~CBLK_DIRECTION, &mCblk->flags); mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; mCblk->waitTimeMs = 0; return NO_ERROR; @@ -484,7 +483,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) audioBuffer->frameCount = 0; audioBuffer->size = 0; - uint32_t framesReady = cblk->framesReady(); + uint32_t framesReady = cblk->framesReadyIn(); if (framesReady == 0) { cblk->lock.lock(); @@ -540,7 +539,7 @@ create_new_record: } // read the server count again start_loop_here: - framesReady = cblk->framesReady(); + framesReady = cblk->framesReadyIn(); } cblk->lock.unlock(); } @@ -570,7 +569,7 @@ create_new_record: void AudioRecord::releaseBuffer(Buffer* audioBuffer) { AutoMutex lock(mLock); - mCblk->stepUser(audioBuffer->frameCount); + mCblk->stepUserIn(audioBuffer->frameCount); } audio_io_handle_t AudioRecord::getInput() const @@ -732,7 +731,7 @@ bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) // Manage overrun callback - if (active && (cblk->framesAvailable() == 0)) { + if (active && (cblk->framesAvailableIn() == 0)) { // The value of active is stale, but we are almost sure to be active here because // otherwise we would have exited when obtainBuffer returned STOPPED earlier. ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 5348646..f55ec9a 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -695,7 +695,7 @@ status_t AudioTrack::reload() flush_l(); audio_track_cblk_t* cblk = mCblk; - cblk->stepUser(cblk->frameCount); + cblk->stepUserOut(cblk->frameCount); return NO_ERROR; } @@ -887,7 +887,6 @@ status_t AudioTrack::createTrack_l( mCblkMemory = iMem; audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer()); mCblk = cblk; - android_atomic_or(CBLK_DIRECTION, &cblk->flags); if (flags & AUDIO_OUTPUT_FLAG_FAST) { if (trackFlags & IAudioFlinger::TRACK_FAST) { ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", cblk->frameCount); @@ -906,7 +905,7 @@ status_t AudioTrack::createTrack_l( } else { cblk->buffers = sharedBuffer->pointer(); // Force buffer full condition as data is already present in shared memory - cblk->stepUser(cblk->frameCount); + cblk->stepUserOut(cblk->frameCount); } cblk->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | @@ -938,7 +937,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) audioBuffer->frameCount = 0; audioBuffer->size = 0; - uint32_t framesAvail = cblk->framesAvailable(); + uint32_t framesAvail = cblk->framesAvailableOut(); cblk->lock.lock(); if (cblk->flags & CBLK_INVALID) { @@ -1009,7 +1008,7 @@ create_new_track: } // read the server count again start_loop_here: - framesAvail = cblk->framesAvailable_l(); + framesAvail = cblk->framesAvailableOut_l(); } cblk->lock.unlock(); } @@ -1038,7 +1037,7 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) { AutoMutex lock(mLock); audio_track_cblk_t* cblk = mCblk; - cblk->stepUser(audioBuffer->frameCount); + cblk->stepUserOut(audioBuffer->frameCount); if (audioBuffer->frameCount > 0) { // restart track if it was disabled by audioflinger due to previous underrun if (mActive && (cblk->flags & CBLK_DISABLED)) { @@ -1193,7 +1192,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) mLock.unlock(); // Manage underrun callback - if (active && (cblk->framesAvailable() == cblk->frameCount)) { + if (active && (cblk->framesAvailableOut() == cblk->frameCount)) { ALOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) { mCbf(EVENT_UNDERRUN, mUserData, 0); @@ -1370,11 +1369,11 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& refCblk, bool fromStart android_atomic_or(CBLK_FORCEREADY, &newCblk->flags); // stepUser() clears CBLK_UNDERRUN flag enabling underrun callbacks to // the client - newCblk->stepUser(frames); + newCblk->stepUserOut(frames); } } if (mSharedBuffer != 0) { - newCblk->stepUser(newCblk->frameCount); + newCblk->stepUserOut(newCblk->frameCount); } if (mActive) { result = mAudioTrack->start(); @@ -1514,14 +1513,14 @@ audio_track_cblk_t::audio_track_cblk_t() { } -uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) +uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount, bool isOut) { 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) { + if (isOut) { // If stepServer() has been called once, switch to normal obtainBuffer() timeout period if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; @@ -1552,7 +1551,7 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) return u; } -bool audio_track_cblk_t::stepServer(uint32_t frameCount) +bool audio_track_cblk_t::stepServer(uint32_t frameCount, bool isOut) { ALOGV("stepserver %08x %08x %d", user, server, frameCount); @@ -1565,7 +1564,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) bool flushed = (s == user); s += frameCount; - if (flags & CBLK_DIRECTION) { + if (isOut) { // Mark that we have read the first buffer so that next time stepUser() is called // we switch to normal obtainBuffer() timeout period if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { @@ -1615,18 +1614,18 @@ void* audio_track_cblk_t::buffer(uint32_t offset) const return (int8_t *)buffers + (offset - userBase) * frameSize; } -uint32_t audio_track_cblk_t::framesAvailable() +uint32_t audio_track_cblk_t::framesAvailable(bool isOut) { Mutex::Autolock _l(lock); - return framesAvailable_l(); + return framesAvailable_l(isOut); } -uint32_t audio_track_cblk_t::framesAvailable_l() +uint32_t audio_track_cblk_t::framesAvailable_l(bool isOut) { uint32_t u = user; uint32_t s = server; - if (flags & CBLK_DIRECTION) { + if (isOut) { uint32_t limit = (s < loopStart) ? s : loopStart; return limit + frameCount - u; } else { @@ -1634,12 +1633,12 @@ uint32_t audio_track_cblk_t::framesAvailable_l() } } -uint32_t audio_track_cblk_t::framesReady() +uint32_t audio_track_cblk_t::framesReady(bool isOut) { uint32_t u = user; uint32_t s = server; - if (flags & CBLK_DIRECTION) { + if (isOut) { if (u < loopEnd) { return u - s; } else { diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 379e936..69ac3e3 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -4286,7 +4286,7 @@ bool AudioFlinger::ThreadBase::TrackBase::step() { bool result; audio_track_cblk_t* cblk = this->cblk(); - result = cblk->stepServer(mFrameCount); + result = cblk->stepServer(mFrameCount, isOut()); if (!result) { ALOGV("stepServer failed acquiring cblk mutex"); mStepServerFailed = true; @@ -4545,7 +4545,7 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer( } // FIXME Same as above - framesReady = cblk->framesReady(); + framesReady = cblk->framesReadyOut(); if (CC_LIKELY(framesReady)) { uint32_t s = cblk->server; @@ -4580,7 +4580,7 @@ getNextBuffer_exit: // the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer. // FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue. size_t AudioFlinger::PlaybackThread::Track::framesReady() const { - return mCblk->framesReady(); + return mCblk->framesReadyOut(); } // Don't call for fast tracks; the framesReady() could result in priority inversion @@ -4875,6 +4875,11 @@ status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& return NO_ERROR; } +bool AudioFlinger::PlaybackThread::Track::isOut() const +{ + return true; +} + // timed audio tracks sp<AudioFlinger::PlaybackThread::TimedTrack> @@ -5436,7 +5441,8 @@ status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvi mStepServerFailed = false; } - framesAvail = cblk->framesAvailable_l(); + // FIXME lock is not actually held, so overrun is possible + framesAvail = cblk->framesAvailableIn_l(); if (CC_LIKELY(framesAvail)) { uint32_t s = cblk->server; @@ -5512,6 +5518,10 @@ void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) mCblk->frameCount); } +bool AudioFlinger::RecordThread::RecordTrack::isOut() const +{ + return false; +} // ---------------------------------------------------------------------------- @@ -5528,7 +5538,6 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( { if (mCblk != NULL) { - mCblk->flags |= CBLK_DIRECTION; mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); mOutBuffer.frameCount = 0; playbackThread->mTracks.add(this); @@ -5631,7 +5640,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount; memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t)); - mCblk->stepUser(outFrames); + mCblk->stepUserOut(outFrames); pInBuffer->frameCount -= outFrames; pInBuffer->i16 += outFrames * channelCount; mOutBuffer.frameCount -= outFrames; @@ -5702,7 +5711,7 @@ status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( ALOGVV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server); buffer->frameCount = 0; - uint32_t framesAvail = cblk->framesAvailable(); + uint32_t framesAvail = cblk->framesAvailableOut(); if (framesAvail == 0) { @@ -5720,7 +5729,7 @@ status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( } // read the server count again start_loop_here: - framesAvail = cblk->framesAvailable_l(); + framesAvail = cblk->framesAvailableOut_l(); } } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index de2fbfa..1417105 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -456,6 +456,9 @@ private: bool step(); void reset(); + virtual bool isOut() const = 0; // true for Track and TimedTrack, false for RecordTrack, + // this could be a track type if needed later + const wp<ThreadBase> mThread; /*const*/ sp<Client> mClient; // see explanation at ~TrackBase() why not const sp<IMemory> mCblkMemory; @@ -859,6 +862,7 @@ private: void triggerEvents(AudioSystem::sync_event_t type); virtual bool isTimedTrack() const { return false; } bool isFastTrack() const { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; } + virtual bool isOut() const; protected: @@ -1468,6 +1472,8 @@ public: static void appendDumpHeader(String8& result); void dump(char* buffer, size_t size); + virtual bool isOut() const; + private: friend class AudioFlinger; // for mState |