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 "OffloadAudioRenderSink"
18 #endif
19
20 #include "sink/offload_audio_render_sink.h"
21 #include <climits>
22 #include <future>
23 #include "audio_hdi_log.h"
24 #include "audio_errors.h"
25 #include "audio_dump_pcm.h"
26 #include "volume_tools.h"
27 #include "media_monitor_manager.h"
28 #include "common/hdi_adapter_info.h"
29 #include "manager/hdi_adapter_manager.h"
30
31 namespace OHOS {
32 namespace AudioStandard {
~OffloadAudioRenderSink()33 OffloadAudioRenderSink::~OffloadAudioRenderSink()
34 {
35 AUDIO_INFO_LOG("volumeDataCount: %{public}" PRId64, volumeDataCount_);
36 }
37
Init(const IAudioSinkAttr & attr)38 int32_t OffloadAudioRenderSink::Init(const IAudioSinkAttr &attr)
39 {
40 std::lock_guard<std::mutex> lock(sinkMutex_);
41 Trace trace("OffloadAudioRenderSink::Init");
42 attr_ = attr;
43 int32_t ret = CreateRender();
44 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create render fail");
45
46 sinkInited_ = true;
47 return SUCCESS;
48 }
49
DeInit(void)50 void OffloadAudioRenderSink::DeInit(void)
51 {
52 AUDIO_INFO_LOG("in");
53 Trace trace("OffloadAudioRenderSink::DeInit");
54 std::lock_guard<std::mutex> lock(sinkMutex_);
55 std::lock_guard<std::mutex> switchDeviceLock(switchDeviceMutex_);
56 sinkInited_ = false;
57 started_ = false;
58 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
59 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
60 CHECK_AND_RETURN(deviceManager != nullptr);
61 deviceManager->DestroyRender(attr_.adapterName, hdiRenderId_);
62 audioRender_ = nullptr;
63 hdiCallback_ = {};
64 muteCount_ = 0;
65 switchDeviceMute_ = false;
66 DumpFileUtil::CloseDumpFile(&dumpFile_);
67 }
68
IsInited(void)69 bool OffloadAudioRenderSink::IsInited(void)
70 {
71 return sinkInited_;
72 }
73
Start(void)74 int32_t OffloadAudioRenderSink::Start(void)
75 {
76 std::lock_guard<std::mutex> lock(sinkMutex_);
77 AUDIO_INFO_LOG("in");
78 Trace trace("OffloadAudioRenderSink::Start");
79 InitLatencyMeasurement();
80
81 if (started_) {
82 if (isFlushing_) {
83 isNeedRestart_ = true;
84 AUDIO_ERR_LOG("start fail, will restart after flush");
85 return ERR_OPERATION_FAILED;
86 }
87 return SUCCESS;
88 }
89 AudioXCollie audioXCollie("OffloadAudioRenderSink::Start", TIMEOUT_SECONDS_10);
90 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
91 int32_t ret = audioRender_->Start(audioRender_);
92 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "start fail, ret: %{public}d", ret);
93 UpdateSinkState(true);
94 dumpFileName_ = "offload_sink_" + GetTime() + "_" + std::to_string(attr_.sampleRate) + "_" +
95 std::to_string(attr_.channel) + "_" + std::to_string(attr_.format) + ".pcm";
96 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileName_, &dumpFile_);
97
98 started_ = true;
99 renderPos_ = 0;
100 return SUCCESS;
101 }
102
Stop(void)103 int32_t OffloadAudioRenderSink::Stop(void)
104 {
105 std::lock_guard<std::mutex> lock(sinkMutex_);
106 AUDIO_INFO_LOG("in");
107 Trace trace("OffloadAudioRenderSink::Stop");
108 DeInitLatencyMeasurement();
109 if (!started_) {
110 UnLockOffloadRunningLock();
111 return SUCCESS;
112 }
113 int32_t ret = Flush();
114 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "flush fail");
115 AudioXCollie audioXCollie("OffloadAudioRenderSink::Stop", TIMEOUT_SECONDS_10);
116 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
117 ret = audioRender_->Stop(audioRender_);
118 UpdateSinkState(false);
119 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail");
120 started_ = false;
121
122 return SUCCESS;
123 }
124
Resume(void)125 int32_t OffloadAudioRenderSink::Resume(void)
126 {
127 AUDIO_INFO_LOG("not support");
128 return ERR_NOT_SUPPORTED;
129 }
130
Pause(void)131 int32_t OffloadAudioRenderSink::Pause(void)
132 {
133 AUDIO_INFO_LOG("not support");
134 return ERR_NOT_SUPPORTED;
135 }
136
Flush(void)137 int32_t OffloadAudioRenderSink::Flush(void)
138 {
139 Trace trace("OffloadAudioRenderSink::Flush");
140 CHECK_AND_RETURN_RET_LOG(!isFlushing_, ERR_OPERATION_FAILED, "duplicate flush");
141 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
142
143 isFlushing_ = true;
144 std::thread([&] {
145 auto future = async(std::launch::async, [&] {
146 std::lock_guard<std::mutex> lock(sinkMutex_);
147 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
148 return audioRender_->Flush(audioRender_);
149 });
150 if (future.wait_for(std::chrono::milliseconds(250)) == std::future_status::timeout) { // 250: max wait 250ms
151 AUDIO_ERR_LOG("flush fail, timeout of 250ms");
152 } else {
153 int32_t ret = future.get();
154 if (ret != SUCCESS) {
155 AUDIO_ERR_LOG("flush fail, ret: %{public}d", ret);
156 }
157 }
158 isFlushing_ = false;
159 if (isNeedRestart_) {
160 isNeedRestart_ = false;
161 Start();
162 }
163 }).detach();
164 renderPos_ = 0;
165 return SUCCESS;
166 }
167
Reset(void)168 int32_t OffloadAudioRenderSink::Reset(void)
169 {
170 Trace trace("OffloadAudioRenderSink::Reset");
171 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
172
173 isNeedRestart_ = true;
174 int32_t ret = Flush();
175 if (ret != SUCCESS) {
176 isNeedRestart_ = false;
177 AUDIO_ERR_LOG("reset fail");
178 return ERR_OPERATION_FAILED;
179 }
180 return SUCCESS;
181 }
182
RenderFrame(char & data,uint64_t len,uint64_t & writeLen)183 int32_t OffloadAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
184 {
185 int64_t stamp = ClockTime::GetCurNano();
186 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
187 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
188 CHECK_AND_RETURN_RET_LOG(!isFlushing_, ERR_OPERATION_FAILED, "during flushing");
189
190 if (audioMonoState_) {
191 AdjustStereoToMono(&data, len);
192 }
193 if (audioBalanceState_) {
194 AdjustAudioBalance(&data, len);
195 }
196 Trace trace("OffloadAudioRenderSink::RenderFrame");
197 CheckLatencySignal(reinterpret_cast<uint8_t *>(&data), len);
198 int32_t ret = audioRender_->RenderFrame(audioRender_, reinterpret_cast<int8_t *>(&data), static_cast<uint32_t>(len),
199 &writeLen);
200 #ifdef FEATURE_POWER_MANAGER
201 if (runningLock_) {
202 runningLock_->UpdateAppsUidToPowerMgr();
203 }
204 #endif
205 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "fail, ret: %{public}x", ret);
206 if (writeLen != 0) {
207 BufferDesc buffer = { reinterpret_cast<uint8_t *>(&data), len, len };
208 AudioStreamInfo streamInfo(static_cast<AudioSamplingRate>(attr_.sampleRate), AudioEncodingType::ENCODING_PCM,
209 static_cast<AudioSampleFormat>(attr_.format), static_cast<AudioChannel>(attr_.channel));
210 VolumeTools::DfxOperation(buffer, streamInfo, logUtilsTag_, volumeDataCount_, OFFLOAD_DFX_SPLIT);
211 if (AudioDump::GetInstance().GetVersionType() == DumpFileUtil::BETA_VERSION) {
212 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(&data), writeLen);
213 AudioCacheMgr::GetInstance().CacheData(dumpFileName_, static_cast<void *>(&data), writeLen);
214 }
215 CheckUpdateState(&data, len);
216 }
217 renderPos_ += writeLen;
218 stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
219 int64_t stampThreshold = 50; // 50ms
220 if (stamp >= stampThreshold) {
221 AUDIO_WARNING_LOG("len: [%{public}" PRIu64 "], cost: [%{public}" PRId64 "]ms", len, stamp);
222 }
223 return SUCCESS;
224 }
225
SuspendRenderSink(void)226 int32_t OffloadAudioRenderSink::SuspendRenderSink(void)
227 {
228 return SUCCESS;
229 }
230
RestoreRenderSink(void)231 int32_t OffloadAudioRenderSink::RestoreRenderSink(void)
232 {
233 return SUCCESS;
234 }
235
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)236 void OffloadAudioRenderSink::SetAudioParameter(const AudioParamKey key, const std::string &condition,
237 const std::string &value)
238 {
239 }
240
GetAudioParameter(const AudioParamKey key,const std::string & condition)241 std::string OffloadAudioRenderSink::GetAudioParameter(const AudioParamKey key, const std::string &condition)
242 {
243 return "";
244 }
245
SetVolume(float left,float right)246 int32_t OffloadAudioRenderSink::SetVolume(float left, float right)
247 {
248 std::lock_guard<std::mutex> lock(switchDeviceMutex_);
249 Trace trace("OffloadAudioRenderSink::SetVolume");
250
251 leftVolume_ = left;
252 rightVolume_ = right;
253
254 if (switchDeviceMute_) {
255 AUDIO_WARNING_LOG("mute for switch device, store volume, left: %{public}f, right: %{public}f", left, right);
256 return SUCCESS;
257 }
258 return SetVolumeInner(left, right);
259 }
260
GetVolume(float & left,float & right)261 int32_t OffloadAudioRenderSink::GetVolume(float &left, float &right)
262 {
263 left = leftVolume_;
264 right = rightVolume_;
265 return SUCCESS;
266 }
267
GetLatency(uint32_t & latency)268 int32_t OffloadAudioRenderSink::GetLatency(uint32_t &latency)
269 {
270 Trace trace("OffloadAudioRenderSink::GetLatency");
271 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
272
273 // 4: bytewidth
274 uint64_t hdiLatency = renderPos_ * SECOND_TO_MICROSECOND / (AUDIO_SAMPLE_RATE_48K * 4 * STEREO_CHANNEL_COUNT);
275 uint64_t frames = 0;
276 int64_t timeSec = 0;
277 int64_t timeNanoSec = 0;
278 int32_t ret = GetPresentationPosition(frames, timeSec, timeNanoSec);
279 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get frames fail");
280 latency = hdiLatency > frames ? (hdiLatency - frames) / MICROSECOND_TO_MILLISECOND : 0;
281 return SUCCESS;
282 }
283
GetTransactionId(uint64_t & transactionId)284 int32_t OffloadAudioRenderSink::GetTransactionId(uint64_t &transactionId)
285 {
286 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
287 transactionId = reinterpret_cast<uint64_t>(audioRender_);
288 return SUCCESS;
289 }
290
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)291 int32_t OffloadAudioRenderSink::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
292 {
293 Trace trace("OffloadAudioRenderSink::GetPresentationPosition");
294 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
295 CHECK_AND_RETURN_RET_LOG(!isFlushing_, ERR_OPERATION_FAILED, "during flushing");
296
297 uint64_t tmpFrames;
298 struct AudioTimeStamp stamp = {};
299 int32_t ret = audioRender_->GetRenderPosition(audioRender_, &tmpFrames, &stamp);
300 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get render position fail, ret: %{public}d", ret);
301 int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it
302 CHECK_AND_RETURN_RET_LOG(stamp.tvSec >= 0 && stamp.tvSec <= maxSec && stamp.tvNSec >= 0 &&
303 stamp.tvNSec <= SECOND_TO_NANOSECOND, ERR_OPERATION_FAILED,
304 "get invalid time, second: %{public}" PRId64 ", nanosecond: %{public}" PRId64, stamp.tvSec, stamp.tvNSec);
305 frames = tmpFrames * SECOND_TO_MICROSECOND / attr_.sampleRate;
306 timeSec = stamp.tvSec;
307 timeNanoSec = stamp.tvNSec;
308
309 // check hdi timestamp out of range 40 * 1000 * 1000 ns
310 struct timespec curStamp;
311 if (clock_gettime(CLOCK_MONOTONIC, &curStamp) >= 0) {
312 int64_t curNs = curStamp.tv_sec * AUDIO_NS_PER_SECOND + curStamp.tv_nsec;
313 int64_t hdiNs = stamp.tvSec * AUDIO_NS_PER_SECOND + stamp.tvNSec;
314 int64_t outNs = 40 * 1000 * 1000; // 40 * 1000 * 1000 ns
315 if (curNs <= hdiNs || curNs > hdiNs + outNs) {
316 AUDIO_PRERELEASE_LOGW("HDI time is not in the range, hdi: %{public}" PRId64 ", cur: %{public}" PRId64,
317 hdiNs, curNs);
318 timeSec = curStamp.tv_sec;
319 timeNanoSec = curStamp.tv_nsec;
320 }
321 }
322 return ret;
323 }
324
GetMaxAmplitude(void)325 float OffloadAudioRenderSink::GetMaxAmplitude(void)
326 {
327 lastGetMaxAmplitudeTime_ = ClockTime::GetCurNano();
328 startUpdate_ = true;
329 return maxAmplitude_;
330 }
331
SetAudioMonoState(bool audioMono)332 void OffloadAudioRenderSink::SetAudioMonoState(bool audioMono)
333 {
334 audioMonoState_ = audioMono;
335 }
336
SetAudioBalanceValue(float audioBalance)337 void OffloadAudioRenderSink::SetAudioBalanceValue(float audioBalance)
338 {
339 // reset the balance coefficient value firstly
340 leftBalanceCoef_ = 1.0f;
341 rightBalanceCoef_ = 1.0f;
342
343 if (std::abs(audioBalance - 0.0f) <= std::numeric_limits<float>::epsilon()) {
344 // audioBalance is equal to 0.0f
345 audioBalanceState_ = false;
346 } else {
347 // audioBalance is not equal to 0.0f
348 audioBalanceState_ = true;
349 // calculate the balance coefficient
350 if (audioBalance > 0.0f) {
351 leftBalanceCoef_ -= audioBalance;
352 } else if (audioBalance < 0.0f) {
353 rightBalanceCoef_ += audioBalance;
354 }
355 }
356 }
357
SetSinkMuteForSwitchDevice(bool mute)358 int32_t OffloadAudioRenderSink::SetSinkMuteForSwitchDevice(bool mute)
359 {
360 std::lock_guard<std::mutex> lock(switchDeviceMutex_);
361 AUDIO_INFO_LOG("set offload mute %{public}d", mute);
362
363 if (mute) {
364 muteCount_++;
365 if (switchDeviceMute_) {
366 AUDIO_INFO_LOG("offload already muted");
367 return SUCCESS;
368 }
369 switchDeviceMute_ = true;
370 SetVolumeInner(0.0f, 0.0f);
371 } else {
372 muteCount_--;
373 if (muteCount_ > 0) {
374 AUDIO_WARNING_LOG("offload not all unmuted");
375 return SUCCESS;
376 }
377 switchDeviceMute_ = false;
378 muteCount_ = 0;
379 SetVolumeInner(leftVolume_, rightVolume_);
380 }
381
382 return SUCCESS;
383 }
384
SetAudioScene(AudioScene audioScene,std::vector<DeviceType> & activeDevices)385 int32_t OffloadAudioRenderSink::SetAudioScene(AudioScene audioScene, std::vector<DeviceType> &activeDevices)
386 {
387 AUDIO_INFO_LOG("not support");
388 return ERR_NOT_SUPPORTED;
389 }
390
GetAudioScene(void)391 int32_t OffloadAudioRenderSink::GetAudioScene(void)
392 {
393 AUDIO_INFO_LOG("not support");
394 return ERR_NOT_SUPPORTED;
395 }
396
UpdateActiveDevice(std::vector<DeviceType> & outputDevices)397 int32_t OffloadAudioRenderSink::UpdateActiveDevice(std::vector<DeviceType> &outputDevices)
398 {
399 AUDIO_INFO_LOG("not support");
400 return ERR_NOT_SUPPORTED;
401 }
402
RegistCallback(uint32_t type,IAudioSinkCallback * callback)403 void OffloadAudioRenderSink::RegistCallback(uint32_t type, IAudioSinkCallback *callback)
404 {
405 std::lock_guard<std::mutex> lock(sinkMutex_);
406 callback_.RegistCallback(type, callback);
407 AUDIO_INFO_LOG("regist succ");
408 }
409
ResetActiveDeviceForDisconnect(DeviceType device)410 void OffloadAudioRenderSink::ResetActiveDeviceForDisconnect(DeviceType device)
411 {
412 AUDIO_INFO_LOG("not support");
413 }
414
SetPaPower(int32_t flag)415 int32_t OffloadAudioRenderSink::SetPaPower(int32_t flag)
416 {
417 AUDIO_INFO_LOG("not support");
418 return ERR_NOT_SUPPORTED;
419 }
420
SetPriPaPower(void)421 int32_t OffloadAudioRenderSink::SetPriPaPower(void)
422 {
423 AUDIO_INFO_LOG("not support");
424 return ERR_NOT_SUPPORTED;
425 }
426
UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS],const size_t size)427 int32_t OffloadAudioRenderSink::UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS], const size_t size)
428 {
429 #ifdef FEATURE_POWER_MANAGER
430 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
431 runningLock_->UpdateAppsUid(appsUid, appsUid + size);
432 #endif
433 return SUCCESS;
434 }
435
UpdateAppsUid(const std::vector<int32_t> & appsUid)436 int32_t OffloadAudioRenderSink::UpdateAppsUid(const std::vector<int32_t> &appsUid)
437 {
438 return SUCCESS;
439 }
440
Drain(AudioDrainType type)441 int32_t OffloadAudioRenderSink::Drain(AudioDrainType type)
442 {
443 Trace trace("OffloadAudioRenderSink::Drain");
444 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
445 int32_t ret = audioRender_->DrainBuffer(audioRender_, (AudioDrainNotifyType*)&type);
446 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "drain fail");
447 return SUCCESS;
448 }
449
RegistOffloadHdiCallback(std::function<void (const RenderCallbackType type)> callback)450 void OffloadAudioRenderSink::RegistOffloadHdiCallback(std::function<void(const RenderCallbackType type)> callback)
451 {
452 AUDIO_INFO_LOG("in");
453
454 hdiCallback_ = {
455 .callback_.RenderCallback = &OffloadAudioRenderSink::OffloadRenderCallback,
456 .serviceCallback_ = callback,
457 .sink_ = this,
458 };
459 int32_t ret = audioRender_->RegCallback(audioRender_, &hdiCallback_.callback_, (int8_t)0);
460 if (ret != SUCCESS) {
461 AUDIO_WARNING_LOG("fail, error code: %{public}d", ret);
462 }
463 }
464
SetBufferSize(uint32_t sizeMs)465 int32_t OffloadAudioRenderSink::SetBufferSize(uint32_t sizeMs)
466 {
467 Trace trace("OffloadAudioRenderSink::SetBufferSize");
468 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
469 CHECK_AND_RETURN_RET_LOG(!isFlushing_, ERR_OPERATION_FAILED, "during flushing");
470
471 // 4: bytewidth
472 uint32_t size = (uint64_t) sizeMs * AUDIO_SAMPLE_RATE_48K * 4 * STEREO_CHANNEL_COUNT / SECOND_TO_MILLISECOND;
473 int32_t ret = audioRender_->SetBufferSize(audioRender_, size);
474 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "set buffer size fail");
475 return SUCCESS;
476 }
477
LockOffloadRunningLock(void)478 int32_t OffloadAudioRenderSink::LockOffloadRunningLock(void)
479 {
480 #ifdef FEATURE_POWER_MANAGER
481 AUDIO_INFO_LOG("in");
482 if (runningLock_ == nullptr) {
483 WatchTimeout guard("create AudioRunningLock start");
484 runningLock_ = std::make_shared<AudioRunningLock>(std::string(RUNNING_LOCK_NAME));
485 guard.CheckCurrTimeout();
486 }
487 CHECK_AND_RETURN_RET_LOG(runningLock_ != nullptr, ERR_OPERATION_FAILED,
488 "running lock is null, playback can not work well");
489 CHECK_AND_RETURN_RET(!runningLocked_, SUCCESS);
490 runningLock_->Lock(RUNNING_LOCK_TIMEOUTMS_LASTING);
491 runningLocked_ = true;
492 #endif
493 return SUCCESS;
494 }
495
UnLockOffloadRunningLock(void)496 int32_t OffloadAudioRenderSink::UnLockOffloadRunningLock(void)
497 {
498 #ifdef FEATURE_POWER_MANAGER
499 AUDIO_INFO_LOG("in");
500 CHECK_AND_RETURN_RET_LOG(runningLock_ != nullptr, ERR_OPERATION_FAILED,
501 "running lock is null, playback can not work well");
502 CHECK_AND_RETURN_RET(runningLocked_, SUCCESS);
503 runningLock_->UnLock();
504 runningLocked_ = false;
505 #endif
506 return SUCCESS;
507 }
508
DumpInfo(std::string & dumpString)509 void OffloadAudioRenderSink::DumpInfo(std::string &dumpString)
510 {
511 dumpString += "type: OffloadSink\tstarted: " + std::string(started_ ? "true" : "false") + "\n";
512 }
513
PcmFormatToBit(AudioSampleFormat format)514 uint32_t OffloadAudioRenderSink::PcmFormatToBit(AudioSampleFormat format)
515 {
516 AudioFormat hdiFormat = ConvertToHdiFormat(format);
517 switch (hdiFormat) {
518 case AUDIO_FORMAT_TYPE_PCM_8_BIT:
519 return PCM_8_BIT;
520 case AUDIO_FORMAT_TYPE_PCM_16_BIT:
521 return PCM_16_BIT;
522 case AUDIO_FORMAT_TYPE_PCM_24_BIT:
523 return PCM_24_BIT;
524 case AUDIO_FORMAT_TYPE_PCM_32_BIT:
525 return PCM_32_BIT;
526 default:
527 AUDIO_DEBUG_LOG("unknown format type, set it to default");
528 return PCM_24_BIT;
529 }
530 }
531
ConvertToHdiFormat(AudioSampleFormat format)532 AudioFormat OffloadAudioRenderSink::ConvertToHdiFormat(AudioSampleFormat format)
533 {
534 AudioFormat hdiFormat;
535 switch (format) {
536 case SAMPLE_U8:
537 hdiFormat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
538 break;
539 case SAMPLE_S16LE:
540 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
541 break;
542 case SAMPLE_S24LE:
543 hdiFormat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
544 break;
545 case SAMPLE_S32LE:
546 hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
547 break;
548 case SAMPLE_F32LE:
549 hdiFormat = AUDIO_FORMAT_TYPE_PCM_FLOAT;
550 break;
551 default:
552 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
553 break;
554 }
555 return hdiFormat;
556 }
557
OffloadRenderCallback(struct IAudioCallback * self,enum AudioCallbackType type,int8_t * reserved,int8_t * cookie)558 int32_t OffloadAudioRenderSink::OffloadRenderCallback(struct IAudioCallback *self, enum AudioCallbackType type,
559 int8_t *reserved, int8_t *cookie)
560 {
561 (void)reserved;
562 (void)cookie;
563 auto *impl = reinterpret_cast<struct OffloadHdiCallback *>(self);
564 CHECK_AND_RETURN_RET_LOG(impl != nullptr, ERR_OPERATION_FAILED, "impl is nullptr");
565 auto *sink = reinterpret_cast<OffloadAudioRenderSink *>(impl->sink_);
566 CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERR_OPERATION_FAILED, "sink is nullptr");
567 if (!sink->started_ || sink->isFlushing_) {
568 AUDIO_DEBUG_LOG("invalid call, started: %{public}d, isFlushing: %{public}d", sink->started_, sink->isFlushing_);
569 return SUCCESS;
570 }
571
572 impl->serviceCallback_(static_cast<RenderCallbackType>(type));
573 return SUCCESS;
574 }
575
InitAudioSampleAttr(struct AudioSampleAttributes & param)576 void OffloadAudioRenderSink::InitAudioSampleAttr(struct AudioSampleAttributes ¶m)
577 {
578 param.channelCount = AUDIO_CHANNELCOUNT;
579 param.sampleRate = AUDIO_SAMPLE_RATE_48K;
580 param.interleaved = true;
581 param.streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_OFFLOAD));
582 param.type = AUDIO_OFFLOAD;
583 param.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
584 param.isBigEndian = false;
585 param.isSignedData = true;
586 param.stopThreshold = INT_MAX;
587 param.silenceThreshold = 0;
588
589 // offload attr
590 param.offloadInfo.sampleRate = AUDIO_SAMPLE_RATE_48K;
591 param.offloadInfo.channelCount = AUDIO_CHANNELCOUNT;
592 param.offloadInfo.bitRate = AUDIO_SAMPLE_RATE_48K * BIT_IN_BYTE;
593 param.offloadInfo.bitWidth = PCM_32_BIT;
594
595 param.sampleRate = attr_.sampleRate;
596 param.channelCount = attr_.channel;
597 if (param.channelCount == MONO) {
598 param.channelLayout = CH_LAYOUT_MONO;
599 } else if (param.channelCount == STEREO) {
600 param.channelLayout = CH_LAYOUT_STEREO;
601 }
602 param.format = ConvertToHdiFormat(attr_.format);
603 param.frameSize = PcmFormatToBit(attr_.format) * param.channelCount / PCM_8_BIT;
604 param.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (param.frameSize);
605
606 param.offloadInfo.format = ConvertToHdiFormat(attr_.format);
607 }
608
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)609 void OffloadAudioRenderSink::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
610 {
611 deviceDesc.pins = PIN_OUT_SPEAKER;
612 deviceDesc.desc = const_cast<char *>("");
613 }
614
CreateRender(void)615 int32_t OffloadAudioRenderSink::CreateRender(void)
616 {
617 Trace trace("AudioRenderSink::CreateRender");
618
619 struct AudioSampleAttributes param;
620 struct AudioDeviceDescriptor deviceDesc;
621 InitAudioSampleAttr(param);
622 InitDeviceDesc(deviceDesc);
623
624 AUDIO_INFO_LOG("create render, rate: %{public}u, channel: %{public}u, format: %{public}u", param.sampleRate,
625 param.channelCount, param.format);
626 AudioXCollie audioXCollie("OffloadAudioRenderSink::CreateRender", TIMEOUT_SECONDS_10);
627 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
628 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
629 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
630 void *render = deviceManager->CreateRender(attr_.adapterName, ¶m, &deviceDesc, hdiRenderId_);
631 audioRender_ = static_cast<struct IAudioRender *>(render);
632 CHECK_AND_RETURN_RET(audioRender_ != nullptr, ERR_NOT_STARTED);
633
634 return SUCCESS;
635 }
636
InitLatencyMeasurement(void)637 void OffloadAudioRenderSink::InitLatencyMeasurement(void)
638 {
639 if (!AudioLatencyMeasurement::CheckIfEnabled()) {
640 return;
641 }
642
643 AUDIO_INFO_LOG("in");
644 signalDetectAgent_ = std::make_shared<SignalDetectAgent>();
645 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "signalDetectAgent is nullptr");
646 signalDetectAgent_->sampleFormat_ = attr_.format;
647 signalDetectAgent_->formatByteSize_ = GetFormatByteSize(attr_.format);
648 signalDetected_ = false;
649 }
650
DeInitLatencyMeasurement(void)651 void OffloadAudioRenderSink::DeInitLatencyMeasurement(void)
652 {
653 signalDetectAgent_ = nullptr;
654 }
655
CheckLatencySignal(uint8_t * data,size_t len)656 void OffloadAudioRenderSink::CheckLatencySignal(uint8_t *data, size_t len)
657 {
658 CHECK_AND_RETURN(signalDetectAgent_ != nullptr);
659 uint32_t byteSize = static_cast<uint32_t>(GetFormatByteSize(attr_.format));
660 size_t newlyCheckedTime = len / (attr_.sampleRate / MILLISECOND_PER_SECOND) /
661 (byteSize * sizeof(uint8_t) * attr_.channel);
662 signalDetectedTime_ += newlyCheckedTime;
663 if (signalDetectedTime_ >= MILLISECOND_PER_SECOND && signalDetectAgent_->signalDetected_ &&
664 !signalDetectAgent_->dspTimestampGot_) {
665 AudioParamKey key = NONE;
666 std::string condition = "debug_audio_latency_measurement";
667 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
668 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
669 CHECK_AND_RETURN(deviceManager != nullptr);
670 std::string value = deviceManager->GetAudioParameter(attr_.adapterName, key, condition);
671
672 LatencyMonitor::GetInstance().UpdateDspTime(value.c_str());
673 LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(true, signalDetectAgent_->lastPeakBufferTime_);
674 LatencyMonitor::GetInstance().ShowTimestamp(true);
675 signalDetectAgent_->dspTimestampGot_ = true;
676 signalDetectAgent_->signalDetected_ = false;
677 }
678 signalDetected_ = signalDetectAgent_->CheckAudioData(data, len);
679 if (signalDetected_) {
680 AUDIO_INFO_LOG("signal detected");
681 signalDetectedTime_ = 0;
682 }
683 }
684
AdjustStereoToMono(char * data,uint64_t len)685 void OffloadAudioRenderSink::AdjustStereoToMono(char *data, uint64_t len)
686 {
687 // only stereo is supported now (stereo channel count is 2)
688 CHECK_AND_RETURN_LOG(attr_.channel == STEREO_CHANNEL_COUNT, "unsupport, channel: %{public}d", attr_.channel);
689
690 switch (attr_.format) {
691 case SAMPLE_U8:
692 AdjustStereoToMonoForPCM8Bit(reinterpret_cast<int8_t *>(data), len);
693 break;
694 case SAMPLE_S16LE:
695 AdjustStereoToMonoForPCM16Bit(reinterpret_cast<int16_t *>(data), len);
696 break;
697 case SAMPLE_S24LE:
698 AdjustStereoToMonoForPCM24Bit(reinterpret_cast<uint8_t *>(data), len);
699 break;
700 case SAMPLE_S32LE:
701 AdjustStereoToMonoForPCM32Bit(reinterpret_cast<int32_t *>(data), len);
702 break;
703 default:
704 // if the audio format is unsupported, the audio data will not be changed
705 AUDIO_ERR_LOG("unsupport, format: %{public}d", attr_.format);
706 break;
707 }
708 }
709
AdjustAudioBalance(char * data,uint64_t len)710 void OffloadAudioRenderSink::AdjustAudioBalance(char *data, uint64_t len)
711 {
712 // only stereo is supported now (stereo channel count is 2)
713 CHECK_AND_RETURN_LOG(attr_.channel == STEREO_CHANNEL_COUNT, "unsupport, channel: %{public}d", attr_.channel);
714
715 switch (attr_.format) {
716 case SAMPLE_U8:
717 // this function needs further tested for usability
718 AdjustAudioBalanceForPCM8Bit(reinterpret_cast<int8_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
719 break;
720 case SAMPLE_S16LE:
721 AdjustAudioBalanceForPCM16Bit(reinterpret_cast<int16_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
722 break;
723 case SAMPLE_S24LE:
724 // this function needs further tested for usability
725 AdjustAudioBalanceForPCM24Bit(reinterpret_cast<uint8_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
726 break;
727 case SAMPLE_S32LE:
728 AdjustAudioBalanceForPCM32Bit(reinterpret_cast<int32_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
729 break;
730 default:
731 // if the audio format is unsupported, the audio data will not be changed
732 AUDIO_ERR_LOG("unsupport, format: %{public}d", attr_.format);
733 break;
734 }
735 }
736
CheckUpdateState(char * data,uint64_t len)737 void OffloadAudioRenderSink::CheckUpdateState(char *data, uint64_t len)
738 {
739 if (startUpdate_) {
740 if (renderFrameNum_ == 0) {
741 last10FrameStartTime_ = ClockTime::GetCurNano();
742 }
743 renderFrameNum_++;
744 maxAmplitude_ = UpdateMaxAmplitude(static_cast<ConvertHdiFormat>(attr_.format), data, len);
745 if (renderFrameNum_ == GET_MAX_AMPLITUDE_FRAMES_THRESHOLD) {
746 renderFrameNum_ = 0;
747 if (last10FrameStartTime_ > lastGetMaxAmplitudeTime_) {
748 startUpdate_ = false;
749 maxAmplitude_ = 0;
750 }
751 }
752 }
753 }
754
SetVolumeInner(float left,float right)755 int32_t OffloadAudioRenderSink::SetVolumeInner(float left, float right)
756 {
757 AudioXCollie audioXCollie("OffloadAudioRenderSink::SetVolumeInner", TIMEOUT_SECONDS_10, nullptr, nullptr,
758 AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
759 AUDIO_INFO_LOG("set offload vol, left: %{public}f, right: %{public}f", left, right);
760
761 CHECK_AND_RETURN_RET_LOG(!isFlushing_, ERR_OPERATION_FAILED, "during flushing");
762 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE,
763 "render is nullptr, because set volume on device which offload is not available");
764
765 float volume;
766 if ((left == 0) && (right != 0)) {
767 volume = right;
768 } else if ((left != 0) && (right == 0)) {
769 volume = left;
770 } else {
771 volume = (left + right) / HALF_FACTOR;
772 }
773
774 int32_t ret = audioRender_->SetVolume(audioRender_, volume);
775 if (ret != SUCCESS) {
776 AUDIO_WARNING_LOG("set volume fail");
777 }
778
779 return ret;
780 }
781
782 // must be called with sinkMutex_ held
UpdateSinkState(bool started)783 void OffloadAudioRenderSink::UpdateSinkState(bool started)
784 {
785 callback_.OnRenderSinkStateChange(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_OFFLOAD), started);
786 }
787
788 } // namespace AudioStandard
789 } // namespace OHOS
790