• 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 "DirectAudioRenderSink"
18 #endif
19 
20 #include "sink/direct_audio_render_sink.h"
21 #include <climits>
22 #include <future>
23 #include "audio_hdi_log.h"
24 #include "audio_errors.h"
25 #include "audio_dump_pcm.h"
26 #include "volume_tools.h"
27 #include "parameters.h"
28 #include "media_monitor_manager.h"
29 #include "common/hdi_adapter_info.h"
30 #include "manager/hdi_adapter_manager.h"
31 
32 namespace OHOS {
33 namespace AudioStandard {
~DirectAudioRenderSink()34 DirectAudioRenderSink::~DirectAudioRenderSink()
35 {
36 }
37 
Init(const IAudioSinkAttr & attr)38 int32_t DirectAudioRenderSink::Init(const IAudioSinkAttr &attr)
39 {
40     std::lock_guard<std::mutex> lock(sinkMutex_);
41     Trace trace("DirectAudioRenderSink::Init");
42     testFlag_ = system::GetIntParameter("persist.multimedia.eac3test", 0);
43     if (!testFlag_) {
44         attr_ = attr;
45         int32_t ret = CreateRender();
46         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create render fail");
47     }
48     sinkInited_ = true;
49     return SUCCESS;
50 }
51 
DeInit(void)52 void DirectAudioRenderSink::DeInit(void)
53 {
54     AUDIO_INFO_LOG("in");
55     Trace trace("DirectAudioRenderSink::DeInit");
56     std::lock_guard<std::mutex> lock(sinkMutex_);
57     sinkInited_ = false;
58     started_ = false;
59     if (!testFlag_) {
60         HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
61         std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
62         CHECK_AND_RETURN(deviceManager != nullptr);
63         deviceManager->DestroyRender(attr_.adapterName, hdiRenderId_);
64         audioRender_ = nullptr;
65     }
66     hdiCallback_ = {};
67     DumpFileUtil::CloseDumpFile(&dumpFile_);
68 }
69 
IsInited(void)70 bool DirectAudioRenderSink::IsInited(void)
71 {
72     return sinkInited_;
73 }
74 
Start(void)75 int32_t DirectAudioRenderSink::Start(void)
76 {
77     std::unique_lock<std::mutex> lock(sinkMutex_);
78     AUDIO_INFO_LOG("in");
79     Trace trace("DirectAudioRenderSink::Start");
80     if (started_) {
81         return SUCCESS;
82     }
83     dumpFileName_ = "direct_sink_" + GetTime() + "_" + std::to_string(attr_.sampleRate) + "_" +
84     std::to_string(attr_.channel) + "_" + std::to_string(attr_.format) + ".pcm";
85     DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpFileName_, &dumpFile_);
86     if (testFlag_) {
87         started_ = true;
88         lock.unlock();
89         StartTestThread();
90         return SUCCESS;
91     }
92     AudioXCollie audioXCollie("DirectAudioRenderSink::Start", TIMEOUT_SECONDS_10,
93         nullptr, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
94     CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
95     int32_t ret = audioRender_->Start(audioRender_);
96     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "start fail, ret: %{public}d", ret);
97     started_ = true;
98     return SUCCESS;
99 }
100 
StartTestThread(void)101 void DirectAudioRenderSink::StartTestThread(void)
102 {
103     std::thread([this]() {
104         bool keepRunning = true;
105         while (keepRunning) {
106             std::unique_lock<std::mutex> lock(sinkMutex_);
107             keepRunning = started_ && sinkInited_;
108             hdiCallback_.serviceCallback_(CB_NONBLOCK_WRITE_COMPLETED);
109             lock.unlock();
110             std::this_thread::sleep_for(std::chrono::milliseconds(TEST_CALLBACK_TIME));
111         }
112     }).detach();
113 }
114 
Stop(void)115 int32_t DirectAudioRenderSink::Stop(void)
116 {
117     std::lock_guard<std::mutex> lock(sinkMutex_);
118     AUDIO_INFO_LOG("in");
119     Trace trace("DirectAudioRenderSink::Stop");
120     if (!started_) {
121         return SUCCESS;
122     }
123     if (!testFlag_) {
124 #ifdef FEATURE_POWER_MANAGER
125         if (runningLock_ != nullptr) {
126             std::thread runningLockThread([this] {
127                 runningLock_->UnLock();
128             });
129             runningLockThread.join();
130         }
131 #endif
132         AudioXCollie audioXCollie("DirectAudioRenderSink::Stop", TIMEOUT_SECONDS_10,
133             nullptr, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
134         CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
135         int32_t ret = audioRender_->Stop(audioRender_);
136         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail");
137     }
138     started_ = false;
139     return SUCCESS;
140 }
141 
Resume(void)142 int32_t DirectAudioRenderSink::Resume(void)
143 {
144     AUDIO_INFO_LOG("not support");
145     return ERR_NOT_SUPPORTED;
146 }
147 
Pause(void)148 int32_t DirectAudioRenderSink::Pause(void)
149 {
150     AUDIO_INFO_LOG("not support");
151     return ERR_NOT_SUPPORTED;
152 }
153 
Flush(void)154 int32_t DirectAudioRenderSink::Flush(void)
155 {
156     return SUCCESS;
157 }
158 
Reset(void)159 int32_t DirectAudioRenderSink::Reset(void)
160 {
161     return SUCCESS;
162 }
163 
RenderFrame(char & data,uint64_t len,uint64_t & writeLen)164 int32_t DirectAudioRenderSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
165 {
166     if (testFlag_) {
167         DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(&data), len);
168     } else {
169         int64_t stamp = ClockTime::GetCurNano();
170         CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
171         CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
172 
173         Trace trace("DirectAudioRenderSink::RenderFrame");
174         int32_t ret = audioRender_->RenderFrame(audioRender_, reinterpret_cast<int8_t *>(&data),
175             static_cast<uint32_t>(len), &writeLen);
176 #ifdef FEATURE_POWER_MANAGER
177         if (runningLock_) {
178             runningLock_->UpdateAppsUidToPowerMgr();
179         }
180 #endif
181         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "fail, ret: %{public}x", ret);
182         if (writeLen != 0) {
183             AudioStreamInfo streamInfo(static_cast<AudioSamplingRate>(attr_.sampleRate),
184                 AudioEncodingType::ENCODING_EAC3, static_cast<AudioSampleFormat>(attr_.format),
185                 static_cast<AudioChannel>(attr_.channel));
186             // EAC3 format is not supported to count volume
187             if (AudioDump::GetInstance().GetVersionType() == DumpFileUtil::BETA_VERSION) {
188                 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(&data), writeLen);
189                 AudioCacheMgr::GetInstance().CacheData(dumpFileName_, static_cast<void *>(&data), writeLen);
190             }
191         }
192         stamp = (ClockTime::GetCurNano() - stamp) / AUDIO_US_PER_SECOND;
193     }
194     return SUCCESS;
195 }
196 
GetVolumeDataCount()197 int64_t DirectAudioRenderSink::GetVolumeDataCount()
198 {
199     AUDIO_WARNING_LOG("not supported");
200     return 0;
201 }
202 
SuspendRenderSink(void)203 int32_t DirectAudioRenderSink::SuspendRenderSink(void)
204 {
205     return SUCCESS;
206 }
207 
RestoreRenderSink(void)208 int32_t DirectAudioRenderSink::RestoreRenderSink(void)
209 {
210     return SUCCESS;
211 }
212 
SetAudioParameter(const AudioParamKey key,const std::string & condition,const std::string & value)213 void DirectAudioRenderSink::SetAudioParameter(const AudioParamKey key, const std::string &condition,
214     const std::string &value)
215 {
216 }
217 
GetAudioParameter(const AudioParamKey key,const std::string & condition)218 std::string DirectAudioRenderSink::GetAudioParameter(const AudioParamKey key, const std::string &condition)
219 {
220     return "";
221 }
222 
SetVolume(float left,float right)223 int32_t DirectAudioRenderSink::SetVolume(float left, float right)
224 {
225     return SUCCESS;
226 }
227 
GetVolume(float & left,float & right)228 int32_t DirectAudioRenderSink::GetVolume(float &left, float &right)
229 {
230     left = leftVolume_;
231     right = rightVolume_;
232     return SUCCESS;
233 }
234 
GetLatency(uint32_t & latency)235 int32_t DirectAudioRenderSink::GetLatency(uint32_t &latency)
236 {
237     AUDIO_INFO_LOG("not support");
238     return ERR_NOT_SUPPORTED;
239 }
240 
GetTransactionId(uint64_t & transactionId)241 int32_t DirectAudioRenderSink::GetTransactionId(uint64_t &transactionId)
242 {
243     CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
244     transactionId = reinterpret_cast<uint64_t>(audioRender_);
245     return SUCCESS;
246 }
247 
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)248 int32_t DirectAudioRenderSink::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
249 {
250     CHECK_AND_RETURN_RET_LOG(audioRender_ != nullptr, ERR_INVALID_HANDLE, "render is nullptr");
251 
252     struct AudioTimeStamp stamp = {};
253     int32_t ret = audioRender_->GetRenderPosition(audioRender_, &frames, &stamp);
254     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get render position fail, ret: %{public}d", ret);
255     int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it
256     CHECK_AND_RETURN_RET_LOG(stamp.tvSec >= 0 && stamp.tvSec <= maxSec && stamp.tvNSec >= 0 &&
257         stamp.tvNSec <= SECOND_TO_NANOSECOND, ERR_OPERATION_FAILED,
258         "get invalid time, second: %{public}" PRId64 ", nanosecond: %{public}" PRId64, stamp.tvSec, stamp.tvNSec);
259     timeSec = stamp.tvSec;
260     timeNanoSec = stamp.tvNSec;
261     return ret;
262 }
263 
GetMaxAmplitude(void)264 float DirectAudioRenderSink::GetMaxAmplitude(void)
265 {
266     return 0.0f;
267 }
268 
SetAudioMonoState(bool audioMono)269 void DirectAudioRenderSink::SetAudioMonoState(bool audioMono)
270 {
271 }
272 
SetAudioBalanceValue(float audioBalance)273 void DirectAudioRenderSink::SetAudioBalanceValue(float audioBalance)
274 {
275     // reset the balance coefficient value firstly
276     leftBalanceCoef_ = 1.0f;
277     rightBalanceCoef_ = 1.0f;
278 
279     if (std::abs(audioBalance - 0.0f) <= std::numeric_limits<float>::epsilon()) {
280         // audioBalance is equal to 0.0f
281         audioBalanceState_ = false;
282     } else {
283         // audioBalance is not equal to 0.0f
284         audioBalanceState_ = true;
285         // calculate the balance coefficient
286         if (audioBalance > 0.0f) {
287             leftBalanceCoef_ -= audioBalance;
288         } else if (audioBalance < 0.0f) {
289             rightBalanceCoef_ += audioBalance;
290         }
291     }
292 }
293 
SetSinkMuteForSwitchDevice(bool mute)294 int32_t DirectAudioRenderSink::SetSinkMuteForSwitchDevice(bool mute)
295 {
296     AUDIO_INFO_LOG("not support");
297     return ERR_NOT_SUPPORTED;
298 }
299 
SetAudioScene(AudioScene audioScene,bool scoExcludeFlag)300 int32_t DirectAudioRenderSink::SetAudioScene(AudioScene audioScene, bool scoExcludeFlag)
301 {
302     AUDIO_INFO_LOG("not support");
303     return ERR_NOT_SUPPORTED;
304 }
305 
GetAudioScene(void)306 int32_t DirectAudioRenderSink::GetAudioScene(void)
307 {
308     AUDIO_INFO_LOG("not support");
309     return ERR_NOT_SUPPORTED;
310 }
311 
UpdateActiveDevice(std::vector<DeviceType> & outputDevices)312 int32_t DirectAudioRenderSink::UpdateActiveDevice(std::vector<DeviceType> &outputDevices)
313 {
314     AUDIO_INFO_LOG("not support");
315     return ERR_NOT_SUPPORTED;
316 }
317 
RegistCallback(uint32_t type,IAudioSinkCallback * callback)318 void DirectAudioRenderSink::RegistCallback(uint32_t type, IAudioSinkCallback *callback)
319 {
320     std::lock_guard<std::mutex> lock(sinkMutex_);
321     callback_.RegistCallback(type, callback);
322     AUDIO_INFO_LOG("regist succ");
323 }
324 
ResetActiveDeviceForDisconnect(DeviceType device)325 void DirectAudioRenderSink::ResetActiveDeviceForDisconnect(DeviceType device)
326 {
327 }
328 
SetPaPower(int32_t flag)329 int32_t DirectAudioRenderSink::SetPaPower(int32_t flag)
330 {
331     AUDIO_INFO_LOG("not support");
332     return ERR_NOT_SUPPORTED;
333 }
334 
SetPriPaPower(void)335 int32_t DirectAudioRenderSink::SetPriPaPower(void)
336 {
337     AUDIO_INFO_LOG("not support");
338     return ERR_NOT_SUPPORTED;
339 }
340 
UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS],const size_t size)341 int32_t DirectAudioRenderSink::UpdateAppsUid(const int32_t appsUid[MAX_MIX_CHANNELS], const size_t size)
342 {
343 #ifdef FEATURE_POWER_MANAGER
344     CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
345     runningLock_->UpdateAppsUid(appsUid, appsUid + size);
346 #endif
347     return SUCCESS;
348 }
349 
UpdateAppsUid(const std::vector<int32_t> & appsUid)350 int32_t DirectAudioRenderSink::UpdateAppsUid(const std::vector<int32_t> &appsUid)
351 {
352 #ifdef FEATURE_POWER_MANAGER
353     CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
354     runningLock_->UpdateAppsUid(appsUid.cbegin(), appsUid.cend());
355     runningLock_->UpdateAppsUidToPowerMgr();
356 #endif
357     return SUCCESS;
358 }
359 
RegistDirectHdiCallback(std::function<void (const RenderCallbackType type)> callback)360 int32_t DirectAudioRenderSink::RegistDirectHdiCallback(std::function<void(const RenderCallbackType type)> callback)
361 {
362     AUDIO_INFO_LOG("in");
363     int32_t ret = SUCCESS;
364     hdiCallback_ = {
365         .callback_.RenderCallback = &DirectAudioRenderSink::DirectRenderCallback,
366         .serviceCallback_ = callback,
367         .sink_ = this,
368     };
369     if (!testFlag_) {
370         ret = audioRender_->RegCallback(audioRender_, &hdiCallback_.callback_, (int8_t)0);
371         if (ret != SUCCESS) {
372             AUDIO_ERR_LOG("fail, error code: %{public}d", ret);
373         }
374     }
375     return ret;
376 }
377 
DumpInfo(std::string & dumpString)378 void DirectAudioRenderSink::DumpInfo(std::string &dumpString)
379 {
380     dumpString += "type: directSink\tstarted: " + std::string(started_ ? "true" : "false") + "\n";
381 }
382 
SetDmDeviceType(uint16_t dmDeviceType,DeviceType deviceType)383 void DirectAudioRenderSink::SetDmDeviceType(uint16_t dmDeviceType, DeviceType deviceType)
384 {
385     AUDIO_INFO_LOG("not support");
386 }
387 
DirectRenderCallback(struct IAudioCallback * self,enum AudioCallbackType type,int8_t * reserved,int8_t * cookie)388 int32_t DirectAudioRenderSink::DirectRenderCallback(struct IAudioCallback *self, enum AudioCallbackType type,
389     int8_t *reserved, int8_t *cookie)
390 {
391     (void)reserved;
392     (void)cookie;
393     auto *impl = reinterpret_cast<struct DirectHdiCallback *>(self);
394     CHECK_AND_RETURN_RET_LOG(impl != nullptr, ERR_OPERATION_FAILED, "impl is nullptr");
395     auto *sink = reinterpret_cast<DirectAudioRenderSink *>(impl->sink_);
396     CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERR_OPERATION_FAILED, "sink is nullptr");
397     if (!sink->started_) {
398         AUDIO_DEBUG_LOG("invalid call, started: %{public}d", sink->started_);
399         return SUCCESS;
400     }
401 
402     impl->serviceCallback_(static_cast<RenderCallbackType>(type));
403     return SUCCESS;
404 }
405 
InitAudioSampleAttr(struct AudioSampleAttributes & param)406 void DirectAudioRenderSink::InitAudioSampleAttr(struct AudioSampleAttributes &param)
407 {
408     param.channelCount = attr_.channel;
409     param.sampleRate = AUDIO_SAMPLE_RATE_48K;
410     param.interleaved = true;
411     param.streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_RENDER_ID_BASE, HDI_RENDER_OFFSET_EAC3));
412     param.type = AUDIO_DIRECT;
413     param.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
414     param.isBigEndian = false;
415     param.isSignedData = true;
416     param.stopThreshold = INT_MAX;
417     param.silenceThreshold = 0;
418     param.sampleRate = attr_.sampleRate;
419     param.channelLayout = attr_.channelLayout;
420 }
421 
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)422 void DirectAudioRenderSink::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
423 {
424     deviceDesc.pins = PIN_OUT_SPEAKER;
425     deviceDesc.desc = const_cast<char *>("");
426 }
427 
CreateRender(void)428 int32_t DirectAudioRenderSink::CreateRender(void)
429 {
430     Trace trace("DirectAudioRenderSink::CreateRender");
431 
432     struct AudioSampleAttributes param;
433     struct AudioDeviceDescriptor deviceDesc;
434     InitAudioSampleAttr(param);
435     InitDeviceDesc(deviceDesc);
436 
437     AUDIO_INFO_LOG("create render, rate: %{public}u, channel: %{public}u, format: %{public}u", param.sampleRate,
438         param.channelCount, param.format);
439     AudioXCollie audioXCollie("DirectAudioRenderSink::CreateRender", TIMEOUT_SECONDS_10,
440          nullptr, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
441     HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
442     std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
443     CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
444     void *render = deviceManager->CreateRender(attr_.adapterName, &param, &deviceDesc, hdiRenderId_);
445     audioRender_ = static_cast<struct IAudioRender *>(render);
446     CHECK_AND_RETURN_RET(audioRender_ != nullptr, ERR_NOT_STARTED);
447 
448     return SUCCESS;
449 }
450 } // namespace AudioStandard
451 } // namespace OHOS
452