1 /*
2 * Copyright (c) 2021-2021 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 #define HST_LOG_TAG "HdiSinkPlugin"
17
18 #include "hos_au_sink.h"
19 #include <memory>
20 #include "audio_adapter.h"
21 #include "audio_manager.h"
22 #include "foundation/log.h"
23 #include "foundation/osal/thread/scoped_lock.h"
24 #include "foundation/osal/utils/util.h"
25 #include "foundation/pre_defines.h"
26 #include "plugin/common/plugin_audio_tags.h"
27 #include "plugin/common/plugin_time.h"
28 #include "plugins/hdi_adapter/utils/hdi_au_utils.h"
29 #include "securec.h"
30 #include "utils/constants.h"
31
32 namespace {
33 using namespace OHOS::Media::Plugin;
34 using namespace OHOS::Media::Plugin::HosLite;
35 using PluginSampleFmt = OHOS::Media::Plugin::AudioSampleFormat;
36 constexpr int32_t MAX_RETRY_CNT = 3;
37 constexpr int32_t RETRY_INTERVAL = 100; // 100ms
38 constexpr int32_t HI_ERR_VI_BUF_FULL = 0xA016800F;
39 constexpr int32_t RANK100 = 100;
40 constexpr int32_t PCM_CHAN_CNT = 2;
41 static std::map<std::string, std::pair<uint32_t, bool>> g_sinkInfos;
42
LoadAndInitAdapter(AudioManager * audioManager,AudioAdapterDescriptor * descriptor,AudioAdapter ** adapter)43 Status LoadAndInitAdapter(AudioManager* audioManager, AudioAdapterDescriptor* descriptor, AudioAdapter** adapter)
44 {
45 if (audioManager == nullptr) {
46 MEDIA_LOG_E("no audio manager when load adapter");
47 return Status::ERROR_UNKNOWN;
48 }
49 if (adapter == nullptr) {
50 MEDIA_LOG_E("**adapter null ptr");
51 return Status::ERROR_INVALID_PARAMETER;
52 }
53 if (audioManager->LoadAdapter(audioManager, descriptor, adapter) < 0) {
54 *adapter = nullptr;
55 MEDIA_LOG_W("failed to load adapter " PUBLIC_LOG_S, descriptor->adapterName);
56 return Status::ERROR_UNSUPPORTED_FORMAT;
57 }
58 if (*adapter == nullptr) {
59 MEDIA_LOG_E("no available adapter after load adapter");
60 return Status::ERROR_UNKNOWN;
61 }
62
63 int32_t retryCnt = 0;
64 do {
65 if ((*adapter)->InitAllPorts(*adapter) != 0) {
66 OHOS::Media::OSAL::SleepFor(RETRY_INTERVAL);
67 } else {
68 break;
69 }
70 MEDIA_LOG_I("retry init port on adapter " PUBLIC_LOG_S, descriptor->adapterName);
71 } while (++retryCnt < MAX_RETRY_CNT);
72 if (retryCnt >= MAX_RETRY_CNT) {
73 MEDIA_LOG_W("cannot init port on adapter " PUBLIC_LOG_S " after retry " PUBLIC_LOG_D32 " times",
74 descriptor->adapterName, retryCnt);
75 audioManager->UnloadAdapter(audioManager, *adapter);
76 *adapter = nullptr;
77 return Status::ERROR_UNKNOWN;
78 }
79 return Status::OK;
80 }
81
UpdatePluginCapWithPortCap(const AudioPortCapability & portCap,Capability & pluginCap)82 void UpdatePluginCapWithPortCap(const AudioPortCapability& portCap, Capability& pluginCap)
83 {
84 std::vector<PluginSampleFmt> sampleFormats;
85 for (size_t cnt = 0; cnt < portCap.supportSampleFormatNum; cnt++) {
86 PluginSampleFmt tmp;
87 if (OHOS::Media::Plugin::HosLite::HdiAuFormat2PluginFormat(portCap.supportSampleFormats[cnt], tmp)) {
88 sampleFormats.emplace_back(tmp);
89 }
90 }
91 if (!sampleFormats.empty()) {
92 if (sampleFormats.size() == 1) {
93 pluginCap.AppendFixedKey<PluginSampleFmt>(Capability::Key::AUDIO_SAMPLE_FORMAT, sampleFormats[0]);
94 } else {
95 pluginCap.AppendDiscreteKeys<PluginSampleFmt>(Capability::Key::AUDIO_SAMPLE_FORMAT, sampleFormats);
96 }
97 }
98 auto pluginSampleRates = OHOS::Media::Plugin::HosLite::HdiSampleRatesMask2PluginRates(portCap.sampleRateMasks);
99 if (!pluginSampleRates.empty()) {
100 if (pluginSampleRates.size() == 1) {
101 pluginCap.AppendFixedKey<uint32_t>(Capability::Key::AUDIO_SAMPLE_RATE, pluginSampleRates[0]);
102 } else {
103 pluginCap.AppendDiscreteKeys<uint32_t>(Capability::Key::AUDIO_SAMPLE_RATE, pluginSampleRates);
104 }
105 }
106 AudioChannelLayout pluginLayout;
107 if (OHOS::Media::Plugin::HosLite::HdiMask2PluginChannelLayout(portCap.channelMasks, pluginLayout)) {
108 pluginCap.AppendFixedKey(Capability::Key::AUDIO_CHANNEL_LAYOUT, pluginLayout);
109 }
110 if (portCap.channelCount > 0) {
111 pluginCap.AppendIntervalKey<uint32_t>(Capability::Key::AUDIO_CHANNELS, 1, portCap.channelCount);
112 }
113 }
114
AudioSinkPluginCreator(const std::string & name)115 std::shared_ptr<AudioSinkPlugin> AudioSinkPluginCreator(const std::string& name)
116 {
117 return std::make_shared<OHOS::Media::Plugin::HosLite::HdiSink>(name);
118 }
119
RegisterOutportOnAdapter(const std::shared_ptr<Register> & reg,const AudioAdapterDescriptor & desc,AudioAdapter * adapter)120 void RegisterOutportOnAdapter(const std::shared_ptr<Register>& reg, const AudioAdapterDescriptor& desc,
121 AudioAdapter* adapter)
122 {
123 CapabilitySet adapterCapabilities;
124 bool usingDefaultCaps = false;
125 uint32_t pIndex = 0;
126 for (uint32_t portIndex = 0; portIndex < desc.portNum; portIndex++) {
127 if (desc.ports[portIndex].dir != PORT_OUT) {
128 continue;
129 }
130 Capability capability(OHOS::Media::MEDIA_MIME_AUDIO_RAW);
131 AudioPortCapability portCap{0};
132 if (adapter->GetPortCapability != nullptr &&
133 adapter->GetPortCapability(adapter, &desc.ports[portIndex], &portCap) == 0) {
134 UpdatePluginCapWithPortCap(portCap, capability);
135 usingDefaultCaps = false;
136 } else {
137 MEDIA_LOG_W("query port capability failed when registering plugin, set audio sample format as S16/S16P");
138 capability.AppendDiscreteKeys<PluginSampleFmt>(Capability::Key::AUDIO_SAMPLE_FORMAT,
139 {PluginSampleFmt::S16, PluginSampleFmt::S16P});
140 usingDefaultCaps = true;
141 }
142 adapterCapabilities.emplace_back(capability);
143 pIndex = portIndex;
144 break; // only take the first out port
145 }
146 if (adapterCapabilities.empty()) {
147 return;
148 }
149 AudioSinkPluginDef sinkPluginDef;
150 sinkPluginDef.creator = AudioSinkPluginCreator;
151 sinkPluginDef.name = desc.adapterName;
152 sinkPluginDef.inCaps = adapterCapabilities;
153 sinkPluginDef.rank = RANK100;
154 if (reg->AddPlugin(sinkPluginDef) == Status::OK) {
155 g_sinkInfos[sinkPluginDef.name] = std::make_pair(pIndex, usingDefaultCaps);
156 MEDIA_LOG_D("register plugin " PUBLIC_LOG_S " succ.", desc.adapterName);
157 } else {
158 MEDIA_LOG_W("register plugin " PUBLIC_LOG_S " failed", desc.adapterName);
159 }
160 }
161
RegisterHdiSinkPlugins(const std::shared_ptr<Register> & reg)162 Status RegisterHdiSinkPlugins(const std::shared_ptr<Register>& reg)
163 {
164 auto audioManager = GetAudioManagerFuncs();
165 if (audioManager == nullptr) {
166 MEDIA_LOG_E("cannot find audio manager funcs");
167 return Status::ERROR_UNKNOWN;
168 }
169 int32_t adapterSize = 0;
170 AudioAdapterDescriptor* descriptors = nullptr;
171 int32_t ret = audioManager->GetAllAdapters(audioManager, &descriptors, &adapterSize);
172 if (ret != 0 || adapterSize == 0) {
173 MEDIA_LOG_E("cannot find available audio adapter");
174 return Status::OK;
175 }
176 for (int32_t index = 0; index < adapterSize; index++) {
177 AudioAdapter* adapter = nullptr;
178 const auto& desc = descriptors[index];
179 if (LoadAndInitAdapter(audioManager, &descriptors[index], &adapter) != Status::OK) {
180 continue;
181 }
182 RegisterOutportOnAdapter(reg, desc, adapter);
183 audioManager->UnloadAdapter(audioManager, adapter);
184 }
185 return Status::OK;
186 }
187
UnRegisterAudioDecoderPlugin()188 void UnRegisterAudioDecoderPlugin()
189 {
190 g_sinkInfos.clear();
191 }
192
193 template <typename T>
AssignIfCastSuccess(T & lvalue,const Any & anyValue,const char * tagName)194 inline Status AssignIfCastSuccess(T& lvalue, const Any& anyValue, const char* tagName)
195 {
196 if (anyValue.SameTypeWith(typeid(T))) {
197 lvalue = AnyCast<const T&>(anyValue);
198 MEDIA_LOG_I("AssignIfCastSuccess found " PUBLIC_LOG_S, tagName);
199 return Status::OK;
200 } else {
201 MEDIA_LOG_W("tag:" PUBLIC_LOG_S " value type mismatch", tagName);
202 return Status::ERROR_MISMATCHED_TYPE;
203 }
204 }
205
CalculateBufferSize(const AudioSampleAttributes & attributes)206 int32_t CalculateBufferSize(const AudioSampleAttributes& attributes)
207 {
208 return attributes.frameSize * attributes.period;
209 }
210
211 PLUGIN_DEFINITION(HdiAuSink, LicenseType::APACHE_V2, RegisterHdiSinkPlugins, UnRegisterAudioDecoderPlugin);
212 } // namespace
213 namespace OHOS {
214 namespace Media {
215 namespace Plugin {
216 namespace HosLite {
217 using namespace OHOS::Media::Plugin;
218
HdiSink(std::string name)219 HdiSink::HdiSink(std::string name)
220 : AudioSinkPlugin(std::move(name)), audioManager_(nullptr), cacheData_(), processing_(false), renderCond_()
221 {
222 // default is media
223 sampleAttributes_.type = AUDIO_IN_MEDIA;
224 if (g_sinkInfos.count(pluginName_) != 0) {
225 usingDefaultInCaps_ = g_sinkInfos[pluginName_].second;
226 }
227 }
228
Init()229 Status HdiSink::Init()
230 {
231 MEDIA_LOG_I("Init entered.");
232 audioManager_ = GetAudioManagerFuncs();
233 if (audioManager_ == nullptr) {
234 MEDIA_LOG_E("Init error due to audioManager nullptr");
235 return Status::ERROR_UNKNOWN;
236 }
237 int32_t adapterSize = 0;
238 AudioAdapterDescriptor* descriptors = nullptr;
239 int32_t ret = audioManager_->GetAllAdapters(audioManager_, &descriptors, &adapterSize);
240 if (ret != 0 || adapterSize == 0) {
241 MEDIA_LOG_E("cannot find available audio adapter");
242 return Status::ERROR_UNKNOWN;
243 }
244 for (int32_t index = 0; index < adapterSize; index++) {
245 const auto& desc = descriptors[index];
246 if (pluginName_ != desc.adapterName) {
247 continue;
248 }
249 if (LoadAndInitAdapter(audioManager_, &descriptors[index], &audioAdapter_) != Status::OK) {
250 continue;
251 }
252 adapterDescriptor_ = descriptors[index];
253 break;
254 }
255 if (audioAdapter_ == nullptr) {
256 MEDIA_LOG_E("cannot find adapter with name " PUBLIC_LOG_S, pluginName_.c_str());
257 return Status::ERROR_UNKNOWN;
258 }
259 return Status::OK;
260 }
261
ReleaseRender()262 Media::Plugin::Status HdiSink::ReleaseRender()
263 {
264 {
265 OSAL::ScopedLock lock(renderMutex_);
266 if (audioAdapter_ != nullptr && audioRender_ != nullptr) {
267 audioAdapter_->DestroyRender(audioAdapter_, audioRender_);
268 audioRender_ = nullptr;
269 }
270 }
271 return Status::OK;
272 }
273
Deinit()274 Status HdiSink::Deinit()
275 {
276 MEDIA_LOG_I("Deinit entered.");
277 Stop();
278 // release all resources
279 ReleaseRender();
280 if (audioManager_ != nullptr) {
281 if (audioAdapter_ != nullptr) {
282 audioManager_->UnloadAdapter(audioManager_, audioAdapter_);
283 audioAdapter_ = nullptr;
284 }
285 audioManager_ = nullptr;
286 }
287 return Status::OK;
288 }
289
ProcessInputSampleFormat(const ValueType & value)290 Status HdiSink::ProcessInputSampleFormat(const ValueType& value)
291 {
292 AudioSampleFormat format;
293 auto ret = AssignIfCastSuccess<AudioSampleFormat>(format, value, "audioSampleFormat");
294 if (ret != Status::OK) {
295 return ret;
296 }
297 if (PluginAuFormat2HdiAttrs(format, sampleAttributes_)) {
298 // if using default in caps e.g. S16/S16P always pass non-interleaved pcm data to hdi
299 // otherwise using the specified format
300 if (usingDefaultInCaps_) {
301 if (sampleAttributes_.interleaved) {
302 isInputInterleaved_ = true;
303 sampleAttributes_.interleaved = false;
304 } else {
305 isInputInterleaved_ = false;
306 }
307 }
308 return Status::OK;
309 } else {
310 MEDIA_LOG_E("audioSampleFormat mismatch");
311 return Status::ERROR_MISMATCHED_TYPE;
312 }
313 }
314
SetParameter(Tag tag,const ValueType & value)315 Status HdiSink::SetParameter(Tag tag, const ValueType& value)
316 {
317 switch (tag) {
318 case Tag::AUDIO_CHANNELS:
319 return AssignIfCastSuccess<uint32_t>(sampleAttributes_.channelCount, value, "channel");
320 case Tag::AUDIO_SAMPLE_RATE:
321 return AssignIfCastSuccess<uint32_t>(sampleAttributes_.sampleRate, value, "sampleRate");
322 case Tag::AUDIO_SAMPLE_FORMAT:
323 return ProcessInputSampleFormat(value);
324 case Tag::AUDIO_SAMPLE_PER_FRAME:
325 return AssignIfCastSuccess<uint32_t>(sampleAttributes_.period, value, "samples per frame");
326 case Tag::AUDIO_CHANNEL_LAYOUT: {
327 AudioChannelLayout layout;
328 auto ret = AssignIfCastSuccess<AudioChannelLayout>(layout, value, "audioChannelLayout");
329 if (ret != Status::OK) {
330 return ret;
331 }
332 if (PluginChannelLayout2HdiMask(layout, channelMask_)) {
333 return Status::OK;
334 } else {
335 MEDIA_LOG_E("audioChannelLayout mismatch");
336 return Status::ERROR_MISMATCHED_TYPE;
337 }
338 }
339 default:
340 MEDIA_LOG_I("receive one parameter with unconcern tag, ignore it");
341 }
342 return Status::OK;
343 }
344
GetParameter(Tag tag,ValueType & value)345 Status HdiSink::GetParameter(Tag tag, ValueType& value)
346 {
347 UNUSED_VARIABLE(tag);
348 UNUSED_VARIABLE(value);
349 return Status::ERROR_UNIMPLEMENTED;
350 }
351
Prepare()352 Status HdiSink::Prepare()
353 {
354 MEDIA_LOG_I("Prepare entered.");
355 sampleAttributes_.frameSize = GetPcmBytes(sampleAttributes_.format) * sampleAttributes_.channelCount;
356 sampleAttributes_.startThreshold = sampleAttributes_.period * sampleAttributes_.frameSize;
357 sampleAttributes_.stopThreshold = INT32_MAX;
358 sampleAttributes_.silenceThreshold = 0;
359 if (g_sinkInfos.count(pluginName_) == 0) {
360 MEDIA_LOG_E("cannot find out port");
361 return Status::ERROR_UNKNOWN;
362 }
363 deviceDescriptor_.portId = g_sinkInfos[pluginName_].first;
364 deviceDescriptor_.pins = PIN_OUT_SPEAKER;
365 deviceDescriptor_.desc = nullptr;
366
367 MEDIA_LOG_I("create render: " PUBLIC_LOG_S ", port: " PUBLIC_LOG_D32 ":\ncategory " PUBLIC_LOG
368 "s,\nchannels " PUBLIC_LOG_D32 ", sampleRate " PUBLIC_LOG_D32 ",\n"
369 " audioChannelMask " PUBLIC_LOG "x, format " PUBLIC_LOG_D32 ",\nisSignedData " PUBLIC_LOG
370 "d, interleaved " PUBLIC_LOG_D32 ",\nperiod " PUBLIC_LOG_U32 ", frameSize " PUBLIC_LOG_U32,
371 adapterDescriptor_.adapterName, deviceDescriptor_.portId,
372 (sampleAttributes_.type == AUDIO_IN_MEDIA) ? "media" : "communication", sampleAttributes_.channelCount,
373 sampleAttributes_.sampleRate, channelMask_, sampleAttributes_.format, sampleAttributes_.isSignedData,
374 sampleAttributes_.interleaved, sampleAttributes_.period, sampleAttributes_.frameSize);
375 {
376 OSAL::ScopedLock lock(renderMutex_);
377 auto ret = audioAdapter_->CreateRender(audioAdapter_, &deviceDescriptor_, &sampleAttributes_, &audioRender_);
378 if (ret != 0) {
379 MEDIA_LOG_E("cannot create render with error code " PUBLIC_LOG_U64 "x",
380 static_cast<uint64_t>(ret));
381 audioRender_ = nullptr;
382 return Status::ERROR_UNKNOWN;
383 }
384 }
385 MEDIA_LOG_I("create audio render successfully");
386 if (sampleAttributes_.channelCount == PCM_CHAN_CNT && usingDefaultInCaps_ && isInputInterleaved_) {
387 cacheData_.resize(CalculateBufferSize(sampleAttributes_));
388 }
389 return Status::OK;
390 }
391
Reset()392 Status HdiSink::Reset()
393 {
394 MEDIA_LOG_I("Reset entered.");
395 ReleaseRender();
396 (void)memset_s(&sampleAttributes_, sizeof(sampleAttributes_), 0, sizeof(sampleAttributes_));
397 (void)memset_s(&deviceDescriptor_, sizeof(deviceDescriptor_), 0, sizeof(deviceDescriptor_));
398 isInputInterleaved_ = false;
399 processing_ = false;
400 channelMask_ = AUDIO_CHANNEL_MONO;
401
402 return Status::OK;
403 }
404
Start()405 Status HdiSink::Start()
406 {
407 MEDIA_LOG_I("Start entered.");
408 OSAL::ScopedLock lock(renderMutex_);
409 if (audioRender_ == nullptr) {
410 MEDIA_LOG_E("no available render");
411 return Status::ERROR_UNKNOWN;
412 }
413
414 if (audioRender_->control.Start(audioRender_) != 0) {
415 MEDIA_LOG_E("audio render start error");
416 return Status::ERROR_UNKNOWN;
417 }
418 processing_ = true;
419 return Status::OK;
420 }
421
Stop()422 Status HdiSink::Stop()
423 {
424 MEDIA_LOG_I("Stop Entered");
425 OSAL::ScopedLock lock(renderMutex_);
426 processing_ = false;
427 renderCond_.NotifyOne();
428 if (audioRender_ == nullptr) {
429 MEDIA_LOG_E("no available render");
430 return Status::OK;
431 }
432 if (audioRender_->control.Stop(audioRender_) != 0) {
433 MEDIA_LOG_E("audio render stop error");
434 return Status::ERROR_UNKNOWN;
435 }
436 MEDIA_LOG_D("Stop Exited");
437 return Status::OK;
438 }
439
GetAllocator()440 std::shared_ptr<Allocator> HdiSink::GetAllocator()
441 {
442 return nullptr;
443 }
444
SetCallback(Callback * cb)445 Status HdiSink::SetCallback(Callback* cb)
446 {
447 eventCallback_ = cb;
448 return Status::OK;
449 }
450
GetMute(bool & mute)451 Status HdiSink::GetMute(bool& mute)
452 {
453 OSAL::ScopedLock lock(renderMutex_);
454 if (audioRender_ == nullptr) {
455 MEDIA_LOG_W("no render available, get mute must be called after prepared");
456 return Status::ERROR_WRONG_STATE;
457 }
458 if (audioRender_->volume.GetMute(audioRender_, &mute) != 0) {
459 MEDIA_LOG_E("get mute failed");
460 return Status::ERROR_UNKNOWN;
461 }
462 return Status::OK;
463 }
464
SetMute(bool mute)465 Status HdiSink::SetMute(bool mute)
466 {
467 // todo when to set mute
468 OSAL::ScopedLock lock(renderMutex_);
469 if (audioRender_ == nullptr) {
470 MEDIA_LOG_W("no render available, set mute must be called after prepare");
471 return Status::ERROR_WRONG_STATE;
472 }
473 if (audioRender_->volume.SetMute(audioRender_, mute) != 0) {
474 MEDIA_LOG_E("set mute failed");
475 return Status::ERROR_UNKNOWN;
476 }
477 return Status::OK;
478 }
479
GetVolume(float & volume)480 Status HdiSink::GetVolume(float& volume)
481 {
482 OSAL::ScopedLock lock(renderMutex_);
483 if (audioRender_ == nullptr) {
484 MEDIA_LOG_W("no render available, get volume must be called after prepare");
485 return Status::ERROR_WRONG_STATE;
486 }
487 if (audioRender_->volume.GetVolume(audioRender_, &volume) != 0) {
488 MEDIA_LOG_E("get volume failed");
489 return Status::ERROR_UNKNOWN;
490 }
491 return Status::OK;
492 }
493
SetVolume(float volume)494 Status HdiSink::SetVolume(float volume)
495 {
496 OSAL::ScopedLock lock(renderMutex_);
497 if (audioRender_ == nullptr) {
498 MEDIA_LOG_W("no render available, set volume must be called after prepare");
499 return Status::ERROR_WRONG_STATE;
500 }
501 constexpr float maxVolume = 100.0f;
502 auto relVolume = volume * maxVolume;
503 if (audioRender_->volume.SetVolume(audioRender_, relVolume) != 0) {
504 MEDIA_LOG_E("set volume failed");
505 return Status::ERROR_UNKNOWN;
506 }
507 MEDIA_LOG_W("set volume to " PUBLIC_LOG ".3f", relVolume);
508 return Status::OK;
509 }
510
GetSpeed(float & speed)511 Status HdiSink::GetSpeed(float& speed)
512 {
513 OSAL::ScopedLock lock(renderMutex_);
514 if (audioRender_ == nullptr) {
515 MEDIA_LOG_W("no render available, get speed must be called after prepare");
516 return Status::ERROR_WRONG_STATE;
517 }
518 if (audioRender_->GetRenderSpeed(audioRender_, &speed) != 0) {
519 MEDIA_LOG_E("get speed failed");
520 return Status::ERROR_UNKNOWN;
521 }
522 return Status::OK;
523 }
524
SetSpeed(float speed)525 Status HdiSink::SetSpeed(float speed)
526 {
527 OSAL::ScopedLock lock(renderMutex_);
528 if (audioRender_ == nullptr) {
529 MEDIA_LOG_W("no render available, set speed must be called after prepare");
530 return Status::ERROR_WRONG_STATE;
531 }
532 if (audioRender_->SetRenderSpeed(audioRender_, speed) != 0) {
533 MEDIA_LOG_E("set speed failed");
534 return Status::ERROR_UNKNOWN;
535 }
536 return Status::OK;
537 }
538
Pause()539 Status HdiSink::Pause()
540 {
541 MEDIA_LOG_I("Pause Entered");
542 OSAL::ScopedLock lock(renderMutex_);
543 processing_ = false;
544 renderCond_.NotifyOne();
545 if (audioRender_ != nullptr && audioRender_->control.Pause(audioRender_) != 0) {
546 MEDIA_LOG_E("pause failed");
547 return Status::ERROR_UNKNOWN;
548 }
549 return Status::OK;
550 }
551
Resume()552 Status HdiSink::Resume()
553 {
554 MEDIA_LOG_I("Resume Entered");
555 OSAL::ScopedLock lock(renderMutex_);
556 processing_ = true;
557 if (audioRender_ != nullptr && audioRender_->control.Resume(audioRender_) != 0) {
558 MEDIA_LOG_E("resume failed");
559 return Status::ERROR_UNKNOWN;
560 }
561 return Status::OK;
562 }
563
GetLatency(uint64_t & hstTime)564 Status HdiSink::GetLatency(uint64_t& hstTime)
565 {
566 OSAL::ScopedLock lock(renderMutex_);
567 if (audioRender_ == nullptr) {
568 MEDIA_LOG_W("no render available, get latency must be called after prepare");
569 return Status::ERROR_WRONG_STATE;
570 }
571 uint32_t tmp;
572 if (audioRender_->GetLatency(audioRender_, &tmp) != 0) {
573 MEDIA_LOG_E("get latency failed");
574 return Status::ERROR_UNKNOWN;
575 }
576 int64_t latency = 0;
577 if (Ms2HstTime(tmp, latency)) {
578 hstTime = latency;
579 return Status::OK;
580 } else {
581 MEDIA_LOG_E("time convert overflow");
582 return Status::ERROR_UNKNOWN;
583 }
584 }
585
GetFrameSize(size_t & size)586 Status HdiSink::GetFrameSize(size_t& size)
587 {
588 UNUSED_VARIABLE(size);
589 return Status::ERROR_UNIMPLEMENTED;
590 }
591
GetFrameCount(uint32_t & count)592 Status HdiSink::GetFrameCount(uint32_t& count)
593 {
594 UNUSED_VARIABLE(count);
595 return Status::ERROR_UNIMPLEMENTED;
596 }
597
Write(const std::shared_ptr<Buffer> & input)598 Status HdiSink::Write(const std::shared_ptr<Buffer>& input)
599 {
600 MEDIA_LOG_DD("Write begin.");
601 if (!input) {
602 MEDIA_LOG_E("Write failed due to nullptr.");
603 return Status::ERROR_INVALID_PARAMETER;
604 }
605 if (!input->IsEmpty()) {
606 RenderFrame(input);
607 }
608 MEDIA_LOG_DD("Write finished.");
609 return Status::OK;
610 }
611
Flush()612 Status HdiSink::Flush()
613 {
614 MEDIA_LOG_I("Flush Entered");
615 OSAL::ScopedLock lock(renderMutex_);
616 if (audioRender_ == nullptr) {
617 MEDIA_LOG_E("no render available, flush must be called after prepare");
618 return Status::ERROR_WRONG_STATE;
619 }
620 if (audioRender_->control.Flush(audioRender_) != 0) {
621 MEDIA_LOG_E("audio render flush error");
622 return Status::ERROR_UNKNOWN;
623 }
624 MEDIA_LOG_I("Flush Exited.");
625 return Status::OK;
626 }
627
Drain()628 Status HdiSink::Drain()
629 {
630 MEDIA_LOG_I("Drain Entered");
631 constexpr int waitTimeForPlaybackCompleteMs = 60; // 60
632 OHOS::Media::OSAL::SleepFor(waitTimeForPlaybackCompleteMs);
633 MEDIA_LOG_I("Drain Exited.");
634 return Status::OK;
635 }
636
637 template <typename T>
Deinterleave(T inData,T outData,int32_t frameCnt)638 static void Deinterleave(T inData, T outData, int32_t frameCnt)
639 {
640 int32_t frameSize = frameCnt / PCM_CHAN_CNT;
641 for (int i = 0; i < PCM_CHAN_CNT; i++) {
642 for (int j = 0; j < frameSize; j++) {
643 outData[i * frameSize + j] = inData[j * PCM_CHAN_CNT + i];
644 }
645 }
646 }
647
Deinterleave16(uint8_t * inData,uint8_t * outData,int32_t frameCnt)648 void HdiSink::Deinterleave16(uint8_t* inData, uint8_t* outData, int32_t frameCnt)
649 {
650 if (sampleAttributes_.isSignedData == true) {
651 Deinterleave(reinterpret_cast<int16_t*>(inData), reinterpret_cast<int16_t*>(outData), frameCnt);
652 } else {
653 Deinterleave(reinterpret_cast<uint16_t*>(inData), reinterpret_cast<uint16_t*>(outData), frameCnt);
654 }
655 }
656
Deinterleave8(uint8_t * inData,uint8_t * outData,int32_t frameCnt)657 void HdiSink::Deinterleave8(uint8_t* inData, uint8_t* outData, int32_t frameCnt)
658 {
659 if (sampleAttributes_.isSignedData == true) {
660 Deinterleave(reinterpret_cast<int8_t*>(inData), reinterpret_cast<int8_t*>(outData), frameCnt);
661 } else {
662 Deinterleave(inData, outData, frameCnt);
663 }
664 }
665
Deinterleave32(uint8_t * inData,uint8_t * outData,int32_t frameCnt)666 void HdiSink::Deinterleave32(uint8_t* inData, uint8_t* outData, int32_t frameCnt)
667 {
668 if (sampleAttributes_.isSignedData == true) {
669 Deinterleave(reinterpret_cast<int32_t*>(inData), reinterpret_cast<int32_t*>(outData), frameCnt);
670 } else {
671 Deinterleave(reinterpret_cast<uint32_t*>(inData), reinterpret_cast<uint32_t*>(outData), frameCnt);
672 }
673 }
674
HandleInterleaveData(uint8_t * origData,int32_t frameCnt)675 bool HdiSink::HandleInterleaveData(uint8_t* origData, int32_t frameCnt)
676 {
677 if (sampleAttributes_.channelCount != PCM_CHAN_CNT || !usingDefaultInCaps_ || !isInputInterleaved_) {
678 return false;
679 }
680 bool isHandled = true;
681 switch (sampleAttributes_.format) {
682 case AUDIO_FORMAT_PCM_16_BIT:
683 Deinterleave16(origData, cacheData_.data(), frameCnt);
684 break;
685 default:
686 isHandled = false;
687 break;
688 }
689 return isHandled;
690 }
691
RenderFrame(const std::shared_ptr<Buffer> & input)692 void HdiSink::RenderFrame(const std::shared_ptr<Buffer>& input)
693 {
694 MEDIA_LOG_DD("RenderFrame started");
695 auto mem = input->GetMemory();
696 auto frame = const_cast<uint8_t*>(mem->GetReadOnlyData());
697 bool dataInterleaved = false;
698 for (size_t remainingBytes = mem->GetSize(); processing_.load() && remainingBytes > 0;) {
699 int32_t ret = 0;
700 uint64_t renderSize = 0;
701 {
702 OSAL::ScopedLock lock(renderMutex_);
703 if (audioRender_ == nullptr) {
704 break;
705 }
706 if (!dataInterleaved && HandleInterleaveData(frame, remainingBytes / PCM_CHAN_CNT)) {
707 frame = cacheData_.data();
708 dataInterleaved = true;
709 }
710 ret = audioRender_->RenderFrame(audioRender_, frame, remainingBytes, &renderSize);
711 }
712 if (ret != 0) {
713 if (ret == HI_ERR_VI_BUF_FULL) {
714 MEDIA_LOG_DD("renderFrame buffer full"); // do not log this info
715 constexpr int timeoutMs = 5;
716 OSAL::ScopedLock lock(renderMutex_);
717 renderCond_.WaitFor(lock, timeoutMs, [this] { return processing_.load() == false; });
718 } else {
719 MEDIA_LOG_E("renderFrame buffer error " PUBLIC_LOG_D32, ret);
720 break;
721 }
722 }
723 frame += renderSize;
724 remainingBytes -= renderSize;
725 }
726 }
727 } // namespace HosLite
728 } // namespace Plugin
729 } // namespace Media
730 } // namespace OHOS
731