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