diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-20 14:03:58 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-20 14:03:58 -0800 |
commit | e5198b620a9a208ec59ea8457282404725f8ff6e (patch) | |
tree | 2ff913c152607cd9d58f0e6ba620461090be7541 /media/libmedia | |
parent | 54ffb8abf94365496a2dbf5d792b6977d6a8ef06 (diff) | |
download | frameworks_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.cpp | 46 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 82 |
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) { |