1 /*
2  * Copyright (c) 2024 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 #include "audio_render_ext_impl.h"
17 
18 #include <hdf_base.h>
19 #include <unistd.h>
20 #include "sys/time.h"
21 
22 #include "cJSON.h"
23 
24 #include "daudio_constants.h"
25 #include "daudio_events.h"
26 #include "daudio_log.h"
27 
28 #undef DH_LOG_TAG
29 #define DH_LOG_TAG "AudioRenderExtImpl"
30 
31 using namespace OHOS::DistributedHardware;
32 namespace OHOS {
33 namespace HDI {
34 namespace DistributedAudio {
35 namespace Audio {
36 namespace V1_0 {
AudioRenderExtImpl()37 AudioRenderExtImpl::AudioRenderExtImpl()
38 {
39     DHLOGI("Distributed lowlatency render constructed.");
40 }
41 
~AudioRenderExtImpl()42 AudioRenderExtImpl::~AudioRenderExtImpl()
43 {
44     UnInitAshmem();
45     DHLOGI("Distributed lowlatency render destructed, id(%{public}d).", devDesc_.pins);
46 }
47 
InitAshmem(int32_t ashmemLength)48 int32_t AudioRenderExtImpl::InitAshmem(int32_t ashmemLength)
49 {
50     std::string memory_name = "Render ShareMemory";
51     if (ashmemLength < DAUDIO_MIN_ASHMEM_LEN || ashmemLength > DAUDIO_MAX_ASHMEM_LEN) {
52         DHLOGE("Init ashmem failed. length is illegal.");
53         return HDF_FAILURE;
54     }
55     ashmem_ = OHOS::Ashmem::CreateAshmem(memory_name.c_str(), ashmemLength);
56     if (ashmem_ == nullptr) {
57         DHLOGE("Create ashmem failed.");
58         return HDF_FAILURE;
59     }
60     bool ret = ashmem_->MapReadAndWriteAshmem();
61     if (ret != true) {
62         DHLOGE("Mmap ashmem failed.");
63         return HDF_FAILURE;
64     }
65     fd_ = ashmem_->GetAshmemFd();
66     DHLOGI("Init Ashmem success, fd: %{public}d, length: %{public}d", fd_, ashmemLength);
67     return HDF_SUCCESS;
68 }
69 
UnInitAshmem()70 void AudioRenderExtImpl::UnInitAshmem()
71 {
72     if (ashmem_ != nullptr) {
73         ashmem_->UnmapAshmem();
74         ashmem_->CloseAshmem();
75         ashmem_ = nullptr;
76         DHLOGI("UnInitAshmem success.");
77     }
78 }
79 
GetLatency(uint32_t & ms)80 int32_t AudioRenderExtImpl::GetLatency(uint32_t &ms)
81 {
82     DHLOGD("Get render device latency, not support yet.");
83     ms = 0;
84     return HDF_SUCCESS;
85 }
86 
GetFadeRate(uint32_t currentIndex,const uint32_t durationIndex)87 float AudioRenderExtImpl::GetFadeRate(uint32_t currentIndex, const uint32_t durationIndex)
88 {
89     if (currentIndex > durationIndex || durationIndex == 0) {
90         return 1.0f;
91     }
92 
93     float fadeRate = static_cast<float>(currentIndex) / durationIndex * DAUDIO_FADE_NORMALIZATION_FACTOR;
94     if (fadeRate < 1) {
95         return pow(fadeRate, DAUDIO_FADE_POWER_NUM) / DAUDIO_FADE_NORMALIZATION_FACTOR;
96     }
97     return -pow(fadeRate - DAUDIO_FADE_MAXIMUM_VALUE, DAUDIO_FADE_POWER_NUM) /
98         DAUDIO_FADE_NORMALIZATION_FACTOR + 1;
99 }
100 
FadeInProcess(const uint32_t durationFrame,int8_t * frameData,const size_t frameLength)101 int32_t AudioRenderExtImpl::FadeInProcess(const uint32_t durationFrame,
102     int8_t* frameData, const size_t frameLength)
103 {
104     int16_t* frame = reinterpret_cast<int16_t *>(frameData);
105     const size_t newFrameLength = frameLength / 2;
106     if (durationFrame < 1) {
107         return HDF_FAILURE;
108     }
109     for (size_t k = 0; k < newFrameLength; ++k) {
110         float rate = GetFadeRate(currentFrame_ * newFrameLength + k, durationFrame * newFrameLength);
111         frame[k] = currentFrame_ == durationFrame - 1 ? frame[k] : static_cast<int16_t>(rate * frame[k]);
112     }
113     DHLOGI("Fade-in frame[currentFrame: %{public}d].", currentFrame_);
114     ++currentFrame_;
115     currentFrame_ = currentFrame_ >= durationFrame ? durationFrame - 1 : currentFrame_;
116 
117     return HDF_SUCCESS;
118 }
119 
RenderFrame(const std::vector<int8_t> & frame,uint64_t & replyBytes)120 int32_t AudioRenderExtImpl::RenderFrame(const std::vector<int8_t> &frame, uint64_t &replyBytes)
121 {
122     DHLOGD("Render frame. not support in low-latency render");
123     (void)devAttrs_.sampleRate;
124     (void)devAttrs_.channelCount;
125     (void)devAttrs_.format;
126 
127     return HDF_SUCCESS;
128 }
129 
GetRenderPosition(uint64_t & frames,AudioTimeStamp & time)130 int32_t AudioRenderExtImpl::GetRenderPosition(uint64_t &frames, AudioTimeStamp &time)
131 {
132     DHLOGD("Get render position, not support yet.");
133     (void)frames;
134     (void)time;
135     return HDF_SUCCESS;
136 }
137 
SetRenderSpeed(float speed)138 int32_t AudioRenderExtImpl::SetRenderSpeed(float speed)
139 {
140     DHLOGD("Set render speed, control render speed is not support yet.");
141     renderSpeed_ = speed;
142     return HDF_SUCCESS;
143 }
144 
GetRenderSpeed(float & speed)145 int32_t AudioRenderExtImpl::GetRenderSpeed(float &speed)
146 {
147     DHLOGD("Get render speed, control render speed is not support yet.");
148     speed = renderSpeed_;
149     return HDF_SUCCESS;
150 }
151 
SetChannelMode(AudioChannelMode mode)152 int32_t AudioRenderExtImpl::SetChannelMode(AudioChannelMode mode)
153 {
154     DHLOGD("Set channel mode, control channel mode is not support yet.");
155     channelMode_ = mode;
156     return HDF_SUCCESS;
157 }
158 
GetChannelMode(AudioChannelMode & mode)159 int32_t AudioRenderExtImpl::GetChannelMode(AudioChannelMode &mode)
160 {
161     DHLOGD("Get channel mode, control channel mode is not support yet.");
162     mode = channelMode_;
163     return HDF_SUCCESS;
164 }
165 
RegCallback(const sptr<IAudioCallback> & audioCallback,int8_t cookie)166 int32_t AudioRenderExtImpl::RegCallback(const sptr<IAudioCallback> &audioCallback, int8_t cookie)
167 {
168     DHLOGI("Register render callback.");
169     (void)cookie;
170     renderCallback_ = audioCallback;
171     return HDF_SUCCESS;
172 }
173 
DrainBuffer(AudioDrainNotifyType & type)174 int32_t AudioRenderExtImpl::DrainBuffer(AudioDrainNotifyType &type)
175 {
176     DHLOGD("Drain audio buffer, not support yet.");
177     (void)type;
178     return HDF_SUCCESS;
179 }
180 
IsSupportsDrain(bool & support)181 int32_t AudioRenderExtImpl::IsSupportsDrain(bool &support)
182 {
183     DHLOGD("Check whether drain is supported, not support yet.");
184     (void)support;
185     return HDF_SUCCESS;
186 }
187 
Start()188 int32_t AudioRenderExtImpl::Start()
189 {
190     DHLOGI("Start render mmap.");
191     if (audioExtCallback_ == nullptr) {
192         DHLOGE("Callback is nullptr.");
193         return HDF_FAILURE;
194     }
195     if (firstOpenFlag_) {
196         firstOpenFlag_ = false;
197     } else {
198         std::string content;
199         std::initializer_list<std::pair<std::string, std::string>> items = { {"ChangeType", HDF_EVENT_RESTART},
200             {KEY_DH_ID, std::to_string(dhId_)} };
201         if (WrapCJsonItem(items, content) != HDF_SUCCESS) {
202             DHLOGE("Wrap the event failed.");
203             return HDF_FAILURE;
204         }
205         DAudioEvent event = { HDF_AUDIO_EVENT_CHANGE_PLAY_STATUS, content };
206         int32_t ret = audioExtCallback_->NotifyEvent(renderId_, event);
207         if (ret != HDF_SUCCESS) {
208             DHLOGE("Restart failed.");
209         }
210     }
211     std::string content;
212     std::initializer_list<std::pair<std::string, std::string>> items = { {KEY_DH_ID, std::to_string(dhId_)} };
213     if (WrapCJsonItem(items, content) != HDF_SUCCESS) {
214         DHLOGE("Wrap the event failed.");
215         return HDF_FAILURE;
216     }
217     DAudioEvent event = { HDF_AUDIO_EVENT_MMAP_START, content };
218     int32_t ret = audioExtCallback_->NotifyEvent(renderId_, event);
219     if (ret != HDF_SUCCESS) {
220         DHLOGE("Start render mmap failed.");
221         return HDF_FAILURE;
222     }
223     return HDF_SUCCESS;
224 }
225 
Stop()226 int32_t AudioRenderExtImpl::Stop()
227 {
228     DHLOGI("Stop render mmap.");
229     if (audioExtCallback_ == nullptr) {
230         DHLOGE("Callback is nullptr.");
231         return HDF_FAILURE;
232     }
233     std::string content;
234     std::initializer_list<std::pair<std::string, std::string>> items = { {KEY_DH_ID, std::to_string(dhId_)} };
235     if (WrapCJsonItem(items, content) != HDF_SUCCESS) {
236         DHLOGE("Wrap the event failed.");
237         return HDF_FAILURE;
238     }
239     DAudioEvent event = { HDF_AUDIO_EVENT_MMAP_STOP, content };
240     int32_t ret = audioExtCallback_->NotifyEvent(renderId_, event);
241     if (ret != HDF_SUCCESS) {
242         DHLOGE("Stop render mmap failed.");
243         return HDF_FAILURE;
244     }
245     items = { {"ChangeType", HDF_EVENT_PAUSE},
246         {KEY_DH_ID, std::to_string(dhId_)} };
247     if (WrapCJsonItem(items, content) != HDF_SUCCESS) {
248         DHLOGE("Wrap the event failed.");
249         return HDF_FAILURE;
250     }
251     event = { HDF_AUDIO_EVENT_CHANGE_PLAY_STATUS, content };
252     ret = audioExtCallback_->NotifyEvent(renderId_, event);
253     if (ret != HDF_SUCCESS) {
254         DHLOGE("Pause and clear cache streams failed.");
255         return HDF_FAILURE;
256     }
257     return HDF_SUCCESS;
258 }
259 
Pause()260 int32_t AudioRenderExtImpl::Pause()
261 {
262     DHLOGI("Pause render.");
263     std::lock_guard<std::mutex> renderLck(renderMtx_);
264     renderStatus_ = RENDER_STATUS_PAUSE;
265     return HDF_SUCCESS;
266 }
267 
Resume()268 int32_t AudioRenderExtImpl::Resume()
269 {
270     return HDF_SUCCESS;
271 }
272 
Flush()273 int32_t AudioRenderExtImpl::Flush()
274 {
275     return HDF_SUCCESS;
276 }
277 
TurnStandbyMode()278 int32_t AudioRenderExtImpl::TurnStandbyMode()
279 {
280     DHLOGD("Turn stand by mode, not support yet.");
281     return HDF_SUCCESS;
282 }
283 
AudioDevDump(int32_t range,int32_t fd)284 int32_t AudioRenderExtImpl::AudioDevDump(int32_t range, int32_t fd)
285 {
286     DHLOGD("Dump audio info, not support yet.");
287     (void)range;
288     (void)fd;
289     return HDF_SUCCESS;
290 }
291 
IsSupportsPauseAndResume(bool & supportPause,bool & supportResume)292 int32_t AudioRenderExtImpl::IsSupportsPauseAndResume(bool &supportPause, bool &supportResume)
293 {
294     DHLOGD("Check whether pause and resume is supported, not support yet.");
295     (void)supportPause;
296     (void)supportResume;
297     return HDF_SUCCESS;
298 }
299 
CheckSceneCapability(const AudioSceneDescriptor & scene,bool & supported)300 int32_t AudioRenderExtImpl::CheckSceneCapability(const AudioSceneDescriptor &scene, bool &supported)
301 {
302     DHLOGD("Check scene capability.");
303     (void)scene;
304     (void)supported;
305     return HDF_SUCCESS;
306 }
307 
SelectScene(const AudioSceneDescriptor & scene)308 int32_t AudioRenderExtImpl::SelectScene(const AudioSceneDescriptor &scene)
309 {
310     DHLOGD("Select audio scene, not support yet.");
311     (void)scene;
312     return HDF_SUCCESS;
313 }
314 
SetMute(bool mute)315 int32_t AudioRenderExtImpl::SetMute(bool mute)
316 {
317     DHLOGD("Set mute, not support yet.");
318     (void)mute;
319     return HDF_SUCCESS;
320 }
321 
GetMute(bool & mute)322 int32_t AudioRenderExtImpl::GetMute(bool &mute)
323 {
324     DHLOGD("Get mute, not support yet.");
325     (void)mute;
326     return HDF_SUCCESS;
327 }
328 
SetVolume(float volume)329 int32_t AudioRenderExtImpl::SetVolume(float volume)
330 {
331     DHLOGD("Can not set vol not by this interface.");
332     (void)volume;
333     return HDF_SUCCESS;
334 }
335 
GetVolume(float & volume)336 int32_t AudioRenderExtImpl::GetVolume(float &volume)
337 {
338     DHLOGD("Can not get vol not by this interface.");
339     (void)volume;
340     return HDF_SUCCESS;
341 }
342 
GetGainThreshold(float & min,float & max)343 int32_t AudioRenderExtImpl::GetGainThreshold(float &min, float &max)
344 {
345     DHLOGD("Get gain threshold, not support yet.");
346     min = 0;
347     max = 0;
348     return HDF_SUCCESS;
349 }
350 
SetGain(float gain)351 int32_t AudioRenderExtImpl::SetGain(float gain)
352 {
353     DHLOGD("Set gain, not support yet.");
354     (void) gain;
355     return HDF_SUCCESS;
356 }
357 
GetGain(float & gain)358 int32_t AudioRenderExtImpl::GetGain(float &gain)
359 {
360     DHLOGD("Get gain, not support yet.");
361     gain = 1.0;
362     return HDF_SUCCESS;
363 }
364 
GetFrameSize(uint64_t & size)365 int32_t AudioRenderExtImpl::GetFrameSize(uint64_t &size)
366 {
367     (void)size;
368     return HDF_SUCCESS;
369 }
370 
GetFrameCount(uint64_t & count)371 int32_t AudioRenderExtImpl::GetFrameCount(uint64_t &count)
372 {
373     (void)count;
374     return HDF_SUCCESS;
375 }
376 
SetSampleAttributes(const AudioSampleAttributes & attrs)377 int32_t AudioRenderExtImpl::SetSampleAttributes(const AudioSampleAttributes &attrs)
378 {
379     DHLOGI("Set sample attributes.");
380     devAttrs_ = attrs;
381     return HDF_SUCCESS;
382 }
383 
GetSampleAttributes(AudioSampleAttributes & attrs)384 int32_t AudioRenderExtImpl::GetSampleAttributes(AudioSampleAttributes &attrs)
385 {
386     DHLOGI("Get sample attributes.");
387     attrs = devAttrs_;
388     return HDF_SUCCESS;
389 }
390 
GetCurrentChannelId(uint32_t & channelId)391 int32_t AudioRenderExtImpl::GetCurrentChannelId(uint32_t &channelId)
392 {
393     DHLOGD("Get current channel id, not support yet.");
394     (void)channelId;
395     return HDF_SUCCESS;
396 }
397 
SetExtraParams(const std::string & keyValueList)398 int32_t AudioRenderExtImpl::SetExtraParams(const std::string &keyValueList)
399 {
400     DHLOGD("Set extra parameters, not support yet.");
401     (void)keyValueList;
402     return HDF_SUCCESS;
403 }
404 
GetExtraParams(std::string & keyValueList)405 int32_t AudioRenderExtImpl::GetExtraParams(std::string &keyValueList)
406 {
407     DHLOGD("Get extra parameters, not support yet.");
408     (void)keyValueList;
409     return HDF_SUCCESS;
410 }
411 
ReqMmapBuffer(int32_t reqSize,AudioMmapBufferDescriptor & desc)412 int32_t AudioRenderExtImpl::ReqMmapBuffer(int32_t reqSize, AudioMmapBufferDescriptor &desc)
413 {
414     DHLOGI("Request mmap buffer.");
415     int32_t minSize = CalculateSampleNum(devAttrs_.sampleRate, minTimeInterval_);
416     int32_t maxSize = CalculateSampleNum(devAttrs_.sampleRate, maxTimeInterval_);
417     int32_t realSize = reqSize;
418     if (reqSize < minSize) {
419         realSize = minSize;
420     } else if (reqSize > maxSize) {
421         realSize = maxSize;
422     }
423     DHLOGI("ReqMmap buffer realsize : %{public}d, minsize: %{public}d, maxsize:%{public}d.",
424         realSize, minSize, maxSize);
425     desc.totalBufferFrames = realSize;
426     ashmemLength_ = realSize * static_cast<int32_t>(devAttrs_.channelCount) * devAttrs_.format;
427     DHLOGI("Init ashmem real sample size : %{public}d, length: %{public}d.", realSize, ashmemLength_);
428     int32_t ret = InitAshmem(ashmemLength_);
429     if (ret != HDF_SUCCESS) {
430         DHLOGE("Init ashmem error..");
431         return HDF_FAILURE;
432     }
433     desc.memoryFd = fd_;
434     desc.transferFrameSize = static_cast<int32_t>(CalculateSampleNum(devAttrs_.sampleRate, timeInterval_));
435     lengthPerTrans_ = desc.transferFrameSize * static_cast<int32_t>(devAttrs_.channelCount) * devAttrs_.format;
436     desc.isShareable = false;
437     if (audioExtCallback_ == nullptr) {
438         DHLOGE("Callback is nullptr.");
439         return HDF_FAILURE;
440     }
441     ret = audioExtCallback_->RefreshAshmemInfo(renderId_, fd_, ashmemLength_, lengthPerTrans_);
442     if (ret != HDF_SUCCESS) {
443         DHLOGE("Refresh ashmem info failed.");
444         return HDF_FAILURE;
445     }
446     return HDF_SUCCESS;
447 }
448 
GetMmapPosition(uint64_t & frames,AudioTimeStamp & time)449 int32_t AudioRenderExtImpl::GetMmapPosition(uint64_t &frames, AudioTimeStamp &time)
450 {
451     DHLOGI("Get mmap render position.");
452     if (audioExtCallback_ == nullptr) {
453         DHLOGE("Callback is nullptr.");
454         return HDF_FAILURE;
455     }
456     CurrentTime cTime;
457     int32_t ret = audioExtCallback_->ReadMmapPosition(renderId_, frames, cTime);
458     if (ret != HDF_SUCCESS) {
459         DHLOGE("Read mmap position failed.");
460         return HDF_FAILURE;
461     }
462     time.tvSec = cTime.tvSec;
463     time.tvNSec = cTime.tvNSec;
464     DHLOGI("Read mmap position. frames: %{public}" PRIu64", tvSec: %{public}" PRId64", tvNSec: %{public}" PRId64,
465         frames, cTime.tvSec, cTime.tvNSec);
466     return HDF_SUCCESS;
467 }
468 
AddAudioEffect(uint64_t effectid)469 int32_t AudioRenderExtImpl::AddAudioEffect(uint64_t effectid)
470 {
471     DHLOGD("Add audio effect, not support yet.");
472     (void)effectid;
473     return HDF_SUCCESS;
474 }
475 
RemoveAudioEffect(uint64_t effectid)476 int32_t AudioRenderExtImpl::RemoveAudioEffect(uint64_t effectid)
477 {
478     DHLOGD("Remove audio effect, not support yet.");
479     (void)effectid;
480     return HDF_SUCCESS;
481 }
482 
GetFrameBufferSize(uint64_t & bufferSize)483 int32_t AudioRenderExtImpl::GetFrameBufferSize(uint64_t &bufferSize)
484 {
485     DHLOGD("Get frame buffer size, not support yet.");
486     (void)bufferSize;
487     return HDF_SUCCESS;
488 }
489 
GetRenderDesc()490 const AudioDeviceDescriptor &AudioRenderExtImpl::GetRenderDesc()
491 {
492     return devDesc_;
493 }
494 
SetVolumeInner(const uint32_t vol)495 void AudioRenderExtImpl::SetVolumeInner(const uint32_t vol)
496 {
497     std::lock_guard<std::mutex> volLck(volMtx_);
498     vol_ = vol;
499 }
500 
SetVolumeRangeInner(const uint32_t volMax,const uint32_t volMin)501 void AudioRenderExtImpl::SetVolumeRangeInner(const uint32_t volMax, const uint32_t volMin)
502 {
503     std::lock_guard<std::mutex> volLck(volMtx_);
504     volMin_ = volMin;
505     volMax_ = volMax;
506 }
507 
GetVolumeInner()508 uint32_t AudioRenderExtImpl::GetVolumeInner()
509 {
510     std::lock_guard<std::mutex> volLck(volMtx_);
511     return vol_;
512 }
513 
GetMaxVolumeInner()514 uint32_t AudioRenderExtImpl::GetMaxVolumeInner()
515 {
516     std::lock_guard<std::mutex> volLck(volMtx_);
517     return volMax_;
518 }
519 
GetMinVolumeInner()520 uint32_t AudioRenderExtImpl::GetMinVolumeInner()
521 {
522     std::lock_guard<std::mutex> volLck(volMtx_);
523     return volMin_;
524 }
525 
SetAttrs(const std::string & adpName,const AudioDeviceDescriptor & desc,const AudioSampleAttributes & attrs,const sptr<IDAudioCallback> & callback,const int32_t dhId)526 void AudioRenderExtImpl::SetAttrs(const std::string &adpName, const AudioDeviceDescriptor &desc,
527     const AudioSampleAttributes &attrs, const sptr<IDAudioCallback> &callback, const int32_t dhId)
528 {
529     adapterName_ = adpName;
530     devDesc_ = desc;
531     devAttrs_ = attrs;
532     audioExtCallback_ = callback;
533     dhId_ = dhId;
534     if (attrs.type == AUDIO_MMAP_NOIRQ) {
535         timeInterval_ = AUDIO_MMAP_NOIRQ_INTERVAL;
536     } else if (attrs.type == AUDIO_MMAP_VOIP) {
537         timeInterval_ = AUDIO_MMAP_VOIP_INTERVAL;
538     }
539     devAttrs_.frameSize = CalculateFrameSize(attrs.sampleRate, attrs.channelCount, attrs.format, timeInterval_, true);
540     DHLOGI("Distributed lowlatency render set attrs, id(%{public}d). framesize(%{public}d)",
541         dhId_, devAttrs_.frameSize);
542 }
543 
SetDumpFlagInner()544 void AudioRenderExtImpl::SetDumpFlagInner()
545 {
546     DHLOGD("Set dump flag, not support yet.");
547 }
548 
GetRenderImplExt()549 AudioRenderInterfaceImplBase *GetRenderImplExt()
550 {
551     DHLOGI("Get low latency render impl.");
552     static AudioRenderExtImpl *implBase = new AudioRenderExtImpl();
553     if (implBase == nullptr) {
554         return nullptr;
555     }
556     return implBase;
557 }
558 } // namespace V1_0
559 } // namespace Audio
560 } // namespace Distributedaudio
561 } // namespace HDI
562 } // namespace OHOS
563