summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-11-06 16:15:41 -0800
committerGlenn Kasten <gkasten@google.com>2012-11-07 08:32:40 -0800
commitba85098eb31bd2637db49816f0591361211024f2 (patch)
treeac7f6e3c4d620dbbc87991dbb41944c53245c72a
parent891b11da870ad3f860c1d2610ef4d8836ed6c590 (diff)
downloadframeworks_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.h38
-rw-r--r--media/libmedia/AudioRecord.cpp9
-rw-r--r--media/libmedia/AudioTrack.cpp37
-rw-r--r--services/audioflinger/AudioFlinger.cpp25
-rw-r--r--services/audioflinger/AudioFlinger.h6
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