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 int64_t result = static_cast<int64_t>(realSize) *
427 static_cast<int64_t>(devAttrs_.channelCount) *
428 static_cast<int64_t>(devAttrs_.format);
429 CHECK_AND_RETURN_RET_LOG(result > INT32_MAX, HDF_FAILURE, "ashmemLength_ overflow");
430 ashmemLength_ = static_cast<int32_t>(result);
431 DHLOGI("Init ashmem real sample size : %{public}d, length: %{public}d.", realSize, ashmemLength_);
432 int32_t ret = InitAshmem(ashmemLength_);
433 if (ret != HDF_SUCCESS) {
434 DHLOGE("Init ashmem error..");
435 return HDF_FAILURE;
436 }
437 desc.memoryFd = fd_;
438 desc.transferFrameSize = static_cast<int32_t>(CalculateSampleNum(devAttrs_.sampleRate, timeInterval_));
439 lengthPerTrans_ = desc.transferFrameSize * static_cast<int32_t>(devAttrs_.channelCount) * devAttrs_.format;
440 desc.isShareable = false;
441 if (audioExtCallback_ == nullptr) {
442 DHLOGE("Callback is nullptr.");
443 return HDF_FAILURE;
444 }
445 ret = audioExtCallback_->RefreshAshmemInfo(renderId_, fd_, ashmemLength_, lengthPerTrans_);
446 if (ret != HDF_SUCCESS) {
447 DHLOGE("Refresh ashmem info failed.");
448 return HDF_FAILURE;
449 }
450 return HDF_SUCCESS;
451 }
452
GetMmapPosition(uint64_t & frames,AudioTimeStamp & time)453 int32_t AudioRenderExtImpl::GetMmapPosition(uint64_t &frames, AudioTimeStamp &time)
454 {
455 DHLOGI("Get mmap render position.");
456 if (audioExtCallback_ == nullptr) {
457 DHLOGE("Callback is nullptr.");
458 return HDF_FAILURE;
459 }
460 CurrentTime cTime;
461 int32_t ret = audioExtCallback_->ReadMmapPosition(renderId_, frames, cTime);
462 if (ret != HDF_SUCCESS) {
463 DHLOGE("Read mmap position failed.");
464 return HDF_FAILURE;
465 }
466 time.tvSec = cTime.tvSec;
467 time.tvNSec = cTime.tvNSec;
468 DHLOGI("Read mmap position. frames: %{public}" PRIu64", tvSec: %{public}" PRId64", tvNSec: %{public}" PRId64,
469 frames, cTime.tvSec, cTime.tvNSec);
470 return HDF_SUCCESS;
471 }
472
AddAudioEffect(uint64_t effectid)473 int32_t AudioRenderExtImpl::AddAudioEffect(uint64_t effectid)
474 {
475 DHLOGD("Add audio effect, not support yet.");
476 (void)effectid;
477 return HDF_SUCCESS;
478 }
479
RemoveAudioEffect(uint64_t effectid)480 int32_t AudioRenderExtImpl::RemoveAudioEffect(uint64_t effectid)
481 {
482 DHLOGD("Remove audio effect, not support yet.");
483 (void)effectid;
484 return HDF_SUCCESS;
485 }
486
GetFrameBufferSize(uint64_t & bufferSize)487 int32_t AudioRenderExtImpl::GetFrameBufferSize(uint64_t &bufferSize)
488 {
489 DHLOGD("Get frame buffer size, not support yet.");
490 (void)bufferSize;
491 return HDF_SUCCESS;
492 }
493
GetRenderDesc()494 const AudioDeviceDescriptor &AudioRenderExtImpl::GetRenderDesc()
495 {
496 return devDesc_;
497 }
498
SetVolumeInner(const uint32_t vol)499 void AudioRenderExtImpl::SetVolumeInner(const uint32_t vol)
500 {
501 std::lock_guard<std::mutex> volLck(volMtx_);
502 vol_ = vol;
503 }
504
SetVolumeRangeInner(const uint32_t volMax,const uint32_t volMin)505 void AudioRenderExtImpl::SetVolumeRangeInner(const uint32_t volMax, const uint32_t volMin)
506 {
507 std::lock_guard<std::mutex> volLck(volMtx_);
508 volMin_ = volMin;
509 volMax_ = volMax;
510 }
511
GetVolumeInner()512 uint32_t AudioRenderExtImpl::GetVolumeInner()
513 {
514 std::lock_guard<std::mutex> volLck(volMtx_);
515 return vol_;
516 }
517
GetMaxVolumeInner()518 uint32_t AudioRenderExtImpl::GetMaxVolumeInner()
519 {
520 std::lock_guard<std::mutex> volLck(volMtx_);
521 return volMax_;
522 }
523
GetMinVolumeInner()524 uint32_t AudioRenderExtImpl::GetMinVolumeInner()
525 {
526 std::lock_guard<std::mutex> volLck(volMtx_);
527 return volMin_;
528 }
529
SetAttrs(const std::string & adpName,const AudioDeviceDescriptor & desc,const AudioSampleAttributes & attrs,const sptr<IDAudioCallback> & callback,const int32_t dhId)530 void AudioRenderExtImpl::SetAttrs(const std::string &adpName, const AudioDeviceDescriptor &desc,
531 const AudioSampleAttributes &attrs, const sptr<IDAudioCallback> &callback, const int32_t dhId)
532 {
533 adapterName_ = adpName;
534 devDesc_ = desc;
535 devAttrs_ = attrs;
536 audioExtCallback_ = callback;
537 dhId_ = dhId;
538 if (attrs.type == AUDIO_MMAP_NOIRQ) {
539 timeInterval_ = AUDIO_MMAP_NOIRQ_INTERVAL;
540 } else if (attrs.type == AUDIO_MMAP_VOIP) {
541 timeInterval_ = AUDIO_MMAP_VOIP_INTERVAL;
542 }
543 devAttrs_.frameSize = CalculateFrameSize(attrs.sampleRate, attrs.channelCount, attrs.format, timeInterval_, true);
544 DHLOGI("Distributed lowlatency render set attrs, id(%{public}d). framesize(%{public}d)",
545 dhId_, devAttrs_.frameSize);
546 }
547
SetDumpFlagInner()548 void AudioRenderExtImpl::SetDumpFlagInner()
549 {
550 DHLOGD("Set dump flag, not support yet.");
551 }
552
GetRenderStatus()553 AudioRenderStatus AudioRenderExtImpl::GetRenderStatus()
554 {
555 std::lock_guard<std::mutex> renderLck(renderMtx_);
556 DHLOGI("Get renderstatus: %{public}d", static_cast<int32_t>(renderStatus_));
557 return renderStatus_;
558 }
559
SetRenderStatus(AudioRenderStatus status)560 void AudioRenderExtImpl::SetRenderStatus(AudioRenderStatus status)
561 {
562 std::lock_guard<std::mutex> renderLck(renderMtx_);
563 renderStatus_ = status;
564 DHLOGI("Set renderstatus: %{public}d", static_cast<int32_t>(status));
565 }
566
GetAudioCallback()567 sptr<IAudioCallback> AudioRenderExtImpl::GetAudioCallback()
568 {
569 return nullptr;
570 }
571
GetRenderImplExt()572 AudioRenderInterfaceImplBase *GetRenderImplExt()
573 {
574 DHLOGI("Get low latency render impl.");
575 static AudioRenderExtImpl *implBase = new AudioRenderExtImpl();
576 if (implBase == nullptr) {
577 return nullptr;
578 }
579 return implBase;
580 }
581 } // namespace V1_0
582 } // namespace Audio
583 } // namespace Distributedaudio
584 } // namespace HDI
585 } // namespace OHOS
586