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 "FastAudioRenderSink"
18 #endif
19
20 #include "sink/fast_audio_render_sink.h"
21 #include <climits>
22 #include "audio_hdi_log.h"
23 #include "audio_errors.h"
24 #include "audio_utils.h"
25 #include "audio_performance_monitor.h"
26 #include "common/hdi_adapter_info.h"
27 #include "manager/hdi_adapter_manager.h"
28
29 namespace OHOS {
30 namespace AudioStandard {
~FastAudioRenderSink()31 FastAudioRenderSink::~FastAudioRenderSink()
32 {
33 AUDIO_INFO_LOG("in");
34 if (sinkInited_) {
35 DeInit();
36 }
37 }
38
Init(const IAudioSinkAttr & attr)39 int32_t FastAudioRenderSink::Init(const IAudioSinkAttr &attr)
40 {
41 AUDIO_INFO_LOG("in");
42 attr_ = attr;
43 halName_ = attr_.audioStreamFlag == AUDIO_FLAG_MMAP ? "primary" : "voip";
44 int32_t ret = CreateRender();
45 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create render fail");
46 ret = PrepareMmapBuffer();
47 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "prepare mmap buffer fail");
48
49 sinkInited_ = true;
50 return SUCCESS;
51 }
52
DeInit(void)53 void FastAudioRenderSink::DeInit(void)
54 {
55 AUDIO_INFO_LOG("in");
56 #ifdef FEATURE_POWER_MANAGER
57 if (runningLock_ != nullptr) {
58 AUDIO_INFO_LOG("running lock unlock");
59 runningLock_->UnLock();
60 } else {
61 AUDIO_WARNING_LOG("running lock is null, playback can not work well");
62 }
63 #endif
64
65 sinkInited_ = false;
66 started_ = false;
67 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
68 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
69 CHECK_AND_RETURN(deviceManager != nullptr);
70 deviceManager->DestroyRender(attr_.adapterName, hdiRenderId_);
71 audioRender_ = nullptr;
72 ReleaseMmapBuffer();
73 }
74
IsInited(void)75 bool FastAudioRenderSink::IsInited(void)
76 {
77 return sinkInited_;
78 }
79
Start(void)80 int32_t FastAudioRenderSink::Start(void)
81 {
82 AUDIO_INFO_LOG("in");
83 std::lock_guard<std::mutex> lock(startMutex_);
84 Trace trace("FastAudioRenderSink::Start");
85 AudioXCollie audioXCollie("FastAudioRenderSink::Start", TIMEOUT_SECONDS_10);
86
87 int64_t stamp = ClockTime::GetCurNano();
88 if (started_) {
89 return SUCCESS;
90 }
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");
94 UpdateSinkState(true);
95 ret = CheckPositionTime();
96 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "check position time fail");
97 #ifdef FEATURE_POWER_MANAGER
98 if (runningLock_ == nullptr) {
99 WatchTimeout guard("create AudioRunningLock start");
100 runningLock_ = std::make_shared<AudioRunningLock>(std::string(RUNNING_LOCK_NAME));
101 guard.CheckCurrTimeout();
102 }
103 if (runningLock_ != nullptr) {
104 runningLock_->Lock(RUNNING_LOCK_TIMEOUTMS_LASTING);
105 } else {
106 AUDIO_ERR_LOG("running lock is null, playback can not work well");
107 }
108 #endif
109 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_FAST, INIT_LASTWRITTEN_TIME);
110 started_ = true;
111 AUDIO_DEBUG_LOG("cost: [%{public}" PRId64 "]ms", (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND);
112 return SUCCESS;
113 }
114
Stop(void)115 int32_t FastAudioRenderSink::Stop(void)
116 {
117 AUDIO_INFO_LOG("in");
118 std::lock_guard<std::mutex> lock(startMutex_);
119 Trace trace("FastAudioRenderSink::Stop");
120 AudioXCollie audioXCollie("FastAudioRenderSink::Stop", TIMEOUT_SECONDS_10);
121
122 #ifdef FEATURE_POWER_MANAGER
123 if (runningLock_ != nullptr) {
124 AUDIO_INFO_LOG("running lock unlock");
125 runningLock_->UnLock();
126 } else {
127 AUDIO_WARNING_LOG("running lock is null, playback can not work well");
128 }
129 #endif
130 if (!started_) {
131 return SUCCESS;
132 }
133 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
134 int32_t ret = audioRender_->Stop(audioRender_);
135 UpdateSinkState(false);
136 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail, ret: %{public}d", ret);
137 started_ = false;
138 return SUCCESS;
139 }
140
Resume(void)141 int32_t FastAudioRenderSink::Resume(void)
142 {
143 Trace trace("FastAudioRenderSink::Resume");
144 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
145 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
146
147 if (!paused_) {
148 return SUCCESS;
149 }
150 int32_t ret = audioRender_->Resume(audioRender_);
151 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "resume fail");
152 AudioPerformanceMonitor::GetInstance().RecordTimeStamp(ADAPTER_TYPE_FAST, INIT_LASTWRITTEN_TIME);
153 paused_ = false;
154 return SUCCESS;
155 }
156
Pause(void)157 int32_t FastAudioRenderSink::Pause(void)
158 {
159 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
160 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
161
162 if (paused_) {
163 return SUCCESS;
164 }
165 int32_t ret = audioRender_->Pause(audioRender_);
166 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "pause fail");
167 paused_ = true;
168 return SUCCESS;
169 }
170
Flush(void)171 int32_t FastAudioRenderSink::Flush(void)
172 {
173 Trace trace("FastAudioRenderSink::Flush");
174 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
175 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
176
177 int32_t ret = audioRender_->Flush(audioRender_);
178 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "flush fail");
179 return SUCCESS;
180 }
181
Reset(void)182 int32_t FastAudioRenderSink::Reset(void)
183 {
184 Trace trace("FastAudioRenderSink::Reset");
185 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
186 CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
187
188 int32_t ret = audioRender_->Flush(audioRender_);
189 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "reset fail");
190 return SUCCESS;
191 }
192
RenderFrame(char & data,uint64_t len,uint64_t & writeLen)193 int32_t FastAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
194 {
195 #ifdef DEBUG_DIRECT_USE_HDI
196 int64_t stamp = ClockTime::GetCurNano();
197 if (len > (bufferSize_ - eachReadFrameSize_ * frameSizeInByte_ * writeAheadPeriod_)) {
198 writeLen = 0;
199 AUDIO_ERR_LOG("fail, too large, len: [%{public}" PRIu64 "]", len);
200 return ERR_WRITE_FAILED;
201 }
202 if (isFirstWrite_) {
203 PreparePosition();
204 }
205 CHECK_AND_RETURN_RET_LOG((curWritePos_ >= 0 && curWritePos_ < bufferSize_), ERR_INVALID_PARAM, "invalid write pos");
206 char *writePtr = bufferAddresss_ + curWritePos_;
207 uint64_t dataBefore = *(uint64_t *)writePtr;
208 uint64_t dataAfter = 0;
209 uint64_t tempPos = curWritePos_ + len;
210 if (tempPos <= bufferSize_) {
211 int32_t ret = memcpy_s(writePtr, (bufferSize_ - curWritePos_), static_cast<void *>(&data), len);
212 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "copy fail");
213 dataAfter = *(uint64_t *)writePtr;
214 curWritePos_ = (tempPos == bufferSize_ ? 0 : tempPos);
215 } else {
216 AUDIO_DEBUG_LOG("curWritePos + len is %{public}" PRIu64 ", more than bufferSize", tempPos);
217 size_t writeableSize = bufferSize_ - curWritePos_;
218 if (memcpy_s(writePtr, writeableSize, static_cast<void *>(&data), writeableSize) ||
219 memcpy_s(bufferAddresss_, bufferSize_, static_cast<void *>((char *)&data + writeableSize),
220 (len - writeableSize))) {
221 AUDIO_ERR_LOG("copy fail");
222 return ERR_WRITE_FAILED;
223 }
224 curWritePos_ = len - writeableSize;
225 }
226 writeLen = len;
227
228 stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
229 AUDIO_DEBUG_LOG("len: [%{public}" PRIu64 "], cost: [%{public}" PRId64 "]ms, curWritePos: [%{public}d], dataBefore: "
230 "[%{public}" PRIu64 "], dataAfter: [%{public}" PRIu64 "]", len, stamp, curWritePos_, dataBefore, dataAfter);
231 return SUCCESS;
232 #else
233 AUDIO_INFO_LOG("not support");
234 return ERR_NOT_SUPPORTED;
235 #endif
236 }
237
SuspendRenderSink(void)238 int32_t FastAudioRenderSink::SuspendRenderSink(void)
239 {
240 return SUCCESS;
241 }
242
RestoreRenderSink(void)243 int32_t FastAudioRenderSink::RestoreRenderSink(void)
244 {
245 return SUCCESS;
246 }
247
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)248 void FastAudioRenderSink::SetAudioParameter(const AudioParamKey key, const std::string &condition,
249 const std::string &value)
250 {
251 }
252
GetAudioParameter(const AudioParamKey key,const std::string & condition)253 std::string FastAudioRenderSink::GetAudioParameter(const AudioParamKey key, const std::string &condition)
254 {
255 return "";
256 }
257
SetVolume(float left,float right)258 int32_t FastAudioRenderSink::SetVolume(float left, float right)
259 {
260 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
261
262 leftVolume_ = left;
263 rightVolume_ = right;
264 CHECK_AND_RETURN_RET_LOG(!(halName_ == "voip" && switchDeviceMute_ && (abs(left) > FLOAT_EPS ||
265 abs(right) > FLOAT_EPS)), ERR_ILLEGAL_STATE, "mute for switch device at voip scene, not support set volume");
266 float volume;
267 if ((abs(leftVolume_) < FLOAT_EPS) && (abs(rightVolume_) > FLOAT_EPS)) {
268 volume = rightVolume_;
269 } else if ((abs(leftVolume_) > FLOAT_EPS) && (abs(rightVolume_) < FLOAT_EPS)) {
270 volume = leftVolume_;
271 } else {
272 volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
273 }
274
275 int32_t ret = audioRender_->SetVolume(audioRender_, volume);
276 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "set volume fail, ret: %{public}d", ret);
277 return SUCCESS;
278 }
279
GetVolume(float & left,float & right)280 int32_t FastAudioRenderSink::GetVolume(float &left, float &right)
281 {
282 left = leftVolume_;
283 right = rightVolume_;
284 return SUCCESS;
285 }
286
GetLatency(uint32_t & latency)287 int32_t FastAudioRenderSink::GetLatency(uint32_t &latency)
288 {
289 Trace trace("FastAudioRenderSink::GetLatency");
290 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
291 uint32_t hdiLatency = 0;
292 int32_t ret = audioRender_->GetLatency(audioRender_, &hdiLatency);
293 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get latency fail, ret: %{public}d", ret);
294 latency = hdiLatency;
295 return SUCCESS;
296 }
297
GetTransactionId(uint64_t & transactionId)298 int32_t FastAudioRenderSink::GetTransactionId(uint64_t &transactionId)
299 {
300 AUDIO_INFO_LOG("not support");
301 transactionId = 6; // 6: mmap device
302 return ERR_NOT_SUPPORTED;
303 }
304
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)305 int32_t FastAudioRenderSink::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
306 {
307 AUDIO_INFO_LOG("not support");
308 return ERR_NOT_SUPPORTED;
309 }
310
GetMaxAmplitude(void)311 float FastAudioRenderSink::GetMaxAmplitude(void)
312 {
313 AUDIO_INFO_LOG("not support");
314 return 0;
315 }
316
SetAudioMonoState(bool audioMono)317 void FastAudioRenderSink::SetAudioMonoState(bool audioMono)
318 {
319 AUDIO_INFO_LOG("not support");
320 }
321
SetAudioBalanceValue(float audioBalance)322 void FastAudioRenderSink::SetAudioBalanceValue(float audioBalance)
323 {
324 AUDIO_INFO_LOG("not support");
325 }
326
SetSinkMuteForSwitchDevice(bool mute)327 int32_t FastAudioRenderSink::SetSinkMuteForSwitchDevice(bool mute)
328 {
329 std::lock_guard<std::mutex> lock(switchDeviceMutex_);
330 AUDIO_INFO_LOG("set fast_%{public}s mute %{public}d", halName_.c_str(), mute);
331 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
332
333 if (mute) {
334 muteCount_++;
335 if (switchDeviceMute_) {
336 AUDIO_INFO_LOG("fast_%{public}s already muted", halName_.c_str());
337 return SUCCESS;
338 }
339 switchDeviceMute_ = true;
340 if (halName_ == "voip") {
341 audioRender_->SetVolume(audioRender_, 0.0f);
342 }
343 } else {
344 muteCount_--;
345 if (muteCount_ > 0) {
346 AUDIO_WARNING_LOG("fast_%{public}s not all unmuted", halName_.c_str());
347 return SUCCESS;
348 }
349 switchDeviceMute_ = false;
350 muteCount_ = 0;
351 if (halName_ == "voip") {
352 SetVolume(leftVolume_, rightVolume_);
353 }
354 }
355
356 return SUCCESS;
357 }
358
SetAudioScene(AudioScene audioScene,std::vector<DeviceType> & activeDevices)359 int32_t FastAudioRenderSink::SetAudioScene(AudioScene audioScene, std::vector<DeviceType> &activeDevices)
360 {
361 AUDIO_INFO_LOG("not support");
362 return SUCCESS;
363 }
364
GetAudioScene(void)365 int32_t FastAudioRenderSink::GetAudioScene(void)
366 {
367 AUDIO_INFO_LOG("not support");
368 return ERR_NOT_SUPPORTED;
369 }
370
UpdateActiveDevice(std::vector<DeviceType> & outputDevices)371 int32_t FastAudioRenderSink::UpdateActiveDevice(std::vector<DeviceType> &outputDevices)
372 {
373 AUDIO_INFO_LOG("not support");
374 return ERR_NOT_SUPPORTED;
375 }
376
RegistCallback(uint32_t type,IAudioSinkCallback * callback)377 void FastAudioRenderSink::RegistCallback(uint32_t type, IAudioSinkCallback *callback)
378 {
379 std::lock_guard<std::mutex> lock(sinkMutex_);
380 callback_.RegistCallback(type, callback);
381 AUDIO_INFO_LOG("regist succ");
382 }
383
ResetActiveDeviceForDisconnect(DeviceType device)384 void FastAudioRenderSink::ResetActiveDeviceForDisconnect(DeviceType device)
385 {
386 AUDIO_INFO_LOG("not support");
387 }
388
SetPaPower(int32_t flag)389 int32_t FastAudioRenderSink::SetPaPower(int32_t flag)
390 {
391 AUDIO_INFO_LOG("not support");
392 return ERR_NOT_SUPPORTED;
393 }
394
SetPriPaPower(void)395 int32_t FastAudioRenderSink::SetPriPaPower(void)
396 {
397 AUDIO_INFO_LOG("not support");
398 return ERR_NOT_SUPPORTED;
399 }
400
UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS],const size_t size)401 int32_t FastAudioRenderSink::UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS], const size_t size)
402 {
403 return SUCCESS;
404 }
405
UpdateAppsUid(const std::vector<int32_t> & appsUid)406 int32_t FastAudioRenderSink::UpdateAppsUid(const std::vector<int32_t> &appsUid)
407 {
408 #ifdef FEATURE_POWER_MANAGER
409 CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
410 runningLock_->UpdateAppsUid(appsUid.cbegin(), appsUid.cend());
411 runningLock_->UpdateAppsUidToPowerMgr();
412 #endif
413 return SUCCESS;
414 }
415
DumpInfo(std::string & dumpString)416 void FastAudioRenderSink::DumpInfo(std::string &dumpString)
417 {
418 dumpString += "type: FastSink\tstarted: " + std::string(started_ ? "true" : "false") + "\n";
419 }
420
GetMmapBufferInfo(int & fd,uint32_t & totalSizeInframe,uint32_t & spanSizeInframe,uint32_t & byteSizePerFrame)421 int32_t FastAudioRenderSink::GetMmapBufferInfo(int &fd, uint32_t &totalSizeInframe, uint32_t &spanSizeInframe,
422 uint32_t &byteSizePerFrame)
423 {
424 CHECK_AND_RETURN_RET_LOG(bufferFd_ != INVALID_FD, ERR_INVALID_HANDLE, "buffer fd has been released");
425 fd = bufferFd_;
426 totalSizeInframe = bufferTotalFrameSize_;
427 spanSizeInframe = eachReadFrameSize_;
428 byteSizePerFrame = PcmFormatToBit(attr_.format) * attr_.channel / PCM_8_BIT;
429 return SUCCESS;
430 }
431
GetMmapHandlePosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)432 int32_t FastAudioRenderSink::GetMmapHandlePosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
433 {
434 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
435
436 struct AudioTimeStamp stamp = {};
437 int32_t ret = audioRender_->GetMmapPosition(audioRender_, &frames, &stamp);
438 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get mmap position fail, ret: %{public}d", ret);
439 #ifdef DEBUG_DIRECT_USE_HDI
440 curReadPos_ = frameSizeInByte_ * (frames - bufferTotalFrameSize_ * (frames / bufferTotalFrameSize_));
441 CHECK_AND_RETURN_RET_LOG(curReadPos_ >= 0 && curReadPos_ < bufferSize_, ERR_INVALID_PARAM, "invalid pos");
442 AUDIO_DEBUG_LOG("frames: [%{public}" PRIu64 "], tvSec: %{public}" PRId64 ", tvNSec: %{public}" PRId64
443 ", alreadyReadFrames: %{public}" PRId64 ", curReadPos: [%{public}d]", frames, stamp.tvSec, stamp.tvNSec,
444 frames, curReadPos_);
445 #endif
446 int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it
447 CHECK_AND_RETURN_RET_LOG(stamp.tvSec >= 0 && stamp.tvSec <= maxSec && stamp.tvNSec >= 0 &&
448 stamp.tvNSec <= SECOND_TO_NANOSECOND, ERR_OPERATION_FAILED,
449 "get invalid time, second: %{public}" PRId64 ", nanosecond: %{public}" PRId64, stamp.tvSec, stamp.tvNSec);
450 timeSec = stamp.tvSec;
451 timeNanoSec = stamp.tvNSec;
452 return ret;
453 }
454
PcmFormatToBit(AudioSampleFormat format)455 uint32_t FastAudioRenderSink::PcmFormatToBit(AudioSampleFormat format)
456 {
457 switch (format) {
458 case SAMPLE_U8:
459 return PCM_8_BIT;
460 case SAMPLE_S16LE:
461 return PCM_16_BIT;
462 case SAMPLE_S24LE:
463 return PCM_24_BIT;
464 case SAMPLE_S32LE:
465 return PCM_32_BIT;
466 case SAMPLE_F32LE:
467 return PCM_32_BIT;
468 default:
469 AUDIO_DEBUG_LOG("unknown format type, set it to default");
470 return PCM_24_BIT;
471 }
472 }
473
ConvertToHdiFormat(AudioSampleFormat format)474 AudioFormat FastAudioRenderSink::ConvertToHdiFormat(AudioSampleFormat format)
475 {
476 AudioFormat hdiFormat;
477 switch (format) {
478 case SAMPLE_U8:
479 hdiFormat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
480 break;
481 case SAMPLE_S16LE:
482 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
483 break;
484 case SAMPLE_S24LE:
485 hdiFormat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
486 break;
487 case SAMPLE_S32LE:
488 hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
489 break;
490 case SAMPLE_F32LE:
491 hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
492 break;
493 default:
494 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
495 break;
496 }
497 return hdiFormat;
498 }
499
InitAudioSampleAttr(struct AudioSampleAttributes & param)500 void FastAudioRenderSink::InitAudioSampleAttr(struct AudioSampleAttributes ¶m)
501 {
502 param.channelCount = AUDIO_CHANNELCOUNT;
503 param.interleaved = true;
504 param.streamId = attr_.audioStreamFlag == AUDIO_FLAG_VOIP_FAST ?
505 static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_VOIP_FAST)) :
506 static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_FAST));
507 param.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
508 param.isBigEndian = false;
509 param.isSignedData = true;
510 param.stopThreshold = INT_MAX;
511 param.silenceThreshold = 0;
512
513 param.type = attr_.audioStreamFlag == AUDIO_FLAG_VOIP_FAST ? AUDIO_MMAP_VOIP : AUDIO_MMAP_NOIRQ;
514 param.sampleRate = attr_.sampleRate;
515 param.channelCount = attr_.channel;
516 if (param.channelCount == MONO) {
517 param.channelLayout = CH_LAYOUT_MONO;
518 } else if (param.channelCount == STEREO) {
519 param.channelLayout = CH_LAYOUT_STEREO;
520 }
521 param.format = ConvertToHdiFormat(attr_.format);
522 param.frameSize = PcmFormatToBit(attr_.format) * param.channelCount / PCM_8_BIT;
523 param.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (param.frameSize); // not passed in hdi
524 }
525
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)526 void FastAudioRenderSink::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
527 {
528 switch (static_cast<DeviceType>(attr_.deviceType)) {
529 case DEVICE_TYPE_EARPIECE:
530 deviceDesc.pins = PIN_OUT_EARPIECE;
531 break;
532 case DEVICE_TYPE_SPEAKER:
533 deviceDesc.pins = PIN_OUT_SPEAKER;
534 break;
535 case DEVICE_TYPE_WIRED_HEADSET:
536 deviceDesc.pins = PIN_OUT_HEADSET;
537 break;
538 case DEVICE_TYPE_USB_HEADSET:
539 deviceDesc.pins = PIN_OUT_USB_EXT;
540 break;
541 case DEVICE_TYPE_BLUETOOTH_SCO:
542 deviceDesc.pins = PIN_OUT_BLUETOOTH_SCO;
543 break;
544 default:
545 AUDIO_WARNING_LOG("unsupport, use default, deviceType: %{public}d", attr_.deviceType);
546 deviceDesc.pins = PIN_OUT_SPEAKER;
547 break;
548 }
549 deviceDesc.desc = const_cast<char *>("");
550 }
551
CreateRender(void)552 int32_t FastAudioRenderSink::CreateRender(void)
553 {
554 struct AudioSampleAttributes param;
555 struct AudioDeviceDescriptor deviceDesc;
556 InitAudioSampleAttr(param);
557 InitDeviceDesc(deviceDesc);
558
559 AUDIO_INFO_LOG("create render, type: %{public}d, rate: %{public}u, channel: %{public}u, format: %{public}u, "
560 "device: %{public}u", param.type, param.sampleRate, param.channelCount, param.format, attr_.deviceType);
561 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
562 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
563 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
564 void *render = deviceManager->CreateRender(attr_.adapterName, ¶m, &deviceDesc, hdiRenderId_);
565 audioRender_ = static_cast<struct IAudioRender *>(render);
566 CHECK_AND_RETURN_RET(audioRender_ != nullptr, ERR_NOT_STARTED);
567 return SUCCESS;
568 }
569
570 // must be called with sinkMutex_ held
UpdateSinkState(bool started)571 void FastAudioRenderSink::UpdateSinkState(bool started)
572 {
573 callback_.OnRenderSinkStateChange(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_FAST), started);
574 }
575
PrepareMmapBuffer(void)576 int32_t FastAudioRenderSink::PrepareMmapBuffer(void)
577 {
578 uint32_t totalBufferInMs = 40; // 40: 5 * (6 + 2 * (1)) = 40ms, the buffer size, not latency
579 uint32_t reqBufferFrameSize = totalBufferInMs * (attr_.sampleRate / SECOND_TO_MILLISECOND);
580 struct AudioMmapBufferDescriptor desc;
581
582 int32_t ret = audioRender_->ReqMmapBuffer(audioRender_, reqBufferFrameSize, &desc);
583 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "request mmap buffer fail, ret: %{public}d", ret);
584 AUDIO_INFO_LOG("memoryAddress: [%{private}p], memoryFd: [%{public}d], totalBufferFrames: [%{public}d], "
585 "transferFrameSize: [%{public}d], isShareable: [%{public}d], offset: [%{public}d]", desc.memoryAddress,
586 desc.memoryFd, desc.totalBufferFrames, desc.transferFrameSize, desc.isShareable, desc.offset);
587
588 bufferFd_ = desc.memoryFd; // fcntl(fd, 1030, 3) after dup?
589 int32_t periodFrameMaxSize = 1920000; // 192khz * 10s
590 CHECK_AND_RETURN_RET_LOG(desc.totalBufferFrames >= 0 && desc.transferFrameSize >= 0 &&
591 desc.transferFrameSize <= periodFrameMaxSize, ERR_OPERATION_FAILED,
592 "invalid value, totalBufferFrames: [%{public}d], transferFrameSize: [%{public}d]", desc.totalBufferFrames,
593 desc.transferFrameSize);
594
595 frameSizeInByte_ = PcmFormatToBit(attr_.format) * attr_.channel / PCM_8_BIT;
596 bufferTotalFrameSize_ = static_cast<uint32_t>(desc.totalBufferFrames); // 1440 ~ 3840
597 eachReadFrameSize_ = static_cast<uint32_t>(desc.transferFrameSize); // 240
598 CHECK_AND_RETURN_RET_LOG(frameSizeInByte_ <= ULLONG_MAX / bufferTotalFrameSize_, ERR_OPERATION_FAILED,
599 "buffer size will overflow");
600
601 bufferSize_ = bufferTotalFrameSize_ * frameSizeInByte_;
602 #ifdef DEBUG_DIRECT_USE_HDI
603 privBufferFd_ = dup(bufferFd_);
604 bufferAddress_ = (char *)mmap(nullptr, bufferSize_, PROT_READ | PROT_WRITE, MAP_SHARED, privBufferFd_, 0);
605 CHECK_AND_RETURN_RET_LOG(bufferAddress_ != nullptr && bufferAddress_ != MAP_FAILED, ERR_OPERATION_FAILED,
606 "mmap buffer fail");
607 #endif
608 return SUCCESS;
609 }
610
ReleaseMmapBuffer(void)611 void FastAudioRenderSink::ReleaseMmapBuffer(void)
612 {
613 #ifdef DEBUG_DIRECT_USE_HDI
614 if (bufferAddress_ != nullptr) {
615 munmap(bufferAddress_, bufferSize_);
616 bufferAddress_ = nullptr;
617 bufferSize_ = 0;
618 AUDIO_INFO_LOG("release mmap buffer succ");
619 } else {
620 AUDIO_WARNING_LOG("buffer is already nullptr");
621 }
622 if (privBufferFd_ != INVALID_FD) {
623 CloseFd(privBufferFd_);
624 privBufferFd_ = INVALID_FD;
625 }
626 #endif
627 if (bufferFd_ != INVALID_FD) {
628 CloseFd(bufferFd_);
629 bufferFd_ = INVALID_FD;
630 }
631 }
632
CheckPositionTime(void)633 int32_t FastAudioRenderSink::CheckPositionTime(void)
634 {
635 int32_t tryCount = MAX_GET_POSITION_TRY_COUNT;
636 uint64_t frames = 0;
637 int64_t timeSec = 0;
638 int64_t timeNanoSec = 0;
639 int64_t maxHandleTime = attr_.audioStreamFlag == AUDIO_FLAG_VOIP_FAST ? VOIP_MAX_GET_POSITION_HANDLE_TIME :
640 GENERAL_MAX_GET_POSITION_HANDLE_TIME;
641 while (tryCount-- > 0) {
642 ClockTime::RelativeSleep(MAX_GET_POSITION_WAIT_TIME);
643 int32_t ret = GetMmapHandlePosition(frames, timeSec, timeNanoSec);
644 int64_t curTime = ClockTime::GetCurNano();
645 int64_t curSec = curTime / AUDIO_NS_PER_SECOND;
646 int64_t curNanoSec = curTime - curSec * AUDIO_NS_PER_SECOND;
647 AUDIO_WARNING_LOG("sec: %{public}" PRId64 ", nanoSec: %{public}" PRId64 ", time cost: %{public}" PRId64,
648 timeSec, timeNanoSec, ClockTime::GetCurNano() - curTime);
649 if (ret != SUCCESS || curSec != timeSec || curNanoSec - timeNanoSec > maxHandleTime) {
650 AUDIO_WARNING_LOG("tryCount: %{public}d, ret: %{public}d", tryCount, ret);
651 continue;
652 } else {
653 AUDIO_INFO_LOG("check succ");
654 return SUCCESS;
655 }
656 }
657 #ifdef FEATURE_POWER_MANAGER
658 if (runningLock_ != nullptr) {
659 AUDIO_INFO_LOG("running lock unlock");
660 runningLock_->UnLock();
661 } else {
662 AUDIO_WARNING_LOG("running lock is null, playback can not work well");
663 }
664 #endif
665 AUDIO_ERR_LOG("fail, stop render");
666 CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
667 int32_t ret = audioRender_->Stop(audioRender_);
668 UpdateSinkState(false);
669 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "stop fail, ret: %{public}d", ret);
670 return ERR_OPERATION_FAILED;
671 }
672
PreparePosition(void)673 void FastAudioRenderSink::PreparePosition(void)
674 {
675 #ifdef DEBUG_DIRECT_USE_HDI
676 isFirstWrite_ = false;
677 uint64_t frames = 0;
678 int64_t timeSec = 0;
679 int64_t timeNanoSec = 0;
680 GetMmapHandlePosition(frames, timeSec, timeNanoSec); // get first start position
681 int32_t periodByteSize = eachReadFrameSize_ * frameSizeInByte_;
682 CHECK_AND_RETURN_LOG(periodByteSize * writeAheadPeriod_ <= ULLONG_MAX - curReadPos_, "pos will overflow");
683 size_t tempPos = curReadPos_ + periodByteSize * writeAheadPeriod_; // 1 period ahead
684 curWritePos_ = (tempPos < bufferSize_ ? tempPos : tempPos - bufferSize_);
685 AUDIO_INFO_LOG("first render frame start, curReadPos: [%{public}d], curWritePos: [%{public}d]", curReadPos_,
686 curWritePos_);
687 #endif
688 }
689
690 } // namespace AudioStandard
691 } // namespace OHOS
692