• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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