summaryrefslogtreecommitdiffstats
path: root/media/libeffects
diff options
context:
space:
mode:
authorjpadmana <jayashree.r.padmanaban@intel.com>2013-06-04 16:03:29 +0530
committerEric Laurent <elaurent@google.com>2013-09-27 16:03:37 -0700
commitfaca05e96744dfaa2f352e3dbb29eead4e55cfa0 (patch)
tree13fdbf3c9f72d9c1d31d367d58556e45703e70ce /media/libeffects
parent2eab94f7dfd41a65e13aca379a1aed97447f8884 (diff)
downloadframeworks_av-faca05e96744dfaa2f352e3dbb29eead4e55cfa0.zip
frameworks_av-faca05e96744dfaa2f352e3dbb29eead4e55cfa0.tar.gz
frameworks_av-faca05e96744dfaa2f352e3dbb29eead4e55cfa0.tar.bz2
Effect Offload Proxy for effects offload
Effect Proxy abstracts the sub effects to the upper layers. It has the following functionalities: - creation and release of sub effects - routing the effect commands and process to the appropriate sub effect Bug: 8174034. Change-Id: Iec34b61104f0bbec4ef67c62f0710a5536dc325b Signed-off-by: jpadmana <jayashree.r.padmanaban@intel.com>
Diffstat (limited to 'media/libeffects')
-rw-r--r--media/libeffects/data/audio_effects.conf2
-rw-r--r--media/libeffects/proxy/Android.mk34
-rw-r--r--media/libeffects/proxy/EffectProxy.cpp298
-rw-r--r--media/libeffects/proxy/EffectProxy.h75
4 files changed, 408 insertions, 1 deletions
diff --git a/media/libeffects/data/audio_effects.conf b/media/libeffects/data/audio_effects.conf
index f1c5f5b..c3c4b67 100644
--- a/media/libeffects/data/audio_effects.conf
+++ b/media/libeffects/data/audio_effects.conf
@@ -10,7 +10,7 @@ libraries {
# the HW and SW effects
#proxy {
- #path /system/lib/soundfx/libProxy.so
+ #path /system/lib/soundfx/libeffectproxy.so
#}
# This is the SW implementation library of the effect
diff --git a/media/libeffects/proxy/Android.mk b/media/libeffects/proxy/Android.mk
new file mode 100644
index 0000000..01b3be1
--- /dev/null
+++ b/media/libeffects/proxy/Android.mk
@@ -0,0 +1,34 @@
+# Copyright 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_MODULE:= libeffectproxy
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE_TAGS := optional
+
+
+LOCAL_SRC_FILES := \
+ EffectProxy.cpp
+
+LOCAL_CFLAGS+= -fvisibility=hidden
+
+LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libdl libeffects
+
+LOCAL_C_INCLUDES := \
+ system/media/audio_effects/include \
+ bionic/libc/include
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp
new file mode 100644
index 0000000..77c6e89
--- /dev/null
+++ b/media/libeffects/proxy/EffectProxy.cpp
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectProxy"
+//#define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <EffectProxy.h>
+#include <utils/threads.h>
+#include <media/EffectsFactoryApi.h>
+
+namespace android {
+// This is a dummy proxy descriptor just to return to Factory during the initial
+// GetDescriptor call. Later in the factory, it is replaced with the
+// SW sub effect descriptor
+const effect_descriptor_t gProxyDescriptor = {
+ EFFECT_UUID_INITIALIZER, // type
+ EFFECT_UUID_INITIALIZER, // uuid
+ EFFECT_CONTROL_API_VERSION, //version of effect control API
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST |
+ EFFECT_FLAG_VOLUME_CTRL), // effect capability flags
+ 0, // CPU load
+ 1, // Data memory
+ "Proxy", //effect name
+ "AOSP", //implementor name
+};
+
+
+static const effect_descriptor_t *const gDescriptors[] =
+{
+ &gProxyDescriptor,
+};
+
+int EffectProxyCreate(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle) {
+
+ effect_descriptor_t* desc;
+ EffectContext* pContext;
+ if (pHandle == NULL || uuid == NULL) {
+ ALOGE("EffectProxyCreate() called with NULL pointer");
+ return -EINVAL;
+ }
+ ALOGV("EffectProxyCreate start..");
+ pContext = new EffectContext;
+ pContext->sessionId = sessionId;
+ pContext->ioId = ioId;
+ pContext->uuid = *uuid;
+ pContext->common_itfe = &gEffectInterface;
+ // The sub effects will be created in effect_command when the first command
+ // for the effect is received
+ pContext->eHandle[SUB_FX_HOST] = pContext->eHandle[SUB_FX_OFFLOAD] = NULL;
+
+ // Get the HW and SW sub effect descriptors from the effects factory
+ desc = new effect_descriptor_t[SUB_FX_COUNT];
+ pContext->desc = new effect_descriptor_t[SUB_FX_COUNT];
+ int retValue = EffectGetSubEffects(uuid, desc,
+ sizeof(effect_descriptor_t) * SUB_FX_COUNT);
+ // EffectGetSubEffects returns the number of sub-effects copied.
+ if (retValue != SUB_FX_COUNT) {
+ ALOGE("EffectCreate() could not get the sub effects");
+ delete desc;
+ delete pContext->desc;
+ return -EINVAL;
+ }
+ // Check which is the HW descriptor and copy the descriptors
+ // to the Context desc array
+ // Also check if there is only one HW and one SW descriptor.
+ // HW descriptor alone has the HW_TUNNEL flag.
+ if ((desc[0].flags & EFFECT_FLAG_HW_ACC_TUNNEL) &&
+ !(desc[1].flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
+ pContext->desc[SUB_FX_OFFLOAD] = desc[0];
+ pContext->desc[SUB_FX_HOST] = desc[1];
+ }
+ else if ((desc[1].flags & EFFECT_FLAG_HW_ACC_TUNNEL) &&
+ !(desc[0].flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
+ pContext->desc[SUB_FX_HOST] = desc[0];
+ pContext->desc[SUB_FX_OFFLOAD] = desc[1];
+ }
+ delete desc;
+#if (LOG_NDEBUG == 0)
+ effect_uuid_t uuid_print = pContext->desc[SUB_FX_HOST].uuid;
+ ALOGV("EffectCreate() UUID of HOST: %08X-%04X-%04X-%04X-%02X%02X%02X%02X"
+ "%02X%02X\n",uuid_print.timeLow, uuid_print.timeMid,
+ uuid_print.timeHiAndVersion, uuid_print.clockSeq, uuid_print.node[0],
+ uuid_print.node[1], uuid_print.node[2], uuid_print.node[3],
+ uuid_print.node[4], uuid_print.node[5]);
+ ALOGV("EffectCreate() UUID of OFFLOAD: %08X-%04X-%04X-%04X-%02X%02X%02X%02X"
+ "%02X%02X\n", uuid_print.timeLow, uuid_print.timeMid,
+ uuid_print.timeHiAndVersion, uuid_print.clockSeq, uuid_print.node[0],
+ uuid_print.node[1], uuid_print.node[2], uuid_print.node[3],
+ uuid_print.node[4], uuid_print.node[5]);
+#endif
+ *pHandle = (effect_handle_t)pContext;
+ ALOGV("EffectCreate end");
+ return 0;
+} //end EffectProxyCreate
+
+int EffectProxyRelease(effect_handle_t handle) {
+ EffectContext * pContext = (EffectContext *)handle;
+ if (pContext == NULL) {
+ ALOGV("ERROR : EffectRelease called with NULL pointer");
+ return -EINVAL;
+ }
+ ALOGV("EffectRelease");
+ delete pContext->desc;
+ if (pContext->eHandle[SUB_FX_HOST])
+ EffectRelease(pContext->eHandle[SUB_FX_HOST]);
+ if (pContext->eHandle[SUB_FX_OFFLOAD])
+ EffectRelease(pContext->eHandle[SUB_FX_OFFLOAD]);
+ delete pContext;
+ pContext = NULL;
+ return 0;
+} /*end EffectProxyRelease */
+
+int EffectProxyGetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor) {
+ const effect_descriptor_t *desc = NULL;
+
+ if (pDescriptor == NULL || uuid == NULL) {
+ ALOGV("EffectGetDescriptor() called with NULL pointer");
+ return -EINVAL;
+ }
+ desc = &gProxyDescriptor;
+ *pDescriptor = *desc;
+ return 0;
+} /* end EffectProxyGetDescriptor */
+
+/* Effect Control Interface Implementation: Process */
+int Effect_process(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer) {
+
+ EffectContext *pContext = (EffectContext *) self;
+ int ret = 0;
+ if (pContext != NULL) {
+ int index = pContext->index;
+ // if the index refers to HW , do not do anything. Just return.
+ if (index == SUB_FX_HOST) {
+ ALOGV("Calling CoreProcess");
+ ret = (*pContext->eHandle[index])->process(pContext->eHandle[index],
+ inBuffer, outBuffer);
+ }
+ }
+ return ret;
+} /* end Effect_process */
+
+/* Effect Control Interface Implementation: Command */
+int Effect_command(effect_handle_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData) {
+
+ EffectContext *pContext = (EffectContext *) self;
+ int status;
+ if (pContext == NULL) {
+ ALOGV("Effect_command() Proxy context is NULL");
+ return -EINVAL;
+ }
+ if (pContext->eHandle[SUB_FX_HOST] == NULL) {
+ ALOGV("Effect_command() Calling HOST EffectCreate");
+ status = EffectCreate(&pContext->desc[SUB_FX_HOST].uuid,
+ pContext->sessionId, pContext->ioId,
+ &(pContext->eHandle[SUB_FX_HOST]));
+ if (status != NO_ERROR || (pContext->eHandle[SUB_FX_HOST] == NULL)) {
+ ALOGV("Effect_command() Error creating SW sub effect");
+ return status;
+ }
+ }
+ if (pContext->eHandle[SUB_FX_OFFLOAD] == NULL) {
+ ALOGV("Effect_command() Calling OFFLOAD EffectCreate");
+ status = EffectCreate(&pContext->desc[SUB_FX_OFFLOAD].uuid,
+ pContext->sessionId, pContext->ioId,
+ &(pContext->eHandle[SUB_FX_OFFLOAD]));
+ if (status != NO_ERROR || (pContext->eHandle[SUB_FX_OFFLOAD] == NULL)) {
+ ALOGV("Effect_command() Error creating HW effect");
+ // Do not return error here as SW effect is created
+ // Return error if the CMD_OFFLOAD sends the index as OFFLOAD
+ }
+ pContext->index = SUB_FX_HOST;
+ }
+ // EFFECT_CMD_OFFLOAD used to (1) send whether the thread is offload or not
+ // (2) Send the ioHandle of the effectThread when the effect
+ // is moved from one type of thread to another.
+ // pCmdData points to a memory holding effect_offload_param_t structure
+ if (cmdCode == EFFECT_CMD_OFFLOAD) {
+ ALOGV("Effect_command() cmdCode = EFFECT_CMD_OFFLOAD");
+ if (cmdSize == 0 || pCmdData == NULL) {
+ ALOGV("effectsOffload: Effect_command: CMD_OFFLOAD has no data");
+ *(int*)pReplyData = FAILED_TRANSACTION;
+ return FAILED_TRANSACTION;
+ }
+ effect_offload_param_t* offloadParam = (effect_offload_param_t*)pCmdData;
+ // Assign the effect context index based on isOffload field of the structure
+ pContext->index = offloadParam->isOffload ? SUB_FX_OFFLOAD : SUB_FX_HOST;
+ // if the index is HW and the HW effect is unavailable, return error
+ // and reset the index to SW
+ if (pContext->eHandle[pContext->index] == NULL) {
+ ALOGV("Effect_command()CMD_OFFLOAD sub effect unavailable");
+ *(int*)pReplyData = FAILED_TRANSACTION;
+ return FAILED_TRANSACTION;
+ }
+ pContext->ioId = offloadParam->ioHandle;
+ ALOGV("Effect_command()CMD_OFFLOAD index:%d io %d", pContext->index, pContext->ioId);
+ // Update the DSP wrapper with the new ioHandle.
+ // Pass the OFFLOAD command to the wrapper.
+ // The DSP wrapper needs to handle this CMD
+ if (pContext->eHandle[SUB_FX_OFFLOAD])
+ status = (*pContext->eHandle[SUB_FX_OFFLOAD])->command(
+ pContext->eHandle[SUB_FX_OFFLOAD], cmdCode, cmdSize,
+ pCmdData, replySize, pReplyData);
+ return status;
+ }
+
+ int index = pContext->index;
+ if (index != SUB_FX_HOST && index != SUB_FX_OFFLOAD) {
+ ALOGV("Effect_command: effect index is neither offload nor host");
+ return -EINVAL;
+ }
+ ALOGV("Effect_command: pContext->eHandle[%d]: %p",
+ index, pContext->eHandle[index]);
+ if (pContext->eHandle[SUB_FX_HOST])
+ (*pContext->eHandle[SUB_FX_HOST])->command(
+ pContext->eHandle[SUB_FX_HOST], cmdCode, cmdSize,
+ pCmdData, replySize, pReplyData);
+ if (pContext->eHandle[SUB_FX_OFFLOAD]) {
+ // In case of SET CMD, when the offload stream is unavailable,
+ // we will store the effect param values in the DSP effect wrapper.
+ // When the offload effects get enabled, we send these values to the
+ // DSP during Effect_config.
+ // So,we send the params to DSP wrapper also
+ (*pContext->eHandle[SUB_FX_OFFLOAD])->command(
+ pContext->eHandle[SUB_FX_OFFLOAD], cmdCode, cmdSize,
+ pCmdData, replySize, pReplyData);
+ }
+ return 0;
+} /* end Effect_command */
+
+
+/* Effect Control Interface Implementation: get_descriptor */
+int Effect_getDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor) {
+
+ EffectContext * pContext = (EffectContext *) self;
+ const effect_descriptor_t *desc;
+
+ ALOGV("Effect_getDescriptor");
+ if (pContext == NULL || pDescriptor == NULL) {
+ ALOGV("Effect_getDescriptor() invalid param");
+ return -EINVAL;
+ }
+ if (pContext->desc == NULL) {
+ ALOGV("Effect_getDescriptor() could not get descriptor");
+ return -EINVAL;
+ }
+ desc = &pContext->desc[SUB_FX_HOST];
+ *pDescriptor = *desc;
+ pDescriptor->uuid = pContext->uuid; // Replace the uuid with the Proxy UUID
+ // Also set/clear the EFFECT_FLAG_OFFLOAD_SUPPORTED flag based on the sub effects availability
+ if (pContext->eHandle[SUB_FX_OFFLOAD] != NULL)
+ pDescriptor->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
+ else
+ pDescriptor->flags &= ~EFFECT_FLAG_OFFLOAD_SUPPORTED;
+ return 0;
+} /* end Effect_getDescriptor */
+
+} // namespace android
+
+__attribute__ ((visibility ("default")))
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ tag : AUDIO_EFFECT_LIBRARY_TAG,
+ version : EFFECT_LIBRARY_API_VERSION,
+ name : "Effect Proxy",
+ implementor : "AOSP",
+ create_effect : android::EffectProxyCreate,
+ release_effect : android::EffectProxyRelease,
+ get_descriptor : android::EffectProxyGetDescriptor,
+};
diff --git a/media/libeffects/proxy/EffectProxy.h b/media/libeffects/proxy/EffectProxy.h
new file mode 100644
index 0000000..8992f93
--- /dev/null
+++ b/media/libeffects/proxy/EffectProxy.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hardware/audio.h>
+#include <hardware/audio_effect.h>
+namespace android {
+enum {
+ SUB_FX_HOST, // Index of HOST in the descriptor and handle arrays
+ // of the Proxy context
+ SUB_FX_OFFLOAD, // Index of OFFLOAD in the descriptor and handle arrays
+ // of the Proxy context
+ SUB_FX_COUNT // The number of sub effects for a Proxy(1 HW, 1 SW)
+};
+#if __cplusplus
+extern "C" {
+#endif
+
+int EffectProxyCreate(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle);
+int EffectProxyRelease(effect_handle_t handle);
+int EffectProxyGetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor);
+/* Effect Control Interface Implementation: Process */
+int Effect_process(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer);
+
+/* Effect Control Interface Implementation: Command */
+int Effect_command(effect_handle_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData);
+int Effect_getDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor);
+
+const struct effect_interface_s gEffectInterface = {
+ Effect_process,
+ Effect_command,
+ Effect_getDescriptor,
+ NULL,
+};
+
+struct EffectContext {
+ const struct effect_interface_s *common_itfe; // Holds the itfe of the Proxy
+ effect_descriptor_t* desc; // Points to the sub effect descriptors
+ effect_handle_t eHandle[SUB_FX_COUNT]; // The effect handles of the sub effects
+ int index; // The index that is currently active - HOST or OFFLOAD
+ int32_t sessionId; // The sessiond in which the effect is created.
+ // Stored in context to pass on to sub effect creation
+ int32_t ioId; // The ioId in which the effect is created.
+ // Stored in context to pass on to sub effect creation
+ effect_uuid_t uuid; // UUID of the Proxy
+};
+
+#if __cplusplus
+} // extern "C"
+#endif
+} //namespace android