1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef HPAE_NODE_H
17 #define HPAE_NODE_H
18 #include <memory>
19 #include <stdint.h>
20 #include <unordered_map>
21 #include <vector>
22 #include <set>
23 #include <sstream>
24 #include "hpae_pcm_buffer.h"
25 #include "hpae_define.h"
26
27 namespace OHOS {
28 namespace AudioStandard {
29 namespace HPAE {
30 static constexpr uint32_t MIN_START_NODE_ID = 100;
31
32 class HpaeNode : public std::enable_shared_from_this<HpaeNode> {
33 public:
HpaeNode()34 HpaeNode()
35 {
36 #ifdef ENABLE_HIDUMP_DFX
37 nodeInfo_.nodeId = GenerateHpaeNodeId();
38 #endif
39 }
40
~HpaeNode()41 virtual ~HpaeNode() {};
42
HpaeNode(HpaeNodeInfo & nodeInfo)43 HpaeNode(HpaeNodeInfo& nodeInfo) : nodeInfo_(nodeInfo)
44 {
45 #ifdef ENABLE_HIDUMP_DFX
46 nodeInfo_.nodeId = GenerateHpaeNodeId();
47 #endif
48 }
49
50 virtual void DoProcess() = 0;
Enqueue(HpaePcmBuffer * buffer)51 virtual void Enqueue(HpaePcmBuffer* buffer) {};
52 // for process node
53 virtual bool Reset() = 0;
54 virtual bool ResetAll() = 0;
55
GetNodeInfo()56 virtual HpaeNodeInfo& GetNodeInfo()
57 {
58 return nodeInfo_;
59 }
60
SetNodeInfo(HpaeNodeInfo & nodeInfo)61 virtual void SetNodeInfo(HpaeNodeInfo& nodeInfo)
62 {
63 nodeInfo_ = nodeInfo;
64 }
65
SetNodeId(uint32_t nodeId)66 virtual void SetNodeId(uint32_t nodeId)
67 {
68 nodeInfo_.nodeId = nodeId;
69 }
70
SetNodeName(std::string nodeName)71 virtual void SetNodeName(std::string nodeName)
72 {
73 nodeInfo_.nodeName = nodeName;
74 }
75
GetSampleRate()76 virtual AudioSamplingRate GetSampleRate()
77 {
78 return nodeInfo_.samplingRate;
79 }
80
GetBitWidth()81 virtual AudioSampleFormat GetBitWidth()
82 {
83 return nodeInfo_.format;
84 }
85
GetChannelCount()86 virtual AudioChannel GetChannelCount()
87 {
88 return nodeInfo_.channels;
89 }
90
GetChannelLayout()91 virtual AudioChannelLayout GetChannelLayout()
92 {
93 return nodeInfo_.channelLayout;
94 }
95
GetFrameLen()96 virtual size_t GetFrameLen()
97 {
98 return nodeInfo_.frameLen;
99 }
100
GetNodeId()101 virtual uint32_t GetNodeId()
102 {
103 return nodeInfo_.nodeId;
104 }
105
GetSessionId()106 virtual uint32_t GetSessionId()
107 {
108 return nodeInfo_.sessionId;
109 }
110
GetStreamType()111 virtual AudioStreamType GetStreamType()
112 {
113 return nodeInfo_.streamType;
114 }
115
GetSceneType()116 virtual HpaeProcessorType GetSceneType()
117 {
118 return nodeInfo_.sceneType;
119 }
120
GetDeviceClass()121 virtual std::string GetDeviceClass()
122 {
123 return nodeInfo_.deviceClass;
124 }
125
GetDeviceNetId()126 virtual std::string GetDeviceNetId()
127 {
128 return nodeInfo_.deviceNetId;
129 }
130
GetNodeName()131 virtual std::string GetNodeName()
132 {
133 return nodeInfo_.nodeName;
134 }
135
GetNodeStatusCallback()136 virtual std::weak_ptr<INodeCallback> GetNodeStatusCallback()
137 {
138 return nodeInfo_.statusCallback;
139 }
140
GetTraceInfo()141 virtual std::string GetTraceInfo()
142 {
143 std::ostringstream oss;
144 oss << "rate[" << nodeInfo_.samplingRate << "]_"
145 << "ch[" << static_cast<int32_t>(nodeInfo_.channels) << "]_"
146 << "len[" << nodeInfo_.frameLen << "]_"
147 << "bit[" << static_cast<int32_t>(nodeInfo_.format) << "]";
148 return oss.str();
149 }
150 private:
GenerateHpaeNodeId()151 static uint32_t GenerateHpaeNodeId()
152 {
153 std::lock_guard<std::mutex> lock(nodeIdCounterMutex_);
154 if (nodeIdCounter_ == std::numeric_limits<uint32_t>::max()) {
155 nodeIdCounter_ = MIN_START_NODE_ID;
156 } else {
157 ++nodeIdCounter_;
158 }
159 return nodeIdCounter_;
160 }
161
162 private:
163 HpaeNodeInfo nodeInfo_;
164 inline static std::mutex nodeIdCounterMutex_;
165 inline static uint32_t nodeIdCounter_ = MIN_START_NODE_ID;
166 };
167
168 template <typename T>
169 class InputPort;
170
171 template <typename T>
172 class OutputPort {
173 public:
OutputPort(HpaeNode * node)174 explicit OutputPort(HpaeNode *node) : hpaeNode_(node)
175 {}
176 void WriteDataToOutput(T data, HpaeBufferType bufferType = HPAE_BUFFER_TYPE_DEFAULT);
177 OutputPort(const OutputPort &that) = delete;
178 T PullOutputData();
179 void AddInput(InputPort<T> *input);
180 void AddInput(InputPort<T> *input, const std::shared_ptr<HpaeNode> &node);
181 bool RemoveInput(InputPort<T> *input, HpaeBufferType bufferType = HPAE_BUFFER_TYPE_DEFAULT);
182 size_t GetInputNum() const;
183 private:
184 std::set<InputPort<T>*> inputPortSet_;
185 std::vector<T> outputData_;
186 HpaeNode *hpaeNode_;
187 std::unordered_map<InputPort<T>*, std::shared_ptr<HpaeNode>> coInputPorts_;
188 };
189
190 template <typename OutputType>
191 class OutputNode : virtual public HpaeNode {
192 public:
~OutputNode()193 virtual ~OutputNode()
194 {}
195 virtual std::shared_ptr<HpaeNode> GetSharedInstance() = 0;
GetSharedInstance(HpaeNodeInfo & nodeInfo)196 virtual std::shared_ptr<HpaeNode> GetSharedInstance(HpaeNodeInfo &nodeInfo) { return nullptr; }
197 virtual OutputPort<OutputType>* GetOutputPort() = 0;
198 virtual OutputPort<OutputType>* GetOutputPort(HpaeNodeInfo &nodeInfo, bool isDisConnect = false) { return nullptr; }
GetOutputPortBufferType(HpaeNodeInfo & nodeInfo)199 virtual HpaeSourceBufferType GetOutputPortBufferType(HpaeNodeInfo &nodeInfo)
200 { return HPAE_SOURCE_BUFFER_TYPE_DEFAULT; }
201 };
202
203 template <typename InputType>
204 class InputNode : virtual public HpaeNode {
205 public:
~InputNode()206 virtual ~InputNode()
207 {}
208 virtual void Connect(const std::shared_ptr<OutputNode<InputType>> &preNode) = 0;
ConnectWithInfo(const std::shared_ptr<OutputNode<InputType>> & preNode,HpaeNodeInfo & nodeInfo)209 virtual void ConnectWithInfo(const std::shared_ptr<OutputNode<InputType>> &preNode, HpaeNodeInfo &nodeInfo) {}
210 virtual void DisConnect(const std::shared_ptr<OutputNode<InputType>> &preNode) = 0;
DisConnectWithInfo(const std::shared_ptr<OutputNode<InputType>> & preNode,HpaeNodeInfo & nodeInfo)211 virtual void DisConnectWithInfo(const std::shared_ptr<OutputNode<InputType>> &preNode, HpaeNodeInfo &nodeInfo) {}
212 };
213
214 template <typename T>
215 class InputPort {
216 public:
InputPort()217 InputPort()
218 {}
219 ~InputPort();
220 std::vector<T>& ReadPreOutputData();
221
222 void Connect(const std::shared_ptr<HpaeNode>& node, OutputPort<T>* output,
223 HpaeBufferType bufferType = HPAE_BUFFER_TYPE_DEFAULT);
224
225 void DisConnect(OutputPort<T>* output, HpaeBufferType bufferType = HPAE_BUFFER_TYPE_DEFAULT);
226
227 size_t GetPreOutputNum() const;
228
229 const std::unordered_map<OutputPort<T> *, std::shared_ptr<HpaeNode>>& GetPreOutputMap();
230
231 bool CheckIfDisConnected(OutputPort<T>* output);
232
233 InputPort(const InputPort &that) = delete;
234
235 void AddPreOutput(const std::shared_ptr<HpaeNode> &node, OutputPort<T>* output);
236 void RemovePreOutput(OutputPort<T>* output);
237 private:
238 std::unordered_map<OutputPort<T>*, std::shared_ptr<HpaeNode>> outputPorts_;
239 std::vector<T> inputData_;
240 };
241
242 template <class T>
~InputPort()243 InputPort<T>::~InputPort()
244 {
245 for (auto &o : outputPorts_) {
246 o.first->RemoveInput(this);
247 }
248 }
249
250 template <class T>
ReadPreOutputData()251 std::vector<T>& InputPort<T>::ReadPreOutputData()
252 {
253 inputData_.clear();
254 for (auto &o : outputPorts_) {
255 T pcmData = o.first->PullOutputData();
256 if (pcmData != nullptr) {
257 inputData_.emplace_back(std::move(pcmData));
258 }
259 }
260 return inputData_;
261 }
262
263 template <class T>
Connect(const std::shared_ptr<HpaeNode> & node,OutputPort<T> * output,HpaeBufferType bufferType)264 void InputPort<T>::Connect(const std::shared_ptr<HpaeNode> &node, OutputPort<T>* output, HpaeBufferType bufferType)
265 {
266 // for default type
267 if (bufferType == HPAE_BUFFER_TYPE_DEFAULT) {
268 if (output) {
269 output->AddInput(this);
270 }
271 AddPreOutput(node, output);
272 return;
273 }
274 // for cobuffer type
275 if (bufferType == HPAE_BUFFER_TYPE_COBUFFER) {
276 if (output) {
277 output->AddInput(this, node);
278 }
279 AddPreOutput(node, output);
280 return;
281 }
282 return;
283 }
284
285 template <class T>
DisConnect(OutputPort<T> * output,HpaeBufferType bufferType)286 void InputPort<T>::DisConnect(OutputPort<T>* output, HpaeBufferType bufferType)
287 {
288 if (output) {
289 output->RemoveInput(this, bufferType);
290 }
291 RemovePreOutput(output);
292 }
293
294 template <class T>
GetPreOutputNum()295 size_t InputPort<T>::GetPreOutputNum() const
296 {
297 return outputPorts_.size();
298 }
299
300 template <class T>
GetPreOutputMap()301 const std::unordered_map<OutputPort<T> *, std::shared_ptr<HpaeNode>>& InputPort<T>::GetPreOutputMap()
302 {
303 return outputPorts_;
304 }
305
306 template <class T>
CheckIfDisConnected(OutputPort<T> * output)307 bool InputPort<T>::CheckIfDisConnected(OutputPort<T>* output)
308 {
309 return outputPorts_.find(output) == outputPorts_.end();
310 }
311
312 template <class T>
AddPreOutput(const std::shared_ptr<HpaeNode> & node,OutputPort<T> * output)313 void InputPort<T>::AddPreOutput(const std::shared_ptr<HpaeNode> &node, OutputPort<T> *output)
314 {
315 outputPorts_[output] = node;
316 }
317
318 template <class T>
RemovePreOutput(OutputPort<T> * output)319 void InputPort<T>::RemovePreOutput(OutputPort<T> *output)
320 {
321 outputPorts_.erase(output);
322 }
323
324 template <class T>
PullOutputData()325 T OutputPort<T>::PullOutputData()
326 {
327 if (outputData_.empty()) {
328 hpaeNode_->DoProcess();
329 }
330 if (!outputData_.empty()) {
331 T retValue = std::move(outputData_.back());
332 outputData_.pop_back();
333 return retValue;
334 } else {
335 return nullptr;
336 }
337 }
338
339 template <class T>
WriteDataToOutput(T data,HpaeBufferType bufferType)340 void OutputPort<T>::WriteDataToOutput(T data, HpaeBufferType bufferType)
341 {
342 // for default type
343 if (bufferType == HPAE_BUFFER_TYPE_DEFAULT) {
344 outputData_.clear();
345 outputData_.emplace_back(std::move(data));
346
347 for (size_t i = 1; i < inputPortSet_.size(); i++) {
348 outputData_.push_back(outputData_[0]);
349 }
350 return;
351 }
352 // for cobuffer type
353 if (bufferType == HPAE_BUFFER_TYPE_COBUFFER) {
354 for (auto &i : coInputPorts_) {
355 i.second->Enqueue(data);
356 }
357 return;
358 }
359 return;
360 }
361
362 template <class T>
AddInput(InputPort<T> * input)363 void OutputPort<T>::AddInput(InputPort<T> *input)
364 {
365 inputPortSet_.insert(input);
366 }
367 template <class T>
AddInput(InputPort<T> * input,const std::shared_ptr<HpaeNode> & node)368 void OutputPort<T>::AddInput(InputPort<T> *input, const std::shared_ptr<HpaeNode> &node)
369 {
370 coInputPorts_[input] = node;
371 }
372 template <class T>
GetInputNum()373 size_t OutputPort<T>::GetInputNum() const
374 {
375 return inputPortSet_.size();
376 }
377 template <class T>
RemoveInput(InputPort<T> * input,HpaeBufferType bufferType)378 bool OutputPort<T>::RemoveInput(InputPort<T> *input, HpaeBufferType bufferType)
379 {
380 // for default type
381 if (bufferType == HPAE_BUFFER_TYPE_DEFAULT) {
382 auto it = inputPortSet_.find(input);
383 if (it == inputPortSet_.end()) {
384 return false;
385 }
386 inputPortSet_.erase(it);
387 return true;
388 }
389 // for cobuffer type
390 if (bufferType == HPAE_BUFFER_TYPE_COBUFFER) {
391 auto it = coInputPorts_.find(input);
392 if (it == coInputPorts_.end()) {
393 return false;
394 }
395 coInputPorts_.erase(it);
396 return true;
397 }
398 return true;
399 }
400
401 } // namespace HPAE
402 } // namespace AudioStandard
403 } // namespace OHOS
404 #endif