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 ¶m, 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_, ¶m, &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