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