diff options
author | Mikhail Naganov <mnaganov@google.com> | 2017-01-10 23:22:49 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-01-10 23:22:49 +0000 |
commit | 5863c4ca84b8d42bd27bf1f684bf4ac95eb0f876 (patch) | |
tree | 68ffb6082386128803ee83fec4ae4814aa3a22a9 | |
parent | 0ebed38d029d1d70c12ab5aba3a37eca37167687 (diff) | |
parent | a331de14219b34b08f4cbb462a45f1fd82a92d48 (diff) | |
download | platform_hardware_interfaces-5863c4ca84b8d42bd27bf1f684bf4ac95eb0f876.tar.gz platform_hardware_interfaces-5863c4ca84b8d42bd27bf1f684bf4ac95eb0f876.tar.bz2 platform_hardware_interfaces-5863c4ca84b8d42bd27bf1f684bf4ac95eb0f876.zip |
Merge "audiohal: Re-implement effect process using FMQ and IMemory"
29 files changed, 581 insertions, 263 deletions
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<Result> 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<uint8_t> 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<void> AcousticEchoCancelerEffect::getDescriptor(getDescriptor_cb _hidl_cb return mEffect->getDescriptor(_hidl_cb); } -Return<void> AcousticEchoCancelerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> AcousticEchoCancelerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> AcousticEchoCancelerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> AcousticEchoCancelerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> AcousticEchoCancelerEffect::command( @@ -167,6 +165,10 @@ Return<Result> AcousticEchoCancelerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> AcousticEchoCancelerEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow. Return<Result> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -97,6 +94,7 @@ struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow. Return<Result> 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 <atomic> + +#include <hidlmemory/mapping.h> + +#include "AudioBufferManager.h" + +namespace android { + +ANDROID_SINGLETON_STATIC_INSTANCE(AudioBufferManager); + +bool AudioBufferManager::wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper) { + // Check if we have this buffer already + std::lock_guard<std::mutex> 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<AudioBufferWrapper> 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<std::mutex> 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<void*>(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 <mutex> + +#include <android/hardware/audio/effect/2.0/types.h> +#include <android/hidl/memory/1.0/IMemory.h> +#include <system/audio_effect.h> +#include <utils/RefBase.h> +#include <utils/KeyedVector.h> +#include <utils/Singleton.h> + +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<IMemory> 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<AudioBufferManager> { + public: + bool wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper); + + private: + friend class hardware::audio::effect::V2_0::implementation::AudioBufferWrapper; + + // Called by AudioBufferWrapper. + void removeEntry(uint64_t id); + + std::mutex mLock; + KeyedVector<uint64_t, wp<AudioBufferWrapper>> 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<void> AutomaticGainControlEffect::getDescriptor(getDescriptor_cb _hidl_cb return mEffect->getDescriptor(_hidl_cb); } -Return<void> AutomaticGainControlEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> AutomaticGainControlEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> AutomaticGainControlEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> AutomaticGainControlEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> AutomaticGainControlEffect::command( @@ -182,6 +180,10 @@ Return<Result> AutomaticGainControlEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> AutomaticGainControlEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow. Return<Result> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -99,6 +96,7 @@ struct AutomaticGainControlEffect : public IAutomaticGainControlEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow. Return<Result> 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<void> BassBoostEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> BassBoostEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> BassBoostEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> BassBoostEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> BassBoostEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> BassBoostEffect::command( @@ -167,6 +165,10 @@ Return<Result> BassBoostEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> BassBoostEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow. Return<void> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -97,6 +94,7 @@ struct BassBoostEffect : public IBassBoostEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow. Return<void> 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<void> DownmixEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> DownmixEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> DownmixEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> DownmixEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> DownmixEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> DownmixEffect::command( @@ -167,6 +165,10 @@ Return<Result> DownmixEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> DownmixEffect::close() { + return mEffect->close(); +} + // Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow. Return<Result> DownmixEffect::setType(IDownmixEffect::Type preset) { return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast<downmix_type_t>(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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -97,6 +94,7 @@ struct DownmixEffect : public IDownmixEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow. Return<Result> 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 <memory.h> #define LOG_TAG "EffectHAL" -#include <media/EffectsFactoryApi.h> #include <android/log.h> +#include <media/EffectsFactoryApi.h> #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<bool>* stop, + effect_handle_t effect, + std::atomic<audio_buffer_t*>* inBuffer, + std::atomic<audio_buffer_t*>* 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<bool>* mStop; + effect_handle_t mEffect; + bool mHasProcessReverse; + std::atomic<audio_buffer_t*>* mInBuffer; + std::atomic<audio_buffer_t*>* 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<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL), + &efState, + NS_PER_SEC); + if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL))) { + continue; // Nothing to do. + } + Result retval = Result::OK; + if (efState & static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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<uint8_t*>(&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<uint8_t[]> 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<void> 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<StatusMQ> 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<Result>()); + return Void(); + } + + mStatusMQ = std::move(tempStatusMQ); + _hidl_cb(Result::OK, *mStatusMQ->getDesc()); + return Void(); +} + +Return<Result> Effect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + AudioBufferManager& manager = AudioBufferManager::getInstance(); + sp<AudioBufferWrapper> 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<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) { return Void(); } -Return<void> Effect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - processImpl((*mHandle)->process, "process", inBuffer, outFrameSize, _hidl_cb); - return Void(); -} - -Return<void> 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<void> Effect::command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -611,6 +715,27 @@ Return<Result> Effect::setCurrentConfigForFeature( EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG", sizeof(halCmd), halCmd); } +Return<Result> 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 <atomic> #include <memory> #include <vector> #include <android/hardware/audio/effect/2.0/IEffect.h> -#include <hidl/Status.h> - +#include <fmq/EventFlag.h> +#include <fmq/MessageQueue.h> #include <hidl/MQDescriptor.h> +#include <hidl/Status.h> +#include <utils/Thread.h> #include <hardware/audio_effect.h> +#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<Result, kSynchronizedReadWrite> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -111,6 +115,7 @@ struct Effect : public IEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Utility methods for extending interfaces. template<typename T> Return<void> 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<void()>; using GetConfigCallback = std::function<void(Result retval, const EffectConfig& config)>; using GetCurrentConfigSuccessCallback = std::function<void(void* configData)>; @@ -170,13 +173,21 @@ struct Effect : public IEffect { std::function<void(uint32_t valueSize, const void* valueData)>; using GetSupportedConfigsSuccessCallback = std::function<void(uint32_t supportedConfigs, void* configsData)>; - using ProcessCallback = std::function<void(Result retval, const AudioBuffer& outBuffer)>; static const char *sContextResultOfCommand; static const char *sContextCallToCommand; static const char *sContextCallFunction; + bool mIsClosed; effect_handle_t mHandle; + sp<AudioBufferWrapper> mInBuffer; + sp<AudioBufferWrapper> mOutBuffer; + std::atomic<audio_buffer_t*> mHalInBufferPtr; + std::atomic<audio_buffer_t*> mHalOutBufferPtr; + std::unique_ptr<StatusMQ> mStatusMQ; + EventFlag* mEfGroup; + std::atomic<bool> mStopProcessThread; + sp<Thread> 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<void> EnvironmentalReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) return mEffect->getDescriptor(_hidl_cb); } -Return<void> EnvironmentalReverbEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> EnvironmentalReverbEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> EnvironmentalReverbEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> EnvironmentalReverbEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> EnvironmentalReverbEffect::command( @@ -196,6 +194,9 @@ Return<Result> EnvironmentalReverbEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> EnvironmentalReverbEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow. Return<Result> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -109,6 +106,7 @@ struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow. Return<Result> 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<void> EqualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> EqualizerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> EqualizerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> EqualizerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> EqualizerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> EqualizerEffect::command( @@ -187,6 +185,9 @@ Return<Result> EqualizerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> EqualizerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow. Return<void> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -111,6 +108,7 @@ struct EqualizerEffect : public IEqualizerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow. Return<void> 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<void> LoudnessEnhancerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> LoudnessEnhancerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> LoudnessEnhancerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> LoudnessEnhancerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> LoudnessEnhancerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> LoudnessEnhancerEffect::command( @@ -169,6 +167,9 @@ Return<Result> LoudnessEnhancerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> LoudnessEnhancerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow. Return<Result> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -107,6 +104,7 @@ struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow. Return<Result> 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<void> NoiseSuppressionEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> NoiseSuppressionEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> NoiseSuppressionEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> NoiseSuppressionEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> NoiseSuppressionEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> NoiseSuppressionEffect::command( @@ -180,6 +178,9 @@ Return<Result> NoiseSuppressionEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> NoiseSuppressionEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow. Return<Result> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -109,6 +106,7 @@ struct NoiseSuppressionEffect : public INoiseSuppressionEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow. Return<Result> 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<void> PresetReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> PresetReverbEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> PresetReverbEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> PresetReverbEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> PresetReverbEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> PresetReverbEffect::command( @@ -167,6 +165,9 @@ Return<Result> PresetReverbEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> PresetReverbEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow. Return<Result> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -107,6 +104,7 @@ struct PresetReverbEffect : public IPresetReverbEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow. Return<Result> 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<void> VirtualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> VirtualizerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> VirtualizerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> VirtualizerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> VirtualizerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> VirtualizerEffect::command( @@ -179,6 +177,9 @@ Return<Result> VirtualizerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> VirtualizerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow. Return<bool> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -108,6 +105,7 @@ struct VirtualizerEffect : public IVirtualizerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow. Return<bool> 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<void> VisualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) { return mEffect->getDescriptor(_hidl_cb); } -Return<void> VisualizerEffect::process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) { - return mEffect->process(inBuffer, outFrameSize, _hidl_cb); +Return<void> VisualizerEffect::prepareForProcessing( + prepareForProcessing_cb _hidl_cb) { + return mEffect->prepareForProcessing(_hidl_cb); } -Return<void> VisualizerEffect::processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) { - return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb); +Return<Result> VisualizerEffect::setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) { + return mEffect->setProcessBuffers(inBuffer, outBuffer); } Return<void> VisualizerEffect::command( @@ -167,6 +165,9 @@ Return<Result> VisualizerEffect::setCurrentConfigForFeature( return mEffect->setCurrentConfigForFeature(featureId, configData); } +Return<Result> VisualizerEffect::close() { + return mEffect->close(); +} // Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow. Return<Result> 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<Result> setAudioSource(AudioSource source) override; Return<Result> offload(const EffectOffloadParameter& param) override; Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override; - Return<void> process( - const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override; - Return<void> processReverse( - const AudioBuffer& inBuffer, - uint32_t outFrameSize, - processReverse_cb _hidl_cb) override; + Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override; + Return<Result> setProcessBuffers( + const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override; Return<void> command( uint32_t commandId, const hidl_vec<uint8_t>& data, @@ -107,6 +104,7 @@ struct VisualizerEffect : public IVisualizerEffect { getCurrentConfigForFeature_cb _hidl_cb) override; Return<Result> setCurrentConfigForFeature( uint32_t featureId, const hidl_vec<uint8_t>& configData) override; + Return<Result> close() override; // Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow. Return<Result> 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<uint8_t> 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 +}; |