blob: 0dbf27ba25dbeb4b155d9e94265bbed2220ed534 [file] [log] [blame]
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2017, 2019, The Linux Foundation. All rights reserved.
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -08003 * Not a Contribution.
4 *
5 * Copyright (C) 2013 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080036 */
37
38#define LOG_TAG "offload_effect_bundle"
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -070039//#define LOG_NDEBUG 0
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080040
Mingming Yin497419f2015-07-01 16:57:32 -070041#include <stdlib.h>
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080042#include <cutils/list.h>
Weiyin Jiangfd19e982019-07-05 11:20:28 +080043#include <cutils/str_parms.h>
Aalique Grahame22e49102018-12-18 14:23:57 -080044#include <log/log.h>
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080045#include <system/thread_defs.h>
46#include <tinyalsa/asoundlib.h>
47#include <hardware/audio_effect.h>
Vinay Vermaaddfa4a2018-04-29 14:03:38 +053048#include <pthread.h>
49#include <unistd.h>
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080050
51#include "bundle.h"
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -070052#include "hw_accelerator.h"
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080053#include "equalizer.h"
54#include "bass_boost.h"
55#include "virtualizer.h"
56#include "reverb.h"
57
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080058#ifdef DTS_EAGLE
59#include "effect_util.h"
60#endif
61
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080062enum {
63 EFFECT_STATE_UNINITIALIZED,
64 EFFECT_STATE_INITIALIZED,
65 EFFECT_STATE_ACTIVE,
66};
67
68const effect_descriptor_t *descriptors[] = {
69 &equalizer_descriptor,
70 &bassboost_descriptor,
71 &virtualizer_descriptor,
72 &aux_env_reverb_descriptor,
73 &ins_env_reverb_descriptor,
74 &aux_preset_reverb_descriptor,
75 &ins_preset_reverb_descriptor,
Mingming Yin497419f2015-07-01 16:57:32 -070076#ifdef HW_ACCELERATED_EFFECTS
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -070077 &hw_accelerator_descriptor,
Mingming Yin497419f2015-07-01 16:57:32 -070078#endif
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -080079 NULL,
80};
81
82pthread_once_t once = PTHREAD_ONCE_INIT;
83int init_status;
84/*
85 * list of created effects.
86 * Updated by offload_effects_bundle_hal_start_output()
87 * and offload_effects_bundle_hal_stop_output()
88 */
89struct listnode created_effects_list;
90/*
91 * list of active output streams.
92 * Updated by offload_effects_bundle_hal_start_output()
93 * and offload_effects_bundle_hal_stop_output()
94 */
95struct listnode active_outputs_list;
96/*
97 * lock must be held when modifying or accessing
98 * created_effects_list or active_outputs_list
99 */
100pthread_mutex_t lock;
101
102
103/*
104 * Local functions
105 */
106static void init_once() {
107 list_init(&created_effects_list);
108 list_init(&active_outputs_list);
109
110 pthread_mutex_init(&lock, NULL);
111
112 init_status = 0;
113}
114
115int lib_init()
116{
117 pthread_once(&once, init_once);
118 return init_status;
119}
120
121bool effect_exists(effect_context_t *context)
122{
123 struct listnode *node;
124
125 list_for_each(node, &created_effects_list) {
126 effect_context_t *fx_ctxt = node_to_item(node,
127 effect_context_t,
128 effects_list_node);
129 if (fx_ctxt == context) {
130 return true;
131 }
132 }
133 return false;
134}
135
136output_context_t *get_output(audio_io_handle_t output)
137{
138 struct listnode *node;
139
140 list_for_each(node, &active_outputs_list) {
141 output_context_t *out_ctxt = node_to_item(node,
142 output_context_t,
143 outputs_list_node);
144 if (out_ctxt->handle == output)
145 return out_ctxt;
146 }
147 return NULL;
148}
149
150void add_effect_to_output(output_context_t * output, effect_context_t *context)
151{
152 struct listnode *fx_node;
153
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530154 ALOGV("%s: e_ctxt %p, o_ctxt %p", __func__, context, output);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800155 list_for_each(fx_node, &output->effects_list) {
156 effect_context_t *fx_ctxt = node_to_item(fx_node,
157 effect_context_t,
158 output_node);
159 if (fx_ctxt == context)
160 return;
161 }
162 list_add_tail(&output->effects_list, &context->output_node);
163 if (context->ops.start)
164 context->ops.start(context, output);
165
166}
167
168void remove_effect_from_output(output_context_t * output,
169 effect_context_t *context)
170{
171 struct listnode *fx_node;
172
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530173 ALOGV("%s: e_ctxt %p, o_ctxt %p", __func__, context, output);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800174 list_for_each(fx_node, &output->effects_list) {
175 effect_context_t *fx_ctxt = node_to_item(fx_node,
176 effect_context_t,
177 output_node);
178 if (fx_ctxt == context) {
179 if (context->ops.stop)
180 context->ops.stop(context, output);
181 list_remove(&context->output_node);
182 return;
183 }
184 }
185}
186
187bool effects_enabled()
188{
189 struct listnode *out_node;
190
191 list_for_each(out_node, &active_outputs_list) {
192 struct listnode *fx_node;
193 output_context_t *out_ctxt = node_to_item(out_node,
194 output_context_t,
195 outputs_list_node);
196
197 list_for_each(fx_node, &out_ctxt->effects_list) {
198 effect_context_t *fx_ctxt = node_to_item(fx_node,
199 effect_context_t,
200 output_node);
201 if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
202 (fx_ctxt->ops.process != NULL))
203 return true;
204 }
205 }
206 return false;
207}
208
209
210/*
211 * Interface from audio HAL
212 */
213__attribute__ ((visibility ("default")))
Ashish Jain5106d362016-05-11 19:23:33 +0530214int offload_effects_bundle_hal_start_output(audio_io_handle_t output, int pcm_id, struct mixer *mixer)
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800215{
216 int ret = 0;
217 struct listnode *node;
218 char mixer_string[128];
wjiang50b81f42014-08-06 08:03:14 +0800219 output_context_t * out_ctxt = NULL;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800220
221 ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
222
Jitendra Naruka1b6513f2014-11-22 19:34:13 -0800223#ifdef DTS_EAGLE
224 create_effect_state_node(pcm_id);
225#endif
226
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800227 if (lib_init() != 0)
228 return init_status;
229
230 pthread_mutex_lock(&lock);
231 if (get_output(output) != NULL) {
232 ALOGW("%s output already started", __func__);
233 ret = -ENOSYS;
234 goto exit;
235 }
236
wjiang50b81f42014-08-06 08:03:14 +0800237 out_ctxt = (output_context_t *)
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800238 malloc(sizeof(output_context_t));
wjiangebb69fa2014-05-15 19:38:26 +0800239 if (!out_ctxt) {
240 ALOGE("%s fail to allocate for output context", __func__);
241 ret = -ENOMEM;
242 goto exit;
243 }
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800244 out_ctxt->handle = output;
245 out_ctxt->pcm_device_id = pcm_id;
246
247 /* populate the mixer control to send offload parameters */
248 snprintf(mixer_string, sizeof(mixer_string),
249 "%s %d", "Audio Effects Config", out_ctxt->pcm_device_id);
Ashish Jain5106d362016-05-11 19:23:33 +0530250
251 if (!mixer) {
252 ALOGE("Invalid mixer");
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800253 out_ctxt->ctl = NULL;
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700254 out_ctxt->ref_ctl = NULL;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800255 ret = -EINVAL;
wjiang50b81f42014-08-06 08:03:14 +0800256 free(out_ctxt);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800257 goto exit;
258 } else {
Ashish Jain5106d362016-05-11 19:23:33 +0530259 out_ctxt->mixer = mixer;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800260 out_ctxt->ctl = mixer_get_ctl_by_name(out_ctxt->mixer, mixer_string);
261 if (!out_ctxt->ctl) {
262 ALOGE("mixer_get_ctl_by_name failed");
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800263 out_ctxt->mixer = NULL;
264 ret = -EINVAL;
wjiang50b81f42014-08-06 08:03:14 +0800265 free(out_ctxt);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800266 goto exit;
267 }
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700268 out_ctxt->ref_ctl = out_ctxt->ctl;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800269 }
270
271 list_init(&out_ctxt->effects_list);
272
273 list_for_each(node, &created_effects_list) {
274 effect_context_t *fx_ctxt = node_to_item(node,
275 effect_context_t,
276 effects_list_node);
277 if (fx_ctxt->out_handle == output) {
278 if (fx_ctxt->ops.start)
279 fx_ctxt->ops.start(fx_ctxt, out_ctxt);
280 list_add_tail(&out_ctxt->effects_list, &fx_ctxt->output_node);
281 }
282 }
283 list_add_tail(&active_outputs_list, &out_ctxt->outputs_list_node);
284exit:
285 pthread_mutex_unlock(&lock);
286 return ret;
287}
288
289__attribute__ ((visibility ("default")))
290int offload_effects_bundle_hal_stop_output(audio_io_handle_t output, int pcm_id)
291{
Preetam Singh Ranawat53194302016-03-15 16:37:42 +0530292 int ret = -1;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800293 struct listnode *fx_node;
294 output_context_t *out_ctxt;
295
296 ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
297
298 if (lib_init() != 0)
299 return init_status;
300
301 pthread_mutex_lock(&lock);
302
303 out_ctxt = get_output(output);
304 if (out_ctxt == NULL) {
305 ALOGW("%s output not started", __func__);
306 ret = -ENOSYS;
307 goto exit;
308 }
309
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800310 list_for_each(fx_node, &out_ctxt->effects_list) {
311 effect_context_t *fx_ctxt = node_to_item(fx_node,
312 effect_context_t,
313 output_node);
314 if (fx_ctxt->ops.stop)
315 fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
316 }
317
318 list_remove(&out_ctxt->outputs_list_node);
319
Jitendra Naruka1b6513f2014-11-22 19:34:13 -0800320#ifdef DTS_EAGLE
321 remove_effect_state_node(pcm_id);
322#endif
323
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800324 free(out_ctxt);
325
326exit:
327 pthread_mutex_unlock(&lock);
328 return ret;
329}
330
Alexy Josephd464f3b2014-11-18 16:14:41 -0800331__attribute__ ((visibility ("default")))
332int offload_effects_bundle_set_hpx_state(bool hpx_state)
333{
334 int ret = 0;
335 struct listnode *node;
336
337 ALOGV("%s hpx state: %d", __func__, hpx_state);
338
339 if (lib_init() != 0)
340 return init_status;
341
342 pthread_mutex_lock(&lock);
343
344 if (hpx_state) {
345 /* set ramp down */
346 list_for_each(node, &active_outputs_list) {
347 output_context_t *out_ctxt = node_to_item(node,
348 output_context_t,
349 outputs_list_node);
350 struct soft_volume_params vol;
351 vol.master_gain = 0x0;
352 offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
353 OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
354 }
355 /* wait for ramp down duration - 30msec */
356 usleep(30000);
357 /* disable effects modules */
358 list_for_each(node, &active_outputs_list) {
359 struct listnode *fx_node;
360 output_context_t *out_ctxt = node_to_item(node,
361 output_context_t,
362 outputs_list_node);
363 list_for_each(fx_node, &out_ctxt->effects_list) {
364 effect_context_t *fx_ctxt = node_to_item(fx_node,
365 effect_context_t,
366 output_node);
367 if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
368 (fx_ctxt->ops.stop != NULL))
369 fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
370 }
371 out_ctxt->ctl = NULL;
372 }
373 /* set the channel mixer */
374 list_for_each(node, &active_outputs_list) {
375 /* send command to set channel mixer */
376 }
377 /* enable hpx modules */
378 list_for_each(node, &active_outputs_list) {
379 output_context_t *out_ctxt = node_to_item(node,
380 output_context_t,
381 outputs_list_node);
382 offload_hpx_send_params(out_ctxt->ref_ctl,
383 OFFLOAD_SEND_HPX_STATE_ON);
384 }
385 /* wait for transition state - 50msec */
386 usleep(50000);
387 /* set ramp up */
388 list_for_each(node, &active_outputs_list) {
389 output_context_t *out_ctxt = node_to_item(node,
390 output_context_t,
391 outputs_list_node);
392 struct soft_volume_params vol;
393 vol.master_gain = 0x2000;
394 offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
395 OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
396 }
397 } else {
398 /* set ramp down */
399 list_for_each(node, &active_outputs_list) {
400 output_context_t *out_ctxt = node_to_item(node,
401 output_context_t,
402 outputs_list_node);
403 struct soft_volume_params vol;
404 vol.master_gain = 0x0;
405 offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
406 OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
407 }
408 /* wait for ramp down duration - 30msec */
409 usleep(30000);
410 /* disable effects modules */
411 list_for_each(node, &active_outputs_list) {
412 output_context_t *out_ctxt = node_to_item(node,
413 output_context_t,
414 outputs_list_node);
415 offload_hpx_send_params(out_ctxt->ref_ctl,
416 OFFLOAD_SEND_HPX_STATE_OFF);
417 }
418 /* set the channel mixer */
419 list_for_each(node, &active_outputs_list) {
420 /* send command to set channel mixer */
421 }
422 /* enable effects modules */
423 list_for_each(node, &active_outputs_list) {
424 struct listnode *fx_node;
425 output_context_t *out_ctxt = node_to_item(node,
426 output_context_t,
427 outputs_list_node);
428 out_ctxt->ctl = out_ctxt->ref_ctl;
429 list_for_each(fx_node, &out_ctxt->effects_list) {
430 effect_context_t *fx_ctxt = node_to_item(fx_node,
431 effect_context_t,
432 output_node);
433 if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
434 (fx_ctxt->ops.start != NULL))
435 fx_ctxt->ops.start(fx_ctxt, out_ctxt);
436 }
437 }
438 /* wait for transition state - 50msec */
439 usleep(50000);
440 /* set ramp up */
441 list_for_each(node, &active_outputs_list) {
442 output_context_t *out_ctxt = node_to_item(node,
443 output_context_t,
444 outputs_list_node);
445 struct soft_volume_params vol;
446 vol.master_gain = 0x2000;
447 offload_transition_soft_volume_send_params(out_ctxt->ref_ctl, vol,
448 OFFLOAD_SEND_TRANSITION_SOFT_VOLUME_GAIN_MASTER);
449 }
450 }
451
Alexy Josephd464f3b2014-11-18 16:14:41 -0800452 pthread_mutex_unlock(&lock);
453 return ret;
454}
455
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800456/*
Dhananjay Kumar1c978df2015-09-04 13:44:59 +0530457 * Effect Bundle Set and get param operations.
Dhananjay Kumar1c978df2015-09-04 13:44:59 +0530458 */
459__attribute__ ((visibility ("default")))
Weiyin Jiangfd19e982019-07-05 11:20:28 +0800460void offload_effects_bundle_get_parameters(struct str_parms *query __unused,
461 struct str_parms *reply __unused)
Dhananjay Kumar1c978df2015-09-04 13:44:59 +0530462{
Dhananjay Kumar1c978df2015-09-04 13:44:59 +0530463}
464
465__attribute__ ((visibility ("default")))
Weiyin Jiangfd19e982019-07-05 11:20:28 +0800466void offload_effects_bundle_set_parameters(struct str_parms *parms __unused)
Dhananjay Kumar1c978df2015-09-04 13:44:59 +0530467{
Dhananjay Kumar1c978df2015-09-04 13:44:59 +0530468}
469
470/*
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800471 * Effect operations
472 */
473int set_config(effect_context_t *context, effect_config_t *config)
474{
475 context->config = *config;
476
477 if (context->ops.reset)
478 context->ops.reset(context);
479
480 return 0;
481}
482
483void get_config(effect_context_t *context, effect_config_t *config)
484{
485 *config = context->config;
486}
487
488
489/*
490 * Effect Library Interface Implementation
491 */
492int effect_lib_create(const effect_uuid_t *uuid,
493 int32_t sessionId,
494 int32_t ioId,
495 effect_handle_t *pHandle) {
496 int ret;
497 int i;
498
499 ALOGV("%s: sessionId: %d, ioId: %d", __func__, sessionId, ioId);
500 if (lib_init() != 0)
501 return init_status;
502
503 if (pHandle == NULL || uuid == NULL)
504 return -EINVAL;
505
506 for (i = 0; descriptors[i] != NULL; i++) {
507 if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0)
508 break;
509 }
510
511 if (descriptors[i] == NULL)
512 return -EINVAL;
513
514 effect_context_t *context;
515 if (memcmp(uuid, &equalizer_descriptor.uuid,
516 sizeof(effect_uuid_t)) == 0) {
517 equalizer_context_t *eq_ctxt = (equalizer_context_t *)
518 calloc(1, sizeof(equalizer_context_t));
wjiangebb69fa2014-05-15 19:38:26 +0800519 if (eq_ctxt == NULL) {
520 return -ENOMEM;
521 }
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800522 context = (effect_context_t *)eq_ctxt;
523 context->ops.init = equalizer_init;
524 context->ops.reset = equalizer_reset;
525 context->ops.set_parameter = equalizer_set_parameter;
526 context->ops.get_parameter = equalizer_get_parameter;
527 context->ops.set_device = equalizer_set_device;
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700528 context->ops.set_hw_acc_mode = equalizer_set_mode;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800529 context->ops.enable = equalizer_enable;
530 context->ops.disable = equalizer_disable;
531 context->ops.start = equalizer_start;
532 context->ops.stop = equalizer_stop;
533
534 context->desc = &equalizer_descriptor;
535 eq_ctxt->ctl = NULL;
536 } else if (memcmp(uuid, &bassboost_descriptor.uuid,
537 sizeof(effect_uuid_t)) == 0) {
Dhananjay Kumar5f15ff92014-05-19 16:45:08 +0800538 bass_context_t *bass_ctxt = (bass_context_t *)
539 calloc(1, sizeof(bass_context_t));
wjiangebb69fa2014-05-15 19:38:26 +0800540 if (bass_ctxt == NULL) {
541 return -ENOMEM;
542 }
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800543 context = (effect_context_t *)bass_ctxt;
Dhananjay Kumar5f15ff92014-05-19 16:45:08 +0800544 context->ops.init = bass_init;
545 context->ops.reset = bass_reset;
546 context->ops.set_parameter = bass_set_parameter;
547 context->ops.get_parameter = bass_get_parameter;
548 context->ops.set_device = bass_set_device;
549 context->ops.set_hw_acc_mode = bass_set_mode;
550 context->ops.enable = bass_enable;
551 context->ops.disable = bass_disable;
552 context->ops.start = bass_start;
553 context->ops.stop = bass_stop;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800554
555 context->desc = &bassboost_descriptor;
Dhananjay Kumar5f15ff92014-05-19 16:45:08 +0800556 bass_ctxt->bassboost_ctxt.ctl = NULL;
557 bass_ctxt->pbe_ctxt.ctl = NULL;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800558 } else if (memcmp(uuid, &virtualizer_descriptor.uuid,
559 sizeof(effect_uuid_t)) == 0) {
560 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)
561 calloc(1, sizeof(virtualizer_context_t));
wjiangebb69fa2014-05-15 19:38:26 +0800562 if (virt_ctxt == NULL) {
563 return -ENOMEM;
564 }
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800565 context = (effect_context_t *)virt_ctxt;
566 context->ops.init = virtualizer_init;
567 context->ops.reset = virtualizer_reset;
568 context->ops.set_parameter = virtualizer_set_parameter;
569 context->ops.get_parameter = virtualizer_get_parameter;
570 context->ops.set_device = virtualizer_set_device;
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700571 context->ops.set_hw_acc_mode = virtualizer_set_mode;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800572 context->ops.enable = virtualizer_enable;
573 context->ops.disable = virtualizer_disable;
574 context->ops.start = virtualizer_start;
575 context->ops.stop = virtualizer_stop;
576
577 context->desc = &virtualizer_descriptor;
578 virt_ctxt->ctl = NULL;
579 } else if ((memcmp(uuid, &aux_env_reverb_descriptor.uuid,
580 sizeof(effect_uuid_t)) == 0) ||
581 (memcmp(uuid, &ins_env_reverb_descriptor.uuid,
582 sizeof(effect_uuid_t)) == 0) ||
583 (memcmp(uuid, &aux_preset_reverb_descriptor.uuid,
584 sizeof(effect_uuid_t)) == 0) ||
585 (memcmp(uuid, &ins_preset_reverb_descriptor.uuid,
586 sizeof(effect_uuid_t)) == 0)) {
587 reverb_context_t *reverb_ctxt = (reverb_context_t *)
588 calloc(1, sizeof(reverb_context_t));
wjiangebb69fa2014-05-15 19:38:26 +0800589 if (reverb_ctxt == NULL) {
590 return -ENOMEM;
591 }
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800592 context = (effect_context_t *)reverb_ctxt;
593 context->ops.init = reverb_init;
594 context->ops.reset = reverb_reset;
595 context->ops.set_parameter = reverb_set_parameter;
596 context->ops.get_parameter = reverb_get_parameter;
597 context->ops.set_device = reverb_set_device;
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700598 context->ops.set_hw_acc_mode = reverb_set_mode;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800599 context->ops.enable = reverb_enable;
600 context->ops.disable = reverb_disable;
601 context->ops.start = reverb_start;
602 context->ops.stop = reverb_stop;
603
604 if (memcmp(uuid, &aux_env_reverb_descriptor.uuid,
605 sizeof(effect_uuid_t)) == 0) {
606 context->desc = &aux_env_reverb_descriptor;
607 reverb_auxiliary_init(reverb_ctxt);
608 } else if (memcmp(uuid, &ins_env_reverb_descriptor.uuid,
609 sizeof(effect_uuid_t)) == 0) {
610 context->desc = &ins_env_reverb_descriptor;
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700611 reverb_insert_init(reverb_ctxt);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800612 } else if (memcmp(uuid, &aux_preset_reverb_descriptor.uuid,
613 sizeof(effect_uuid_t)) == 0) {
614 context->desc = &aux_preset_reverb_descriptor;
615 reverb_auxiliary_init(reverb_ctxt);
616 } else if (memcmp(uuid, &ins_preset_reverb_descriptor.uuid,
617 sizeof(effect_uuid_t)) == 0) {
618 context->desc = &ins_preset_reverb_descriptor;
619 reverb_preset_init(reverb_ctxt);
620 }
621 reverb_ctxt->ctl = NULL;
Mingming Yin497419f2015-07-01 16:57:32 -0700622#ifdef HW_ACCELERATED_EFFECTS
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700623 } else if (memcmp(uuid, &hw_accelerator_descriptor.uuid,
624 sizeof(effect_uuid_t)) == 0) {
625 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)
626 calloc(1, sizeof(hw_accelerator_context_t));
627 if (hw_acc_ctxt == NULL) {
628 ALOGE("h/w acc context allocation failed");
629 return -ENOMEM;
630 }
631 context = (effect_context_t *)hw_acc_ctxt;
632 context->ops.init = hw_accelerator_init;
633 context->ops.reset = hw_accelerator_reset;
634 context->ops.set_parameter = hw_accelerator_set_parameter;
635 context->ops.get_parameter = hw_accelerator_get_parameter;
636 context->ops.set_device = hw_accelerator_set_device;
637 context->ops.set_hw_acc_mode = hw_accelerator_set_mode;
638 context->ops.enable = hw_accelerator_enable;
639 context->ops.disable = hw_accelerator_disable;
640 context->ops.release = hw_accelerator_release;
641 context->ops.process = hw_accelerator_process;
642
643 context->desc = &hw_accelerator_descriptor;
Mingming Yin497419f2015-07-01 16:57:32 -0700644#endif
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800645 } else {
646 return -EINVAL;
647 }
648
649 context->itfe = &effect_interface;
650 context->state = EFFECT_STATE_UNINITIALIZED;
651 context->out_handle = (audio_io_handle_t)ioId;
652
653 ret = context->ops.init(context);
654 if (ret < 0) {
655 ALOGW("%s init failed", __func__);
656 free(context);
657 return ret;
658 }
659
660 context->state = EFFECT_STATE_INITIALIZED;
661
662 pthread_mutex_lock(&lock);
663 list_add_tail(&created_effects_list, &context->effects_list_node);
664 output_context_t *out_ctxt = get_output(ioId);
665 if (out_ctxt != NULL)
666 add_effect_to_output(out_ctxt, context);
667 pthread_mutex_unlock(&lock);
668
669 *pHandle = (effect_handle_t)context;
670
671 ALOGV("%s created context %p", __func__, context);
672
673 return 0;
674
675}
676
677int effect_lib_release(effect_handle_t handle)
678{
679 effect_context_t *context = (effect_context_t *)handle;
680 int status;
681
682 if (lib_init() != 0)
683 return init_status;
684
685 ALOGV("%s context %p", __func__, handle);
686 pthread_mutex_lock(&lock);
687 status = -EINVAL;
688 if (effect_exists(context)) {
689 output_context_t *out_ctxt = get_output(context->out_handle);
690 if (out_ctxt != NULL)
691 remove_effect_from_output(out_ctxt, context);
692 list_remove(&context->effects_list_node);
693 if (context->ops.release)
694 context->ops.release(context);
695 free(context);
696 status = 0;
697 }
698 pthread_mutex_unlock(&lock);
699
700 return status;
701}
702
703int effect_lib_get_descriptor(const effect_uuid_t *uuid,
704 effect_descriptor_t *descriptor)
705{
706 int i;
707
708 if (lib_init() != 0)
709 return init_status;
710
711 if (descriptor == NULL || uuid == NULL) {
712 ALOGV("%s called with NULL pointer", __func__);
713 return -EINVAL;
714 }
715
716 for (i = 0; descriptors[i] != NULL; i++) {
717 if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
718 *descriptor = *descriptors[i];
719 return 0;
720 }
721 }
722
723 return -EINVAL;
724}
725
726
727/*
728 * Effect Control Interface Implementation
729 */
730
731/* Stub function for effect interface: never called for offloaded effects */
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700732/* called for hw accelerated effects */
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800733int effect_process(effect_handle_t self,
Weiyin Jiangb64b7dd2015-03-23 00:54:14 +0800734 audio_buffer_t *inBuffer __unused,
735 audio_buffer_t *outBuffer __unused)
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800736{
737 effect_context_t * context = (effect_context_t *)self;
738 int status = 0;
739
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700740 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800741
742 pthread_mutex_lock(&lock);
743 if (!effect_exists(context)) {
wjiang50b81f42014-08-06 08:03:14 +0800744 status = -ENOSYS;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800745 goto exit;
746 }
747
748 if (context->state != EFFECT_STATE_ACTIVE) {
wjiang50b81f42014-08-06 08:03:14 +0800749 status = -ENODATA;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800750 goto exit;
751 }
752
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700753 if (context->ops.process)
754 status = context->ops.process(context, inBuffer, outBuffer);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800755exit:
756 pthread_mutex_unlock(&lock);
757 return status;
758}
759
760int effect_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
761 void *pCmdData, uint32_t *replySize, void *pReplyData)
762{
763
764 effect_context_t * context = (effect_context_t *)self;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800765 int status = 0;
766
767 pthread_mutex_lock(&lock);
768
769 if (!effect_exists(context)) {
wjiang50b81f42014-08-06 08:03:14 +0800770 status = -ENOSYS;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800771 goto exit;
772 }
773
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530774 ALOGV("%s: ctxt %p, cmd %d", __func__, context, cmdCode);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800775 if (context == NULL || context->state == EFFECT_STATE_UNINITIALIZED) {
wjiang50b81f42014-08-06 08:03:14 +0800776 status = -ENOSYS;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800777 goto exit;
778 }
779
780 switch (cmdCode) {
781 case EFFECT_CMD_INIT:
782 if (pReplyData == NULL || *replySize != sizeof(int)) {
783 status = -EINVAL;
784 goto exit;
785 }
786 if (context->ops.init)
787 *(int *) pReplyData = context->ops.init(context);
788 else
789 *(int *) pReplyData = 0;
790 break;
791 case EFFECT_CMD_SET_CONFIG:
792 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
793 || pReplyData == NULL || *replySize != sizeof(int)) {
794 status = -EINVAL;
795 goto exit;
796 }
797 *(int *) pReplyData = set_config(context, (effect_config_t *) pCmdData);
798 break;
799 case EFFECT_CMD_GET_CONFIG:
800 if (pReplyData == NULL ||
801 *replySize != sizeof(effect_config_t)) {
802 status = -EINVAL;
803 goto exit;
804 }
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700805 if (!context->offload_enabled && !context->hw_acc_enabled) {
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800806 status = -EINVAL;
807 goto exit;
808 }
809
810 get_config(context, (effect_config_t *)pReplyData);
811 break;
812 case EFFECT_CMD_RESET:
813 if (context->ops.reset)
814 context->ops.reset(context);
815 break;
816 case EFFECT_CMD_ENABLE:
817 if (pReplyData == NULL || *replySize != sizeof(int)) {
818 status = -EINVAL;
819 goto exit;
820 }
821 if (context->state != EFFECT_STATE_INITIALIZED) {
822 status = -ENOSYS;
823 goto exit;
824 }
825 context->state = EFFECT_STATE_ACTIVE;
826 if (context->ops.enable)
827 context->ops.enable(context);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800828 *(int *)pReplyData = 0;
829 break;
830 case EFFECT_CMD_DISABLE:
831 if (pReplyData == NULL || *replySize != sizeof(int)) {
832 status = -EINVAL;
833 goto exit;
834 }
835 if (context->state != EFFECT_STATE_ACTIVE) {
836 status = -ENOSYS;
837 goto exit;
838 }
839 context->state = EFFECT_STATE_INITIALIZED;
840 if (context->ops.disable)
841 context->ops.disable(context);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800842 *(int *)pReplyData = 0;
843 break;
844 case EFFECT_CMD_GET_PARAM: {
845 if (pCmdData == NULL ||
846 cmdSize < (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
847 pReplyData == NULL ||
Andy Hungeae4d562016-04-28 13:43:44 -0700848 *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint16_t)) ||
849 // constrain memcpy below
850 ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t)) {
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800851 status = -EINVAL;
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530852 ALOGW("EFFECT_CMD_GET_PARAM invalid command cmdSize %d *replySize %d",
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800853 cmdSize, *replySize);
854 goto exit;
855 }
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700856 if (!context->offload_enabled && !context->hw_acc_enabled) {
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800857 status = -EINVAL;
858 goto exit;
859 }
860 effect_param_t *q = (effect_param_t *)pCmdData;
861 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + q->psize);
862 effect_param_t *p = (effect_param_t *)pReplyData;
863 if (context->ops.get_parameter)
864 context->ops.get_parameter(context, p, replySize);
865 } break;
866 case EFFECT_CMD_SET_PARAM: {
867 if (pCmdData == NULL ||
868 cmdSize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) +
869 sizeof(uint16_t)) ||
870 pReplyData == NULL || *replySize != sizeof(int32_t)) {
871 status = -EINVAL;
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530872 ALOGW("EFFECT_CMD_SET_PARAM invalid command cmdSize %d *replySize %d",
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800873 cmdSize, *replySize);
874 goto exit;
875 }
876 *(int32_t *)pReplyData = 0;
877 effect_param_t *p = (effect_param_t *)pCmdData;
878 if (context->ops.set_parameter)
879 *(int32_t *)pReplyData = context->ops.set_parameter(context, p,
880 *replySize);
881
882 } break;
883 case EFFECT_CMD_SET_DEVICE: {
884 uint32_t device;
885 ALOGV("\t EFFECT_CMD_SET_DEVICE start");
886 if (pCmdData == NULL || cmdSize < sizeof(uint32_t)) {
887 status = -EINVAL;
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530888 ALOGW("EFFECT_CMD_SET_DEVICE invalid command cmdSize %d", cmdSize);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800889 goto exit;
890 }
891 device = *(uint32_t *)pCmdData;
892 if (context->ops.set_device)
893 context->ops.set_device(context, device);
894 } break;
Weiyin Jiang90ac1ea2017-04-13 14:18:23 +0800895 case EFFECT_CMD_SET_VOLUME: {
896 // if pReplyData is NULL, VOL_CTRL is delegated to another effect
897 if (pReplyData == NULL) {
898 break;
899 }
900 if (pCmdData == NULL || cmdSize != 2 * sizeof(uint32_t) ||
901 replySize == NULL || *replySize < 2*sizeof(int32_t)) {
902 return -EINVAL;
903 }
904 memcpy(pReplyData, pCmdData, sizeof(int32_t)*2);
905 } break;
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800906 case EFFECT_CMD_SET_AUDIO_MODE:
907 break;
908
909 case EFFECT_CMD_OFFLOAD: {
910 output_context_t *out_ctxt;
911
912 if (cmdSize != sizeof(effect_offload_param_t) || pCmdData == NULL
913 || pReplyData == NULL || *replySize != sizeof(int)) {
Dhananjay Kumar574f3922014-03-25 17:41:44 +0530914 ALOGW("%s EFFECT_CMD_OFFLOAD bad format", __func__);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800915 status = -EINVAL;
916 break;
917 }
918
919 effect_offload_param_t* offload_param = (effect_offload_param_t*)pCmdData;
920
921 ALOGV("%s EFFECT_CMD_OFFLOAD offload %d output %d", __func__,
922 offload_param->isOffload, offload_param->ioHandle);
923
924 *(int *)pReplyData = 0;
925
926 context->offload_enabled = offload_param->isOffload;
927 if (context->out_handle == offload_param->ioHandle)
928 break;
929
930 out_ctxt = get_output(context->out_handle);
931 if (out_ctxt != NULL)
932 remove_effect_from_output(out_ctxt, context);
933
934 context->out_handle = offload_param->ioHandle;
935 out_ctxt = get_output(context->out_handle);
936 if (out_ctxt != NULL)
937 add_effect_to_output(out_ctxt, context);
938
939 } break;
Mingming Yin497419f2015-07-01 16:57:32 -0700940#ifdef HW_ACCELERATED_EFFECTS
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700941 case EFFECT_CMD_HW_ACC: {
942 ALOGV("EFFECT_CMD_HW_ACC cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
943 cmdSize, pCmdData, *replySize, pReplyData);
944 if (cmdSize != sizeof(uint32_t) || pCmdData == NULL
945 || pReplyData == NULL || *replySize != sizeof(int)) {
946 return -EINVAL;
947 }
948 uint32_t value = *(uint32_t *)pCmdData;
949 if (context->ops.set_hw_acc_mode)
950 context->ops.set_hw_acc_mode(context, value);
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800951
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700952 context->hw_acc_enabled = (value > 0) ? true : false;
953 break;
954 }
Mingming Yin497419f2015-07-01 16:57:32 -0700955#endif
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800956 default:
957 if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY && context->ops.command)
958 status = context->ops.command(context, cmdCode, cmdSize,
959 pCmdData, replySize, pReplyData);
960 else {
961 ALOGW("%s invalid command %d", __func__, cmdCode);
962 status = -EINVAL;
963 }
964 break;
965 }
966
967exit:
968 pthread_mutex_unlock(&lock);
969
970 return status;
971}
972
973/* Effect Control Interface Implementation: get_descriptor */
974int effect_get_descriptor(effect_handle_t self,
975 effect_descriptor_t *descriptor)
976{
977 effect_context_t *context = (effect_context_t *)self;
978
979 if (!effect_exists(context) || (descriptor == NULL))
980 return -EINVAL;
981
982 *descriptor = *context->desc;
983
984 return 0;
985}
986
wjiang50b81f42014-08-06 08:03:14 +0800987bool effect_is_active(effect_context_t * ctxt) {
988 return ctxt->state == EFFECT_STATE_ACTIVE;
989}
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -0800990
991/* effect_handle_t interface implementation for offload effects */
992const struct effect_interface_s effect_interface = {
993 effect_process,
994 effect_command,
995 effect_get_descriptor,
996 NULL,
997};
998
999__attribute__ ((visibility ("default")))
1000audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
Weiyin Jiang90ac1ea2017-04-13 14:18:23 +08001001 .tag = AUDIO_EFFECT_LIBRARY_TAG,
1002 .version = EFFECT_LIBRARY_API_VERSION,
1003 .name = "Offload Effects Bundle Library",
1004 .implementor = "The Linux Foundation",
1005 .create_effect = effect_lib_create,
1006 .release_effect = effect_lib_release,
1007 .get_descriptor = effect_lib_get_descriptor,
Subhash Chandra Bose Naripeddy3eedc002013-11-12 20:45:15 -08001008};