diff options
Diffstat (limited to 'media/libmedia')
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 2 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 59 |
2 files changed, 39 insertions, 22 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 666fafa..ccbc5a3 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -545,13 +545,13 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) } const struct timespec *requested; + struct timespec timeout; if (waitCount == -1) { requested = &ClientProxy::kForever; } else if (waitCount == 0) { requested = &ClientProxy::kNonBlocking; } else if (waitCount > 0) { long long ms = WAIT_PERIOD_MS * (long long) waitCount; - struct timespec timeout; timeout.tv_sec = ms / 1000; timeout.tv_nsec = (int) (ms % 1000) * 1000000; requested = &timeout; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a9d6993..3f3a88c 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -85,7 +85,8 @@ AudioTrack::AudioTrack() : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { } @@ -106,7 +107,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, @@ -131,7 +133,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mPausedPosition(0) { mStatus = set(streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags, cbf, user, notificationFrames, @@ -529,6 +532,16 @@ void AudioTrack::pause() } mProxy->interrupt(); mAudioTrack->pause(); + + if (isOffloaded()) { + if (mOutput != 0) { + uint32_t halFrames; + // OffloadThread sends HAL pause in its threadLoop.. time saved + // here can be slightly off + AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition); + ALOGV("AudioTrack::pause for offload, cache current position %u", mPausedPosition); + } + } } status_t AudioTrack::setVolume(float left, float right) @@ -747,6 +760,12 @@ status_t AudioTrack::getPosition(uint32_t *position) const if (isOffloaded()) { uint32_t dspFrames = 0; + if ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING)) { + ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition); + *position = mPausedPosition; + return NO_ERROR; + } + if (mOutput != 0) { uint32_t halFrames; AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames); @@ -1113,13 +1132,13 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) } const struct timespec *requested; + struct timespec timeout; if (waitCount == -1) { requested = &ClientProxy::kForever; } else if (waitCount == 0) { requested = &ClientProxy::kNonBlocking; } else if (waitCount > 0) { long long ms = WAIT_PERIOD_MS * (long long) waitCount; - struct timespec timeout; timeout.tv_sec = ms / 1000; timeout.tv_nsec = (int) (ms % 1000) * 1000000; requested = &timeout; @@ -1451,6 +1470,7 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) } size_t misalignment = mProxy->getMisalignment(); uint32_t sequence = mSequence; + sp<AudioTrackClientProxy> proxy = mProxy; // These fields don't need to be cached, because they are assigned only by set(): // mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFrameSizeAF, mFlags @@ -1459,35 +1479,32 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) mLock.unlock(); if (waitStreamEnd) { - AutoMutex lock(mLock); - - sp<AudioTrackClientProxy> proxy = mProxy; - sp<IMemory> iMem = mCblkMemory; - struct timespec timeout; timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC; timeout.tv_nsec = 0; - mLock.unlock(); - status_t status = mProxy->waitStreamEndDone(&timeout); - mLock.lock(); + status_t status = proxy->waitStreamEndDone(&timeout); switch (status) { case NO_ERROR: case DEAD_OBJECT: case TIMED_OUT: - mLock.unlock(); mCbf(EVENT_STREAM_END, mUserData, NULL); - mLock.lock(); - if (mState == STATE_STOPPING) { - mState = STATE_STOPPED; - if (status != DEAD_OBJECT) { - return NS_INACTIVE; + { + AutoMutex lock(mLock); + // The previously assigned value of waitStreamEnd is no longer valid, + // since the mutex has been unlocked and either the callback handler + // or another thread could have re-started the AudioTrack during that time. + waitStreamEnd = mState == STATE_STOPPING; + if (waitStreamEnd) { + mState = STATE_STOPPED; } } - return 0; - default: - return 0; + if (waitStreamEnd && status != DEAD_OBJECT) { + return NS_INACTIVE; + } + break; } + return 0; } // perform callbacks while unlocked |