Loading audio/effect/2.0/IEffect.hal +44 −36 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); }; audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp +10 −8 Original line number Diff line number Diff line Loading @@ -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( Loading Loading @@ -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); Loading audio/effect/2.0/default/AcousticEchoCancelerEffect.h +4 −6 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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; Loading audio/effect/2.0/default/Android.mk +8 −2 Original line number Diff line number Diff line Loading @@ -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 \ Loading @@ -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) audio/effect/2.0/default/AudioBufferManager.cpp 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * 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 Loading
audio/effect/2.0/IEffect.hal +44 −36 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); };
audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp +10 −8 Original line number Diff line number Diff line Loading @@ -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( Loading Loading @@ -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); Loading
audio/effect/2.0/default/AcousticEchoCancelerEffect.h +4 −6 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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; Loading
audio/effect/2.0/default/Android.mk +8 −2 Original line number Diff line number Diff line Loading @@ -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 \ Loading @@ -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)
audio/effect/2.0/default/AudioBufferManager.cpp 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * 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