From a331de14219b34b08f4cbb462a45f1fd82a92d48 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 4 Jan 2017 16:33:55 -0800 Subject: audiohal: Re-implement effect process using FMQ and IMemory Result: no hwbinder calls due music processing. Added IEffect.close method for explicitly freeing up of resources consumed by the effect before automatic server objects reaping gets to it. Added IEffect.setProcessBuffers method for updating the input / output buffers on the go. Test: make, use Play Music with effects, check traces Bug: 30222631 Change-Id: Ia1e1bc7098fab59aa970e0ce4acdb48007409644 --- audio/effect/2.0/IEffect.hal | 80 +++---- .../2.0/default/AcousticEchoCancelerEffect.cpp | 18 +- .../2.0/default/AcousticEchoCancelerEffect.h | 10 +- audio/effect/2.0/default/Android.mk | 10 +- audio/effect/2.0/default/AudioBufferManager.cpp | 88 ++++++++ audio/effect/2.0/default/AudioBufferManager.h | 82 ++++++++ .../2.0/default/AutomaticGainControlEffect.cpp | 18 +- .../2.0/default/AutomaticGainControlEffect.h | 10 +- audio/effect/2.0/default/BassBoostEffect.cpp | 18 +- audio/effect/2.0/default/BassBoostEffect.h | 10 +- audio/effect/2.0/default/DownmixEffect.cpp | 18 +- audio/effect/2.0/default/DownmixEffect.h | 10 +- audio/effect/2.0/default/Effect.cpp | 229 ++++++++++++++++----- audio/effect/2.0/default/Effect.h | 39 ++-- .../2.0/default/EnvironmentalReverbEffect.cpp | 17 +- .../effect/2.0/default/EnvironmentalReverbEffect.h | 10 +- audio/effect/2.0/default/EqualizerEffect.cpp | 17 +- audio/effect/2.0/default/EqualizerEffect.h | 10 +- .../effect/2.0/default/LoudnessEnhancerEffect.cpp | 17 +- audio/effect/2.0/default/LoudnessEnhancerEffect.h | 10 +- .../effect/2.0/default/NoiseSuppressionEffect.cpp | 17 +- audio/effect/2.0/default/NoiseSuppressionEffect.h | 10 +- audio/effect/2.0/default/PresetReverbEffect.cpp | 17 +- audio/effect/2.0/default/PresetReverbEffect.h | 10 +- audio/effect/2.0/default/VirtualizerEffect.cpp | 17 +- audio/effect/2.0/default/VirtualizerEffect.h | 10 +- audio/effect/2.0/default/VisualizerEffect.cpp | 17 +- audio/effect/2.0/default/VisualizerEffect.h | 10 +- audio/effect/2.0/types.hal | 15 +- 29 files changed, 581 insertions(+), 263 deletions(-) create mode 100644 audio/effect/2.0/default/AudioBufferManager.cpp create mode 100644 audio/effect/2.0/default/AudioBufferManager.h diff --git a/audio/effect/2.0/IEffect.hal b/audio/effect/2.0/IEffect.hal index 615a460eb8..9027c68d61 100644 --- a/audio/effect/2.0/IEffect.hal +++ b/audio/effect/2.0/IEffect.hal @@ -226,49 +226,47 @@ interface IEffect { getDescriptor() generates (Result retval, EffectDescriptor descriptor); /* - * Effect process function. Takes input samples as specified (count and - * location) in input buffer and returns processed samples as specified in - * output buffer. If the buffer descriptor is empty the function must use - * either the buffer or the buffer provider callback installed by the - * setConfig command. The effect framework must call the 'process' function - * after the 'enable' command is received and until the 'disable' is - * received. When the engine receives the 'disable' command it should turn - * off the effect gracefully and when done indicate that it is OK to stop - * calling the 'process' function by returning the INVALID_STATE status. - * - * Output audio buffer must contain no more frames than the input audio - * buffer. Since the effect may transform input channels into a different - * amount of channels, the caller provides the output frame size. - * - * @param inBuffer input audio buffer. - * @param outFrameSize output frame size in bytes. - * @return retval operation completion status. - * @return outBuffer output audio buffer. + * Set up required transports for passing audio buffers to the effect. + * + * The transport consists of shared memory and a message queue for reporting + * effect processing operation status. The shared memory is set up + * separately using 'setProcessBuffers' method. + * + * Processing is requested by setting 'REQUEST_PROCESS' or + * 'REQUEST_PROCESS_REVERSE' EventFlags associated with the status message + * queue. The result of processing may be one of the following: + * OK if there were no errors during processing; + * INVALID_ARGUMENTS if audio buffers are invalid; + * INVALID_STATE if the engine has finished the disable phase; + * NOT_INITIALIZED if the audio buffers were not set; + * NOT_SUPPORTED if the requested processing type is not supported by + * the effect. + * + * @return retval OK if both message queues were created successfully. + * INVALID_STATE if the method was already called. + * INVALID_ARGUMENTS if there was a problem setting up + * the queue. + * @return statusMQ a message queue used for passing status from the effect. */ - // TODO(mnaganov): replace with FMQ version. - @callflow(next={"*"}) - process(AudioBuffer inBuffer, uint32_t outFrameSize) - generates (Result retval, AudioBuffer outBuffer); + prepareForProcessing() generates (Result retval, fmq_sync statusMQ); /* - * Process reverse stream function. This function is used to pass a - * reference stream to the effect engine. If the engine does not need a - * reference stream, this function MUST return NOT_SUPPORTED. For example, - * this function would typically implemented by an Echo Canceler. + * Set up input and output buffers for processing audio data. The effect + * may modify both the input and the output buffer during the operation. + * Buffers may be set multiple times during effect lifetime. * - * Output audio buffer must contain no more frames than the input audio - * buffer. Since the effect may transform input channels into a different - * amount of channels, the caller provides the output frame size. + * The input and the output buffer may be reused between different effects, + * and the input buffer may be used as an output buffer. Buffers are + * distinguished using 'AudioBuffer.id' field. * * @param inBuffer input audio buffer. - * @param outFrameSize output frame size in bytes. - * @return retval operation completion status. - * @return outBuffer output audio buffer. + * @param outBuffer output audio buffer. + * @return retval OK if both buffers were mapped successfully. + * INVALID_ARGUMENTS if there was a problem with mapping + * any of the buffers. */ - // TODO(mnaganov): replace with FMQ version. - @callflow(next={"*"}) - processReverse(AudioBuffer inBuffer, uint32_t outFrameSize) - generates (Result retval, AudioBuffer outBuffer); + setProcessBuffers(AudioBuffer inBuffer, AudioBuffer outBuffer) generates ( + Result retval); /* * Execute a vendor specific command on the effect. The command code @@ -406,4 +404,14 @@ interface IEffect { */ setCurrentConfigForFeature(uint32_t featureId, vec configData) generates (Result retval); + + /* + * Called by the framework to deinitialize the effect and free up + * all the currently allocated resources. It is recommended to close + * the effect on the client side as soon as it is becomes unused. + * + * @return retval OK in case the success. + * INVALID_STATE if the effect was already closed. + */ + close() generates (Result retval); }; diff --git a/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp index 341466f4c9..f6e72bf87d 100644 --- a/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp +++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp @@ -115,16 +115,14 @@ Return AcousticEchoCancelerEffect::getDescriptor(getDescriptor_cb _hidl_cb return mEffect->getDescriptor(_hidl_cb); } -Return AcousticEchoCancelerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return AcousticEchoCancelerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return AcousticEchoCancelerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return AcousticEchoCancelerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return AcousticEchoCancelerEffect::command( @@ -167,6 +165,10 @@ Return AcousticEchoCancelerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return AcousticEchoCancelerEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow. Return AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs) { return mEffect->setParam(AEC_PARAM_ECHO_DELAY, echoDelayMs); diff --git a/audio/effect/2.0/default/AcousticEchoCancelerEffect.h b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h index 71fcc97ac9..c777b0230d 100644 --- a/audio/effect/2.0/default/AcousticEchoCancelerEffect.h +++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h @@ -69,12 +69,9 @@ struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -97,6 +94,7 @@ struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow. Return setEchoDelay(uint32_t echoDelayMs) override; diff --git a/audio/effect/2.0/default/Android.mk b/audio/effect/2.0/default/Android.mk index 9b997374fb..18076edc7e 100644 --- a/audio/effect/2.0/default/Android.mk +++ b/audio/effect/2.0/default/Android.mk @@ -5,6 +5,7 @@ LOCAL_MODULE := android.hardware.audio.effect@2.0-impl LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := \ AcousticEchoCancelerEffect.cpp \ + AudioBufferManager.cpp \ AutomaticGainControlEffect.cpp \ BassBoostEffect.cpp \ Conversions.cpp \ @@ -20,14 +21,19 @@ LOCAL_SRC_FILES := \ VisualizerEffect.cpp \ LOCAL_SHARED_LIBRARIES := \ + libbase \ + libcutils \ + libeffects \ + libfmq \ libhidlbase \ + libhidlmemory \ libhidltransport \ libhwbinder \ - libutils \ - libeffects \ liblog \ + libutils \ android.hardware.audio.common@2.0 \ android.hardware.audio.common@2.0-util \ android.hardware.audio.effect@2.0 \ + android.hidl.memory@1.0 \ include $(BUILD_SHARED_LIBRARY) diff --git a/audio/effect/2.0/default/AudioBufferManager.cpp b/audio/effect/2.0/default/AudioBufferManager.cpp new file mode 100644 index 0000000000..603dbb8cfd --- /dev/null +++ b/audio/effect/2.0/default/AudioBufferManager.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 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 + +#include + +#include "AudioBufferManager.h" + +namespace android { + +ANDROID_SINGLETON_STATIC_INSTANCE(AudioBufferManager); + +bool AudioBufferManager::wrap(const AudioBuffer& buffer, sp* wrapper) { + // Check if we have this buffer already + std::lock_guard lock(mLock); + ssize_t idx = mBuffers.indexOfKey(buffer.id); + if (idx >= 0) { + *wrapper = mBuffers[idx].promote(); + if (*wrapper != nullptr) return true; + mBuffers.removeItemsAt(idx); + } + // Need to create and init a new AudioBufferWrapper. + sp tempBuffer(new AudioBufferWrapper(buffer)); + if (!tempBuffer->init()) return false; + *wrapper = tempBuffer; + mBuffers.add(buffer.id, *wrapper); + return true; +} + +void AudioBufferManager::removeEntry(uint64_t id) { + std::lock_guard lock(mLock); + ssize_t idx = mBuffers.indexOfKey(id); + if (idx >= 0) mBuffers.removeItemsAt(idx); +} + +namespace hardware { +namespace audio { +namespace effect { +namespace V2_0 { +namespace implementation { + +AudioBufferWrapper::AudioBufferWrapper(const AudioBuffer& buffer) : + mHidlBuffer(buffer), mHalBuffer{ 0, { nullptr } } { +} + +AudioBufferWrapper::~AudioBufferWrapper() { + AudioBufferManager::getInstance().removeEntry(mHidlBuffer.id); +} + +bool AudioBufferWrapper::init() { + if (mHalBuffer.raw != nullptr) { + ALOGE("An attempt to init AudioBufferWrapper twice"); + return false; + } + mHidlMemory = mapMemory(mHidlBuffer.data); + if (mHidlMemory == nullptr) { + ALOGE("Could not map HIDL memory to IMemory"); + return false; + } + mHalBuffer.raw = static_cast(mHidlMemory->getPointer()); + if (mHalBuffer.raw == nullptr) { + ALOGE("IMemory buffer pointer is null"); + return false; + } + mHalBuffer.frameCount = mHidlBuffer.frameCount; + return true; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace effect +} // namespace audio +} // namespace hardware +} // namespace android diff --git a/audio/effect/2.0/default/AudioBufferManager.h b/audio/effect/2.0/default/AudioBufferManager.h new file mode 100644 index 0000000000..6d6599555b --- /dev/null +++ b/audio/effect/2.0/default/AudioBufferManager.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 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. + */ + +#ifndef android_hardware_audio_effect_V2_0_AudioBufferManager_H_ +#define android_hardware_audio_effect_V2_0_AudioBufferManager_H_ + +#include + +#include +#include +#include +#include +#include +#include + +using ::android::hardware::audio::effect::V2_0::AudioBuffer; +using ::android::hidl::memory::V1_0::IMemory; + +namespace android { +namespace hardware { +namespace audio { +namespace effect { +namespace V2_0 { +namespace implementation { + +class AudioBufferWrapper : public RefBase { + public: + explicit AudioBufferWrapper(const AudioBuffer& buffer); + virtual ~AudioBufferWrapper(); + bool init(); + audio_buffer_t* getHalBuffer() { return &mHalBuffer; } + private: + AudioBufferWrapper(const AudioBufferWrapper&) = delete; + void operator=(AudioBufferWrapper) = delete; + + AudioBuffer mHidlBuffer; + sp mHidlMemory; + audio_buffer_t mHalBuffer; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace effect +} // namespace audio +} // namespace hardware +} // namespace android + +using ::android::hardware::audio::effect::V2_0::implementation::AudioBufferWrapper; + +namespace android { + +// This class needs to be in 'android' ns because Singleton macros require that. +class AudioBufferManager : public Singleton { + public: + bool wrap(const AudioBuffer& buffer, sp* wrapper); + + private: + friend class hardware::audio::effect::V2_0::implementation::AudioBufferWrapper; + + // Called by AudioBufferWrapper. + void removeEntry(uint64_t id); + + std::mutex mLock; + KeyedVector> mBuffers; +}; + +} // namespace android + +#endif // android_hardware_audio_effect_V2_0_AudioBufferManager_H_ diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.cpp b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp index 6ebfb3c239..2c386d3dec 100644 --- a/audio/effect/2.0/default/AutomaticGainControlEffect.cpp +++ b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp @@ -130,16 +130,14 @@ Return AutomaticGainControlEffect::getDescriptor(getDescriptor_cb _hidl_cb return mEffect->getDescriptor(_hidl_cb); } -Return AutomaticGainControlEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return AutomaticGainControlEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return AutomaticGainControlEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return AutomaticGainControlEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return AutomaticGainControlEffect::command( @@ -182,6 +180,10 @@ Return AutomaticGainControlEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return AutomaticGainControlEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow. Return AutomaticGainControlEffect::setTargetLevel(int16_t targetLevelMb) { return mEffect->setParam(AGC_PARAM_TARGET_LEVEL, targetLevelMb); diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.h b/audio/effect/2.0/default/AutomaticGainControlEffect.h index 1696d3c1c2..73d94a5a44 100644 --- a/audio/effect/2.0/default/AutomaticGainControlEffect.h +++ b/audio/effect/2.0/default/AutomaticGainControlEffect.h @@ -71,12 +71,9 @@ struct AutomaticGainControlEffect : public IAutomaticGainControlEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -99,6 +96,7 @@ struct AutomaticGainControlEffect : public IAutomaticGainControlEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow. Return setTargetLevel(int16_t targetLevelMb) override; diff --git a/audio/effect/2.0/default/BassBoostEffect.cpp b/audio/effect/2.0/default/BassBoostEffect.cpp index 8a648063e7..4120e6e4ca 100644 --- a/audio/effect/2.0/default/BassBoostEffect.cpp +++ b/audio/effect/2.0/default/BassBoostEffect.cpp @@ -115,16 +115,14 @@ Return BassBoostEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return BassBoostEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return BassBoostEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return BassBoostEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return BassBoostEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return BassBoostEffect::command( @@ -167,6 +165,10 @@ Return BassBoostEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return BassBoostEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow. Return BassBoostEffect::isStrengthSupported(isStrengthSupported_cb _hidl_cb) { return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH_SUPPORTED, _hidl_cb); diff --git a/audio/effect/2.0/default/BassBoostEffect.h b/audio/effect/2.0/default/BassBoostEffect.h index 66367171d2..1861937308 100644 --- a/audio/effect/2.0/default/BassBoostEffect.h +++ b/audio/effect/2.0/default/BassBoostEffect.h @@ -69,12 +69,9 @@ struct BassBoostEffect : public IBassBoostEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -97,6 +94,7 @@ struct BassBoostEffect : public IBassBoostEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow. Return isStrengthSupported(isStrengthSupported_cb _hidl_cb) override; diff --git a/audio/effect/2.0/default/DownmixEffect.cpp b/audio/effect/2.0/default/DownmixEffect.cpp index 40bb5ec740..41497d0d2d 100644 --- a/audio/effect/2.0/default/DownmixEffect.cpp +++ b/audio/effect/2.0/default/DownmixEffect.cpp @@ -115,16 +115,14 @@ Return DownmixEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return DownmixEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return DownmixEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return DownmixEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return DownmixEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return DownmixEffect::command( @@ -167,6 +165,10 @@ Return DownmixEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return DownmixEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow. Return DownmixEffect::setType(IDownmixEffect::Type preset) { return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast(preset)); diff --git a/audio/effect/2.0/default/DownmixEffect.h b/audio/effect/2.0/default/DownmixEffect.h index c7e1b9b538..1d4c3a9e01 100644 --- a/audio/effect/2.0/default/DownmixEffect.h +++ b/audio/effect/2.0/default/DownmixEffect.h @@ -69,12 +69,9 @@ struct DownmixEffect : public IDownmixEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -97,6 +94,7 @@ struct DownmixEffect : public IDownmixEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow. Return setType(IDownmixEffect::Type preset) override; diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp index 1a7ea9cb9d..9ca58347cf 100644 --- a/audio/effect/2.0/default/Effect.cpp +++ b/audio/effect/2.0/default/Effect.cpp @@ -17,8 +17,8 @@ #include #define LOG_TAG "EffectHAL" -#include #include +#include #include "Conversions.h" #include "Effect.h" @@ -33,20 +33,108 @@ namespace implementation { using ::android::hardware::audio::common::V2_0::AudioChannelMask; using ::android::hardware::audio::common::V2_0::AudioFormat; +using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits; + +namespace { + +class ProcessThread : public Thread { + public: + // ProcessThread's lifespan never exceeds Effect's lifespan. + ProcessThread(std::atomic* stop, + effect_handle_t effect, + std::atomic* inBuffer, + std::atomic* outBuffer, + Effect::StatusMQ* statusMQ, + EventFlag* efGroup) + : Thread(false /*canCallJava*/), + mStop(stop), + mEffect(effect), + mHasProcessReverse((*mEffect)->process_reverse != NULL), + mInBuffer(inBuffer), + mOutBuffer(outBuffer), + mStatusMQ(statusMQ), + mEfGroup(efGroup) { + } + virtual ~ProcessThread() {} + + private: + std::atomic* mStop; + effect_handle_t mEffect; + bool mHasProcessReverse; + std::atomic* mInBuffer; + std::atomic* mOutBuffer; + Effect::StatusMQ* mStatusMQ; + EventFlag* mEfGroup; + + bool threadLoop() override; +}; + +bool ProcessThread::threadLoop() { + // This implementation doesn't return control back to the Thread until it decides to stop, + // as the Thread uses mutexes, and this can lead to priority inversion. + while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) { + uint32_t efState = 0; + mEfGroup->wait( + static_cast(MessageQueueFlagBits::REQUEST_PROCESS_ALL), + &efState, + NS_PER_SEC); + if (!(efState & static_cast(MessageQueueFlagBits::REQUEST_PROCESS_ALL))) { + continue; // Nothing to do. + } + Result retval = Result::OK; + if (efState & static_cast(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE) + && !mHasProcessReverse) { + retval = Result::NOT_SUPPORTED; + } + + if (retval == Result::OK) { + // affects both buffer pointers and their contents. + std::atomic_thread_fence(std::memory_order_acquire); + int32_t processResult; + audio_buffer_t* inBuffer = + std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed); + audio_buffer_t* outBuffer = + std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed); + if (inBuffer != nullptr && outBuffer != nullptr) { + if (efState & static_cast(MessageQueueFlagBits::REQUEST_PROCESS)) { + processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer); + } else { + processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer); + } + std::atomic_thread_fence(std::memory_order_release); + } else { + ALOGE("processing buffers were not set before calling 'process'"); + processResult = -ENODEV; + } + switch(processResult) { + case 0: retval = Result::OK; break; + case -ENODATA: retval = Result::INVALID_STATE; break; + case -EINVAL: retval = Result::INVALID_ARGUMENTS; break; + default: retval = Result::NOT_INITIALIZED; + } + } + if (!mStatusMQ->write(&retval)) { + ALOGW("status message queue write failed"); + } + mEfGroup->wake(static_cast(MessageQueueFlagBits::DONE_PROCESSING)); + } + + return false; +} + +} // namespace // static const char *Effect::sContextResultOfCommand = "returned status"; const char *Effect::sContextCallToCommand = "error"; const char *Effect::sContextCallFunction = sContextCallToCommand; -Effect::Effect(effect_handle_t handle) : mHandle(handle) { +Effect::Effect(effect_handle_t handle) + : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) { } Effect::~Effect() { - int status = EffectRelease(mHandle); - ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status)); - EffectMap::getInstance().remove(mHandle); - mHandle = 0; + close(); } // static @@ -83,9 +171,6 @@ void Effect::effectAuxChannelsConfigToHal( // static void Effect::effectBufferConfigFromHal( const buffer_config_t& halConfig, EffectBufferConfig* config) { - // TODO(mnaganov): Use FMQ instead of AudioBuffer. - (void)halConfig.buffer.frameCount; - (void)halConfig.buffer.raw; config->samplingRateHz = halConfig.samplingRate; config->channels = AudioChannelMask(halConfig.channels); config->format = AudioFormat(halConfig.format); @@ -95,12 +180,13 @@ void Effect::effectBufferConfigFromHal( // static void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) { - // TODO(mnaganov): Use FMQ instead of AudioBuffer. + // Note: setting the buffers directly is considered obsolete. They need to be set + // using 'setProcessBuffers'. halConfig->buffer.frameCount = 0; halConfig->buffer.raw = NULL; halConfig->samplingRate = config.samplingRateHz; halConfig->channels = static_cast(config.channels); - // TODO(mnaganov): As the calling code does not use BP for now, implement later. + // TODO(mnaganov): The framework code currently does not use BP, implement later. halConfig->bufferProvider.cookie = NULL; halConfig->bufferProvider.getBuffer = NULL; halConfig->bufferProvider.releaseBuffer = NULL; @@ -250,31 +336,66 @@ Result Effect::getSupportedConfigsImpl( }); } -void Effect::processImpl( - ProcessFunction process, - const char* funcName, - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - ProcessCallback cb) { - audio_buffer_t halInBuffer; - halInBuffer.frameCount = inBuffer.frameCount; - halInBuffer.u8 = const_cast(&inBuffer.data[0]); - audio_buffer_t halOutBuffer; - halOutBuffer.frameCount = halInBuffer.frameCount; - // TODO(mnaganov): Consider stashing the buffer to avoid reallocating it every time. - std::unique_ptr halOutBufferData( - new uint8_t[halOutBuffer.frameCount * outFrameSize]); - halOutBuffer.u8 = &halOutBufferData[0]; - status_t status = process(mHandle, &halInBuffer, &halOutBuffer); - Result retval = analyzeStatus(funcName, "", sContextCallFunction, status); - AudioBuffer outBuffer; - if (status == OK) { - outBuffer.frameCount = halOutBuffer.frameCount; - outBuffer.data.setToExternal(halOutBuffer.u8, halOutBuffer.frameCount * outFrameSize); - } else { - outBuffer.frameCount = 0; +Return Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) { + status_t status; + // Create message queue. + if (mStatusMQ) { + ALOGE("the client attempts to call prepareForProcessing_cb twice"); + _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor()); + return Void(); + } + std::unique_ptr tempStatusMQ(new StatusMQ(1, true /*EventFlag*/)); + if (!tempStatusMQ->isValid()) { + ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid"); + _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor()); + return Void(); } - cb(retval, outBuffer); + status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup); + if (status != OK || !mEfGroup) { + ALOGE("failed creating event flag for status MQ: %s", strerror(-status)); + _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor()); + return Void(); + } + + // Create and launch the thread. + mProcessThread = new ProcessThread( + &mStopProcessThread, + mHandle, + &mHalInBufferPtr, + &mHalOutBufferPtr, + tempStatusMQ.get(), + mEfGroup); + status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO); + if (status != OK) { + ALOGW("failed to start effect processing thread: %s", strerror(-status)); + _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync()); + return Void(); + } + + mStatusMQ = std::move(tempStatusMQ); + _hidl_cb(Result::OK, *mStatusMQ->getDesc()); + return Void(); +} + +Return Effect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + AudioBufferManager& manager = AudioBufferManager::getInstance(); + sp tempInBuffer, tempOutBuffer; + if (!manager.wrap(inBuffer, &tempInBuffer)) { + ALOGE("Could not map memory of the input buffer"); + return Result::INVALID_ARGUMENTS; + } + if (!manager.wrap(outBuffer, &tempOutBuffer)) { + ALOGE("Could not map memory of the output buffer"); + return Result::INVALID_ARGUMENTS; + } + mInBuffer = tempInBuffer; + mOutBuffer = tempOutBuffer; + // The processing thread only reads these pointers after waking up by an event flag, + // so it's OK to update the pair non-atomically. + mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release); + mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release); + return Result::OK; } Result Effect::sendCommand(int commandCode, const char* commandName) { @@ -510,23 +631,6 @@ Return Effect::getDescriptor(getDescriptor_cb _hidl_cb) { return Void(); } -Return Effect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - processImpl((*mHandle)->process, "process", inBuffer, outFrameSize, _hidl_cb); - return Void(); -} - -Return Effect::processReverse( - const AudioBuffer& inBuffer, uint32_t outFrameSize, processReverse_cb _hidl_cb) { - if ((*mHandle)->process_reverse != NULL) { - processImpl( - (*mHandle)->process_reverse, "process_reverse", inBuffer, outFrameSize, _hidl_cb); - } else { - _hidl_cb(Result::NOT_SUPPORTED, AudioBuffer()); - } - return Void(); -} - Return Effect::command( uint32_t commandId, const hidl_vec& data, @@ -611,6 +715,27 @@ Return Effect::setCurrentConfigForFeature( EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG", sizeof(halCmd), halCmd); } +Return Effect::close() { + if (mIsClosed) return Result::INVALID_STATE; + mIsClosed = true; + if (mProcessThread.get()) { + mStopProcessThread.store(true, std::memory_order_release); + status_t status = mProcessThread->requestExitAndWait(); + ALOGE_IF(status, "processing thread exit error: %s", strerror(-status)); + } + if (mEfGroup) { + status_t status = EventFlag::deleteEventFlag(&mEfGroup); + ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status)); + } + mInBuffer.clear(); + mOutBuffer.clear(); + int status = EffectRelease(mHandle); + ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status)); + EffectMap::getInstance().remove(mHandle); + mHandle = 0; + return Result::OK; +} + } // namespace implementation } // namespace V2_0 } // namespace effect diff --git a/audio/effect/2.0/default/Effect.h b/audio/effect/2.0/default/Effect.h index 61d01211d9..8daffb81ea 100644 --- a/audio/effect/2.0/default/Effect.h +++ b/audio/effect/2.0/default/Effect.h @@ -17,16 +17,21 @@ #ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H #define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H +#include #include #include #include -#include - +#include +#include #include +#include +#include #include +#include "AudioBufferManager.h" + namespace android { namespace hardware { namespace audio { @@ -54,6 +59,8 @@ using ::android::hardware::hidl_string; using ::android::sp; struct Effect : public IEffect { + typedef MessageQueue StatusMQ; + explicit Effect(effect_handle_t handle); // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow. @@ -83,12 +90,9 @@ struct Effect : public IEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -111,6 +115,7 @@ struct Effect : public IEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Utility methods for extending interfaces. template Return getIntegerParam( @@ -161,8 +166,6 @@ struct Effect : public IEffect { friend struct VirtualizerEffect; // for getParameterImpl friend struct VisualizerEffect; // to allow executing commands - typedef int32_t (*ProcessFunction)( - effect_handle_t self, audio_buffer_t* inBuffer, audio_buffer_t* outBuffer); using CommandSuccessCallback = std::function; using GetConfigCallback = std::function; using GetCurrentConfigSuccessCallback = std::function; @@ -170,13 +173,21 @@ struct Effect : public IEffect { std::function; using GetSupportedConfigsSuccessCallback = std::function; - using ProcessCallback = std::function; static const char *sContextResultOfCommand; static const char *sContextCallToCommand; static const char *sContextCallFunction; + bool mIsClosed; effect_handle_t mHandle; + sp mInBuffer; + sp mOutBuffer; + std::atomic mHalInBufferPtr; + std::atomic mHalOutBufferPtr; + std::unique_ptr mStatusMQ; + EventFlag* mEfGroup; + std::atomic mStopProcessThread; + sp mProcessThread; virtual ~Effect(); @@ -218,12 +229,6 @@ struct Effect : public IEffect { uint32_t maxConfigs, uint32_t configSize, GetSupportedConfigsSuccessCallback onSuccess); - void processImpl( - ProcessFunction process, - const char* funcName, - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - ProcessCallback cb); Result sendCommand(int commandCode, const char* commandName); Result sendCommand(int commandCode, const char* commandName, uint32_t size, void* data); Result sendCommandReturningData( diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp index db1ad51f68..2c1fd683fb 100644 --- a/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp +++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp @@ -144,16 +144,14 @@ Return EnvironmentalReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) return mEffect->getDescriptor(_hidl_cb); } -Return EnvironmentalReverbEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return EnvironmentalReverbEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return EnvironmentalReverbEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return EnvironmentalReverbEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return EnvironmentalReverbEffect::command( @@ -196,6 +194,9 @@ Return EnvironmentalReverbEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return EnvironmentalReverbEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow. Return EnvironmentalReverbEffect::setBypass(bool bypass) { diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.h b/audio/effect/2.0/default/EnvironmentalReverbEffect.h index edb57477ba..d0c8962537 100644 --- a/audio/effect/2.0/default/EnvironmentalReverbEffect.h +++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.h @@ -81,12 +81,9 @@ struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -109,6 +106,7 @@ struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow. Return setBypass(bool bypass) override; diff --git a/audio/effect/2.0/default/EqualizerEffect.cpp b/audio/effect/2.0/default/EqualizerEffect.cpp index 490a300355..833ea5b046 100644 --- a/audio/effect/2.0/default/EqualizerEffect.cpp +++ b/audio/effect/2.0/default/EqualizerEffect.cpp @@ -135,16 +135,14 @@ Return EqualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return EqualizerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return EqualizerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return EqualizerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return EqualizerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return EqualizerEffect::command( @@ -187,6 +185,9 @@ Return EqualizerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return EqualizerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow. Return EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) { diff --git a/audio/effect/2.0/default/EqualizerEffect.h b/audio/effect/2.0/default/EqualizerEffect.h index ba99e2b8c5..200ca1a520 100644 --- a/audio/effect/2.0/default/EqualizerEffect.h +++ b/audio/effect/2.0/default/EqualizerEffect.h @@ -83,12 +83,9 @@ struct EqualizerEffect : public IEqualizerEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -111,6 +108,7 @@ struct EqualizerEffect : public IEqualizerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow. Return getNumBands(getNumBands_cb _hidl_cb) override; diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp index a49019c0a5..1f7124beeb 100644 --- a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp +++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp @@ -117,16 +117,14 @@ Return LoudnessEnhancerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return LoudnessEnhancerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return LoudnessEnhancerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return LoudnessEnhancerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return LoudnessEnhancerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return LoudnessEnhancerEffect::command( @@ -169,6 +167,9 @@ Return LoudnessEnhancerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return LoudnessEnhancerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow. Return LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) { diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.h b/audio/effect/2.0/default/LoudnessEnhancerEffect.h index 8ca6e94fad..308c47f337 100644 --- a/audio/effect/2.0/default/LoudnessEnhancerEffect.h +++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.h @@ -79,12 +79,9 @@ struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -107,6 +104,7 @@ struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow. Return setTargetGain(int32_t targetGainMb) override; diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.cpp b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp index 69a12261a4..b0b929f0c1 100644 --- a/audio/effect/2.0/default/NoiseSuppressionEffect.cpp +++ b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp @@ -128,16 +128,14 @@ Return NoiseSuppressionEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return NoiseSuppressionEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return NoiseSuppressionEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return NoiseSuppressionEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return NoiseSuppressionEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return NoiseSuppressionEffect::command( @@ -180,6 +178,9 @@ Return NoiseSuppressionEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return NoiseSuppressionEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow. Return NoiseSuppressionEffect::setSuppressionLevel(INoiseSuppressionEffect::Level level) { diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.h b/audio/effect/2.0/default/NoiseSuppressionEffect.h index b73727ead7..5e3a5c160f 100644 --- a/audio/effect/2.0/default/NoiseSuppressionEffect.h +++ b/audio/effect/2.0/default/NoiseSuppressionEffect.h @@ -81,12 +81,9 @@ struct NoiseSuppressionEffect : public INoiseSuppressionEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -109,6 +106,7 @@ struct NoiseSuppressionEffect : public INoiseSuppressionEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow. Return setSuppressionLevel(INoiseSuppressionEffect::Level level) override; diff --git a/audio/effect/2.0/default/PresetReverbEffect.cpp b/audio/effect/2.0/default/PresetReverbEffect.cpp index 0e6d1b8a31..803c9bef1a 100644 --- a/audio/effect/2.0/default/PresetReverbEffect.cpp +++ b/audio/effect/2.0/default/PresetReverbEffect.cpp @@ -115,16 +115,14 @@ Return PresetReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return PresetReverbEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return PresetReverbEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return PresetReverbEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return PresetReverbEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return PresetReverbEffect::command( @@ -167,6 +165,9 @@ Return PresetReverbEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return PresetReverbEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow. Return PresetReverbEffect::setPreset(IPresetReverbEffect::Preset preset) { diff --git a/audio/effect/2.0/default/PresetReverbEffect.h b/audio/effect/2.0/default/PresetReverbEffect.h index 4d39569428..f6a900ca15 100644 --- a/audio/effect/2.0/default/PresetReverbEffect.h +++ b/audio/effect/2.0/default/PresetReverbEffect.h @@ -79,12 +79,9 @@ struct PresetReverbEffect : public IPresetReverbEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -107,6 +104,7 @@ struct PresetReverbEffect : public IPresetReverbEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow. Return setPreset(IPresetReverbEffect::Preset preset) override; diff --git a/audio/effect/2.0/default/VirtualizerEffect.cpp b/audio/effect/2.0/default/VirtualizerEffect.cpp index 313674d41e..4f193e75e9 100644 --- a/audio/effect/2.0/default/VirtualizerEffect.cpp +++ b/audio/effect/2.0/default/VirtualizerEffect.cpp @@ -127,16 +127,14 @@ Return VirtualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return VirtualizerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return VirtualizerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return VirtualizerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return VirtualizerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return VirtualizerEffect::command( @@ -179,6 +177,9 @@ Return VirtualizerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return VirtualizerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow. Return VirtualizerEffect::isStrengthSupported() { diff --git a/audio/effect/2.0/default/VirtualizerEffect.h b/audio/effect/2.0/default/VirtualizerEffect.h index ba89a6198e..5b0773d3b3 100644 --- a/audio/effect/2.0/default/VirtualizerEffect.h +++ b/audio/effect/2.0/default/VirtualizerEffect.h @@ -80,12 +80,9 @@ struct VirtualizerEffect : public IVirtualizerEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -108,6 +105,7 @@ struct VirtualizerEffect : public IVirtualizerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow. Return isStrengthSupported() override; diff --git a/audio/effect/2.0/default/VisualizerEffect.cpp b/audio/effect/2.0/default/VisualizerEffect.cpp index a53eabcccd..141817b40c 100644 --- a/audio/effect/2.0/default/VisualizerEffect.cpp +++ b/audio/effect/2.0/default/VisualizerEffect.cpp @@ -115,16 +115,14 @@ Return VisualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return VisualizerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return VisualizerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return VisualizerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return VisualizerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return VisualizerEffect::command( @@ -167,6 +165,9 @@ Return VisualizerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return VisualizerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow. Return VisualizerEffect::setCaptureSize(uint16_t captureSize) { diff --git a/audio/effect/2.0/default/VisualizerEffect.h b/audio/effect/2.0/default/VisualizerEffect.h index ae0b05c03b..b6dc768375 100644 --- a/audio/effect/2.0/default/VisualizerEffect.h +++ b/audio/effect/2.0/default/VisualizerEffect.h @@ -79,12 +79,9 @@ struct VisualizerEffect : public IVisualizerEffect { Return setAudioSource(AudioSource source) override; Return offload(const EffectOffloadParameter& param) override; Return getDescriptor(getDescriptor_cb _hidl_cb) override; - Return process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return command( uint32_t commandId, const hidl_vec& data, @@ -107,6 +104,7 @@ struct VisualizerEffect : public IVisualizerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return setCurrentConfigForFeature( uint32_t featureId, const hidl_vec& configData) override; + Return close() override; // Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow. Return setCaptureSize(uint16_t captureSize) override; diff --git a/audio/effect/2.0/types.hal b/audio/effect/2.0/types.hal index ad7f4ce0b1..0cac59ad8f 100644 --- a/audio/effect/2.0/types.hal +++ b/audio/effect/2.0/types.hal @@ -222,10 +222,10 @@ struct EffectDescriptor { * samples for all channels at a given time. Frame size for unspecified format * (AUDIO_FORMAT_OTHER) is 8 bit by definition. */ -// TODO(mnaganov): replace with FMQ version. struct AudioBuffer { + uint64_t id; uint32_t frameCount; - vec data; + memory data; }; @export(name="effect_buffer_access_e", value_prefix="EFFECT_BUFFER_") @@ -284,3 +284,14 @@ struct EffectOffloadParameter { AudioIoHandle ioHandle; // io handle of the playback thread // the effect is attached to }; + +/* + * The message queue flags used to synchronize reads and writes from + * the status message queue used by effects. + */ +enum MessageQueueFlagBits : uint32_t { + DONE_PROCESSING = 1 << 0, + REQUEST_PROCESS = 1 << 1, + REQUEST_PROCESS_REVERSE = 1 << 2, + REQUEST_PROCESS_ALL = REQUEST_PROCESS | REQUEST_PROCESS_REVERSE +}; -- cgit v1.2.3