summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/Effects.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/Effects.cpp')
-rw-r--r--services/audioflinger/Effects.cpp116
1 files changed, 94 insertions, 22 deletions
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 942ea35..a8a5169 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -19,6 +19,7 @@
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
+#include "Configuration.h"
#include <utils/Log.h>
#include <audio_effects/effect_visualizer.h>
#include <audio_utils/primitives.h>
@@ -94,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);
}
@@ -487,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,
@@ -495,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();
@@ -509,7 +508,7 @@ status_t AudioFlinger::EffectModule::stop_l()
}
}
}
- return status;
+ return NO_ERROR;
}
status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
@@ -765,6 +764,46 @@ bool AudioFlinger::EffectModule::purgeHandles()
return enabled;
}
+status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
+{
+ Mutex::Autolock _l(mLock);
+ if (mStatus != NO_ERROR) {
+ return mStatus;
+ }
+ status_t status = NO_ERROR;
+ if ((mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0) {
+ status_t cmdStatus;
+ uint32_t size = sizeof(status_t);
+ effect_offload_param_t cmd;
+
+ cmd.isOffload = offloaded;
+ cmd.ioHandle = io;
+ status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_OFFLOAD,
+ sizeof(effect_offload_param_t),
+ &cmd,
+ &size,
+ &cmdStatus);
+ if (status == NO_ERROR) {
+ status = cmdStatus;
+ }
+ mOffloaded = (status == NO_ERROR) ? offloaded : false;
+ } else {
+ if (offloaded) {
+ status = INVALID_OPERATION;
+ }
+ mOffloaded = false;
+ }
+ ALOGV("setOffloaded() offloaded %d io %d status %d", offloaded, io, status);
+ return status;
+}
+
+bool AudioFlinger::EffectModule::isOffloaded() const
+{
+ Mutex::Autolock _l(mLock);
+ return mOffloaded;
+}
+
void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -932,6 +971,23 @@ status_t AudioFlinger::EffectHandle::enable()
thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
}
mEnabled = false;
+ } else {
+ if (thread != 0) {
+ if (thread->type() == ThreadBase::OFFLOAD) {
+ PlaybackThread *t = (PlaybackThread *)thread.get();
+ Mutex::Autolock _l(t->mLock);
+ t->broadcast_l();
+ }
+ if (!mEffect->isOffloadable()) {
+ if (thread->type() == ThreadBase::OFFLOAD) {
+ PlaybackThread *t = (PlaybackThread *)thread.get();
+ t->invalidateTracks(AUDIO_STREAM_MUSIC);
+ }
+ if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
+ thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable();
+ }
+ }
+ }
}
return status;
}
@@ -960,6 +1016,11 @@ status_t AudioFlinger::EffectHandle::disable()
sp<ThreadBase> thread = mEffect->thread().promote();
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
+ if (thread->type() == ThreadBase::OFFLOAD) {
+ PlaybackThread *t = (PlaybackThread *)thread.get();
+ Mutex::Autolock _l(t->mLock);
+ t->broadcast_l();
+ }
}
return status;
@@ -1217,9 +1278,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
@@ -1232,9 +1291,10 @@ void AudioFlinger::EffectChain::process_l()
}
bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
(mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
- // always process effects unless no more tracks are on the session and the effect tail
- // has been rendered
- bool doProcess = true;
+ // never process effects when:
+ // - on an OFFLOAD thread
+ // - no more tracks are on the session and the effect tail has been rendered
+ bool doProcess = (thread->type() != ThreadBase::OFFLOAD);
if (!isGlobalSession) {
bool tracksOnSession = (trackCnt() != 0);
@@ -1720,4 +1780,16 @@ void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModul
}
}
+bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
+{
+ Mutex::Autolock _l(mLock);
+ size_t size = mEffects.size();
+ for (size_t i = 0; i < size; i++) {
+ if (mEffects[i]->isEnabled() && !mEffects[i]->isOffloadable()) {
+ return true;
+ }
+ }
+ return false;
+}
+
}; // namespace android