summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/Effects.cpp
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2013-01-07 09:53:42 -0800
committerEric Laurent <elaurent@google.com>2013-07-25 14:08:09 -0700
commitbfb1b832079bbb9426f72f3863199a54aefd02da (patch)
tree5007d22456776dc77d124be84bcfe8bc4152bbb2 /services/audioflinger/Effects.cpp
parentfc5ea08326b510c6f82f71845d95a8758a6ab698 (diff)
downloadframeworks_av-bfb1b832079bbb9426f72f3863199a54aefd02da.zip
frameworks_av-bfb1b832079bbb9426f72f3863199a54aefd02da.tar.gz
frameworks_av-bfb1b832079bbb9426f72f3863199a54aefd02da.tar.bz2
AudioFlinger: offload playback, non-blocking write
- Added specialized playback thread class for offload playback, derived from directoutput thread. This thread type handles specific state transitions for offloaded tracks and offloading commands (pause/resume/drain/flush..) to audio HAL. As opposed to other threads, does not go to standby if the track is paused. - Added support for asynchronous write and drain operations at audio HAL. Use a thread to handle async callback events from HAL: this avoids locking playback thread mutex when executing the callback and cause deadlocks when calling audio HAL functions with the playback thread mutex locked. - Better accouting for track activity: call start/stop and release Output methods in audio policy manager when tracks are actually added and removed from the active tracks list. Added a command thread in audio policy service to handle stop/release commands asynchronously and avoid deadlocks with playback thread. - Track terminated status is not a state anymore. This condition is othogonal to state to permitted state transitions while terminated. Change-Id: Id157f4b3277620568d8eace7535d9186602564de
Diffstat (limited to 'services/audioflinger/Effects.cpp')
-rw-r--r--services/audioflinger/Effects.cpp45
1 files changed, 26 insertions, 19 deletions
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 1c7a64b..d5a21a7 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -95,16 +95,7 @@ AudioFlinger::EffectModule::~EffectModule()
{
ALOGV("Destructor %p", this);
if (mEffectInterface != NULL) {
- if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
- (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- audio_stream_t *stream = thread->stream();
- if (stream != NULL) {
- stream->remove_audio_effect(stream, mEffectInterface);
- }
- }
- }
+ remove_effect_from_hal_l();
// release effect engine
EffectRelease(mEffectInterface);
}
@@ -488,7 +479,7 @@ status_t AudioFlinger::EffectModule::stop_l()
if (mStatus != NO_ERROR) {
return mStatus;
}
- status_t cmdStatus;
+ status_t cmdStatus = NO_ERROR;
uint32_t size = sizeof(status_t);
status_t status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_DISABLE,
@@ -496,12 +487,19 @@ status_t AudioFlinger::EffectModule::stop_l()
NULL,
&size,
&cmdStatus);
- if (status == 0) {
+ if (status == NO_ERROR) {
status = cmdStatus;
}
- if (status == 0 &&
- ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
- (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
+ if (status == NO_ERROR) {
+ status = remove_effect_from_hal_l();
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
+{
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+ (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
audio_stream_t *stream = thread->stream();
@@ -510,7 +508,7 @@ status_t AudioFlinger::EffectModule::stop_l()
}
}
}
- return status;
+ return NO_ERROR;
}
status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
@@ -595,6 +593,17 @@ status_t AudioFlinger::EffectModule::setEnabled_l(bool enabled)
h->setEnabled(enabled);
}
}
+//EL_FIXME not sure why this is needed?
+// sp<ThreadBase> thread = mThread.promote();
+// if (thread == 0) {
+// return NO_ERROR;
+// }
+//
+// if ((thread->type() == ThreadBase::OFFLOAD) && (enabled)) {
+// PlaybackThread *p = (PlaybackThread *)thread.get();
+// ALOGV("setEnabled: Offload, invalidate tracks");
+// p->invalidateTracks(AUDIO_STREAM_MUSIC);
+// }
}
return NO_ERROR;
}
@@ -1218,9 +1227,7 @@ void AudioFlinger::EffectChain::clearInputBuffer()
// Must be called with EffectChain::mLock locked
void AudioFlinger::EffectChain::clearInputBuffer_l(sp<ThreadBase> thread)
{
- size_t numSamples = thread->frameCount() * thread->channelCount();
- memset(mInBuffer, 0, numSamples * sizeof(int16_t));
-
+ memset(mInBuffer, 0, thread->frameCount() * thread->frameSize());
}
// Must be called with EffectChain::mLock locked