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