diff options
-rw-r--r-- | include/media/MediaPlayerInterface.h | 6 | ||||
-rwxr-xr-x | include/media/stagefright/LPAPlayer.h | 4 | ||||
-rw-r--r-- | include/media/stagefright/TunnelPlayer.h | 15 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 7 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 6 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 18 | ||||
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 7 | ||||
-rw-r--r-- | media/libstagefright/LPAPlayerALSA.cpp | 37 | ||||
-rwxr-xr-x | media/libstagefright/MPEG4Writer.cpp | 6 | ||||
-rw-r--r-- | media/libstagefright/TunnelPlayer.cpp | 200 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 27 |
11 files changed, 241 insertions, 92 deletions
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 00d53af..5f9eb01 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -1,5 +1,8 @@ /* * Copyright (C) 2007 The Android Open Source Project + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution, Apache license notifications and license are retained + * for attribution purposes only. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,6 +90,9 @@ public: virtual ssize_t channelCount() const = 0; virtual ssize_t frameSize() const = 0; virtual uint32_t latency() const = 0; +#ifdef QCOM_HARDWARE + virtual audio_stream_type_t streamType() const {return AUDIO_STREAM_DEFAULT;} +#endif virtual float msecsPerFrame() const = 0; virtual status_t getPosition(uint32_t *position) const = 0; virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0; diff --git a/include/media/stagefright/LPAPlayer.h b/include/media/stagefright/LPAPlayer.h index 91f9b3a..ceba399 100755 --- a/include/media/stagefright/LPAPlayer.h +++ b/include/media/stagefright/LPAPlayer.h @@ -206,6 +206,9 @@ private: void handleA2DPSwitch(); void onPauseTimeOut(); + int64_t getMediaTimeUs_l(); + bool seekTooClose(int64_t); + sp<AudioFlingerLPAdecodeClient> AudioFlingerClient; friend class AudioFlingerLPAdecodeClient; Mutex AudioFlingerLock; @@ -260,7 +263,6 @@ private: MediaPlayerBase::AudioSink *audioSink, void *buffer, size_t size, void *cookie); size_t AudioCallback(void *cookie, void *data, size_t size); - int64_t getMediaTimeUs_l(); void convertMonoToStereo(int16_t *data, size_t size); diff --git a/include/media/stagefright/TunnelPlayer.h b/include/media/stagefright/TunnelPlayer.h index 04cc750..0b083b3 100644 --- a/include/media/stagefright/TunnelPlayer.h +++ b/include/media/stagefright/TunnelPlayer.h @@ -133,8 +133,7 @@ private: //Declare the condition Variables and Mutex - pthread_mutex_t extractor_mutex; - pthread_cond_t extractor_cv; + Condition mExtractorCV; // make sure Decoder thread has exited @@ -198,8 +197,18 @@ private: sp<TimedEventQueue::Event> mPauseEvent; bool mPauseEventPending; + typedef enum { + NCREATED = -1, + INITIALIZED, + RUNNING, + SLEEPING, + EXITING, + } ThreadState; + sp<MediaPlayerBase::AudioSink> mAudioSink; AwesomePlayer *mObserver; + ThreadState mThreadState; + bool mStopSinkPending; static size_t AudioSinkCallback( MediaPlayerBase::AudioSink *audioSink, @@ -218,6 +227,8 @@ private: size_t fillBuffer(void *data, size_t size); void reset(); + status_t schedPauseTimeOut(); + status_t stopAudioSink(); TunnelPlayer(const TunnelPlayer &); TunnelPlayer &operator=(const TunnelPlayer &); diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index f238e89..5b88f5f 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1357,6 +1357,13 @@ uint32_t MediaPlayerService::AudioOutput::latency () const return mTrack->latency(); } +#ifdef QCOM_HARDWARE +audio_stream_type_t MediaPlayerService::AudioOutput::streamType () const +{ + return mStreamType; +} +#endif + float MediaPlayerService::AudioOutput::msecsPerFrame() const { return mMsecsPerFrame; diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 54df9d2..972de37 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -1,6 +1,9 @@ /* ** ** Copyright 2008, The Android Open Source Project +** Copyright (c) 2013, The Linux Foundation. All rights reserved. +** Not a Contribution, Apache license notifications and license are retained +** for attribution purposes only. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -85,6 +88,9 @@ class MediaPlayerService : public BnMediaPlayerService virtual ssize_t channelCount() const; virtual ssize_t frameSize() const; virtual uint32_t latency() const; +#ifdef QCOM_HARDWARE + virtual audio_stream_type_t streamType() const; +#endif virtual float msecsPerFrame() const; virtual status_t getPosition(uint32_t *position) const; virtual status_t getFramesWritten(uint32_t *frameswritten) const; diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 94886e8..ad6d1cc 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -448,6 +448,11 @@ status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) { ALOGW("Target file size (%lld bytes) is too small to be respected", bytes); } + if (bytes >= 0xffffffffLL) { + ALOGW("Target file size (%lld bytes) too larger than supported, clip to 4GB", bytes); + bytes = 0xffffffffLL; + } + mMaxFileSizeBytes = bytes; return OK; } @@ -765,7 +770,18 @@ status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listen } status_t StagefrightRecorder::prepare() { - return OK; + ALOGV(" %s E", __func__ ); + + if(mVideoSource != VIDEO_SOURCE_LIST_END && mVideoEncoder != VIDEO_ENCODER_LIST_END && mVideoHeight && mVideoWidth && /*Video recording*/ + (mMaxFileDurationUs <=0 || /*Max duration is not set*/ + (mVideoHeight * mVideoWidth < 720 * 1280 && mMaxFileDurationUs > 30*60*1000*1000) || + (mVideoHeight * mVideoWidth >= 720 * 1280 && mMaxFileDurationUs > 10*60*1000*1000))) { + /*Above Check can be further optimized for lower resolutions to reduce file size*/ + ALOGV("File is huge so setting 64 bit file offsets"); + setParam64BitFileOffset(true); + } + ALOGV(" %s X", __func__ ); + return OK; } status_t StagefrightRecorder::start() { diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 34e1007..c68b476 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -3064,6 +3064,13 @@ void AwesomePlayer::checkTunnelExceptions() return; } + /* exception 2: use tunnel player only for AUDIO_STREAM_MUSIC */ + if (mAudioSink->streamType() != AUDIO_STREAM_MUSIC ) { + ALOGD("Use tunnel player only for AUDIO_STREAM_MUSIC"); + mIsTunnelAudio = false; + return; + } + /* below exceptions are only for av content */ if (mVideoTrack == NULL) return; diff --git a/media/libstagefright/LPAPlayerALSA.cpp b/media/libstagefright/LPAPlayerALSA.cpp index 56746d0..0aa419c 100644 --- a/media/libstagefright/LPAPlayerALSA.cpp +++ b/media/libstagefright/LPAPlayerALSA.cpp @@ -310,18 +310,11 @@ status_t LPAPlayer::seekTo(int64_t time_us) { Mutex::Autolock autoLock(mLock); ALOGV("seekTo: time_us %lld", time_us); - int64_t mediaTimeUs = getMediaTimeUs_l(); - - if (mediaTimeUs != 0) { - //check for return conditions only if seektime - // is set - int64_t diffUs = time_us - mediaTimeUs; - - if (labs(diffUs) < LPA_BUFFER_TIME) { - ALOGV("In seekTo(), ignoring time_us %lld mSeekTimeUs %lld", time_us, mSeekTimeUs); - mObserver->postAudioSeekComplete(); - return OK; - } + if (seekTooClose(time_us)) { + mLock.unlock(); + mObserver->postAudioSeekComplete(); + mLock.lock(); + return OK; } mSeeking = true; @@ -808,7 +801,9 @@ int64_t LPAPlayer::getTimeStamp(A2DPState state) { return timestamp; } -int64_t LPAPlayer::getMediaTimeUs_l() { +int64_t LPAPlayer::getMediaTimeUs_l( ) { + ALOGV("getMediaTimeUs() mPaused %d mSeekTimeUs %lld mPauseTime %lld", + mPaused, mSeekTimeUs, mPauseTime); if (mPaused) { return mPauseTime; } else { @@ -905,4 +900,20 @@ void LPAPlayer::convertMonoToStereo(int16_t *data, size_t size) } } +bool LPAPlayer::seekTooClose(int64_t time_us) { + int64_t t1 = getMediaTimeUs_l(); + /* + * empirical + * ----------- + * This constant signifies how much data (in Us) has been rendered by the + * DSP in the interval between the moment flush is issued on AudioSink to + * after ioctl(PAUSE) returns in Audio HAL. (flush triggers an implicit + * pause in audio HAL) + * + */ + const int64_t kDeltaUs = 60000LL; /* 60-70ms on msm8974, must be measured for other targets */ + t1 += kDeltaUs; + return (time_us > t1) && ((time_us - t1) <= LPA_BUFFER_TIME); +} + } //namespace android diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 2b76660..6d1f8c6 100755 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -44,6 +44,7 @@ namespace android { static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; static const int64_t kMax32BitFileSize = 0x007fffffffLL; +static const int64_t kMax64BitFileSize = 0x00ffffffffLL; //fat32 max size limited to 4GB static const uint8_t kNalUnitTypeSeqParamSet = 0x07; static const uint8_t kNalUnitTypePicParamSet = 0x08; static const int64_t kInitialDelayTimeUs = 700000LL; @@ -525,11 +526,14 @@ status_t MPEG4Writer::start(MetaData *param) { mIsFileSizeLimitExplicitlyRequested = true; } - int32_t use64BitOffset; + int32_t use64BitOffset = 0; if (param && param->findInt32(kKey64BitFileOffset, &use64BitOffset) && use64BitOffset) { mUse32BitOffset = false; + if (mMaxFileSizeLimitBytes == 0) { + mMaxFileSizeLimitBytes = kMax64BitFileSize; + } } if (mUse32BitOffset) { diff --git a/media/libstagefright/TunnelPlayer.cpp b/media/libstagefright/TunnelPlayer.cpp index f9d0976..1d76780 100644 --- a/media/libstagefright/TunnelPlayer.cpp +++ b/media/libstagefright/TunnelPlayer.cpp @@ -90,7 +90,9 @@ mIsFirstBuffer(false), mFirstBufferResult(OK), mFirstBuffer(NULL), mAudioSink(audioSink), -mObserver(observer) { +mObserver(observer), +mThreadState(NCREATED), +mStopSinkPending(false) { ALOGD("TunnelPlayer::TunnelPlayer()"); mTunnelObjectsAlive++; numChannels = 0; @@ -272,6 +274,7 @@ void TunnelPlayer::setSource(const sp<MediaSource> &source) { } status_t TunnelPlayer::start(bool sourceAlreadyStarted) { + Mutex::Autolock _l(mLock); CHECK(!mStarted); CHECK(mSource != NULL); @@ -374,8 +377,7 @@ status_t TunnelPlayer::start(bool sourceAlreadyStarted) { mStarted = true; mAudioSink->start(); ALOGV("Waking up extractor thread"); - pthread_cond_signal(&extractor_cv); - + mExtractorCV.signal(); return OK; } @@ -430,7 +432,7 @@ status_t TunnelPlayer::seekTo(int64_t time_us) { mReachedOutputEOS = false; if(mPaused == false) { ALOGV("Going to signal extractor thread since playback is already going on "); - pthread_cond_signal(&extractor_cv); + mExtractorCV.signal(); ALOGV("Signalled extractor thread."); } } @@ -438,19 +440,16 @@ status_t TunnelPlayer::seekTo(int64_t time_us) { return OK; } void TunnelPlayer::pause(bool playPendingSamples) { + Mutex::Autolock autoLock(mLock); CHECK(mStarted); if (mPaused) { return; } - Mutex::Autolock autoLock(mLock); ALOGV("pause: playPendingSamples %d", playPendingSamples); mPaused = true; int64_t playedTime = 0; - if(!mPauseEventPending) { - ALOGV("Posting an event for Pause timeout"); - mQueue.postEventWithDelay(mPauseEvent, TUNNEL_PAUSE_TIMEOUT_USEC); - mPauseEventPending = true; - } + schedPauseTimeOut(); + getPlayedTimeFromDSP_l(&playedTime); mPauseTime = mSeekTimeUs + playedTime; if (mAudioSink.get() != NULL) { @@ -470,7 +469,7 @@ void TunnelPlayer::resume() { mPauseEventPending = false; mQueue.cancelEvent(mPauseEvent->eventID()); } - + mStopSinkPending = false; } audio_format_t format; @@ -492,7 +491,7 @@ void TunnelPlayer::resume() { ALOGV("Audio sink open succeeded."); mAudioSink->start(); ALOGV("Audio sink start succeeded."); - pthread_cond_signal(&extractor_cv); + mExtractorCV.signal(); ALOGV("Audio signalling extractor thread."); } } @@ -547,6 +546,7 @@ void TunnelPlayer::reset() { //doesnt matter if the event is really present or not mPauseEventPending = false; mQueue.cancelEvent(mPauseEvent->eventID()); + mStopSinkPending = false; mReachedEOS = true; @@ -610,7 +610,6 @@ void *TunnelPlayer::extractorThreadWrapper(void *me) { void TunnelPlayer::extractorThreadEntry() { - pthread_mutex_lock(&extractor_mutex); uint32_t BufferSizeToUse = MEM_BUFFER_SIZE; pid_t tid = gettid(); @@ -618,15 +617,20 @@ void TunnelPlayer::extractorThreadEntry() { ANDROID_PRIORITY_AUDIO); prctl(PR_SET_NAME, (unsigned long)"Extractor Thread", 0, 0, 0); - ALOGV("extractorThreadEntry wait for signal \n"); - if (!mStarted) { - pthread_cond_wait(&extractor_cv, &extractor_mutex); + { + Mutex::Autolock _l(mLock); + mThreadState = INITIALIZED; + ALOGV("extractorThreadEntry wait for signal \n"); + if (!mStarted) { + mExtractorCV.wait(mLock); + } + if (killExtractorThread) { + mThreadState = EXITING; + return; + } } + ALOGV("extractorThreadEntry ready to work \n"); - pthread_mutex_unlock(&extractor_mutex); - if (killExtractorThread) { - return; - } if(mSource != NULL) { sp<MetaData> format = mSource->getFormat(); const char *mime; @@ -637,52 +641,69 @@ void TunnelPlayer::extractorThreadEntry() { int bytesWritten = 0; bool lSeeking = false; bool lPaused = false; + mThreadState = RUNNING; + while (!killExtractorThread) { + { + Mutex::Autolock _l(mLock); + if (mPaused) { + if (mStopSinkPending) { + ALOGD("extractor thread to stop and close the audio sink"); + stopAudioSink(); + } + } - if (mReachedEOS || mPaused || !mIsAudioRouted) { - ALOGV("Going to sleep before write since " - "mReachedEOS %d, mPaused %d, mIsAudioRouted %d", - mReachedEOS, mPaused, mIsAudioRouted); - pthread_mutex_lock(&extractor_mutex); - pthread_cond_wait(&extractor_cv, &extractor_mutex); - pthread_mutex_unlock(&extractor_mutex); - ALOGV("Woke up from sleep before write since " - "mReachedEOS %d, mPaused %d, mIsAudioRouted %d", - mReachedEOS, mPaused, mIsAudioRouted); - continue; + if (mReachedEOS || mPaused || !mIsAudioRouted) { + ALOGV("Going to sleep before write since " + "mReachedEOS %d, mPaused %d, mIsAudioRouted %d", + mReachedEOS, mPaused, mIsAudioRouted); + mThreadState = SLEEPING; + mExtractorCV.wait(mLock); + ALOGV("Woke up from sleep before write since " + "mReachedEOS %d, mPaused %d, mIsAudioRouted %d", + mReachedEOS, mPaused, mIsAudioRouted); + mThreadState = RUNNING; + continue; + } } - if (!mIsA2DPEnabled) { - ALOGV("FillBuffer: MemBuffer size %d", BufferSizeToUse); - ALOGV("Fillbuffer started"); - bytesWritten = fillBuffer(local_buf, BufferSizeToUse); - ALOGV("FillBuffer completed bytesToWrite %d", bytesWritten); - if(!killExtractorThread) { - mLock.lock(); - lPaused = mPaused; - mLock.unlock(); - - if(lPaused == true) { + ALOGV("FillBuffer: MemBuffer size %d", BufferSizeToUse); + ALOGV("Fillbuffer started"); + bytesWritten = fillBuffer(local_buf, BufferSizeToUse); + ALOGV("FillBuffer completed bytesToWrite %d", bytesWritten); + if (!killExtractorThread) { + { + Mutex::Autolock _l(mLock); + if (mPaused) { //write only if player is not in paused state. Sleep on lock // resume is called ALOGV("Going to sleep in decodethreadiwrite since sink is paused"); - pthread_mutex_lock(&extractor_mutex); - pthread_cond_wait(&extractor_cv, &extractor_mutex); + if (mStopSinkPending) { + ALOGD("w/ a buffer, extractor thread to stop and close" + " the extractor thread"); + stopAudioSink(); + } + + mThreadState = SLEEPING; + mExtractorCV.wait(mLock); ALOGV("Going to unlock n decodethreadwrite since sink " "resumed mPaused %d, mIsAudioRouted %d, mReachedEOS %d", mPaused, mIsAudioRouted, mReachedEOS); - pthread_mutex_unlock(&extractor_mutex); + mThreadState = RUNNING; } - mLock.lock(); - lSeeking = mSeeking||mInternalSeeking; - mLock.unlock(); + } + + mLock.lock(); + lSeeking = mSeeking||mInternalSeeking; + mLock.unlock(); - if(lSeeking == false && (killExtractorThread == false)){ + if (lSeeking == false && (killExtractorThread == false)) { //if we are seeking, ignore write, otherwise write - ALOGV("Fillbuffer before seek flag %d", mSeeking); + ALOGV("Fillbuffer before seek flag %d", mSeeking); int lWrittenBytes = mAudioSink->write(local_buf, bytesWritten); - ALOGV("Fillbuffer after write, written bytes %d and seek flag %d", lWrittenBytes, mSeeking); - if(lWrittenBytes > 0) { + ALOGV("Fillbuffer after write, written bytes %d and seek flag %d", + lWrittenBytes, mSeeking); + if (lWrittenBytes > 0) { //send EOS only if write was successful, if is_buffer_available // is flushed out (which returns 0 do not SEND EOS ALOGV("Fillbuffer after write and seek flag %d", mSeeking); @@ -690,7 +711,7 @@ void TunnelPlayer::extractorThreadEntry() { lSeeking = mSeeking||mInternalSeeking; mLock.unlock(); //ignore posting zero length buffer is seeking is set - if(mReachedEOS && bytesWritten && !lSeeking && (killExtractorThread == false)) { + if (mReachedEOS && bytesWritten && !lSeeking) { ALOGV("Fillbuffer after write sent EOS flag %d", lSeeking); mAudioSink->write(local_buf, 0); } else { @@ -701,25 +722,21 @@ void TunnelPlayer::extractorThreadEntry() { } else { ALOGV("write exited because of flush %d", mSeeking); } - } else { - ALOGV("Fillbuffer ignored since we seeked after fillBuffer was set %d", mSeeking); - } + } else { + ALOGV("Fillbuffer ignored since we seeked after fillBuffer was set %d", mSeeking); } } } + mThreadState = EXITING; free(local_buf); //TODO: Call fillbuffer with different size and write to mAudioSink() } void TunnelPlayer::createThreads() { - //Initialize all the Mutexes and Condition Variables - pthread_mutex_init(&extractor_mutex, NULL); - pthread_cond_init (&extractor_cv, NULL); - - // Create 4 threads Effect, decoder, event and A2dp + // Create the extractor thread pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); @@ -851,6 +868,19 @@ size_t TunnelPlayer::fillBuffer(void *data, size_t size) { int64_t TunnelPlayer::getRealTimeUs() { Mutex::Autolock autoLock(mLock); + + /* + * If it so happens that the client (e.g. AwesomePlayer), + * queries for the current time before compressed + * data from the new position is given to the compressed + * driver, we need to return the seek position + */ + if (mSeeking || mInternalSeeking) { + ALOGV("Seek yet to be processed, return seek time as current time %lld", + mSeekTimeUs); + return mSeekTimeUs; + } + getOffsetRealTime_l(&mPositionTimeRealUs); //update media time too mPositionTimeMediaUs = mPositionTimeRealUs; @@ -906,7 +936,7 @@ void TunnelPlayer::requestAndWaitForExtractorThreadExit() { } ALOGV("requestAndWaitForExtractorThreadExit +1"); - pthread_cond_signal(&extractor_cv); + mExtractorCV.signal(); ALOGV("requestAndWaitForExtractorThreadExit +2"); mLock.unlock(); pthread_join(extractorThread,NULL); @@ -942,12 +972,13 @@ void TunnelPlayer::onPauseTimeOut() { // 2.) Close routing Session ALOGV("onPauseTimeOut +4"); mAudioSink->flush(); - ALOGV("onPauseTimeOut +5"); - mAudioSink->stop(); - ALOGV("onPauseTimeOut +6"); - mAudioSink->close(); - ALOGV("onPauseTimeOut +7"); - mIsAudioRouted = false; + mStopSinkPending = true; + + if (mThreadState == SLEEPING) { + stopAudioSink(); + } else { + ALOGD("Delay stop and destroy of audio sink to the extractor thread"); + } // 3.) Release Wake Lock releaseWakeLock(); @@ -955,4 +986,37 @@ void TunnelPlayer::onPauseTimeOut() { } +/* mLock acquired by caller */ +status_t TunnelPlayer::schedPauseTimeOut() { + if (mPauseEventPending) { + return INVALID_OPERATION; + } + + ALOGD("Posting an event for Pause timeout by %d", gettid()); + mQueue.postEventWithDelay(mPauseEvent, TUNNEL_PAUSE_TIMEOUT_USEC); + mPauseEventPending = true; + return NO_ERROR; +} + +/* mLock acquired by caller */ +status_t TunnelPlayer::stopAudioSink() { + /* This function is for a very special purpose, hence the assertion */ + CHECK(mPaused); + + if (!mStopSinkPending) { + return INVALID_OPERATION; + } + mStopSinkPending = false; + + if (!mIsAudioRouted) { + return INVALID_OPERATION; + } + ALOGD("stop and close the audio sink"); + mAudioSink->stop(); + mAudioSink->close(); + mIsAudioRouted = false; + return NO_ERROR; +} + + } //namespace android diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 88da88c..ed221ed 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -249,6 +249,9 @@ AudioFlinger::AudioFlinger() mNextUniqueId(1), mMode(AUDIO_MODE_INVALID), mBtNrecIsOff(false) +#ifdef QCOM_HARDWARE + ,mAllChainsLocked(false) +#endif { } @@ -6232,16 +6235,17 @@ AudioFlinger::DirectAudioTrack::~DirectAudioTrack() { } status_t AudioFlinger::DirectAudioTrack::start() { + AudioSystem::startOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType); if(mIsPaused) { mIsPaused = false; mOutputDesc->stream->start(mOutputDesc->stream); } mOutputDesc->mActive = true; - AudioSystem::startOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType); return NO_ERROR; } void AudioFlinger::DirectAudioTrack::stop() { + ALOGV("DirectAudioTrack::stop"); mOutputDesc->mActive = false; mOutputDesc->stream->stop(mOutputDesc->stream); AudioSystem::stopOutput(mOutput, (audio_stream_type_t)mOutputDesc->mStreamType); @@ -6290,11 +6294,14 @@ void AudioFlinger::DirectAudioTrack::mute(bool muted) { } void AudioFlinger::DirectAudioTrack::setVolume(float left, float right) { - mOutputDesc->mVolumeLeft = left; - mOutputDesc->mVolumeRight = right; - mOutputDesc->stream->set_volume(mOutputDesc->stream, + ALOGV("DirectAudioTrack::setVolume left: %f, right: %f", left, right); + if(mOutputDesc && mOutputDesc->mActive) { + mOutputDesc->mVolumeLeft = left; + mOutputDesc->mVolumeRight = right; + mOutputDesc->stream->set_volume(mOutputDesc->stream, left * mOutputDesc->mVolumeScale, right* mOutputDesc->mVolumeScale); + } } int64_t AudioFlinger::DirectAudioTrack::getTimeStamp() { @@ -8760,11 +8767,19 @@ void AudioFlinger::ThreadBase::lockEffectChains_l( Vector< sp<AudioFlinger::EffectChain> >& effectChains) { effectChains = mEffectChains; +#ifdef QCOM_HARDWARE + mAudioFlinger->mAllChainsLocked = true; +#endif for (size_t i = 0; i < mEffectChains.size(); i++) { #ifdef QCOM_HARDWARE - if (mEffectChains[i] != mAudioFlinger->mLPAEffectChain) + if (mEffectChains[i] != mAudioFlinger->mLPAEffectChain) { #endif mEffectChains[i]->lock(); +#ifdef QCOM_HARDWARE + } else { + mAudioFlinger-> mAllChainsLocked = false; + } +#endif } } @@ -8773,7 +8788,7 @@ void AudioFlinger::ThreadBase::unlockEffectChains( { for (size_t i = 0; i < effectChains.size(); i++) { #ifdef QCOM_HARDWARE - if (mEffectChains[i] != mAudioFlinger->mLPAEffectChain) + if (mAudioFlinger-> mAllChainsLocked || mEffectChains[i] != mAudioFlinger->mLPAEffectChain) #endif effectChains[i]->unlock(); } |