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 LOG_TAG
17 #define LOG_TAG "HpaeInnerCapSinkNode"
18 #endif
19
20 #include <ctime>
21 #include "hpae_inner_cap_sink_node.h"
22 #include "hpae_format_convert.h"
23 #include "audio_errors.h"
24 #include "hpae_node_common.h"
25 #include "audio_utils.h"
26 #ifdef ENABLE_HOOK_PCM
27 #include "hpae_pcm_dumper.h"
28 #endif
29 #include "audio_engine_log.h"
30
31 namespace OHOS {
32 namespace AudioStandard {
33 namespace HPAE {
34
35 constexpr auto DEFAULT_NANO_SECONDS = std::chrono::nanoseconds(20000000); // 20000000ns = 20ms
36
HpaeInnerCapSinkNode(HpaeNodeInfo & nodeInfo)37 HpaeInnerCapSinkNode::HpaeInnerCapSinkNode(HpaeNodeInfo &nodeInfo)
38 : HpaeNode(nodeInfo), outputStream_(this),
39 pcmBufferInfo_(nodeInfo.channels, nodeInfo.frameLen, nodeInfo.samplingRate), silenceData_(pcmBufferInfo_)
40 {
41 silenceData_.Reset();
42 historyTime_ = std::chrono::high_resolution_clock::now();
43 sleepTime_ = std::chrono::nanoseconds(0);
44 #ifdef ENABLE_HOOK_PCM
45 outputPcmDumper_ = std::make_unique<HpaePcmDumper>("HpaeInnerCapSinkNode_bit_" +
46 std::to_string(SAMPLE_F32LE) + "_ch_" + std::to_string(GetChannelCount()) +
47 "_rate_" + std::to_string(GetSampleRate()) + ".pcm");
48 #endif
49 #ifdef ENABLE_HIDUMP_DFX
50 SetNodeName("hpaeInnerCapSinkNode");
51 if (auto callback = GetNodeStatusCallback().lock()) {
52 callback->OnNotifyDfxNodeInfo(true, 0, GetNodeInfo());
53 }
54 #endif
55 }
56
~HpaeInnerCapSinkNode()57 HpaeInnerCapSinkNode::~HpaeInnerCapSinkNode()
58 {
59 #ifdef ENABLE_HIDUMP_DFX
60 AUDIO_INFO_LOG("NodeId: %{public}u NodeName: %{public}s destructed.",
61 GetNodeId(), GetNodeName().c_str());
62 #endif
63 }
64
DoProcess()65 void HpaeInnerCapSinkNode::DoProcess()
66 {
67 Trace trace("[" + std::to_string(GetSessionId()) + "]HpaeInnerCapSinkNode::DoProcess " + GetTraceInfo());
68 std::vector<HpaePcmBuffer *> &outputVec = inputStream_.ReadPreOutputData();
69 if (outputVec.empty() || isMute_ == true) {
70 outputStream_.WriteDataToOutput(&silenceData_);
71 #ifdef ENABLE_HOOK_PCM
72 if (outputPcmDumper_) {
73 outputPcmDumper_->Dump((int8_t *)silenceData_.GetPcmDataBuffer(), GetChannelCount() *
74 GetFrameLen() * GetSizeFromFormat(SAMPLE_F32LE));
75 }
76 #endif
77 } else {
78 HpaePcmBuffer *outputData = outputVec.front();
79 #ifdef ENABLE_HOOK_PCM
80 if (outputPcmDumper_) {
81 outputPcmDumper_->Dump((int8_t *)outputData->GetPcmDataBuffer(), GetChannelCount() *
82 GetFrameLen() * GetSizeFromFormat(SAMPLE_F32LE));
83 }
84 #endif
85 // no need convert
86 outputStream_.WriteDataToOutput(outputVec[0]);
87 }
88 // sleep
89 endTime_ = std::chrono::high_resolution_clock::now();
90 std::this_thread::sleep_for(std::chrono::duration_cast<std::chrono::nanoseconds>(DEFAULT_NANO_SECONDS -
91 (endTime_ - historyTime_ - sleepTime_)));
92 AUDIO_DEBUG_LOG("sleeptime : %{public} " PRIi64"", static_cast<int64_t>(std::chrono::duration_cast
93 <std::chrono::nanoseconds>(DEFAULT_NANO_SECONDS - (endTime_ - historyTime_ - sleepTime_)).count()));
94 if (static_cast<int64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(DEFAULT_NANO_SECONDS -
95 (endTime_ - historyTime_ - sleepTime_)).count()) <= 0) {
96 sleepTime_ = std::chrono::nanoseconds(0);
97 } else {
98 sleepTime_ = DEFAULT_NANO_SECONDS - (endTime_ - historyTime_ - sleepTime_);
99 }
100 historyTime_ = endTime_;
101 }
102
Reset()103 bool HpaeInnerCapSinkNode::Reset()
104 {
105 const auto preOutputMap = inputStream_.GetPreOutputMap();
106 for (const auto &preOutput : preOutputMap) {
107 OutputPort<HpaePcmBuffer *> *output = preOutput.first;
108 inputStream_.DisConnect(output);
109 }
110 return true;
111 }
112
ResetAll()113 bool HpaeInnerCapSinkNode::ResetAll()
114 {
115 const auto preOutputMap = inputStream_.GetPreOutputMap();
116 for (const auto &preOutput : preOutputMap) {
117 OutputPort<HpaePcmBuffer *> *output = preOutput.first;
118 std::shared_ptr<HpaeNode> hpaeNode = preOutput.second;
119 if (hpaeNode->ResetAll()) {
120 inputStream_.DisConnect(output);
121 }
122 }
123 return true;
124 }
125
126 // todo
GetSharedInstance()127 std::shared_ptr<HpaeNode> HpaeInnerCapSinkNode::GetSharedInstance()
128 {
129 return shared_from_this();
130 }
131
132 // todo
GetOutputPort()133 OutputPort<HpaePcmBuffer *> *HpaeInnerCapSinkNode::GetOutputPort()
134 {
135 return &outputStream_;
136 }
137
Connect(const std::shared_ptr<OutputNode<HpaePcmBuffer * >> & preNode)138 void HpaeInnerCapSinkNode::Connect(const std::shared_ptr<OutputNode<HpaePcmBuffer*>>& preNode)
139 {
140 AUDIO_INFO_LOG("Connect");
141 inputStream_.Connect(preNode->GetSharedInstance(), preNode->GetOutputPort());
142 #ifdef ENABLE_HIDUMP_DFX
143 if (auto callback = GetNodeStatusCallback().lock()) {
144 callback->OnNotifyDfxNodeInfo(true, GetNodeId(), preNode->GetSharedInstance()->GetNodeInfo());
145 }
146 #endif
147 }
148
DisConnect(const std::shared_ptr<OutputNode<HpaePcmBuffer * >> & preNode)149 void HpaeInnerCapSinkNode::DisConnect(const std::shared_ptr<OutputNode<HpaePcmBuffer*>>& preNode)
150 {
151 AUDIO_INFO_LOG("DisConnect");
152 inputStream_.DisConnect(preNode->GetOutputPort());
153 #ifdef ENABLE_HIDUMP_DFX
154 if (auto callback = GetNodeStatusCallback().lock()) {
155 auto preNodeReal = preNode->GetSharedInstance();
156 callback->OnNotifyDfxNodeInfo(false, preNodeReal->GetNodeId(), preNodeReal->GetNodeInfo());
157 }
158 #endif
159 }
160
InnerCapturerSinkInit()161 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkInit()
162 {
163 AUDIO_INFO_LOG("Init");
164 SetSinkState(STREAM_MANAGER_IDLE);
165 return SUCCESS;
166 }
167
InnerCapturerSinkDeInit()168 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkDeInit()
169 {
170 AUDIO_INFO_LOG("DeInit");
171 SetSinkState(STREAM_MANAGER_RELEASED);
172 return SUCCESS;
173 }
174
InnerCapturerSinkFlush()175 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkFlush()
176 {
177 AUDIO_INFO_LOG("Flush");
178 return SUCCESS;
179 }
180
InnerCapturerSinkPause()181 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkPause()
182 {
183 AUDIO_INFO_LOG("Pause");
184 SetSinkState(STREAM_MANAGER_SUSPENDED);
185 return SUCCESS;
186 }
187
InnerCapturerSinkReset()188 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkReset()
189 {
190 AUDIO_INFO_LOG("Reset");
191 return SUCCESS;
192 }
193
InnerCapturerSinkResume()194 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkResume()
195 {
196 AUDIO_INFO_LOG("Resume");
197 SetSinkState(STREAM_MANAGER_RUNNING);
198 return SUCCESS;
199 }
200
InnerCapturerSinkStart()201 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkStart()
202 {
203 AUDIO_INFO_LOG("Start");
204 SetSinkState(STREAM_MANAGER_RUNNING);
205 return SUCCESS;
206 }
207
InnerCapturerSinkStop()208 int32_t HpaeInnerCapSinkNode::InnerCapturerSinkStop()
209 {
210 AUDIO_INFO_LOG("Stop");
211 SetSinkState(STREAM_MANAGER_SUSPENDED);
212 return SUCCESS;
213 }
214
GetSinkState(void)215 StreamManagerState HpaeInnerCapSinkNode::GetSinkState(void)
216 {
217 return state_;
218 }
219
SetSinkState(StreamManagerState sinkState)220 int32_t HpaeInnerCapSinkNode::SetSinkState(StreamManagerState sinkState)
221 {
222 AUDIO_INFO_LOG("Sink[%{public}s] state change:[%{public}s]-->[%{public}s]",
223 GetDeviceClass().c_str(), ConvertStreamManagerState2Str(state_).c_str(),
224 ConvertStreamManagerState2Str(sinkState).c_str());
225 state_ = sinkState;
226 return SUCCESS;
227 }
228
SetMute(bool isMute)229 void HpaeInnerCapSinkNode::SetMute(bool isMute)
230 {
231 if (isMute_ != isMute) {
232 isMute_ = isMute;
233 AUDIO_INFO_LOG("SetMute: %{public}d", isMute);
234 }
235 }
236
GetPreOutNum()237 size_t HpaeInnerCapSinkNode::GetPreOutNum()
238 {
239 return inputStream_.GetPreOutputNum();
240 }
241
GetOutputPortNum()242 size_t HpaeInnerCapSinkNode::GetOutputPortNum()
243 {
244 return outputStream_.GetInputNum();
245 }
246 } // namespace HPAE
247 } // namespace AudioStandard
248 } // namespace OHOS