blob: 4f226c4bf65c1440a953b2d5c4c95f7815446f95 [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;
25using aidl::android::media::audio::common::PcmType;
26using ::android::hardware::EventFlag;
27
28namespace aidl::android::hardware::audio::effect {
29
30EffectContext::EffectContext(size_t statusDepth, const Parameter::Common& common) {
31 LOG_ALWAYS_FATAL_IF(RetCode::SUCCESS != setCommon(common), "illegalCommonParameter");
32
33 // in/outBuffer size in float (FMQ data format defined for DataMQ)
34 size_t inBufferSizeInFloat = common.input.frameCount * mInputFrameSize / sizeof(float);
35 size_t outBufferSizeInFloat = common.output.frameCount * mOutputFrameSize / sizeof(float);
36
37 // only status FMQ use the EventFlag
38 mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
39 mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
40 mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
41
42 if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
43 LOG(ERROR) << __func__ << " created invalid FMQ";
44 }
45
46 ::android::status_t status =
47 EventFlag::createEventFlag(mStatusMQ->getEventFlagWord(), &mEfGroup);
48 LOG_ALWAYS_FATAL_IF(status != ::android::OK || !mEfGroup, " create EventFlagGroup failed ");
Shunkai Yao08c05dd2024-01-25 00:45:55 +000049 mWorkBuffer.resize(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
Shunkai Yao65c7c702024-01-09 20:50:53 +000050}
51
52// reset buffer status by abandon input data in FMQ
53void EffectContext::resetBuffer() {
54 auto buffer = static_cast<float*>(mWorkBuffer.data());
55 std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
56 if (mInputMQ) {
57 mInputMQ->read(buffer, mInputMQ->availableToRead());
58 }
59}
60
61void EffectContext::dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet) {
62 if (!mInputMQ) {
63 mInputMQ = std::make_shared<DataMQ>(mCommon.input.frameCount * mInputFrameSize /
64 sizeof(float));
65 }
66 if (!mOutputMQ) {
67 mOutputMQ = std::make_shared<DataMQ>(mCommon.output.frameCount * mOutputFrameSize /
68 sizeof(float));
69 }
70 dupeFmq(effectRet);
71}
72
73void EffectContext::dupeFmq(IEffect::OpenEffectReturn* effectRet) {
74 if (effectRet) {
75 effectRet->statusMQ = mStatusMQ->dupeDesc();
76 effectRet->inputDataMQ = mInputMQ->dupeDesc();
77 effectRet->outputDataMQ = mOutputMQ->dupeDesc();
78 }
79}
80
81float* EffectContext::getWorkBuffer() {
82 return static_cast<float*>(mWorkBuffer.data());
83}
84
Shunkai Yao08c05dd2024-01-25 00:45:55 +000085size_t EffectContext::getWorkBufferSize() const {
86 return mWorkBuffer.size();
87}
88
Shunkai Yao65c7c702024-01-09 20:50:53 +000089std::shared_ptr<EffectContext::StatusMQ> EffectContext::getStatusFmq() const {
90 return mStatusMQ;
91}
92
93std::shared_ptr<EffectContext::DataMQ> EffectContext::getInputDataFmq() const {
94 return mInputMQ;
95}
96
97std::shared_ptr<EffectContext::DataMQ> EffectContext::getOutputDataFmq() const {
98 return mOutputMQ;
99}
100
101size_t EffectContext::getInputFrameSize() const {
102 return mInputFrameSize;
103}
104
105size_t EffectContext::getOutputFrameSize() const {
106 return mOutputFrameSize;
107}
108
109int EffectContext::getSessionId() const {
110 return mCommon.session;
111}
112
113int EffectContext::getIoHandle() const {
114 return mCommon.ioHandle;
115}
116
117RetCode EffectContext::setOutputDevice(
118 const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device) {
119 mOutputDevice = device;
120 return RetCode::SUCCESS;
121}
122
123std::vector<aidl::android::media::audio::common::AudioDeviceDescription>
124EffectContext::getOutputDevice() {
125 return mOutputDevice;
126}
127
128RetCode EffectContext::setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
129 mMode = mode;
130 return RetCode::SUCCESS;
131}
132aidl::android::media::audio::common::AudioMode EffectContext::getAudioMode() {
133 return mMode;
134}
135
136RetCode EffectContext::setAudioSource(
137 const aidl::android::media::audio::common::AudioSource& source) {
138 mSource = source;
139 return RetCode::SUCCESS;
140}
141
142aidl::android::media::audio::common::AudioSource EffectContext::getAudioSource() {
143 return mSource;
144}
145
146RetCode EffectContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
147 mVolumeStereo = volumeStereo;
148 return RetCode::SUCCESS;
149}
150
151Parameter::VolumeStereo EffectContext::getVolumeStereo() {
152 return mVolumeStereo;
153}
154
155RetCode EffectContext::setCommon(const Parameter::Common& common) {
156 LOG(VERBOSE) << __func__ << common.toString();
157 auto& input = common.input;
158 auto& output = common.output;
159
160 if (input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT ||
161 output.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT) {
162 LOG(ERROR) << __func__ << " illegal IO, input "
163 << ::android::internal::ToString(input.base.format) << ", output "
164 << ::android::internal::ToString(output.base.format);
165 return RetCode::ERROR_ILLEGAL_PARAMETER;
166 }
167
168 if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
169 return ret;
170 }
171
172 mInputChannelCount = getChannelCount(input.base.channelMask);
173 mOutputChannelCount = getChannelCount(output.base.channelMask);
174 if (mInputChannelCount == 0 || mOutputChannelCount == 0) {
175 LOG(ERROR) << __func__ << " illegal channel count input " << mInputChannelCount
176 << ", output " << mOutputChannelCount;
177 return RetCode::ERROR_ILLEGAL_PARAMETER;
178 }
179
180 mCommon = common;
181 return RetCode::SUCCESS;
182}
183
184Parameter::Common EffectContext::getCommon() {
185 LOG(VERBOSE) << __func__ << mCommon.toString();
186 return mCommon;
187}
188
189EventFlag* EffectContext::getStatusEventFlag() {
190 return mEfGroup;
191}
192
193RetCode EffectContext::updateIOFrameSize(const Parameter::Common& common) {
194 const auto iFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
195 common.input.base.format, common.input.base.channelMask);
196 const auto oFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
197 common.output.base.format, common.output.base.channelMask);
198
199 bool needUpdateMq = false;
200 if (mInputMQ &&
201 (mInputFrameSize != iFrameSize || mCommon.input.frameCount != common.input.frameCount)) {
202 mInputMQ.reset();
203 needUpdateMq = true;
204 }
205 if (mOutputMQ &&
206 (mOutputFrameSize != oFrameSize || mCommon.output.frameCount != common.output.frameCount)) {
207 mOutputMQ.reset();
208 needUpdateMq = true;
209 }
210 mInputFrameSize = iFrameSize;
211 mOutputFrameSize = oFrameSize;
212 if (needUpdateMq) {
Shunkai Yao08c05dd2024-01-25 00:45:55 +0000213 mWorkBuffer.resize(std::max(common.input.frameCount * mInputFrameSize / sizeof(float),
214 common.output.frameCount * mOutputFrameSize / sizeof(float)));
Shunkai Yao65c7c702024-01-09 20:50:53 +0000215 return notifyDataMqUpdate();
216 }
217 return RetCode::SUCCESS;
218}
219
220RetCode EffectContext::notifyDataMqUpdate() {
221 if (!mEfGroup) {
222 LOG(ERROR) << __func__ << ": invalid EventFlag group";
223 return RetCode::ERROR_EVENT_FLAG_ERROR;
224 }
225
226 if (const auto ret = mEfGroup->wake(kEventFlagDataMqUpdate); ret != ::android::OK) {
227 LOG(ERROR) << __func__ << ": wake failure with ret " << ret;
228 return RetCode::ERROR_EVENT_FLAG_ERROR;
229 }
230 LOG(DEBUG) << __func__ << " : signal client for reopen";
231 return RetCode::SUCCESS;
232}
233} // namespace aidl::android::hardware::audio::effect