• 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("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 &param)
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, &param, &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