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