summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/MediaPlayerInterface.h6
-rwxr-xr-xinclude/media/stagefright/LPAPlayer.h4
-rw-r--r--include/media/stagefright/TunnelPlayer.h15
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp7
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h6
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp18
-rw-r--r--media/libstagefright/AwesomePlayer.cpp7
-rw-r--r--media/libstagefright/LPAPlayerALSA.cpp37
-rwxr-xr-xmedia/libstagefright/MPEG4Writer.cpp6
-rw-r--r--media/libstagefright/TunnelPlayer.cpp200
-rw-r--r--services/audioflinger/AudioFlinger.cpp27
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();
}