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