summaryrefslogtreecommitdiffstats
path: root/media/libmedia
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-20 14:03:58 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-20 14:03:58 -0800
commite5198b620a9a208ec59ea8457282404725f8ff6e (patch)
tree2ff913c152607cd9d58f0e6ba620461090be7541 /media/libmedia
parent54ffb8abf94365496a2dbf5d792b6977d6a8ef06 (diff)
downloadframeworks_av-e5198b620a9a208ec59ea8457282404725f8ff6e.zip
frameworks_av-e5198b620a9a208ec59ea8457282404725f8ff6e.tar.gz
frameworks_av-e5198b620a9a208ec59ea8457282404725f8ff6e.tar.bz2
auto import from //branches/cupcake/...@127101
Diffstat (limited to 'media/libmedia')
-rw-r--r--media/libmedia/AudioRecord.cpp46
-rw-r--r--media/libmedia/AudioTrack.cpp82
2 files changed, 78 insertions, 50 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index bbb9548..3d39181 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -245,6 +245,8 @@ status_t AudioRecord::start()
if (android_atomic_or(1, &mActive) == 0) {
mNewPosition = mCblk->user + mUpdatePeriod;
+ mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
@@ -342,7 +344,7 @@ status_t AudioRecord::getPosition(uint32_t *position)
// -------------------------------------------------------------------------
-status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking)
+status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
{
int active;
int timeout = 0;
@@ -362,14 +364,21 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking)
active = mActive;
if (UNLIKELY(!active))
return NO_MORE_BUFFERS;
- if (UNLIKELY(!blocking))
+ if (UNLIKELY(!waitCount))
return WOULD_BLOCK;
timeout = 0;
- result = cblk->cv.waitRelative(cblk->lock, seconds(1));
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
if (__builtin_expect(result!=NO_ERROR, false)) {
- LOGW( "obtainBuffer timed out (is the CPU pegged?) "
- "user=%08x, server=%08x", cblk->user, cblk->server);
- timeout = 1;
+ cblk->waitTimeMs += WAIT_PERIOD_MS;
+ if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
+ LOGW( "obtainBuffer timed out (is the CPU pegged?) "
+ "user=%08x, server=%08x", cblk->user, cblk->server);
+ timeout = 1;
+ cblk->waitTimeMs = 0;
+ }
+ if (--waitCount == 0) {
+ return TIMED_OUT;
+ }
}
// read the server count again
start_loop_here:
@@ -382,6 +391,8 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking)
"but didn't need to be locked. We recovered, but "
"this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
+ cblk->waitTimeMs = 0;
+
if (framesReq > framesReady) {
framesReq = framesReady;
}
@@ -430,7 +441,9 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize)
audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t);
- status_t err = obtainBuffer(&audioBuffer, true);
+ // Calling obtainBuffer() with a negative wait count causes
+ // an (almost) infinite wait time.
+ status_t err = obtainBuffer(&audioBuffer, -1);
if (err < 0) {
// out of buffers, return #bytes written
if (err == status_t(NO_MORE_BUFFERS))
@@ -457,7 +470,7 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
{
Buffer audioBuffer;
uint32_t frames = mRemainingFrames;
- size_t readSize = 0;
+ size_t readSize;
// Manage marker callback
if (mMarkerPosition > 0) {
@@ -477,17 +490,19 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
do {
audioBuffer.frameCount = frames;
- status_t err = obtainBuffer(&audioBuffer, false);
+ // Calling obtainBuffer() with a wait count of 1
+ // limits wait time to WAIT_PERIOD_MS. This prevents from being
+ // stuck here not being able to handle timed events (position, markers).
+ status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
- if (err != WOULD_BLOCK) {
+ if (err != TIMED_OUT) {
LOGE("Error obtaining an audio buffer, giving up.");
return false;
}
+ break;
}
if (err == status_t(STOPPED)) return false;
- if (audioBuffer.size == 0) break;
-
size_t reqSize = audioBuffer.size;
mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
readSize = audioBuffer.size;
@@ -514,13 +529,6 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
}
}
- // If no data was read, it is likely that obtainBuffer() did
- // not find available data in PCM buffer: we release the processor for
- // a few millisecond before polling again for available data.
- if (readSize == 0) {
- usleep(5000);
- }
-
if (frames == 0) {
mRemainingFrames = mNotificationFrames;
} else {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ce65312..f9f8568 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -330,6 +330,8 @@ void AudioTrack::start()
if (android_atomic_or(1, &mActive) == 0) {
mNewPosition = mCblk->server + mUpdatePeriod;
+ mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+ mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
@@ -572,7 +574,7 @@ status_t AudioTrack::reload()
// -------------------------------------------------------------------------
-status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking)
+status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
{
int active;
int timeout = 0;
@@ -594,15 +596,23 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking)
LOGV("Not active and NO_MORE_BUFFERS");
return NO_MORE_BUFFERS;
}
- if (UNLIKELY(!blocking))
+ if (UNLIKELY(!waitCount))
return WOULD_BLOCK;
timeout = 0;
- result = cblk->cv.waitRelative(cblk->lock, seconds(1));
- if (__builtin_expect(result!=NO_ERROR, false)) {
- LOGW( "obtainBuffer timed out (is the CPU pegged?) "
- "user=%08x, server=%08x", cblk->user, cblk->server);
- mAudioTrack->start(); // FIXME: Wake up audioflinger
- timeout = 1;
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+ if (__builtin_expect(result!=NO_ERROR, false)) {
+ cblk->waitTimeMs += WAIT_PERIOD_MS;
+ if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
+ LOGW( "obtainBuffer timed out (is the CPU pegged?) "
+ "user=%08x, server=%08x", cblk->user, cblk->server);
+ mAudioTrack->start(); // FIXME: Wake up audioflinger
+ timeout = 1;
+ cblk->waitTimeMs = 0;
+ }
+ ;
+ if (--waitCount == 0) {
+ return TIMED_OUT;
+ }
}
// read the server count again
start_loop_here:
@@ -610,6 +620,8 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking)
}
}
+ cblk->waitTimeMs = 0;
+
if (framesReq > framesAvail) {
framesReq = framesAvail;
}
@@ -667,8 +679,9 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize)
if (mFormat == AudioSystem::PCM_16_BIT) {
audioBuffer.frameCount >>= 1;
}
-
- status_t err = obtainBuffer(&audioBuffer, true);
+ // Calling obtainBuffer() with a negative wait count causes
+ // an (almost) infinite wait time.
+ status_t err = obtainBuffer(&audioBuffer, -1);
if (err < 0) {
// out of buffers, return #bytes written
if (err == status_t(NO_MORE_BUFFERS))
@@ -706,7 +719,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
{
Buffer audioBuffer;
uint32_t frames;
- size_t writtenSize = 0;
+ size_t writtenSize;
// Manage underrun callback
if (mActive && (mCblk->framesReady() == 0)) {
@@ -756,18 +769,20 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
do {
audioBuffer.frameCount = frames;
-
- status_t err = obtainBuffer(&audioBuffer, false);
+
+ // Calling obtainBuffer() with a wait count of 1
+ // limits wait time to WAIT_PERIOD_MS. This prevents from being
+ // stuck here not being able to handle timed events (position, markers, loops).
+ status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
- if (err != WOULD_BLOCK) {
+ if (err != TIMED_OUT) {
LOGE("Error obtaining an audio buffer, giving up.");
return false;
}
+ break;
}
if (err == status_t(STOPPED)) return false;
- if (audioBuffer.size == 0) break;
-
// Divide buffer size by 2 to take into account the expansion
// due to 8 to 16 bit conversion: the callback must fill only half
// of the destination buffer
@@ -802,13 +817,6 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
}
while (frames);
- // If no data was written, it is likely that obtainBuffer() did
- // not find room in PCM buffer: we release the processor for
- // a few millisecond before polling again for available room.
- if (writtenSize == 0) {
- usleep(5000);
- }
-
if (frames == 0) {
mRemainingFrames = mNotificationFrames;
} else {
@@ -872,7 +880,12 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
u += frameCount;
// Ensure that user is never ahead of server for AudioRecord
- if (!out && u > this->server) {
+ if (out) {
+ // If stepServer() has been called once, switch to normal obtainBuffer() timeout period
+ if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
+ bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ }
+ } else if (u > this->server) {
LOGW("stepServer occured after track reset");
u = this->server;
}
@@ -909,13 +922,20 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
uint32_t s = this->server;
s += frameCount;
- // It is possible that we receive a flush()
- // 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 (out && s > this->user) {
- LOGW("stepServer occured after track reset");
- s = this->user;
+ if (out) {
+ // 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) {
+ bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
+ }
+ // It is possible that we receive a flush()
+ // 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 > this->user) {
+ LOGW("stepServer occured after track reset");
+ s = this->user;
+ }
}
if (s >= loopEnd) {