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