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 "BluetoothAudioRenderSink"
18 #endif
19
20 #include "sink/bluetooth_audio_render_sink.h"
21 #include <climits>
22 #include "parameters.h"
23 #include "audio_hdi_log.h"
24 #include "audio_errors.h"
25 #include "volume_tools.h"
26 #include "media_monitor_manager.h"
27 #include "audio_dump_pcm.h"
28 #include "audio_performance_monitor.h"
29 #include "common/hdi_adapter_info.h"
30 #include "manager/hdi_adapter_manager.h"
31 #include "adapter/i_device_manager.h"
32
33 using namespace OHOS::HDI::Audio_Bluetooth;
34
35 namespace OHOS {
36 namespace AudioStandard {
BluetoothAudioRenderSink(bool isBluetoothLowLatency)37 BluetoothAudioRenderSink::BluetoothAudioRenderSink(bool isBluetoothLowLatency)
38 : isBluetoothLowLatency_(isBluetoothLowLatency)
39 {
40 }
41
~BluetoothAudioRenderSink()42 BluetoothAudioRenderSink::~BluetoothAudioRenderSink()
43 {
44 DeInit();
45 AudioPerformanceMonitor::GetInstance().DeleteOvertimeMonitor(ADAPTER_TYPE_BLUETOOTH);
46 AUDIO_INFO_LOG("[%{public}s] volumeDataCount: %{public}" PRId64, logUtilsTag_.c_str(), volumeDataCount_);
47 }
48
Init(const IAudioSinkAttr & attr)49 int32_t BluetoothAudioRenderSink::Init(const IAudioSinkAttr &attr)
50 {
51 std::lock_guard<std::mutex> lock(sinkMutex_);
52 if (sinkInited_) {
53 AUDIO_WARNING_LOG("sink already inited");
54 ++sinkInitCount_;
55 return SUCCESS;
56 }
57
58 AUDIO_INFO_LOG("in");
59 logMode_ = system::GetIntParameter("persist.multimedia.audiolog.switch", 0);
60 logUtilsTag_ = "A2dpSink";
61
62 attr_ = attr;
63 audioSampleFormat_ = attr_.format;
64 int32_t ret = InitRender();
65 CHECK_AND_RETURN_RET(ret == SUCCESS, ret);
66 sinkInited_ = true;
67 ++sinkInitCount_;
68 return SUCCESS;
69 }
70
DeInit(void)71 void BluetoothAudioRenderSink::DeInit(void)
72 {
73 AUDIO_INFO_LOG("in");
74 std::lock_guard<std::mutex> lock(sinkMutex_);
75 Trace trace("BluetoothAudioRenderSink::DeInit");
76 if (!sinkInited_) {
77 AUDIO_WARNING_LOG("sink not inited");
78 return;
79 }
80 if (--sinkInitCount_ > 0) {
81 AUDIO_WARNING_LOG("sink is still used, count: %{public}d", sinkInitCount_);
82 return;
83 }
84
85 sinkInited_ = false;
86 started_ = false;
87
88 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
89 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_BLUETOOTH);
90 CHECK_AND_RETURN(deviceManager != nullptr);
91 std::string adapterNameCase = isBluetoothLowLatency_ ? "bt_a2dp_fast" : "bt_a2dp";
92 deviceManager->DestroyRender(adapterNameCase, hdiRenderId_);
93 audioRender_ = nullptr;
94 DumpFileUtil::CloseDumpFile(&dumpFile_);
95 }
96
IsInited(void)97 bool BluetoothAudioRenderSink::IsInited(void)
98 {
99 return sinkInited_;
100 }
101
Start(void)102 int32_t BluetoothAudioRenderSink::Start(void)
103 {
104 std::lock_guard<std::mutex> lock(sinkMutex_);
105 Trace trace("BluetoothAudioRenderSink::Start");
106 AUDIO_INFO_LOG("in");
107 #ifdef FEATURE_POWER_MANAGER
108 if (runningLock_ == nullptr) {
109 WatchTimeout guard("create AudioRunningLock start");
110 runningLock_ = std::make_shared<AudioRunningLock>(std::string(RUNNING_LOCK_NAME));
111 guard.CheckCurrTimeout();
112 }
113 if (runningLock_ != nullptr) {
114 runningLock_->Lock(RUNNING_LOCK_TIMEOUTMS_LASTING);
115 } else {
116 AUDIO_ERR_LOG("running lock is null, playback can not work well");
117 }
118 #endif
119 dumpFileName_ = "bluetooth_sink_" + GetTime() + "_" + std::to_string(attr_.sampleRate) + "_" +
120 std::to_string(attr_.channel) + "_" + std::to_string(attr_.format) + ".pcm";
121 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileName_, &dumpFile_);
122
123 InitLatencyMeasurement();
124 if (started_) {
125 return SUCCESS;
126 }
127 int32_t tryCount = 3;
128 while (tryCount-- > 0) {
129 AUDIO_INFO_LOG("try to start bluetooth render");
130 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
131 int32_t ret = audioRender_->control.Start(reinterpret_cast<AudioHandle>(audioRender_));
132 if (ret) {
133 AUDIO_ERR_LOG("start fail, remain %{public}d attempt(s)", tryCount);
134 usleep(WAIT_TIME_FOR_RETRY_IN_MICROSECOND);
135 continue;
136 }
137 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_BLUETOOTH, INIT_LASTWRITTEN_TIME);
138 started_ = true;
139 return CheckBluetoothScenario();
140 }
141 AUDIO_ERR_LOG("start fail for three times, return");
142 #ifdef FEATURE_POWER_MANAGER
143 if (runningLock_ != nullptr) {
144 AUDIO_INFO_LOG("running lock unlock");
145 runningLock_->UnLock();
146 } else {
147 AUDIO_WARNING_LOG("running lock is null, playback can not work well");
148 }
149 #endif
150 return ERR_NOT_STARTED;
151 }
152
Stop(void)153 int32_t BluetoothAudioRenderSink::Stop(void)
154 {
155 std::lock_guard<std::mutex> lock(sinkMutex_);
156 Trace trace("BluetoothAudioRenderSink::Stop");
157 AUDIO_INFO_LOG("in");
158 DeInitLatencyMeasurement();
159 #ifdef FEATURE_POWER_MANAGER
160 if (runningLock_ != nullptr) {
161 AUDIO_INFO_LOG("running lock unlock");
162 runningLock_->UnLock();
163 } else {
164 AUDIO_WARNING_LOG("running lock is null, playback can not work well");
165 }
166 #endif
167 if (!started_) {
168 return SUCCESS;
169 }
170 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
171 Trace renderTrace("BluetoothAudioRenderSink::Stop inner stop");
172 AUDIO_DEBUG_LOG("before render stop");
173 int32_t ret = audioRender_->control.Stop(reinterpret_cast<AudioHandle>(audioRender_));
174 UpdateSinkState(false);
175 AUDIO_DEBUG_LOG("after render stop");
176 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail");
177 started_ = false;
178 paused_ = false;
179 return SUCCESS;
180 }
181
Resume(void)182 int32_t BluetoothAudioRenderSink::Resume(void)
183 {
184 std::lock_guard<std::mutex> lock(sinkMutex_);
185 AUDIO_INFO_LOG("in");
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
189 if (!paused_) {
190 return SUCCESS;
191 }
192 int32_t ret = audioRender_->control.Resume(reinterpret_cast<AudioHandle>(audioRender_));
193 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "resume fail");
194 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_BLUETOOTH, INIT_LASTWRITTEN_TIME);
195 paused_ = false;
196 return SUCCESS;
197 }
198
Pause(void)199 int32_t BluetoothAudioRenderSink::Pause(void)
200 {
201 std::lock_guard<std::mutex> lock(sinkMutex_);
202 AUDIO_INFO_LOG("in");
203 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
204 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
205
206 if (paused_) {
207 return SUCCESS;
208 }
209 int32_t ret = audioRender_->control.Pause(reinterpret_cast<AudioHandle>(audioRender_));
210 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "pause fail");
211 paused_ = true;
212 return SUCCESS;
213 }
214
Flush(void)215 int32_t BluetoothAudioRenderSink::Flush(void)
216 {
217 AUDIO_INFO_LOG("in");
218 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
219 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
220
221 int32_t ret = audioRender_->control.Flush(reinterpret_cast<AudioHandle>(audioRender_));
222 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "flush fail");
223 return SUCCESS;
224 }
225
Reset(void)226 int32_t BluetoothAudioRenderSink::Reset(void)
227 {
228 AUDIO_INFO_LOG("in");
229 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
230 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
231
232 int32_t ret = audioRender_->control.Flush(reinterpret_cast<AudioHandle>(audioRender_));
233 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "reset fail");
234 return SUCCESS;
235 }
236
RenderFrame(char & data,uint64_t len,uint64_t & writeLen)237 int32_t BluetoothAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
238 {
239 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
240 if (audioMonoState_) {
241 AdjustStereoToMono(&data, len);
242 }
243 if (audioBalanceState_) {
244 AdjustAudioBalance(&data, len);
245 }
246 CheckLatencySignal(reinterpret_cast<uint8_t *>(&data), len);
247 CheckUpdateState(&data, len);
248 if (suspend_) {
249 return SUCCESS;
250 }
251 Trace trace("BluetoothAudioRenderSink::RenderFrame");
252 if (switchDeviceMute_) {
253 Trace renderTrace("BluetoothAudioRenderSink::RenderFrame::renderEmpty");
254 if (memset_s(reinterpret_cast<void *>(&data), static_cast<size_t>(len), 0, static_cast<size_t>(len)) != EOK) {
255 AUDIO_WARNING_LOG("call memset_s fail");
256 }
257 }
258
259 BufferDesc buffer = { reinterpret_cast<uint8_t *>(&data), len, len };
260 AudioStreamInfo streamInfo(static_cast<AudioSamplingRate>(attr_.sampleRate), AudioEncodingType::ENCODING_PCM,
261 audioSampleFormat_, static_cast<AudioChannel>(attr_.channel));
262 VolumeTools::DfxOperation(buffer, streamInfo, logUtilsTag_, volumeDataCount_);
263 if (AudioDump::GetInstance().GetVersionType() == DumpFileUtil::BETA_VERSION) {
264 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(&data), len);
265 AudioCacheMgr::GetInstance().CacheData(dumpFileName_, static_cast<void *>(&data), len);
266 }
267 int32_t ret = DoRenderFrame(data, len, writeLen);
268 #ifdef FEATURE_POWER_MANAGER
269 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
270 runningLock_->UpdateAppsUidToPowerMgr();
271 #endif
272 return ret;
273 }
274
SuspendRenderSink(void)275 int32_t BluetoothAudioRenderSink::SuspendRenderSink(void)
276 {
277 AUDIO_INFO_LOG("in");
278 Trace trace("BluetoothAudioRenderSink::SuspendRenderSink");
279 suspend_ = true;
280 return SUCCESS;
281 }
282
RestoreRenderSink(void)283 int32_t BluetoothAudioRenderSink::RestoreRenderSink(void)
284 {
285 AUDIO_INFO_LOG("in");
286 Trace trace("BluetoothAudioRenderSink::RestoreRenderSink");
287 suspend_ = false;
288 return SUCCESS;
289 }
290
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)291 void BluetoothAudioRenderSink::SetAudioParameter(const AudioParamKey key, const std::string &condition,
292 const std::string &value)
293 {
294 AUDIO_INFO_LOG("key: %{public}d, condition: %{public}s, value: %{public}s", key, condition.c_str(), value.c_str());
295 CHECK_AND_RETURN_LOG(audioRender_ != nullptr, "render is nullptr");
296 int32_t ret = audioRender_->attr.SetExtraParams(reinterpret_cast<AudioHandle>(audioRender_), value.c_str());
297 if (ret != SUCCESS) {
298 AUDIO_WARNING_LOG("set parameter fail, error code: %{public}d", ret);
299 }
300
301 std::lock_guard<std::mutex> lock(sinkMutex_);
302 if (started_ && isBluetoothLowLatency_ && !strcmp(value.c_str(), "A2dpSuspended=0;")) {
303 int32_t tryCount = 3;
304 while (tryCount-- > 0) {
305 AUDIO_INFO_LOG("try to start bluetooth render");
306 CHECK_AND_RETURN_LOG(audioRender_ != nullptr, "render is nullptr");
307 ret = audioRender_->control.Start(reinterpret_cast<AudioHandle>(audioRender_));
308 if (ret == SUCCESS) {
309 AUDIO_INFO_LOG("start succ");
310 started_ = true;
311 CheckBluetoothScenario();
312 return;
313 } else {
314 AUDIO_ERR_LOG("start fail, remain %{public}d attempt(s)", tryCount);
315 usleep(WAIT_TIME_FOR_RETRY_IN_MICROSECOND);
316 }
317 }
318 }
319 }
320
GetAudioParameter(const AudioParamKey key,const std::string & condition)321 std::string BluetoothAudioRenderSink::GetAudioParameter(const AudioParamKey key, const std::string &condition)
322 {
323 AUDIO_INFO_LOG("not support");
324 return "";
325 }
326
SetVolume(float left,float right)327 int32_t BluetoothAudioRenderSink::SetVolume(float left, float right)
328 {
329 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
330
331 leftVolume_ = left;
332 rightVolume_ = right;
333 float volume;
334 if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
335 volume = rightVolume_;
336 } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
337 volume = leftVolume_;
338 } else {
339 volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
340 }
341
342 int32_t ret = audioRender_->volume.SetVolume(reinterpret_cast<AudioHandle>(audioRender_), volume);
343 if (ret != SUCCESS) {
344 AUDIO_WARNING_LOG("set volume fail");
345 }
346
347 return ret;
348 }
349
GetVolume(float & left,float & right)350 int32_t BluetoothAudioRenderSink::GetVolume(float &left, float &right)
351 {
352 left = leftVolume_;
353 right = rightVolume_;
354 return SUCCESS;
355 }
356
GetLatency(uint32_t & latency)357 int32_t BluetoothAudioRenderSink::GetLatency(uint32_t &latency)
358 {
359 Trace trace("BluetoothAudioRenderSink::GetLatency");
360 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
361
362 uint32_t hdiLatency;
363 int32_t ret = audioRender_->GetLatency(audioRender_, &hdiLatency);
364 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get latency fail");
365 latency = hdiLatency;
366 return SUCCESS;
367 }
368
GetTransactionId(uint64_t & transactionId)369 int32_t BluetoothAudioRenderSink::GetTransactionId(uint64_t &transactionId)
370 {
371 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
372 transactionId = reinterpret_cast<uint64_t>(audioRender_);
373 return SUCCESS;
374 }
375
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)376 int32_t BluetoothAudioRenderSink::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
377 {
378 AUDIO_INFO_LOG("not support");
379 return ERR_NOT_SUPPORTED;
380 }
381
GetMaxAmplitude(void)382 float BluetoothAudioRenderSink::GetMaxAmplitude(void)
383 {
384 lastGetMaxAmplitudeTime_ = ClockTime::GetCurNano();
385 startUpdate_ = true;
386 return maxAmplitude_;
387 }
388
SetAudioMonoState(bool audioMono)389 void BluetoothAudioRenderSink::SetAudioMonoState(bool audioMono)
390 {
391 audioMonoState_ = audioMono;
392 }
393
SetAudioBalanceValue(float audioBalance)394 void BluetoothAudioRenderSink::SetAudioBalanceValue(float audioBalance)
395 {
396 // reset the balance coefficient value firstly
397 leftBalanceCoef_ = 1.0f;
398 rightBalanceCoef_ = 1.0f;
399
400 if (std::abs(audioBalance - 0.0f) <= std::numeric_limits<float>::epsilon()) {
401 // audioBalance is equal to 0.0f
402 audioBalanceState_ = false;
403 } else {
404 // audioBalance is not equal to 0.0f
405 audioBalanceState_ = true;
406 // calculate the balance coefficient
407 if (audioBalance > 0.0f) {
408 leftBalanceCoef_ -= audioBalance;
409 } else if (audioBalance < 0.0f) {
410 rightBalanceCoef_ += audioBalance;
411 }
412 }
413 }
414
SetSinkMuteForSwitchDevice(bool mute)415 int32_t BluetoothAudioRenderSink::SetSinkMuteForSwitchDevice(bool mute)
416 {
417 std::lock_guard<std::mutex> lock(switchDeviceMutex_);
418 AUDIO_INFO_LOG("set a2dp mute %{public}d", mute);
419
420 if (mute) {
421 muteCount_++;
422 if (switchDeviceMute_) {
423 AUDIO_INFO_LOG("a2dp already muted");
424 return SUCCESS;
425 }
426 switchDeviceMute_ = true;
427 } else {
428 muteCount_--;
429 if (muteCount_ > 0) {
430 AUDIO_WARNING_LOG("a2dp not all unmuted");
431 return SUCCESS;
432 }
433 switchDeviceMute_ = false;
434 muteCount_ = 0;
435 }
436
437 return SUCCESS;
438 }
439
SetAudioScene(AudioScene audioScene,std::vector<DeviceType> & activeDevices)440 int32_t BluetoothAudioRenderSink::SetAudioScene(AudioScene audioScene, std::vector<DeviceType> &activeDevices)
441 {
442 AUDIO_INFO_LOG("not support");
443 return ERR_NOT_SUPPORTED;
444 }
445
GetAudioScene(void)446 int32_t BluetoothAudioRenderSink::GetAudioScene(void)
447 {
448 AUDIO_INFO_LOG("not support");
449 return ERR_NOT_SUPPORTED;
450 }
451
UpdateActiveDevice(std::vector<DeviceType> & outputDevices)452 int32_t BluetoothAudioRenderSink::UpdateActiveDevice(std::vector<DeviceType> &outputDevices)
453 {
454 AUDIO_INFO_LOG("not support");
455 return ERR_NOT_SUPPORTED;
456 }
457
RegistCallback(uint32_t type,IAudioSinkCallback * callback)458 void BluetoothAudioRenderSink::RegistCallback(uint32_t type, IAudioSinkCallback *callback)
459 {
460 std::lock_guard<std::mutex> lock(sinkMutex_);
461 callback_.RegistCallback(type, callback);
462 AUDIO_INFO_LOG("regist succ");
463 }
464
ResetActiveDeviceForDisconnect(DeviceType device)465 void BluetoothAudioRenderSink::ResetActiveDeviceForDisconnect(DeviceType device)
466 {
467 AUDIO_INFO_LOG("not support");
468 }
469
SetPaPower(int32_t flag)470 int32_t BluetoothAudioRenderSink::SetPaPower(int32_t flag)
471 {
472 AUDIO_INFO_LOG("not support");
473 return ERR_NOT_SUPPORTED;
474 }
475
SetPriPaPower(void)476 int32_t BluetoothAudioRenderSink::SetPriPaPower(void)
477 {
478 AUDIO_INFO_LOG("not support");
479 return ERR_NOT_SUPPORTED;
480 }
481
UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS],const size_t size)482 int32_t BluetoothAudioRenderSink::UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS], const size_t size)
483 {
484 #ifdef FEATURE_POWER_MANAGER
485 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
486 runningLock_->UpdateAppsUid(appsUid, appsUid + size);
487 #endif
488 return SUCCESS;
489 }
490
UpdateAppsUid(const std::vector<int32_t> & appsUid)491 int32_t BluetoothAudioRenderSink::UpdateAppsUid(const std::vector<int32_t> &appsUid)
492 {
493 #ifdef FEATURE_POWER_MANAGER
494 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
495 runningLock_->UpdateAppsUid(appsUid.cbegin(), appsUid.cend());
496 runningLock_->UpdateAppsUidToPowerMgr();
497 #endif
498 return SUCCESS;
499 }
500
DumpInfo(std::string & dumpString)501 void BluetoothAudioRenderSink::DumpInfo(std::string &dumpString)
502 {
503 dumpString += "type: BtSink\tstarted: " + std::string(started_ ? "true" : "false") + "\tisLowLatency: " +
504 std::string(isBluetoothLowLatency_ ? "true" : "false") + "\n";
505 }
506
GetMmapBufferInfo(int & fd,uint32_t & totalSizeInframe,uint32_t & spanSizeInframe,uint32_t & byteSizePerFrame)507 int32_t BluetoothAudioRenderSink::GetMmapBufferInfo(int &fd, uint32_t &totalSizeInframe, uint32_t &spanSizeInframe,
508 uint32_t &byteSizePerFrame)
509 {
510 CHECK_AND_RETURN_RET_LOG(bufferFd_ != INVALID_FD, ERR_INVALID_HANDLE, "buffer fd has been released");
511 fd = bufferFd_;
512 totalSizeInframe = bufferTotalFrameSize_;
513 spanSizeInframe = eachReadFrameSize_;
514 byteSizePerFrame = PcmFormatToBit(attr_.format) * attr_.channel / PCM_8_BIT;
515 return SUCCESS;
516 }
517
GetMmapHandlePosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)518 int32_t BluetoothAudioRenderSink::GetMmapHandlePosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
519 {
520 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
521
522 struct AudioTimeStamp stamp = {};
523 int32_t ret = audioRender_->attr.GetMmapPosition(audioRender_, &frames, &stamp);
524 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get mmap position fail, ret: %{public}d", ret);
525 int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it
526 CHECK_AND_RETURN_RET_LOG(stamp.tvSec >= 0 && stamp.tvSec <= maxSec && stamp.tvNSec >= 0 &&
527 stamp.tvNSec <= SECOND_TO_NANOSECOND, ERR_OPERATION_FAILED,
528 "get invalid time, second: %{public}" PRId64 ", nanosecond: %{public}" PRId64, stamp.tvSec, stamp.tvNSec);
529 timeSec = stamp.tvSec;
530 timeNanoSec = stamp.tvNSec;
531 return ret;
532 }
533
PcmFormatToBit(AudioSampleFormat format)534 uint32_t BluetoothAudioRenderSink::PcmFormatToBit(AudioSampleFormat format)
535 {
536 AudioFormat hdiFormat = ConvertToHdiFormat(format);
537 switch (hdiFormat) {
538 case AUDIO_FORMAT_TYPE_PCM_8_BIT:
539 return PCM_8_BIT;
540 case AUDIO_FORMAT_TYPE_PCM_16_BIT:
541 return PCM_16_BIT;
542 case AUDIO_FORMAT_TYPE_PCM_24_BIT:
543 return PCM_24_BIT;
544 case AUDIO_FORMAT_TYPE_PCM_32_BIT:
545 return PCM_32_BIT;
546 default:
547 AUDIO_DEBUG_LOG("unknown format type, set it to default");
548 return PCM_24_BIT;
549 }
550 }
551
ConvertToHdiFormat(AudioSampleFormat format)552 AudioFormat BluetoothAudioRenderSink::ConvertToHdiFormat(AudioSampleFormat format)
553 {
554 AudioFormat hdiFormat;
555 switch (format) {
556 case SAMPLE_U8:
557 hdiFormat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
558 break;
559 case SAMPLE_S16LE:
560 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
561 break;
562 case SAMPLE_S24LE:
563 hdiFormat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
564 break;
565 case SAMPLE_S32LE:
566 hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
567 break;
568 default:
569 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
570 break;
571 }
572
573 return hdiFormat;
574 }
575
InitAudioSampleAttr(struct AudioSampleAttributes & param)576 void BluetoothAudioRenderSink::InitAudioSampleAttr(struct AudioSampleAttributes ¶m)
577 {
578 // audio parameters for playback
579 param.format = AUDIO_FORMAT_TYPE_PCM_16_BIT;
580 param.channelCount = AUDIO_CHANNELCOUNT;
581 param.frameSize = PCM_16_BIT * param.channelCount / PCM_8_BIT;
582 param.sampleRate = AUDIO_SAMPLE_RATE_48K;
583 param.interleaved = 0;
584 // HDI use adapterNameCase to choose low latency / normal
585 param.type = AUDIO_IN_MEDIA;
586 param.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
587 param.isBigEndian = false;
588 param.isSignedData = true;
589 param.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (param.frameSize);
590 param.stopThreshold = INT_MAX;
591 param.silenceThreshold = 0;
592
593 param.sampleRate = attr_.sampleRate;
594 param.channelCount = attr_.channel;
595 param.format = ConvertToHdiFormat(attr_.format);
596 param.frameSize = PcmFormatToBit(attr_.format) * param.channelCount / PCM_8_BIT;
597 param.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (param.frameSize);
598 }
599
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)600 void BluetoothAudioRenderSink::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
601 {
602 deviceDesc.pins = PIN_OUT_SPEAKER;
603 deviceDesc.desc = nullptr;
604 }
605
CreateRender(void)606 int32_t BluetoothAudioRenderSink::CreateRender(void)
607 {
608 struct AudioSampleAttributes param;
609 struct AudioDeviceDescriptor deviceDesc;
610 InitAudioSampleAttr(param);
611 InitDeviceDesc(deviceDesc);
612
613 AUDIO_INFO_LOG("create render, rate: %{public}u, channel: %{public}u, format: %{public}u", param.sampleRate,
614 param.channelCount, param.format);
615
616 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
617 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_BLUETOOTH);
618 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
619 std::string adapterNameCase = "";
620 if (strcmp(attr_.adapterName, "dp") == 0) {
621 adapterNameCase = attr_.adapterName;
622 } else {
623 adapterNameCase = isBluetoothLowLatency_ ? "bt_a2dp_fast" : "bt_a2dp"; // set sound card infomation
624 }
625 void *render = deviceManager->CreateRender(adapterNameCase, ¶m, &deviceDesc, hdiRenderId_);
626 audioRender_ = static_cast<struct AudioRender *>(render);
627 CHECK_AND_RETURN_RET(audioRender_ != nullptr, ERR_NOT_STARTED);
628
629 return SUCCESS;
630 }
631
InitRender(void)632 int32_t BluetoothAudioRenderSink::InitRender(void)
633 {
634 int32_t ret = CreateRender();
635 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create render fail");
636 if (isBluetoothLowLatency_) {
637 ret = PrepareMmapBuffer();
638 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "prepare mmap buffer fail");
639 }
640 return SUCCESS;
641 }
642
InitLatencyMeasurement(void)643 void BluetoothAudioRenderSink::InitLatencyMeasurement(void)
644 {
645 if (!AudioLatencyMeasurement::CheckIfEnabled()) {
646 return;
647 }
648
649 AUDIO_INFO_LOG("in");
650 signalDetectAgent_ = std::make_shared<SignalDetectAgent>();
651 CHECK_AND_RETURN_LOG(signalDetectAgent_ != nullptr, "signalDetectAgent is nullptr");
652 signalDetectAgent_->sampleFormat_ = attr_.format;
653 signalDetectAgent_->formatByteSize_ = GetFormatByteSize(attr_.format);
654 signalDetected_ = false;
655 }
656
DeInitLatencyMeasurement(void)657 void BluetoothAudioRenderSink::DeInitLatencyMeasurement(void)
658 {
659 signalDetectAgent_ = nullptr;
660 }
661
CheckLatencySignal(uint8_t * data,size_t len)662 void BluetoothAudioRenderSink::CheckLatencySignal(uint8_t *data, size_t len)
663 {
664 CHECK_AND_RETURN(signalDetectAgent_ != nullptr);
665 signalDetected_ = signalDetectAgent_->CheckAudioData(data, len);
666 if (signalDetected_) {
667 AUDIO_INFO_LOG("signal detected");
668 LatencyMonitor::GetInstance().UpdateSinkOrSourceTime(true, signalDetectAgent_->lastPeakBufferTime_);
669 LatencyMonitor::GetInstance().ShowBluetoothTimestamp();
670 }
671 }
672
AdjustStereoToMono(char * data,uint64_t len)673 void BluetoothAudioRenderSink::AdjustStereoToMono(char *data, uint64_t len)
674 {
675 // only stereo is supported now (stereo channel count is 2)
676 CHECK_AND_RETURN_LOG(attr_.channel == STEREO_CHANNEL_COUNT, "unsupport, channel: %{public}d", attr_.channel);
677
678 switch (ConvertToHdiFormat(attr_.format)) {
679 case AUDIO_FORMAT_TYPE_PCM_8_BIT:
680 // this function needs further tested for usability
681 AdjustStereoToMonoForPCM8Bit(reinterpret_cast<int8_t *>(data), len);
682 break;
683 case AUDIO_FORMAT_TYPE_PCM_16_BIT:
684 AdjustStereoToMonoForPCM16Bit(reinterpret_cast<int16_t *>(data), len);
685 break;
686 case AUDIO_FORMAT_TYPE_PCM_24_BIT:
687 // this function needs further tested for usability
688 AdjustStereoToMonoForPCM24Bit(reinterpret_cast<uint8_t *>(data), len);
689 break;
690 case AUDIO_FORMAT_TYPE_PCM_32_BIT:
691 AdjustStereoToMonoForPCM32Bit(reinterpret_cast<int32_t *>(data), len);
692 break;
693 default:
694 // if the audio format is unsupported, the audio data will not be changed
695 AUDIO_ERR_LOG("unsupport, format: %{public}d", attr_.format);
696 break;
697 }
698 }
699
AdjustAudioBalance(char * data,uint64_t len)700 void BluetoothAudioRenderSink::AdjustAudioBalance(char *data, uint64_t len)
701 {
702 // only stereo is supported now (stereo channel count is 2)
703 CHECK_AND_RETURN_LOG(attr_.channel == STEREO_CHANNEL_COUNT, "unsupport, channel: %{public}d", attr_.channel);
704
705 switch (ConvertToHdiFormat(attr_.format)) {
706 case AUDIO_FORMAT_TYPE_PCM_8_BIT:
707 // this function needs further tested for usability
708 AdjustAudioBalanceForPCM8Bit(reinterpret_cast<int8_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
709 break;
710 case AUDIO_FORMAT_TYPE_PCM_16_BIT:
711 AdjustAudioBalanceForPCM16Bit(reinterpret_cast<int16_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
712 break;
713 case AUDIO_FORMAT_TYPE_PCM_24_BIT:
714 // this function needs further tested for usability
715 AdjustAudioBalanceForPCM24Bit(reinterpret_cast<uint8_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
716 break;
717 case AUDIO_FORMAT_TYPE_PCM_32_BIT:
718 AdjustAudioBalanceForPCM32Bit(reinterpret_cast<int32_t *>(data), len, leftBalanceCoef_, rightBalanceCoef_);
719 break;
720 default:
721 // if the audio format is unsupported, the audio data will not be changed
722 AUDIO_ERR_LOG("unsupport, format: %{public}d", attr_.format);
723 break;
724 }
725 }
726
CheckUpdateState(char * data,uint64_t len)727 void BluetoothAudioRenderSink::CheckUpdateState(char *data, uint64_t len)
728 {
729 if (startUpdate_) {
730 if (renderFrameNum_ == 0) {
731 last10FrameStartTime_ = ClockTime::GetCurNano();
732 }
733 renderFrameNum_++;
734 maxAmplitude_ = UpdateMaxAmplitude(static_cast<ConvertHdiFormat>(attr_.format), data, len);
735 if (renderFrameNum_ == GET_MAX_AMPLITUDE_FRAMES_THRESHOLD) {
736 renderFrameNum_ = 0;
737 if (last10FrameStartTime_ > lastGetMaxAmplitudeTime_) {
738 startUpdate_ = false;
739 maxAmplitude_ = 0;
740 }
741 }
742 }
743 }
744
DoRenderFrame(char & data,uint64_t len,uint64_t & writeLen)745 int32_t BluetoothAudioRenderSink::DoRenderFrame(char &data, uint64_t len, uint64_t &writeLen)
746 {
747 int32_t ret = SUCCESS;
748
749 while (true) {
750 Trace trace("BluetoothAudioRenderSink::DoRenderFrame");
751 int64_t stamp = ClockTime::GetCurNano();
752 ret = audioRender_->RenderFrame(audioRender_, (void *)&data, len, &writeLen);
753 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_BLUETOOTH, ClockTime::GetCurNano());
754 stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
755 if (logMode_ || stamp >= STAMP_THRESHOLD_MS) {
756 AUDIO_PRERELEASE_LOGW("A2dp RenderFrame, len: [%{public}" PRIu64 "], cost: [%{public}" PRId64 "]ms, "
757 "writeLen: [%{public}" PRIu64 "], ret: %{public}x", len, stamp, writeLen, ret);
758 }
759 if (ret == RENDER_FRAME_NUM) {
760 AUDIO_ERR_LOG("retry render frame");
761 usleep(RENDER_FRAME_INTERVAL_IN_MICROSECONDS);
762 continue;
763 }
764 if (ret != SUCCESS) {
765 AUDIO_ERR_LOG("A2dp RenderFrame fail, ret: %{public}x", ret);
766 ret = ERR_WRITE_FAILED;
767 }
768 break;
769 }
770
771 return ret;
772 }
773
774 // must be called with sinkMutex_ held
UpdateSinkState(bool started)775 void BluetoothAudioRenderSink::UpdateSinkState(bool started)
776 {
777 callback_.OnRenderSinkStateChange(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_BLUETOOTH), started);
778 }
779
PrepareMmapBuffer(void)780 int32_t BluetoothAudioRenderSink::PrepareMmapBuffer(void)
781 {
782 uint32_t totalBufferInMs = 40; // 40: 5 * (6 + 2 * (1)) = 40ms, the buffer size, not latency
783 uint32_t reqBufferFrameSize = totalBufferInMs * (attr_.sampleRate / SECOND_TO_MILLISECOND);
784 struct AudioMmapBufferDescriptor desc = {0};
785
786 // reqBufferFrameSize means frames in total, for example, 40ms * 48K = 1920
787 // transferFrameSize means frames in one block, for example 5ms per block, 5ms * 48K = 240
788 int32_t ret = audioRender_->attr.ReqMmapBuffer(audioRender_, reqBufferFrameSize, &desc);
789 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "request mmap buffer fail, ret: %{public}d", ret);
790 AUDIO_INFO_LOG("memoryAddress: [%{private}p], memoryFd: [%{public}d], totalBufferFrames: [%{public}d], "
791 "transferFrameSize: [%{public}d], isShareable: [%{public}d], offset: [%{public}d]", desc.memoryAddress,
792 desc.memoryFd, desc.totalBufferFrames, desc.transferFrameSize, desc.isShareable, desc.offset);
793
794 bufferFd_ = desc.memoryFd; // fcntl(fd, 1030, 3) after dup?
795 int32_t periodFrameMaxSize = 1920000; // 192khz * 10s
796 CHECK_AND_RETURN_RET_LOG(desc.totalBufferFrames >= 0 && desc.transferFrameSize >= 0 &&
797 desc.transferFrameSize <= periodFrameMaxSize, ERR_OPERATION_FAILED,
798 "invalid value, totalBufferFrames: [%{public}d], transferFrameSize: [%{public}d]", desc.totalBufferFrames,
799 desc.transferFrameSize);
800
801 uint32_t frameSizeInByte = PcmFormatToBit(attr_.format) * attr_.channel / PCM_8_BIT;
802 bufferTotalFrameSize_ = static_cast<uint32_t>(desc.totalBufferFrames); // 1440 ~ 3840
803 eachReadFrameSize_ = static_cast<uint32_t>(desc.transferFrameSize); // 240
804 CHECK_AND_RETURN_RET_LOG(frameSizeInByte <= ULLONG_MAX / bufferTotalFrameSize_, ERR_OPERATION_FAILED,
805 "buffer size will overflow");
806 return SUCCESS;
807 }
808
CheckPositionTime(void)809 int32_t BluetoothAudioRenderSink::CheckPositionTime(void)
810 {
811 int32_t tryCount = MAX_GET_POSITION_TRY_COUNT;
812 uint64_t frames = 0;
813 int64_t timeSec = 0;
814 int64_t timeNanoSec = 0;
815 while (tryCount-- > 0) {
816 ClockTime::RelativeSleep(MAX_GET_POSITION_WAIT_TIME);
817 int32_t ret = GetMmapHandlePosition(frames, timeSec, timeNanoSec);
818 int64_t curTime = ClockTime::GetCurNano();
819 int64_t curSec = curTime / AUDIO_NS_PER_SECOND;
820 int64_t curNanoSec = curTime - curSec * AUDIO_NS_PER_SECOND;
821 if (ret != SUCCESS || curSec != timeSec || curNanoSec - timeNanoSec > MAX_GET_POSITION_HANDLE_TIME) {
822 AUDIO_WARNING_LOG("tryCount: %{public}d, ret: %{public}d", tryCount, ret);
823 continue;
824 } else {
825 AUDIO_INFO_LOG("check succ");
826 return SUCCESS;
827 }
828 }
829 return ERR_OPERATION_FAILED;
830 }
831
CheckBluetoothScenario(void)832 int32_t BluetoothAudioRenderSink::CheckBluetoothScenario(void)
833 {
834 UpdateSinkState(true);
835 if (isBluetoothLowLatency_ && CheckPositionTime() != SUCCESS) {
836 AUDIO_ERR_LOG("check position time fail");
837 #ifdef FEATURE_POWER_MANAGER
838 if (runningLock_ != nullptr) {
839 AUDIO_INFO_LOG("running lock unlock");
840 runningLock_->UnLock();
841 } else {
842 AUDIO_WARNING_LOG("running lock is null, playback can not work well");
843 }
844 #endif
845 return ERR_NOT_STARTED;
846 }
847 return SUCCESS;
848 }
849
850 } // namespace AudioStandard
851 } // namespace OHOS
852