• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param)
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, &param, &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