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 "MultichannelAudioRenderSink"
18 #endif
19
20 #include "sink/multichannel_audio_render_sink.h"
21 #include <climits>
22 #include "parameters.h"
23 #include "audio_hdi_log.h"
24 #include "audio_errors.h"
25 #include "audio_dump_pcm.h"
26 #include "volume_tools.h"
27 #include "audio_performance_monitor.h"
28 #include "common/hdi_adapter_info.h"
29 #include "manager/hdi_adapter_manager.h"
30
31 namespace {
32 const std::string DEFAULT_NAME = "multichannel";
33 }
34 namespace OHOS {
35 namespace AudioStandard {
MultichannelAudioRenderSink(const std::string & halName)36 MultichannelAudioRenderSink::MultichannelAudioRenderSink(const std::string &halName)
37 : halName_(halName == HDI_ID_INFO_DEFAULT ? DEFAULT_NAME : halName)
38 {
39 AUDIO_INFO_LOG("construction");
40 }
41
~MultichannelAudioRenderSink()42 MultichannelAudioRenderSink::~MultichannelAudioRenderSink()
43 {
44 AUDIO_INFO_LOG("destruction");
45 AudioPerformanceMonitor::GetInstance().DeleteOvertimeMonitor(ADAPTER_TYPE_MULTICHANNEL);
46 }
47
Init(const IAudioSinkAttr & attr)48 int32_t MultichannelAudioRenderSink::Init(const IAudioSinkAttr &attr)
49 {
50 std::lock_guard<std::mutex> lock(sinkMutex_);
51 attr_ = attr;
52 adapterNameCase_ = attr_.adapterName;
53 openSpeaker_ = attr_.openMicSpeaker;
54 logMode_ = system::GetIntParameter("persist.multimedia.audiolog.switch", 0);
55
56 int32_t ret = InitRender();
57 CHECK_AND_RETURN_RET(ret == SUCCESS, ret);
58
59 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
60 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
61 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
62
63 sinkInited_ = true;
64 return SUCCESS;
65 }
66
DeInit(void)67 void MultichannelAudioRenderSink::DeInit(void)
68 {
69 std::lock_guard<std::mutex> lock(sinkMutex_);
70 sinkInited_ = false;
71 started_ = false;
72
73 AUDIO_INFO_LOG("destroy render, hdiRenderId: %{public}u", hdiRenderId_);
74 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
75 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
76 CHECK_AND_RETURN(deviceManager != nullptr);
77 renderInited_ = false;
78 deviceManager->DestroyRender(adapterNameCase_, hdiRenderId_);
79 audioRender_ = nullptr;
80
81 DumpFileUtil::CloseDumpFile(&dumpFile_);
82 }
83
IsInited(void)84 bool MultichannelAudioRenderSink::IsInited(void)
85 {
86 return sinkInited_;
87 }
88
Start(void)89 int32_t MultichannelAudioRenderSink::Start(void)
90 {
91 std::lock_guard<std::mutex> lock(sinkMutex_);
92 Trace trace("MultichannelAudioRenderSink::Start");
93 #ifdef FEATURE_POWER_MANAGER
94 if (runningLock_ == nullptr) {
95 WatchTimeout guard("create AudioRunningLock start");
96 runningLock_ = std::make_shared<AudioRunningLock>(std::string(RUNNING_LOCK_NAME_BASE) + halName_);
97 guard.CheckCurrTimeout();
98 }
99 if (runningLock_ != nullptr) {
100 runningLock_->Lock(RUNNING_LOCK_TIMEOUTMS_LASTING);
101 } else {
102 AUDIO_ERR_LOG("running lock is null, playback can not work well");
103 }
104 #endif
105 dumpFileName_ = "multichannel_sink_" + GetTime() + "_" + std::to_string(attr_.sampleRate) + "_" +
106 std::to_string(attr_.channel) + "_" + std::to_string(attr_.format) + ".pcm";
107 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileName_, &dumpFile_);
108 if (started_) {
109 return SUCCESS;
110 }
111 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
112 int32_t ret = audioRender_->Start(audioRender_);
113 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "start fail");
114 UpdateSinkState(true);
115 started_ = true;
116
117 uint64_t frameSize = 0;
118 uint64_t frameCount = 0;
119 ret = audioRender_->GetFrameSize(audioRender_, &frameSize);
120 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "get frame size fail");
121 ret = audioRender_->GetFrameCount(audioRender_, &frameCount);
122 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "get frame count fail");
123 ret = audioRender_->SetVolume(audioRender_, 1);
124 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "set volume fail");
125 AUDIO_INFO_LOG("start success, frameSize: %{public}" PRIu64 ", frameCount: %{public}" PRIu64, frameSize,
126 frameCount);
127 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_MULTICHANNEL, INIT_LASTWRITTEN_TIME);
128 return SUCCESS;
129 }
130
Stop(void)131 int32_t MultichannelAudioRenderSink::Stop(void)
132 {
133 std::lock_guard<std::mutex> lock(sinkMutex_);
134 Trace trace("MultichannelAudioRenderSink::Stop");
135 AUDIO_INFO_LOG("in");
136 #ifdef FEATURE_POWER_MANAGER
137 if (runningLock_ != nullptr) {
138 AUDIO_INFO_LOG("running lock unlock");
139 runningLock_->UnLock();
140 } else {
141 AUDIO_WARNING_LOG("running lock is null, playback can not work well");
142 }
143 #endif
144 if (!started_) {
145 return SUCCESS;
146 }
147 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
148 int32_t ret = audioRender_->Stop(audioRender_);
149 UpdateSinkState(false);
150 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail");
151 started_ = false;
152 return SUCCESS;
153 }
154
Resume(void)155 int32_t MultichannelAudioRenderSink::Resume(void)
156 {
157 std::lock_guard<std::mutex> lock(sinkMutex_);
158 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
159 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
160
161 if (!paused_) {
162 return SUCCESS;
163 }
164 int32_t ret = audioRender_->Resume(audioRender_);
165 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "resume fail");
166 paused_ = false;
167 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_MULTICHANNEL, INIT_LASTWRITTEN_TIME);
168 return SUCCESS;
169 }
170
Pause(void)171 int32_t MultichannelAudioRenderSink::Pause(void)
172 {
173 std::lock_guard<std::mutex> lock(sinkMutex_);
174 Trace trace("MultichannelAudioRenderSink::Pause");
175 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
176 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
177
178 if (paused_) {
179 return SUCCESS;
180 }
181 int32_t ret = audioRender_->Pause(audioRender_);
182 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "pause fail");
183 paused_ = true;
184 return SUCCESS;
185 }
186
Flush(void)187 int32_t MultichannelAudioRenderSink::Flush(void)
188 {
189 Trace trace("MultichannelAudioRenderSink::Flush");
190 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
191 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
192
193 int32_t ret = audioRender_->Flush(audioRender_);
194 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "flush fail");
195 return SUCCESS;
196 }
197
Reset(void)198 int32_t MultichannelAudioRenderSink::Reset(void)
199 {
200 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
201 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
202
203 int32_t ret = audioRender_->Flush(audioRender_);
204 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "reset fail");
205 return SUCCESS;
206 }
207
RenderFrame(char & data,uint64_t len,uint64_t & writeLen)208 int32_t MultichannelAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
209 {
210 int64_t stamp = ClockTime::GetCurNano();
211 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
212 if (audioMonoState_) {
213 AdjustStereoToMono(&data, len);
214 }
215 if (audioBalanceState_) {
216 AdjustAudioBalance(&data, len);
217 }
218 CheckUpdateState(&data, len);
219 if (switchDeviceMute_) {
220 Trace trace("MultichannelAudioRenderSink::RenderFrame::switch");
221 writeLen = len;
222 return SUCCESS;
223 }
224 if (emptyFrameCount_ > 0) {
225 Trace trace("MultichannelAudioRenderSink::RenderFrame::renderEmpty");
226 if (memset_s(reinterpret_cast<void *>(&data), static_cast<size_t>(len), 0, static_cast<size_t>(len)) != EOK) {
227 AUDIO_WARNING_LOG("call memset_s fail");
228 }
229 --emptyFrameCount_;
230 if (emptyFrameCount_ == 0) {
231 switchDeviceCV_.notify_all();
232 }
233 }
234
235 BufferDesc buffer = { reinterpret_cast<uint8_t *>(&data), len, len };
236 AudioStreamInfo streamInfo(static_cast<AudioSamplingRate>(attr_.sampleRate), AudioEncodingType::ENCODING_PCM,
237 static_cast<AudioSampleFormat>(attr_.format), static_cast<AudioChannel>(attr_.channel));
238 VolumeTools::DfxOperation(buffer, streamInfo, logUtilsTag_, volumeDataCount_);
239 Trace trace("MultichannelAudioRenderSink::RenderFrame");
240 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(&data), len);
241 if (AudioDump::GetInstance().GetVersionType() == DumpFileUtil::BETA_VERSION) {
242 AudioCacheMgr::GetInstance().CacheData(dumpFileName_, static_cast<void *>(&data), len);
243 }
244 int32_t ret = audioRender_->RenderFrame(audioRender_, reinterpret_cast<int8_t *>(&data), static_cast<uint32_t>(len),
245 &writeLen);
246 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "fail, ret: %{public}x", ret);
247 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_MULTICHANNEL, ClockTime::GetCurNano());
248 stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
249 if (logMode_) {
250 AUDIO_DEBUG_LOG("len: [%{public}" PRIu64 "], cost: [%{public}" PRId64 "]ms", len, stamp);
251 }
252
253 return SUCCESS;
254 }
255
GetVolumeDataCount()256 int64_t MultichannelAudioRenderSink::GetVolumeDataCount()
257 {
258 return volumeDataCount_;
259 }
260
SuspendRenderSink(void)261 int32_t MultichannelAudioRenderSink::SuspendRenderSink(void)
262 {
263 return SUCCESS;
264 }
265
RestoreRenderSink(void)266 int32_t MultichannelAudioRenderSink::RestoreRenderSink(void)
267 {
268 return SUCCESS;
269 }
270
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)271 void MultichannelAudioRenderSink::SetAudioParameter(const AudioParamKey key, const std::string &condition,
272 const std::string &value)
273 {
274 }
275
GetAudioParameter(const AudioParamKey key,const std::string & condition)276 std::string MultichannelAudioRenderSink::GetAudioParameter(const AudioParamKey key, const std::string &condition)
277 {
278 if (condition == "get_usb_info") {
279 // init adapter to get parameter before load sink module (need fix)
280 adapterNameCase_ = "usb";
281 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
282 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
283 CHECK_AND_RETURN_RET(deviceManager != nullptr, "");
284 return deviceManager->GetAudioParameter(adapterNameCase_, key, condition);
285 }
286 return "";
287 }
288
SetVolume(float left,float right)289 int32_t MultichannelAudioRenderSink::SetVolume(float left, float right)
290 {
291 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
292
293 leftVolume_ = left;
294 rightVolume_ = right;
295 float volume;
296 if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
297 volume = rightVolume_;
298 } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
299 volume = leftVolume_;
300 } else {
301 volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
302 }
303
304 int32_t ret = audioRender_->SetVolume(audioRender_, volume);
305 if (ret != SUCCESS) {
306 AUDIO_WARNING_LOG("set volume fail");
307 }
308
309 return ret;
310 }
311
GetVolume(float & left,float & right)312 int32_t MultichannelAudioRenderSink::GetVolume(float &left, float &right)
313 {
314 left = leftVolume_;
315 right = rightVolume_;
316 return SUCCESS;
317 }
318
GetLatency(uint32_t & latency)319 int32_t MultichannelAudioRenderSink::GetLatency(uint32_t &latency)
320 {
321 Trace trace("MultichannelAudioRenderSink::GetLatency");
322 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
323
324 uint32_t hdiLatency;
325 int32_t ret = audioRender_->GetLatency(audioRender_, &hdiLatency);
326 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get latency fail");
327 latency = hdiLatency;
328 return SUCCESS;
329 }
330
GetTransactionId(uint64_t & transactionId)331 int32_t MultichannelAudioRenderSink::GetTransactionId(uint64_t &transactionId)
332 {
333 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
334 transactionId = reinterpret_cast<uint64_t>(audioRender_);
335 return SUCCESS;
336 }
337
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)338 int32_t MultichannelAudioRenderSink::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
339 {
340 AUDIO_INFO_LOG("not support");
341 return ERR_NOT_SUPPORTED;
342 }
343
GetMaxAmplitude(void)344 float MultichannelAudioRenderSink::GetMaxAmplitude(void)
345 {
346 lastGetMaxAmplitudeTime_ = ClockTime::GetCurNano();
347 startUpdate_ = true;
348 return maxAmplitude_;
349 }
350
SetAudioMonoState(bool audioMono)351 void MultichannelAudioRenderSink::SetAudioMonoState(bool audioMono)
352 {
353 audioMonoState_ = audioMono;
354 }
355
SetAudioBalanceValue(float audioBalance)356 void MultichannelAudioRenderSink::SetAudioBalanceValue(float audioBalance)
357 {
358 // reset the balance coefficient value firstly
359 leftBalanceCoef_ = 1.0f;
360 rightBalanceCoef_ = 1.0f;
361
362 if (std::abs(audioBalance - 0.0f) <= std::numeric_limits<float>::epsilon()) {
363 // audioBalance is equal to 0.0f
364 audioBalanceState_ = false;
365 } else {
366 // audioBalance is not equal to 0.0f
367 audioBalanceState_ = true;
368 // calculate the balance coefficient
369 if (audioBalance > 0.0f) {
370 leftBalanceCoef_ -= audioBalance;
371 } else if (audioBalance < 0.0f) {
372 rightBalanceCoef_ += audioBalance;
373 }
374 }
375 }
376
SetAudioScene(AudioScene audioScene,bool scoExcludeFlag)377 int32_t MultichannelAudioRenderSink::SetAudioScene(AudioScene audioScene, bool scoExcludeFlag)
378 {
379 CHECK_AND_RETURN_RET_LOG(audioScene >= AUDIO_SCENE_DEFAULT && audioScene < AUDIO_SCENE_MAX, ERR_INVALID_PARAM,
380 "invalid scene");
381 if (!openSpeaker_) {
382 return SUCCESS;
383 }
384
385 if (audioScene != currentAudioScene_) {
386 struct AudioSceneDescriptor sceneDesc;
387 InitSceneDesc(sceneDesc, audioScene);
388
389 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
390 int32_t ret = audioRender_->SelectScene(audioRender_, &sceneDesc);
391 CHECK_AND_RETURN_RET_LOG(ret >= 0, ERR_OPERATION_FAILED, "select scene fail, ret: %{public}d", ret);
392 currentAudioScene_ = audioScene;
393 }
394 return SUCCESS;
395 }
396
GetAudioScene(void)397 int32_t MultichannelAudioRenderSink::GetAudioScene(void)
398 {
399 return currentAudioScene_;
400 }
401
UpdateActiveDevice(std::vector<DeviceType> & outputDevices)402 int32_t MultichannelAudioRenderSink::UpdateActiveDevice(std::vector<DeviceType> &outputDevices)
403 {
404 CHECK_AND_RETURN_RET_LOG(!outputDevices.empty() && outputDevices.size() == 1, ERR_INVALID_PARAM, "invalid device");
405 if (currentActiveDevice_ == outputDevices[0]) {
406 AUDIO_INFO_LOG("output device not change, device: %{public}d", outputDevices[0]);
407 return SUCCESS;
408 }
409 currentActiveDevice_ = outputDevices[0];
410
411 emptyFrameCount_ = 5; // 5: frame count before update route
412 std::unique_lock<std::mutex> lock(switchDeviceMutex_);
413 switchDeviceCV_.wait_for(lock, std::chrono::milliseconds(SLEEP_TIME_FOR_EMPTY_FRAME), [this] {
414 if (emptyFrameCount_ == 0) {
415 AUDIO_INFO_LOG("wait for empty frame end");
416 return true;
417 }
418 AUDIO_DEBUG_LOG("emptyFrameCount: %{public}d", emptyFrameCount_.load());
419 return false;
420 });
421 int32_t ret = DoSetOutputRoute(outputDevices);
422 emptyFrameCount_ = 5; // 5: frame count after update route
423 return ret;
424 }
425
RegistCallback(uint32_t type,IAudioSinkCallback * callback)426 void MultichannelAudioRenderSink::RegistCallback(uint32_t type, IAudioSinkCallback *callback)
427 {
428 std::lock_guard<std::mutex> lock(sinkMutex_);
429 callback_.RegistCallback(type, callback);
430 AUDIO_INFO_LOG("regist succ");
431 }
432
ResetActiveDeviceForDisconnect(DeviceType device)433 void MultichannelAudioRenderSink::ResetActiveDeviceForDisconnect(DeviceType device)
434 {
435 if (currentActiveDevice_ == device) {
436 currentActiveDevice_ = DEVICE_TYPE_NONE;
437 }
438 }
439
SetPaPower(int32_t flag)440 int32_t MultichannelAudioRenderSink::SetPaPower(int32_t flag)
441 {
442 AUDIO_INFO_LOG("not support");
443 return ERR_NOT_SUPPORTED;
444 }
445
SetPriPaPower(void)446 int32_t MultichannelAudioRenderSink::SetPriPaPower(void)
447 {
448 AUDIO_INFO_LOG("not support");
449 return ERR_NOT_SUPPORTED;
450 }
451
UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS],const size_t size)452 int32_t MultichannelAudioRenderSink::UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS], const size_t size)
453 {
454 #ifdef FEATURE_POWER_MANAGER
455 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
456 runningLock_->UpdateAppsUid(appsUid, appsUid + size);
457 #endif
458 return SUCCESS;
459 }
460
UpdateAppsUid(const std::vector<int32_t> & appsUid)461 int32_t MultichannelAudioRenderSink::UpdateAppsUid(const std::vector<int32_t> &appsUid)
462 {
463 #ifdef FEATURE_POWER_MANAGER
464 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
465 runningLock_->UpdateAppsUid(appsUid.cbegin(), appsUid.cend());
466 runningLock_->UpdateAppsUidToPowerMgr();
467 #endif
468 return SUCCESS;
469 }
470
DumpInfo(std::string & dumpString)471 void MultichannelAudioRenderSink::DumpInfo(std::string &dumpString)
472 {
473 dumpString += "type: MchSink\tstarted: " + std::string(started_ ? "true" : "false") + "\thalName: " + halName_ +
474 "\tcurrentActiveDevice: " + std::to_string(currentActiveDevice_) + "\n";
475 }
476
SetDmDeviceType(uint16_t dmDeviceType,DeviceType deviceType)477 void MultichannelAudioRenderSink::SetDmDeviceType(uint16_t dmDeviceType, DeviceType deviceType)
478 {
479 AUDIO_INFO_LOG("not support");
480 }
481
PcmFormatToBit(AudioSampleFormat format)482 uint32_t MultichannelAudioRenderSink::PcmFormatToBit(AudioSampleFormat format)
483 {
484 AudioFormat hdiFormat = ConvertToHdiFormat(format);
485 switch (hdiFormat) {
486 case AUDIO_FORMAT_TYPE_PCM_8_BIT:
487 return PCM_8_BIT;
488 case AUDIO_FORMAT_TYPE_PCM_16_BIT:
489 return PCM_16_BIT;
490 case AUDIO_FORMAT_TYPE_PCM_24_BIT:
491 return PCM_24_BIT;
492 case AUDIO_FORMAT_TYPE_PCM_32_BIT:
493 return PCM_32_BIT;
494 default:
495 AUDIO_DEBUG_LOG("unknown format type, set it to default");
496 return PCM_24_BIT;
497 }
498 }
499
ConvertToHdiFormat(AudioSampleFormat format)500 AudioFormat MultichannelAudioRenderSink::ConvertToHdiFormat(AudioSampleFormat format)
501 {
502 AudioFormat hdiFormat;
503 switch (format) {
504 case SAMPLE_U8:
505 hdiFormat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
506 break;
507 case SAMPLE_S16LE:
508 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
509 break;
510 case SAMPLE_S24LE:
511 hdiFormat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
512 break;
513 case SAMPLE_S32LE:
514 hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
515 break;
516 default:
517 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
518 break;
519 }
520 return hdiFormat;
521 }
522
ParseAudioFormat(const std::string & format)523 AudioSampleFormat MultichannelAudioRenderSink::ParseAudioFormat(const std::string &format)
524 {
525 if (format == "AUDIO_FORMAT_PCM_16_BIT") {
526 return SAMPLE_S16LE;
527 } else if (format == "AUDIO_FORMAT_PCM_24_BIT" || format == "AUDIO_FORMAT_PCM_24_BIT_PACKED") {
528 return SAMPLE_S24LE;
529 } else if (format == "AUDIO_FORMAT_PCM_32_BIT") {
530 return SAMPLE_S32LE;
531 } else {
532 return SAMPLE_S16LE;
533 }
534 }
535
GetAudioCategory(AudioScene audioScene)536 AudioCategory MultichannelAudioRenderSink::GetAudioCategory(AudioScene audioScene)
537 {
538 AudioCategory audioCategory;
539 switch (audioScene) {
540 case AUDIO_SCENE_DEFAULT:
541 audioCategory = AUDIO_IN_MEDIA;
542 break;
543 case AUDIO_SCENE_RINGING:
544 case AUDIO_SCENE_VOICE_RINGING:
545 audioCategory = AUDIO_IN_RINGTONE;
546 break;
547 case AUDIO_SCENE_PHONE_CALL:
548 audioCategory = AUDIO_IN_CALL;
549 break;
550 case AUDIO_SCENE_PHONE_CHAT:
551 audioCategory = AUDIO_IN_COMMUNICATION;
552 break;
553 default:
554 audioCategory = AUDIO_IN_MEDIA;
555 break;
556 }
557 AUDIO_DEBUG_LOG("audioCategory: %{public}d", audioCategory);
558
559 return audioCategory;
560 }
561
InitAudioSampleAttr(struct AudioSampleAttributes & param)562 void MultichannelAudioRenderSink::InitAudioSampleAttr(struct AudioSampleAttributes ¶m)
563 {
564 param.channelCount = CHANNEL_6;
565 param.sampleRate = AUDIO_SAMPLE_RATE_48K;
566 param.interleaved = true;
567 param.streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_MULTICHANNEL));
568 param.type = AUDIO_MULTI_CHANNEL;
569 param.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
570 param.isBigEndian = false;
571 param.isSignedData = true;
572 param.stopThreshold = INT_MAX;
573 param.silenceThreshold = 0;
574
575 param.sampleRate = attr_.sampleRate;
576 param.channelCount = attr_.channel;
577 param.channelLayout = attr_.channelLayout;
578 param.format = ConvertToHdiFormat(attr_.format);
579 param.frameSize = PcmFormatToBit(attr_.format) * param.channelCount / PCM_8_BIT;
580 if (param.frameSize != 0) {
581 param.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (param.frameSize);
582 }
583 }
584
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)585 void MultichannelAudioRenderSink::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
586 {
587 deviceDesc.desc = const_cast<char *>("");
588 deviceDesc.pins = PIN_OUT_SPEAKER;
589 if (halName_ == HDI_ID_INFO_USB) {
590 deviceDesc.pins = PIN_OUT_USB_HEADSET;
591 }
592 }
593
InitSceneDesc(struct AudioSceneDescriptor & sceneDesc,AudioScene audioScene)594 void MultichannelAudioRenderSink::InitSceneDesc(struct AudioSceneDescriptor &sceneDesc, AudioScene audioScene)
595 {
596 sceneDesc.scene.id = GetAudioCategory(audioScene);
597
598 AudioPortPin port = PIN_OUT_SPEAKER;
599 if (halName_ == HDI_ID_INFO_USB) {
600 port = PIN_OUT_USB_HEADSET;
601 }
602 AUDIO_DEBUG_LOG("port: %{public}d", port);
603 sceneDesc.desc.pins = port;
604 sceneDesc.desc.desc = const_cast<char *>("");
605 }
606
CreateRender(void)607 int32_t MultichannelAudioRenderSink::CreateRender(void)
608 {
609 struct AudioSampleAttributes param;
610 struct AudioDeviceDescriptor deviceDesc;
611 InitAudioSampleAttr(param);
612 InitDeviceDesc(deviceDesc);
613
614 AUDIO_INFO_LOG("create render, halName: %{public}s, rate: %{public}u, channel: %{public}u, format: %{public}u",
615 halName_.c_str(), param.sampleRate, param.channelCount, param.format);
616 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
617 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
618 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
619 void *render = deviceManager->CreateRender(adapterNameCase_, ¶m, &deviceDesc, hdiRenderId_);
620 audioRender_ = static_cast<struct IAudioRender *>(render);
621 CHECK_AND_RETURN_RET(audioRender_ != nullptr, ERR_NOT_STARTED);
622
623 AUDIO_INFO_LOG("create render success, hdiRenderId_: %{public}u", hdiRenderId_);
624 return SUCCESS;
625 }
626
DoSetOutputRoute(std::vector<DeviceType> & outputDevices)627 int32_t MultichannelAudioRenderSink::DoSetOutputRoute(std::vector<DeviceType> &outputDevices)
628 {
629 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
630 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
631 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
632 int32_t ret = deviceManager->SetOutputRoute(adapterNameCase_, outputDevices,
633 GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_MULTICHANNEL));
634 return ret;
635 }
636
InitRender(void)637 int32_t MultichannelAudioRenderSink::InitRender(void)
638 {
639 AUDIO_INFO_LOG("in");
640 if (renderInited_) {
641 AUDIO_INFO_LOG("render already inited");
642 return SUCCESS;
643 }
644
645 int32_t ret = CreateRender();
646 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create render fail");
647 renderInited_ = true;
648 return SUCCESS;
649 }
650
AdjustStereoToMono(char * data,uint64_t len)651 void MultichannelAudioRenderSink::AdjustStereoToMono(char *data, uint64_t len)
652 {
653 // only stereo is supported now (stereo channel count is 2)
654 CHECK_AND_RETURN_LOG(attr_.channel == STEREO_CHANNEL_COUNT, "unsupport, channel: %{public}d", attr_.channel);
655
656 switch (attr_.format) {
657 case SAMPLE_U8:
658 AdjustStereoToMonoForPCM8Bit(reinterpret_cast<int8_t *>(data), len);
659 break;
660 case SAMPLE_S16LE:
661 AdjustStereoToMonoForPCM16Bit(reinterpret_cast<int16_t *>(data), len);
662 break;
663 case SAMPLE_S24LE:
664 AdjustStereoToMonoForPCM24Bit(reinterpret_cast<uint8_t *>(data), len);
665 break;
666 case SAMPLE_S32LE:
667 AdjustStereoToMonoForPCM32Bit(reinterpret_cast<int32_t *>(data), len);
668 break;
669 default:
670 // if the audio format is unsupported, the audio data will not be changed
671 AUDIO_ERR_LOG("unsupport, format: %{public}d", attr_.format);
672 break;
673 }
674 }
675
AdjustAudioBalance(char * data,uint64_t len)676 void MultichannelAudioRenderSink::AdjustAudioBalance(char *data, uint64_t len)
677 {
678 // only stereo is supported now (stereo channel count is 2)
679 CHECK_AND_RETURN_LOG(attr_.channel == STEREO_CHANNEL_COUNT, "unsupport, channel: %{public}d", attr_.channel);
680
681 switch (attr_.format) {
682 case SAMPLE_U8:
683 // this function needs further tested for usability
684 AdjustAudioBalanceForPCM8Bit(reinterpret_cast<int8_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
685 break;
686 case SAMPLE_S16LE:
687 AdjustAudioBalanceForPCM16Bit(reinterpret_cast<int16_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
688 break;
689 case SAMPLE_S24LE:
690 // this function needs further tested for usability
691 AdjustAudioBalanceForPCM24Bit(reinterpret_cast<uint8_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
692 break;
693 case SAMPLE_S32LE:
694 AdjustAudioBalanceForPCM32Bit(reinterpret_cast<int32_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
695 break;
696 default:
697 // if the audio format is unsupported, the audio data will not be changed
698 AUDIO_ERR_LOG("unsupport, format: %{public}d", attr_.format);
699 break;
700 }
701 }
702
CheckUpdateState(char * data,uint64_t len)703 void MultichannelAudioRenderSink::CheckUpdateState(char *data, uint64_t len)
704 {
705 if (startUpdate_) {
706 if (renderFrameNum_ == 0) {
707 last10FrameStartTime_ = ClockTime::GetCurNano();
708 }
709 renderFrameNum_++;
710 maxAmplitude_ = UpdateMaxAmplitude(static_cast<ConvertHdiFormat>(attr_.format), data, len);
711 if (renderFrameNum_ == GET_MAX_AMPLITUDE_FRAMES_THRESHOLD) {
712 renderFrameNum_ = 0;
713 if (last10FrameStartTime_ > lastGetMaxAmplitudeTime_) {
714 startUpdate_ = false;
715 maxAmplitude_ = 0;
716 }
717 }
718 }
719 }
720
721 // must be called with sinkMutex_ held
UpdateSinkState(bool started)722 void MultichannelAudioRenderSink::UpdateSinkState(bool started)
723 {
724 callback_.OnRenderSinkStateChange(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_MULTICHANNEL),
725 started);
726 }
727
728 } // namespace AudioStandard
729 } // namespace OHOS
730