blob: 7b8cfb13aedb9bb7b020207770dd0e3c19f5fdf8 [file] [log] [blame]
Shunkai Yao65c7c702024-01-09 20:50:53 +00001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <memory>
18#define LOG_TAG "AHAL_EffectContext"
19#include "effect-impl/EffectContext.h"
20#include "include/effect-impl/EffectTypes.h"
21
22using aidl::android::hardware::audio::common::getChannelCount;
23using aidl::android::hardware::audio::common::getFrameSizeInBytes;
24using aidl::android::hardware::audio::effect::IEffect;
Shunkai Yao7e2c3712024-02-03 06:47:18 +000025using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
Shunkai Yao65c7c702024-01-09 20:50:53 +000026using aidl::android::media::audio::common::PcmType;
27using ::android::hardware::EventFlag;
28
29namespace aidl::android::hardware::audio::effect {
30
31EffectContext::EffectContext(size_t statusDepth, const Parameter::Common& common) {
32 LOG_ALWAYS_FATAL_IF(RetCode::SUCCESS != setCommon(common), "illegalCommonParameter");
33
34 // in/outBuffer size in float (FMQ data format defined for DataMQ)
35 size_t inBufferSizeInFloat = common.input.frameCount * mInputFrameSize / sizeof(float);
36 size_t outBufferSizeInFloat = common.output.frameCount * mOutputFrameSize / sizeof(float);
37
38 // only status FMQ use the EventFlag
39 mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
40 mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
41 mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
42
43 if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
Shunkai Yao7e2c3712024-02-03 06:47:18 +000044 LOG(ERROR) << __func__ << " created invalid FMQ, statusMQ: " << mStatusMQ->isValid()
45 << " inputMQ: " << mInputMQ->isValid() << " outputMQ: " << mOutputMQ->isValid();
Shunkai Yao65c7c702024-01-09 20:50:53 +000046 }
47
48 ::android::status_t status =
49 EventFlag::createEventFlag(mStatusMQ->getEventFlagWord(), &mEfGroup);
50 LOG_ALWAYS_FATAL_IF(status != ::android::OK || !mEfGroup, " create EventFlagGroup failed ");
Shunkai Yao08c05dd2024-01-25 00:45:55 +000051 mWorkBuffer.resize(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
Shunkai Yao65c7c702024-01-09 20:50:53 +000052}
53
54// reset buffer status by abandon input data in FMQ
55void EffectContext::resetBuffer() {
56 auto buffer = static_cast<float*>(mWorkBuffer.data());
Shunkai Yao7e2c3712024-02-03 06:47:18 +000057 if (mStatusMQ) {
58 std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
59 }
Shunkai Yao65c7c702024-01-09 20:50:53 +000060 if (mInputMQ) {
61 mInputMQ->read(buffer, mInputMQ->availableToRead());
62 }
63}
64
65void EffectContext::dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet) {
66 if (!mInputMQ) {
67 mInputMQ = std::make_shared<DataMQ>(mCommon.input.frameCount * mInputFrameSize /
68 sizeof(float));
69 }
70 if (!mOutputMQ) {
71 mOutputMQ = std::make_shared<DataMQ>(mCommon.output.frameCount * mOutputFrameSize /
72 sizeof(float));
73 }
74 dupeFmq(effectRet);
75}
76
77void EffectContext::dupeFmq(IEffect::OpenEffectReturn* effectRet) {
Shunkai Yao7e2c3712024-02-03 06:47:18 +000078 if (effectRet && mStatusMQ && mInputMQ && mOutputMQ) {
Shunkai Yao65c7c702024-01-09 20:50:53 +000079 effectRet->statusMQ = mStatusMQ->dupeDesc();
80 effectRet->inputDataMQ = mInputMQ->dupeDesc();
81 effectRet->outputDataMQ = mOutputMQ->dupeDesc();
82 }
83}
84
85float* EffectContext::getWorkBuffer() {
86 return static_cast<float*>(mWorkBuffer.data());
87}
88
Shunkai Yao08c05dd2024-01-25 00:45:55 +000089size_t EffectContext::getWorkBufferSize() const {
90 return mWorkBuffer.size();
91}
92
Shunkai Yao65c7c702024-01-09 20:50:53 +000093std::shared_ptr<EffectContext::StatusMQ> EffectContext::getStatusFmq() const {
94 return mStatusMQ;
95}
96
97std::shared_ptr<EffectContext::DataMQ> EffectContext::getInputDataFmq() const {
98 return mInputMQ;
99}
100
101std::shared_ptr<EffectContext::DataMQ> EffectContext::getOutputDataFmq() const {
102 return mOutputMQ;
103}
104
105size_t EffectContext::getInputFrameSize() const {
106 return mInputFrameSize;
107}
108
109size_t EffectContext::getOutputFrameSize() const {
110 return mOutputFrameSize;
111}
112
113int EffectContext::getSessionId() const {
114 return mCommon.session;
115}
116
117int EffectContext::getIoHandle() const {
118 return mCommon.ioHandle;
119}
120
121RetCode EffectContext::setOutputDevice(
122 const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device) {
123 mOutputDevice = device;
124 return RetCode::SUCCESS;
125}
126
127std::vector<aidl::android::media::audio::common::AudioDeviceDescription>
128EffectContext::getOutputDevice() {
129 return mOutputDevice;
130}
131
132RetCode EffectContext::setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
133 mMode = mode;
134 return RetCode::SUCCESS;
135}
136aidl::android::media::audio::common::AudioMode EffectContext::getAudioMode() {
137 return mMode;
138}
139
140RetCode EffectContext::setAudioSource(
141 const aidl::android::media::audio::common::AudioSource& source) {
142 mSource = source;
143 return RetCode::SUCCESS;
144}
145
146aidl::android::media::audio::common::AudioSource EffectContext::getAudioSource() {
147 return mSource;
148}
149
150RetCode EffectContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
151 mVolumeStereo = volumeStereo;
152 return RetCode::SUCCESS;
153}
154
155Parameter::VolumeStereo EffectContext::getVolumeStereo() {
156 return mVolumeStereo;
157}
158
159RetCode EffectContext::setCommon(const Parameter::Common& common) {
Shunkai Yao65c7c702024-01-09 20:50:53 +0000160 auto& input = common.input;
161 auto& output = common.output;
162
163 if (input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT ||
164 output.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT) {
165 LOG(ERROR) << __func__ << " illegal IO, input "
166 << ::android::internal::ToString(input.base.format) << ", output "
167 << ::android::internal::ToString(output.base.format);
168 return RetCode::ERROR_ILLEGAL_PARAMETER;
169 }
170
171 if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
172 return ret;
173 }
174
175 mInputChannelCount = getChannelCount(input.base.channelMask);
176 mOutputChannelCount = getChannelCount(output.base.channelMask);
177 if (mInputChannelCount == 0 || mOutputChannelCount == 0) {
178 LOG(ERROR) << __func__ << " illegal channel count input " << mInputChannelCount
179 << ", output " << mOutputChannelCount;
180 return RetCode::ERROR_ILLEGAL_PARAMETER;
181 }
182
183 mCommon = common;
184 return RetCode::SUCCESS;
185}
186
187Parameter::Common EffectContext::getCommon() {
Shunkai Yao65c7c702024-01-09 20:50:53 +0000188 return mCommon;
189}
190
191EventFlag* EffectContext::getStatusEventFlag() {
192 return mEfGroup;
193}
194
195RetCode EffectContext::updateIOFrameSize(const Parameter::Common& common) {
Shunkai Yao7e2c3712024-02-03 06:47:18 +0000196 const auto prevInputFrameSize = mInputFrameSize;
197 const auto prevOutputFrameSize = mOutputFrameSize;
198 mInputFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
Shunkai Yao65c7c702024-01-09 20:50:53 +0000199 common.input.base.format, common.input.base.channelMask);
Shunkai Yao7e2c3712024-02-03 06:47:18 +0000200 mOutputFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
Shunkai Yao65c7c702024-01-09 20:50:53 +0000201 common.output.base.format, common.output.base.channelMask);
202
Shunkai Yao7e2c3712024-02-03 06:47:18 +0000203 // workBuffer and data MQ not allocated yet, no need to update
204 if (mWorkBuffer.size() == 0 || !mInputMQ || !mOutputMQ) {
205 return RetCode::SUCCESS;
206 }
207 // IEffect::reopen introduced in android.hardware.audio.effect-V2
208 if (mVersion < kReopenSupportedVersion) {
209 LOG(WARNING) << __func__ << " skipped for HAL version " << mVersion;
210 return RetCode::SUCCESS;
211 }
Shunkai Yao65c7c702024-01-09 20:50:53 +0000212 bool needUpdateMq = false;
Shunkai Yao7e2c3712024-02-03 06:47:18 +0000213 if (mInputFrameSize != prevInputFrameSize ||
214 mCommon.input.frameCount != common.input.frameCount) {
Shunkai Yao65c7c702024-01-09 20:50:53 +0000215 mInputMQ.reset();
216 needUpdateMq = true;
217 }
Shunkai Yao7e2c3712024-02-03 06:47:18 +0000218 if (mOutputFrameSize != prevOutputFrameSize ||
219 mCommon.output.frameCount != common.output.frameCount) {
Shunkai Yao65c7c702024-01-09 20:50:53 +0000220 mOutputMQ.reset();
221 needUpdateMq = true;
222 }
Shunkai Yao7e2c3712024-02-03 06:47:18 +0000223
Shunkai Yao65c7c702024-01-09 20:50:53 +0000224 if (needUpdateMq) {
Shunkai Yao08c05dd2024-01-25 00:45:55 +0000225 mWorkBuffer.resize(std::max(common.input.frameCount * mInputFrameSize / sizeof(float),
226 common.output.frameCount * mOutputFrameSize / sizeof(float)));
Shunkai Yao65c7c702024-01-09 20:50:53 +0000227 return notifyDataMqUpdate();
228 }
229 return RetCode::SUCCESS;
230}
231
232RetCode EffectContext::notifyDataMqUpdate() {
233 if (!mEfGroup) {
234 LOG(ERROR) << __func__ << ": invalid EventFlag group";
235 return RetCode::ERROR_EVENT_FLAG_ERROR;
236 }
237
238 if (const auto ret = mEfGroup->wake(kEventFlagDataMqUpdate); ret != ::android::OK) {
239 LOG(ERROR) << __func__ << ": wake failure with ret " << ret;
240 return RetCode::ERROR_EVENT_FLAG_ERROR;
241 }
Shunkai Yaobb35eff2024-03-14 22:04:02 +0000242 LOG(VERBOSE) << __func__ << " : signal client for reopen";
Shunkai Yao65c7c702024-01-09 20:50:53 +0000243 return RetCode::SUCCESS;
244}
245} // namespace aidl::android::hardware::audio::effect