• 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 "RemoteAudioRenderSink"
18 #endif
19 
20 #include "sink/remote_audio_render_sink.h"
21 #include <sstream>
22 #include <climits>
23 #include <utility>
24 #include <algorithm>
25 #include "audio_hdi_log.h"
26 #include "audio_errors.h"
27 #include "audio_utils.h"
28 #include "audio_dump_pcm.h"
29 #include "volume_tools.h"
30 #include "audio_performance_monitor.h"
31 #include "common/hdi_adapter_info.h"
32 #include "manager/hdi_adapter_manager.h"
33 
34 using namespace OHOS::HDI::DistributedAudio::Audio::V1_0;
35 
36 namespace OHOS {
37 namespace AudioStandard {
38 const std::unordered_map<std::string, AudioCategory> RemoteAudioRenderSink::SPLIT_STREAM_MAP = {
39     { std::string(MEDIA_STREAM_TYPE), AudioCategory::AUDIO_IN_MEDIA },
40     { std::string(NAVIGATION_STREAM_TYPE), AudioCategory::AUDIO_IN_NAVIGATION },
41     { std::string(COMMUNICATION_STREAM_TYPE), AudioCategory::AUDIO_IN_COMMUNICATION },
42 };
43 
RemoteAudioRenderSink(const std::string & deviceNetworkId)44 RemoteAudioRenderSink::RemoteAudioRenderSink(const std::string &deviceNetworkId)
45     : deviceNetworkId_(deviceNetworkId)
46 {
47     AUDIO_DEBUG_LOG("construction");
48 }
49 
~RemoteAudioRenderSink()50 RemoteAudioRenderSink::~RemoteAudioRenderSink()
51 {
52     if (sinkInited_.load()) {
53         DeInit();
54     }
55     AUDIO_DEBUG_LOG("destruction");
56     AudioPerformanceMonitor::GetInstance().DeleteOvertimeMonitor(ADAPTER_TYPE_REMOTE);
57 }
58 
Init(const IAudioSinkAttr & attr)59 int32_t RemoteAudioRenderSink::Init(const IAudioSinkAttr &attr)
60 {
61     AUDIO_INFO_LOG("in");
62     attr_ = attr;
63     std::vector<AudioCategory> splitStreamVector;
64     InitSplitStream(attr_.aux, splitStreamVector);
65     for (auto &splitStream : splitStreamVector) {
66         audioRenderWrapperMap_[splitStream] = {};
67     }
68     sinkInited_.store(true);
69     return SUCCESS;
70 }
71 
DeInit(void)72 void RemoteAudioRenderSink::DeInit(void)
73 {
74     Trace trace("RemoteAudioRenderSink::DeInit");
75     AUDIO_INFO_LOG("in");
76     sinkInited_.store(false);
77     renderInited_.store(false);
78     started_.store(false);
79     paused_.store(false);
80 
81     HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
82     std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_REMOTE);
83     CHECK_AND_RETURN(deviceManager != nullptr);
84     for (auto &it : audioRenderWrapperMap_) {
85         deviceManager->DestroyRender(deviceNetworkId_, it.second.hdiRenderId_);
86         deviceManager->UnRegistRenderSinkCallback(deviceNetworkId_, it.second.hdiRenderId_);
87         it.second.audioRender_.ForceSetRefPtr(nullptr);
88         DumpFileUtil::CloseDumpFile(&it.second.dumpFile_);
89     }
90     audioRenderWrapperMap_.clear();
91     AUDIO_INFO_LOG("end");
92 }
93 
IsInited(void)94 bool RemoteAudioRenderSink::IsInited(void)
95 {
96     return sinkInited_.load();
97 }
98 
Start(void)99 int32_t RemoteAudioRenderSink::Start(void)
100 {
101     Trace trace("RemoteAudioRenderSink::Start");
102     AUDIO_INFO_LOG("in");
103     std::lock_guard<std::mutex> lock(createRenderMutex_);
104 
105     for (auto &it : audioRenderWrapperMap_) {
106         it.second.dumpFileName_ = std::string(DUMP_REMOTE_RENDER_SINK_FILENAME) + "_" + GetTime() + "_" +
107             std::to_string(attr_.sampleRate) + "_" + std::to_string(attr_.channel) + "_" +
108             std::to_string(attr_.format) + ".pcm";
109         DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, it.second.dumpFileName_ + std::to_string(it.first) +
110             ".pcm", &(it.second.dumpFile_));
111     }
112 
113     if (!renderInited_.load()) {
114         for (auto &it : audioRenderWrapperMap_) {
115             int32_t ret = CreateRender(it.first);
116             CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "create render fail");
117             renderInited_.store(true);
118         }
119     }
120 
121     if (started_.load()) {
122         AUDIO_INFO_LOG("already started");
123         return SUCCESS;
124     }
125 
126     for (auto &it : audioRenderWrapperMap_) {
127         CHECK_AND_RETURN_RET_LOG(it.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
128             "render is nullptr, type: %{public}d", it.first);
129         int32_t ret = it.second.audioRender_->Start();
130         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "start fail, type: %{public}d, ret: %{public}d",
131             it.first, ret);
132     }
133     started_.store(true);
134     AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_REMOTE, INIT_LASTWRITTEN_TIME);
135     return SUCCESS;
136 }
137 
Stop(void)138 int32_t RemoteAudioRenderSink::Stop(void)
139 {
140     Trace trace("RemoteAudioRenderSink::Stop");
141     AUDIO_INFO_LOG("in");
142     if (!started_.load()) {
143         AUDIO_INFO_LOG("already stopped");
144         return SUCCESS;
145     }
146 
147     for (auto &it : audioRenderWrapperMap_) {
148         CHECK_AND_RETURN_RET_LOG(it.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
149             "render is nullptr, type: %{public}d", it.first);
150         int32_t ret = it.second.audioRender_->Stop();
151         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail, type: %{public}d, ret: %{public}d",
152             it.first, ret);
153     }
154     started_.store(false);
155     return SUCCESS;
156 }
157 
Resume(void)158 int32_t RemoteAudioRenderSink::Resume(void)
159 {
160     Trace trace("RemoteAudioRenderSink::Resume");
161     AUDIO_INFO_LOG("in");
162     CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
163 
164     if (!paused_.load()) {
165         AUDIO_INFO_LOG("already resumed");
166         return SUCCESS;
167     }
168 
169     for (auto &it : audioRenderWrapperMap_) {
170         CHECK_AND_RETURN_RET_LOG(it.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
171             "render is nullptr, type: %{public}d", it.first);
172         int32_t ret = it.second.audioRender_->Resume();
173         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "resume fail, type: %{public}d, ret: %{public}d",
174             it.first, ret);
175     }
176     paused_.store(false);
177     AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_REMOTE, INIT_LASTWRITTEN_TIME);
178     return SUCCESS;
179 }
180 
Pause(void)181 int32_t RemoteAudioRenderSink::Pause(void)
182 {
183     AUDIO_INFO_LOG("in");
184     CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
185 
186     if (paused_.load()) {
187         AUDIO_INFO_LOG("already paused");
188         return SUCCESS;
189     }
190 
191     for (auto &it : audioRenderWrapperMap_) {
192         CHECK_AND_RETURN_RET_LOG(it.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
193             "render is nullptr, type: %{public}d", it.first);
194         int32_t ret = it.second.audioRender_->Pause();
195         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "pause fail, type: %{public}d, ret: %{public}d",
196             it.first, ret);
197     }
198     paused_.store(true);
199     return SUCCESS;
200 }
201 
Flush(void)202 int32_t RemoteAudioRenderSink::Flush(void)
203 {
204     Trace trace("RemoteAudioRenderSink::Flush");
205     AUDIO_INFO_LOG("in");
206     CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
207 
208     for (auto &it : audioRenderWrapperMap_) {
209         CHECK_AND_RETURN_RET_LOG(it.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
210             "render is nullptr, type: %{public}d", it.first);
211         int32_t ret = it.second.audioRender_->Flush();
212         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "flush fail, type: %{public}d, ret: %{public}d",
213             it.first, ret);
214     }
215     return SUCCESS;
216 }
217 
Reset(void)218 int32_t RemoteAudioRenderSink::Reset(void)
219 {
220     Trace trace("RemoteAudioRenderSink::Reset");
221     AUDIO_INFO_LOG("in");
222     CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
223 
224     for (auto &it : audioRenderWrapperMap_) {
225         CHECK_AND_RETURN_RET_LOG(it.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
226             "render is nullptr, type: %{public}d", it.first);
227         int32_t ret = it.second.audioRender_->Flush();
228         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "reset fail, type: %{public}d, ret: %{public}d",
229             it.first, ret);
230     }
231     return SUCCESS;
232 }
233 
RenderFrame(char & data,uint64_t len,uint64_t & writeLen)234 int32_t RemoteAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
235 {
236     Trace trace("RemoteAudioRenderSink::RenderFrame");
237     AUDIO_DEBUG_LOG("in");
238     return RenderFrame(data, len, writeLen, AUDIO_IN_MEDIA);
239 }
240 
SuspendRenderSink(void)241 int32_t RemoteAudioRenderSink::SuspendRenderSink(void)
242 {
243     return SUCCESS;
244 }
245 
RestoreRenderSink(void)246 int32_t RemoteAudioRenderSink::RestoreRenderSink(void)
247 {
248     return SUCCESS;
249 }
250 
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)251 void RemoteAudioRenderSink::SetAudioParameter(const AudioParamKey key, const std::string &condition,
252     const std::string &value)
253 {
254 }
255 
GetAudioParameter(const AudioParamKey key,const std::string & condition)256 std::string RemoteAudioRenderSink::GetAudioParameter(const AudioParamKey key, const std::string &condition)
257 {
258     return "";
259 }
260 
SetVolume(float left,float right)261 int32_t RemoteAudioRenderSink::SetVolume(float left, float right)
262 {
263     leftVolume_ = left;
264     rightVolume_ = right;
265     float volume;
266     if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
267         volume = rightVolume_;
268     } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
269         volume = leftVolume_;
270     } else {
271         volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
272     }
273 
274     for (const auto &wrapper : audioRenderWrapperMap_) {
275         CHECK_AND_RETURN_RET_LOG(wrapper.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
276             "render is nullptr, type: %{public}d", wrapper.first);
277         int32_t ret = wrapper.second.audioRender_->SetVolume(volume);
278         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "set volume fail, ret: %{public}d", ret);
279     }
280     return SUCCESS;
281 }
282 
GetVolume(float & left,float & right)283 int32_t RemoteAudioRenderSink::GetVolume(float &left, float &right)
284 {
285     left = leftVolume_;
286     right = rightVolume_;
287     return SUCCESS;
288 }
289 
GetLatency(uint32_t & latency)290 int32_t RemoteAudioRenderSink::GetLatency(uint32_t &latency)
291 {
292     uint32_t hdiLatency = 0;
293     for (const auto &wrapper : audioRenderWrapperMap_) {
294         CHECK_AND_RETURN_RET_LOG(wrapper.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
295             "render is nullptr, type: %{public}d", wrapper.first);
296         int32_t ret = wrapper.second.audioRender_->GetLatency(hdiLatency);
297         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get latency fail, ret: %{public}d", ret);
298     }
299     latency = hdiLatency;
300     return SUCCESS;
301 }
302 
GetTransactionId(uint64_t & transactionId)303 int32_t RemoteAudioRenderSink::GetTransactionId(uint64_t &transactionId)
304 {
305     AUDIO_INFO_LOG("not support");
306     return ERR_NOT_SUPPORTED;
307 }
308 
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)309 int32_t RemoteAudioRenderSink::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
310 {
311     AUDIO_INFO_LOG("not support");
312     return ERR_NOT_SUPPORTED;
313 }
314 
GetMaxAmplitude(void)315 float RemoteAudioRenderSink::GetMaxAmplitude(void)
316 {
317     lastGetMaxAmplitudeTime_ = ClockTime::GetCurNano();
318     startUpdate_ = true;
319     return maxAmplitude_;
320 }
321 
SetAudioMonoState(bool audioMono)322 void RemoteAudioRenderSink::SetAudioMonoState(bool audioMono)
323 {
324     AUDIO_INFO_LOG("not support");
325 }
326 
SetAudioBalanceValue(float audioBalance)327 void RemoteAudioRenderSink::SetAudioBalanceValue(float audioBalance)
328 {
329     AUDIO_INFO_LOG("not support");
330 }
331 
SetAudioScene(AudioScene audioScene,std::vector<DeviceType> & activeDevices)332 int32_t RemoteAudioRenderSink::SetAudioScene(AudioScene audioScene, std::vector<DeviceType> &activeDevices)
333 {
334     CHECK_AND_RETURN_RET_LOG(audioScene >= AUDIO_SCENE_DEFAULT && audioScene < AUDIO_SCENE_MAX, ERR_INVALID_PARAM,
335         "invalid scene");
336     CHECK_AND_RETURN_RET_LOG(!activeDevices.empty() && activeDevices.size() <= AUDIO_CONCURRENT_ACTIVE_DEVICES_LIMIT,
337         ERR_INVALID_PARAM, "invalid device");
338     AUDIO_INFO_LOG("scene: %{public}d, device: %{public}d", audioScene, activeDevices.front());
339 
340     int32_t ret = DoSetOutputRoute();
341     if (ret != SUCCESS) {
342         AUDIO_WARNING_LOG("update route fail, ret: %{public}d", ret);
343     }
344 
345     struct AudioSceneDescriptor sceneDesc = {
346         .scene.id = GetAudioCategory(audioScene),
347         .desc.pins = AudioPortPin::PIN_OUT_SPEAKER,
348     };
349     AUDIO_DEBUG_LOG("start");
350     for (const auto &wrapper : audioRenderWrapperMap_) {
351         CHECK_AND_RETURN_RET_LOG(wrapper.second.audioRender_ != nullptr, ERR_INVALID_HANDLE,
352             "render is nullptr, type: %{public}d", wrapper.first);
353         ret = wrapper.second.audioRender_->SelectScene(sceneDesc);
354         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "select scene fail, ret: %{public}d", ret);
355     }
356     AUDIO_DEBUG_LOG("end, audioScene: %{public}d", audioScene);
357     return SUCCESS;
358 }
359 
GetAudioScene(void)360 int32_t RemoteAudioRenderSink::GetAudioScene(void)
361 {
362     AUDIO_INFO_LOG("not support");
363     return ERR_NOT_SUPPORTED;
364 }
365 
UpdateActiveDevice(std::vector<DeviceType> & outputDevices)366 int32_t RemoteAudioRenderSink::UpdateActiveDevice(std::vector<DeviceType> &outputDevices)
367 {
368     AUDIO_INFO_LOG("not support");
369     return ERR_NOT_SUPPORTED;
370 }
371 
RegistCallback(uint32_t type,IAudioSinkCallback * callback)372 void RemoteAudioRenderSink::RegistCallback(uint32_t type, IAudioSinkCallback *callback)
373 {
374     AUDIO_INFO_LOG("in");
375     callback_.RegistCallback(type, callback);
376 }
377 
ResetActiveDeviceForDisconnect(DeviceType device)378 void RemoteAudioRenderSink::ResetActiveDeviceForDisconnect(DeviceType device)
379 {
380     AUDIO_INFO_LOG("not support");
381 }
382 
SetPaPower(int32_t flag)383 int32_t RemoteAudioRenderSink::SetPaPower(int32_t flag)
384 {
385     AUDIO_INFO_LOG("not support");
386     return ERR_NOT_SUPPORTED;
387 }
388 
SetPriPaPower(void)389 int32_t RemoteAudioRenderSink::SetPriPaPower(void)
390 {
391     AUDIO_INFO_LOG("not support");
392     return ERR_NOT_SUPPORTED;
393 }
394 
UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS],const size_t size)395 int32_t RemoteAudioRenderSink::UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS], const size_t size)
396 {
397     return ERR_NOT_SUPPORTED;
398 }
399 
UpdateAppsUid(const std::vector<int32_t> & appsUid)400 int32_t RemoteAudioRenderSink::UpdateAppsUid(const std::vector<int32_t> &appsUid)
401 {
402     return ERR_NOT_SUPPORTED;
403 }
404 
SplitRenderFrame(char & data,uint64_t len,uint64_t & writeLen,const char * streamType)405 int32_t RemoteAudioRenderSink::SplitRenderFrame(char &data, uint64_t len, uint64_t &writeLen, const char *streamType)
406 {
407     Trace trace("RemoteAudioRenderSink::SplitRenderFrame");
408     AUDIO_DEBUG_LOG("in, type: %{public}s", streamType);
409     auto it = SPLIT_STREAM_MAP.find(streamType);
410     CHECK_AND_RETURN_RET_LOG(it != SPLIT_STREAM_MAP.end(), ERR_INVALID_PARAM, "invalid stream type");
411     return RenderFrame(data, len, writeLen, it->second);
412 }
413 
DumpInfo(std::string & dumpString)414 void RemoteAudioRenderSink::DumpInfo(std::string &dumpString)
415 {
416     dumpString += "type: RemoteSink\tstarted: " + std::string(started_.load() ? "true" : "false") +
417         "\tdeviceNetworkId: " + deviceNetworkId_ + "\n";
418 }
419 
OnAudioParamChange(const std::string & adapterName,const AudioParamKey key,const std::string & condition,const std::string & value)420 void RemoteAudioRenderSink::OnAudioParamChange(const std::string &adapterName, const AudioParamKey key,
421     const std::string &condition, const std::string &value)
422 {
423     AUDIO_INFO_LOG("key: %{public}d, condition: %{public}s, value: %{public}s", key, condition.c_str(), value.c_str());
424     if (key == AudioParamKey::PARAM_KEY_STATE) {
425         DeInit();
426     }
427 
428     callback_.OnRenderSinkParamChange(adapterName, key, condition, value);
429 }
430 
ConvertToHdiFormat(AudioSampleFormat format)431 AudioFormat RemoteAudioRenderSink::ConvertToHdiFormat(AudioSampleFormat format)
432 {
433     AudioFormat hdiFormat;
434     switch (format) {
435         case SAMPLE_U8:
436             hdiFormat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
437             break;
438         case SAMPLE_S16LE:
439             hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
440             break;
441         case SAMPLE_S24LE:
442             hdiFormat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
443             break;
444         case SAMPLE_S32LE:
445             hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
446             break;
447         default:
448             hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
449             break;
450     }
451 
452     return hdiFormat;
453 }
454 
GetAudioCategory(AudioScene audioScene)455 AudioCategory RemoteAudioRenderSink::GetAudioCategory(AudioScene audioScene)
456 {
457     AudioCategory audioCategory;
458     switch (audioScene) {
459         case AUDIO_SCENE_DEFAULT:
460             audioCategory = AUDIO_IN_MEDIA;
461             break;
462         case AUDIO_SCENE_RINGING:
463         case AUDIO_SCENE_VOICE_RINGING:
464             audioCategory = AUDIO_IN_RINGTONE;
465             break;
466         case AUDIO_SCENE_PHONE_CALL:
467             audioCategory = AUDIO_IN_CALL;
468             break;
469         case AUDIO_SCENE_PHONE_CHAT:
470             audioCategory = AUDIO_IN_COMMUNICATION;
471             break;
472         default:
473             audioCategory = AUDIO_IN_MEDIA;
474             break;
475     }
476     AUDIO_DEBUG_LOG("audioCategory: %{public}d", audioCategory);
477 
478     return audioCategory;
479 }
480 
InitSplitStream(const char * splitStreamStr,std::vector<AudioCategory> & splitStreamVector)481 void RemoteAudioRenderSink::InitSplitStream(const char *splitStreamStr, std::vector<AudioCategory> &splitStreamVector)
482 {
483     AUDIO_INFO_LOG("splitStreamStr: %{public}s", splitStreamStr);
484     if (splitStreamStr == nullptr) {
485         splitStreamVector.push_back(AudioCategory::AUDIO_IN_MEDIA);
486         AUDIO_INFO_LOG("split stream use default 1");
487         return;
488     }
489 
490     std::istringstream iss(splitStreamStr);
491     std::string currentSplitStream;
492     std::vector<std::string> splitStreamStrVector;
493     while (getline(iss, currentSplitStream, ':')) {
494         splitStreamStrVector.push_back(currentSplitStream);
495         AUDIO_INFO_LOG("current split stream type is %{public}s", currentSplitStream.c_str());
496     }
497     sort(splitStreamStrVector.begin(), splitStreamStrVector.end());
498     for (auto &splitStream : splitStreamStrVector) {
499         auto it = SPLIT_STREAM_MAP.find(splitStream);
500         if (it == SPLIT_STREAM_MAP.end()) {
501             AUDIO_ERR_LOG("invalid stream type %{public}s", splitStream.c_str());
502             continue;
503         }
504         splitStreamVector.push_back(it->second);
505     }
506 }
507 
InitAudioSampleAttr(AudioSampleAttributes & param,AudioCategory type)508 void RemoteAudioRenderSink::InitAudioSampleAttr(AudioSampleAttributes &param, AudioCategory type)
509 {
510     param.channelCount = AUDIO_CHANNELCOUNT;
511     param.sampleRate = AUDIO_SAMPLE_RATE_48K;
512     param.interleaved = 0;
513     param.streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_REMOTE));
514     param.type = AUDIO_IN_MEDIA;
515     param.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
516     param.isBigEndian = false;
517     param.isSignedData = true;
518     param.stopThreshold = INT_MAX;
519     param.silenceThreshold = 0;
520 
521     param.sampleRate = attr_.sampleRate;
522     param.channelCount = attr_.channel;
523     param.format = ConvertToHdiFormat(attr_.format);
524     param.frameSize = PCM_16_BIT * param.channelCount / PCM_8_BIT;
525     param.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (param.frameSize);
526 
527     param.type = type;
528 }
529 
InitDeviceDesc(AudioDeviceDescriptor & deviceDesc)530 void RemoteAudioRenderSink::InitDeviceDesc(AudioDeviceDescriptor &deviceDesc)
531 {
532     deviceDesc.pins = AudioPortPin::PIN_OUT_SPEAKER;
533     deviceDesc.desc = "";
534 }
535 
CreateRender(AudioCategory type)536 int32_t RemoteAudioRenderSink::CreateRender(AudioCategory type)
537 {
538     int64_t stamp = ClockTime::GetCurNano();
539 
540     struct AudioSampleAttributes param;
541     struct AudioDeviceDescriptor deviceDesc;
542     InitAudioSampleAttr(param, type);
543     InitDeviceDesc(deviceDesc);
544     struct RenderWrapper &wrapper = audioRenderWrapperMap_[type];
545 
546     AUDIO_INFO_LOG("create render, format: %{public}u", param.format);
547     HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
548     std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_REMOTE);
549     CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
550     void *render = deviceManager->CreateRender(deviceNetworkId_, &param, &deviceDesc, wrapper.hdiRenderId_);
551     wrapper.audioRender_.ForceSetRefPtr(static_cast<IAudioRender *>(render));
552     CHECK_AND_RETURN_RET(wrapper.audioRender_ != nullptr, ERR_NOT_STARTED);
553     deviceManager->RegistRenderSinkCallback(deviceNetworkId_, wrapper.hdiRenderId_, this);
554 
555     stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
556     AUDIO_INFO_LOG("create render success, cost: [%{public}" PRId64 "]ms", stamp);
557     return SUCCESS;
558 }
559 
DoSetOutputRoute(void)560 int32_t RemoteAudioRenderSink::DoSetOutputRoute(void)
561 {
562     if (audioRenderWrapperMap_.find(AUDIO_IN_MEDIA) == audioRenderWrapperMap_.end()) {
563         AUDIO_WARNING_LOG("render not include AUDIO_IN_MEDIA");
564         return ERR_INVALID_HANDLE;
565     }
566     HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
567     std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_REMOTE);
568     CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
569     int32_t ret = deviceManager->SetOutputRoute(deviceNetworkId_, { DEVICE_TYPE_SPEAKER }, static_cast<int32_t>(
570         GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_REMOTE)));
571     return ret;
572 }
573 
CheckUpdateState(char * data,uint64_t len)574 void RemoteAudioRenderSink::CheckUpdateState(char *data, uint64_t len)
575 {
576     if (startUpdate_) {
577         if (renderFrameNum_ == 0) {
578             last10FrameStartTime_ = ClockTime::GetCurNano();
579         }
580         renderFrameNum_++;
581         maxAmplitude_ = UpdateMaxAmplitude(static_cast<ConvertHdiFormat>(attr_.format), data, len);
582         if (renderFrameNum_ == GET_MAX_AMPLITUDE_FRAMES_THRESHOLD) {
583             renderFrameNum_ = 0;
584             if (last10FrameStartTime_ > lastGetMaxAmplitudeTime_) {
585                 startUpdate_ = false;
586                 maxAmplitude_ = 0;
587             }
588         }
589     }
590 }
591 
RenderFrame(char & data,uint64_t len,uint64_t & writeLen,AudioCategory type)592 int32_t RemoteAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen, AudioCategory type)
593 {
594     AUDIO_DEBUG_LOG("type: %{public}d", type);
595     int64_t stamp = ClockTime::GetCurNano();
596     sptr<IAudioRender> audioRender = audioRenderWrapperMap_[type].audioRender_;
597     CHECK_AND_RETURN_RET_LOG(audioRender != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
598     if (!started_.load()) {
599         AUDIO_WARNING_LOG("not start, invalid state");
600     }
601 
602     std::vector<int8_t> bufferVec(len);
603     int32_t ret = memcpy_s(bufferVec.data(), len, &data, len);
604     CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_OPERATION_FAILED, "copy fail, error code: %{public}d", ret);
605 
606     BufferDesc buffer = { reinterpret_cast<uint8_t *>(&data), len, len };
607     AudioStreamInfo streamInfo(static_cast<AudioSamplingRate>(attr_.sampleRate), AudioEncodingType::ENCODING_PCM,
608         static_cast<AudioSampleFormat>(attr_.format), static_cast<AudioChannel>(attr_.channel));
609     VolumeTools::DfxOperation(buffer, streamInfo, logUtilsTag_, volumeDataCount_);
610     Trace trace("RemoteAudioRenderSink::RenderFrame inner renderFrame");
611     Trace::CountVolume("RemoteAudioRenderSink::RenderFrame", static_cast<uint8_t>(data));
612     ret = audioRender->RenderFrame(bufferVec, writeLen);
613     AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_REMOTE, ClockTime::GetCurNano());
614     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "fail, ret: %{public}x", ret);
615     writeLen = len;
616 
617     FILE *dumpFile = audioRenderWrapperMap_[type].dumpFile_;
618     DumpFileUtil::WriteDumpFile(dumpFile, static_cast<void *>(&data), len);
619     std::string dumpFileName = audioRenderWrapperMap_[type].dumpFileName_;
620     AudioCacheMgr::GetInstance().CacheData(dumpFileName, static_cast<void *>(&data), len);
621     CheckUpdateState(&data, len);
622 
623     stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
624     int64_t stampThreshold = 50; // 50ms
625     if (stamp >= stampThreshold) {
626         AUDIO_WARNING_LOG("len: [%{public}" PRIu64 "], cost: [%{public}" PRId64 "]ms", len, stamp);
627     }
628     return SUCCESS;
629 }
630 
631 } // namespace AudioStandard
632 } // namespace OHOS
633