• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "HpaeRemoteOutputCluster"
18 #endif
19 
20 #include <sstream>
21 #include "hpae_remote_output_cluster.h"
22 #include "hpae_node_common.h"
23 #include "audio_errors.h"
24 #include "audio_utils.h"
25 #include "audio_engine_log.h"
26 
27 namespace OHOS {
28 namespace AudioStandard {
29 namespace HPAE {
30 
HpaeRemoteOutputCluster(HpaeNodeInfo & nodeInfo,HpaeSinkInfo & sinkInfo)31 HpaeRemoteOutputCluster::HpaeRemoteOutputCluster(HpaeNodeInfo &nodeInfo, HpaeSinkInfo &sinkInfo)
32     : HpaeNode(nodeInfo), hpaeSinkOutputNode_(std::make_shared<HpaeRemoteSinkOutputNode>(nodeInfo, sinkInfo))
33 {
34     frameLenMs_ = nodeInfo.frameLen * MILLISECOND_PER_SECOND / nodeInfo.samplingRate;
35     AUDIO_INFO_LOG("HpaeRemoteOutputCluster frameLenMs_:%{public}u ms,"
36         "timeoutThdFrames_:%{public}u", frameLenMs_, timeoutThdFrames_);
37 #ifdef ENABLE_HIDUMP_DFX
38     SetNodeName("HpaeRemoteOutputCluster");
39 #endif
40 }
41 
~HpaeRemoteOutputCluster()42 HpaeRemoteOutputCluster::~HpaeRemoteOutputCluster()
43 {
44     Reset();
45 #ifdef ENABLE_HIDUMP_DFX
46     AUDIO_INFO_LOG("NodeId: %{public}u NodeName: %{public}s destructed.",
47         GetNodeId(), GetNodeName().c_str());
48 #endif
49 }
50 
DoProcess()51 void HpaeRemoteOutputCluster::DoProcess()
52 {
53     Trace trace("HpaeRemoteOutputCluster::DoProcess");
54     hpaeSinkOutputNode_->DoProcess();
55     std::vector<HpaeProcessorType> needErased;
56     for (auto &mixerNode : sceneMixerMap_) {
57         if (mixerNode.second->GetPreOutNum() == 0) {
58             ++sceneStopCountMap_[mixerNode.first];
59         } else {
60             sceneStopCountMap_[mixerNode.first] = 0;
61         }
62         if (sceneStopCountMap_[mixerNode.first] > timeoutThdFrames_) {
63             needErased.emplace_back(mixerNode.first);
64             hpaeSinkOutputNode_->DisConnect(mixerNode.second);
65         }
66     }
67     for (auto sceneType : needErased) {
68         sceneMixerMap_.erase(sceneType);
69     }
70     if (hpaeSinkOutputNode_->GetPreOutNum() == 0) {
71         int32_t ret = hpaeSinkOutputNode_->RenderSinkStop();
72         AUDIO_INFO_LOG("HpaeRemoteOutputCluster timeout RenderSinkStop ret :%{public}d", ret);
73     }
74 }
75 
Reset()76 bool HpaeRemoteOutputCluster::Reset()
77 {
78     hpaeSinkOutputNode_->Reset();
79     for (auto &mixerNode : sceneMixerMap_) {
80         mixerNode.second->Reset();
81     }
82     for (auto converterNode : sceneConverterMap_) {
83         converterNode.second->Reset();
84     }
85 #ifdef ENABLE_HIDUMP_DFX
86     if (auto callBack = hpaeSinkOutputNode_->GetNodeStatusCallback().lock()) {
87         callBack->OnNotifyDfxNodeInfo(false, hpaeSinkOutputNode_->GetNodeId(), hpaeSinkOutputNode_->GetNodeInfo());
88     }
89 #endif
90     return true;
91 }
92 
ResetAll()93 bool HpaeRemoteOutputCluster::ResetAll()
94 {
95     return hpaeSinkOutputNode_->ResetAll();  // Complete the code here
96 }
97 
Connect(const std::shared_ptr<OutputNode<HpaePcmBuffer * >> & preNode)98 void HpaeRemoteOutputCluster::Connect(const std::shared_ptr<OutputNode<HpaePcmBuffer *>> &preNode)
99 {
100     HpaeNodeInfo &preNodeInfo = preNode->GetSharedInstance()->GetNodeInfo();
101     HpaeNodeInfo nodeInfo = GetNodeInfo();
102     HpaeProcessorType sceneType = preNodeInfo.sceneType;
103     AUDIO_INFO_LOG("HpaeRemoteOutputCluster input sceneType is %{public}u", sceneType);
104     AUDIO_INFO_LOG("HpaeRemoteOutputCluster input rate is %{public}u, ch is %{public}u",
105         preNodeInfo.samplingRate, preNodeInfo.channels);
106     AUDIO_INFO_LOG(" HpaeRemoteOutputCluster output rate is %{public}u, ch is %{public}u",
107         nodeInfo.samplingRate, nodeInfo.channels);
108     AUDIO_INFO_LOG(" HpaeRemoteOutputCluster preNode name %{public}s, curNode name is %{public}s",
109         preNodeInfo.nodeName.c_str(), nodeInfo.nodeName.c_str());
110     nodeInfo.sceneType = sceneType;
111     if (!SafeGetMap(sceneConverterMap_, sceneType)) {
112         sceneConverterMap_[sceneType] = std::make_shared<HpaeAudioFormatConverterNode>(preNodeInfo, nodeInfo);
113     }
114     if (!SafeGetMap(sceneMixerMap_, sceneType)) {
115         sceneMixerMap_[sceneType] = std::make_shared<HpaeMixerNode>(nodeInfo);
116         sceneStopCountMap_[sceneType] = 0;
117         hpaeSinkOutputNode_->Connect(sceneMixerMap_[sceneType]);
118     }
119     sceneMixerMap_[sceneType]->Connect(sceneConverterMap_[sceneType]);
120     sceneConverterMap_[sceneType]->Connect(preNode);
121     connectedProcessCluster_.insert(sceneType);
122 }
123 
DisConnect(const std::shared_ptr<OutputNode<HpaePcmBuffer * >> & preNode)124 void HpaeRemoteOutputCluster::DisConnect(const std::shared_ptr<OutputNode<HpaePcmBuffer *>> &preNode)
125 {
126     HpaeNodeInfo &preNodeInfo = preNode->GetSharedInstance()->GetNodeInfo();
127     HpaeProcessorType sceneType = preNodeInfo.sceneType;
128     AUDIO_INFO_LOG("HpaeRemoteOutputCluster input sceneType is %{public}u", preNodeInfo.sceneType);
129     if (SafeGetMap(sceneConverterMap_, sceneType)) {
130         sceneConverterMap_[sceneType]->DisConnect(preNode);
131         sceneMixerMap_[sceneType]->DisConnect(sceneConverterMap_[sceneType]);
132         sceneConverterMap_.erase(sceneType);
133     }
134     connectedProcessCluster_.erase(sceneType);
135 }
136 
GetConverterNodeCount()137 int32_t HpaeRemoteOutputCluster::GetConverterNodeCount()
138 {
139     return sceneConverterMap_.size();
140 }
141 
GetInstance(const std::string & deviceClass,const std::string & deviceNetId)142 int32_t HpaeRemoteOutputCluster::GetInstance(const std::string &deviceClass, const std::string &deviceNetId)
143 {
144     return hpaeSinkOutputNode_->GetRenderSinkInstance(deviceClass, deviceNetId);
145 }
146 
Init(IAudioSinkAttr & attr)147 int32_t HpaeRemoteOutputCluster::Init(IAudioSinkAttr &attr)
148 {
149     return hpaeSinkOutputNode_->RenderSinkInit(attr);
150 }
151 
DeInit()152 int32_t HpaeRemoteOutputCluster::DeInit()
153 {
154     return hpaeSinkOutputNode_->RenderSinkDeInit();
155 }
156 
Flush(void)157 int32_t HpaeRemoteOutputCluster::Flush(void)
158 {
159     return hpaeSinkOutputNode_->RenderSinkFlush();
160 }
161 
Pause(void)162 int32_t HpaeRemoteOutputCluster::Pause(void)
163 {
164     return hpaeSinkOutputNode_->RenderSinkPause();
165 }
166 
ResetRender(void)167 int32_t HpaeRemoteOutputCluster::ResetRender(void)
168 {
169     return hpaeSinkOutputNode_->RenderSinkReset();
170 }
171 
Resume(void)172 int32_t HpaeRemoteOutputCluster::Resume(void)
173 {
174     return hpaeSinkOutputNode_->RenderSinkResume();
175 }
176 
Start(void)177 int32_t HpaeRemoteOutputCluster::Start(void)
178 {
179     return hpaeSinkOutputNode_->RenderSinkStart();
180 }
181 
Stop(void)182 int32_t HpaeRemoteOutputCluster::Stop(void)
183 {
184     return hpaeSinkOutputNode_->RenderSinkStop();
185 }
186 
GetFrameData(void)187 const char *HpaeRemoteOutputCluster::GetFrameData(void)
188 {
189     return hpaeSinkOutputNode_->GetRenderFrameData();
190 }
191 
GetState(void)192 StreamManagerState HpaeRemoteOutputCluster::GetState(void)
193 {
194     return hpaeSinkOutputNode_->GetSinkState();
195 }
196 
GetPreOutNum()197 int32_t HpaeRemoteOutputCluster::GetPreOutNum()
198 {
199     return hpaeSinkOutputNode_->GetPreOutNum();
200 }
201 
SetTimeoutStopThd(uint32_t timeoutThdMs)202 int32_t HpaeRemoteOutputCluster::SetTimeoutStopThd(uint32_t timeoutThdMs)
203 {
204     if (frameLenMs_ != 0) {
205         timeoutThdFrames_ = timeoutThdMs / frameLenMs_;
206     }
207     AUDIO_INFO_LOG(
208         "SetTimeoutStopThd: timeoutThdFrames_:%{public}u, timeoutThdMs :%{public}u", timeoutThdFrames_, timeoutThdMs);
209     return SUCCESS;
210 }
211 
IsProcessClusterConnected(HpaeProcessorType sceneType)212 bool HpaeRemoteOutputCluster::IsProcessClusterConnected(HpaeProcessorType sceneType)
213 {
214     return connectedProcessCluster_.find(sceneType) != connectedProcessCluster_.end();
215 }
216 
TransStreamUsageToSplitSceneType(StreamUsage streamUsage,const std::string & splitMode)217 HpaeProcessorType TransStreamUsageToSplitSceneType(StreamUsage streamUsage, const std::string &splitMode)
218 {
219     static constexpr int splitOneStream = 1;
220     static constexpr int splitTwoStream = 2;
221     static constexpr int splitThreeStream = 3;
222     static constexpr int maxParts = 3;
223     AUDIO_INFO_LOG("streamUsage is: %{public}d, splitMode is: %{public}s",
224         static_cast<int>(streamUsage), splitMode.c_str());
225     int splitNums = 0;
226     if (splitMode.empty()) {
227         AUDIO_ERR_LOG("input SPLIT_MODE is empty");
228         return HPAE_SCENE_DEFAULT;
229     }
230     std::istringstream iss(splitMode);
231     std::string token;
232     while (splitNums < maxParts && std::getline(iss, token, ':')) {
233         ++splitNums;
234     }
235     const auto getSceneType = [streamUsage](size_t splitNums) -> HpaeProcessorType {
236         return
237             (splitNums == splitOneStream) ? HPAE_SCENE_SPLIT_MEDIA :
238             (splitNums == splitTwoStream) ? (streamUsage == STREAM_USAGE_NAVIGATION ?
239                 HPAE_SCENE_SPLIT_NAVIGATION : HPAE_SCENE_SPLIT_MEDIA) :
240             (splitNums == splitThreeStream) ? (
241                 (streamUsage == STREAM_USAGE_NAVIGATION) ? HPAE_SCENE_SPLIT_NAVIGATION :
242                 (streamUsage == STREAM_USAGE_VOICE_COMMUNICATION || streamUsage == STREAM_USAGE_VIDEO_COMMUNICATION)
243                     ? HPAE_SCENE_SPLIT_COMMUNICATION
244                     : HPAE_SCENE_SPLIT_MEDIA
245             ) : HPAE_SCENE_DEFAULT;
246     };
247     return getSceneType(splitNums);
248 }
249 
UpdateAppsUid(const std::vector<int32_t> & appsUid)250 int32_t HpaeRemoteOutputCluster::UpdateAppsUid(const std::vector<int32_t> &appsUid)
251 {
252     return hpaeSinkOutputNode_->UpdateAppsUid(appsUid);
253 }
254 }  // namespace HPAE
255 }  // namespace AudioStandard
256 }  // namespace OHOS
257