1 /*
2 * Copyright (c) 2022-2022 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 "AudioServerSinkPlugin"
17
18 #include "audio_server_sink_plugin.h"
19 #include <functional>
20 #include "audio_errors.h"
21 #include "foundation/cpp_ext/algorithm_ext.h"
22 #include "foundation/log.h"
23 #include "foundation/osal/thread/scoped_lock.h"
24 #include "foundation/osal/utils/util.h"
25 #include "foundation/utils/constants.h"
26 #include "plugin/common/plugin_attr_desc.h"
27 #include "plugin/common/plugin_time.h"
28
29 namespace {
30 using namespace OHOS::Media::Plugin;
31 constexpr uint32_t DEFAULT_OUTPUT_CHANNELS = 2;
32 constexpr AudioChannelLayout DEFAULT_OUTPUT_CHANNEL_LAYOUT = AudioChannelLayout::STEREO;
33 const std::pair<OHOS::AudioStandard::AudioSamplingRate, uint32_t> g_auSampleRateMap[] = {
34 {OHOS::AudioStandard::SAMPLE_RATE_8000, 8000},
35 {OHOS::AudioStandard::SAMPLE_RATE_11025, 11025},
36 {OHOS::AudioStandard::SAMPLE_RATE_12000, 12000},
37 {OHOS::AudioStandard::SAMPLE_RATE_16000, 16000},
38 {OHOS::AudioStandard::SAMPLE_RATE_22050, 22050},
39 {OHOS::AudioStandard::SAMPLE_RATE_24000, 24000},
40 {OHOS::AudioStandard::SAMPLE_RATE_32000, 32000},
41 {OHOS::AudioStandard::SAMPLE_RATE_44100, 44100},
42 {OHOS::AudioStandard::SAMPLE_RATE_48000, 48000},
43 {OHOS::AudioStandard::SAMPLE_RATE_64000, 64000},
44 {OHOS::AudioStandard::SAMPLE_RATE_96000, 96000},
45 };
46
47 const std::pair<AudioInterruptMode, OHOS::AudioStandard::InterruptMode> g_auInterruptMap[] = {
48 {AudioInterruptMode::SHARE_MODE, OHOS::AudioStandard::InterruptMode::SHARE_MODE},
49 {AudioInterruptMode::INDEPENDENT_MODE, OHOS::AudioStandard::InterruptMode::INDEPENDENT_MODE},
50 };
51
52 const std::vector<std::tuple<AudioSampleFormat, OHOS::AudioStandard::AudioSampleFormat, AVSampleFormat>> g_aduFmtMap = {
53 {AudioSampleFormat::S8, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
54 {AudioSampleFormat::U8, OHOS::AudioStandard::AudioSampleFormat::SAMPLE_U8, AV_SAMPLE_FMT_U8},
55 {AudioSampleFormat::S8P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
56 {AudioSampleFormat::U8P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_U8P},
57 {AudioSampleFormat::S16, OHOS::AudioStandard::AudioSampleFormat::SAMPLE_S16LE, AV_SAMPLE_FMT_S16},
58 {AudioSampleFormat::U16, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
59 {AudioSampleFormat::S16P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_S16P},
60 {AudioSampleFormat::U16P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
61 {AudioSampleFormat::S24, OHOS::AudioStandard::AudioSampleFormat::SAMPLE_S24LE, AV_SAMPLE_FMT_NONE},
62 {AudioSampleFormat::U24, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
63 {AudioSampleFormat::S24P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
64 {AudioSampleFormat::U24P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
65 {AudioSampleFormat::S32, OHOS::AudioStandard::AudioSampleFormat::SAMPLE_S32LE, AV_SAMPLE_FMT_S32},
66 {AudioSampleFormat::U32, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
67 {AudioSampleFormat::S32P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_S32P},
68 {AudioSampleFormat::U32P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
69 {AudioSampleFormat::F32, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_FLT},
70 {AudioSampleFormat::F32P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_FLTP},
71 {AudioSampleFormat::F64, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_DBL},
72 {AudioSampleFormat::F64P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_DBLP},
73 {AudioSampleFormat::S64, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_S64},
74 {AudioSampleFormat::U64, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
75 {AudioSampleFormat::S64P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_S64P},
76 {AudioSampleFormat::U64P, OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH, AV_SAMPLE_FMT_NONE},
77 };
78
79 const std::pair<OHOS::AudioStandard::AudioChannel, uint32_t> g_auChannelsMap[] = {
80 {OHOS::AudioStandard::MONO, 1},
81 {OHOS::AudioStandard::STEREO, 2},
82 };
83
SampleRateEnum2Num(OHOS::AudioStandard::AudioSamplingRate enumVal,uint32_t & numVal)84 bool SampleRateEnum2Num (OHOS::AudioStandard::AudioSamplingRate enumVal, uint32_t& numVal)
85 {
86 for (const auto& item : g_auSampleRateMap) {
87 if (item.first == enumVal) {
88 numVal = item.second;
89 return true;
90 }
91 }
92 numVal = 0;
93 return false;
94 }
95
SampleRateNum2Enum(uint32_t numVal,OHOS::AudioStandard::AudioSamplingRate & enumVal)96 bool SampleRateNum2Enum (uint32_t numVal, OHOS::AudioStandard::AudioSamplingRate& enumVal)
97 {
98 for (const auto& item : g_auSampleRateMap) {
99 if (item.second == numVal) {
100 enumVal = item.first;
101 return true;
102 }
103 }
104 return false;
105 }
106
ChannelNumNum2Enum(uint32_t numVal,OHOS::AudioStandard::AudioChannel & enumVal)107 bool ChannelNumNum2Enum(uint32_t numVal, OHOS::AudioStandard::AudioChannel& enumVal)
108 {
109 for (const auto& item : g_auChannelsMap) {
110 if (item.second == numVal) {
111 enumVal = item.first;
112 return true;
113 }
114 }
115 return false;
116 }
117
AudioInterruptMode2InterruptMode(AudioInterruptMode audioInterruptMode,OHOS::AudioStandard::InterruptMode & interruptMode)118 void AudioInterruptMode2InterruptMode(AudioInterruptMode audioInterruptMode,
119 OHOS::AudioStandard::InterruptMode& interruptMode)
120 {
121 for (const auto& item : g_auInterruptMap) {
122 if (item.first == audioInterruptMode) {
123 interruptMode = item.second;
124 }
125 }
126 }
127
AudioServerSinkPluginCreater(const std::string & name)128 std::shared_ptr<AudioSinkPlugin> AudioServerSinkPluginCreater(const std::string& name)
129 {
130 return std::make_shared<OHOS::Media::Plugin::AuSrSinkPlugin::AudioServerSinkPlugin>(name);
131 }
132
UpdateSupportedSampleRate(Capability & inCaps)133 void UpdateSupportedSampleRate(Capability& inCaps)
134 {
135 auto supportedSampleRateList = OHOS::AudioStandard::AudioRenderer::GetSupportedSamplingRates();
136 if (!supportedSampleRateList.empty()) {
137 DiscreteCapability<uint32_t> values;
138 for (const auto& rate : supportedSampleRateList) {
139 uint32_t sampleRate = 0;
140 if (SampleRateEnum2Num(rate, sampleRate)) {
141 values.push_back(sampleRate);
142 }
143 }
144 if (!values.empty()) {
145 inCaps.AppendDiscreteKeys<uint32_t>(Capability::Key::AUDIO_SAMPLE_RATE, values);
146 }
147 }
148 }
149
UpdateSupportedSampleFormat(Capability & inCaps)150 void UpdateSupportedSampleFormat(Capability& inCaps)
151 {
152 DiscreteCapability<AudioSampleFormat> values(g_aduFmtMap.size());
153 for (const auto& item : g_aduFmtMap) {
154 if (std::get<1>(item) != OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH ||
155 std::get<2>(item) != AV_SAMPLE_FMT_NONE) {
156 values.emplace_back(std::get<0>(item));
157 }
158 }
159 inCaps.AppendDiscreteKeys(Capability::Key::AUDIO_SAMPLE_FORMAT, values);
160 }
161
AudioServerSinkRegister(const std::shared_ptr<Register> & reg)162 Status AudioServerSinkRegister(const std::shared_ptr<Register>& reg)
163 {
164 AudioSinkPluginDef definition;
165 definition.name = "AudioServerSink";
166 definition.description = "Audio sink for audio server of media standard";
167 definition.rank = 100; // 100: max rank
168 definition.creator = AudioServerSinkPluginCreater;
169 Capability inCaps(OHOS::Media::MEDIA_MIME_AUDIO_RAW);
170 UpdateSupportedSampleRate(inCaps);
171 UpdateSupportedSampleFormat(inCaps);
172 definition.inCaps.push_back(inCaps);
173 return reg->AddPlugin(definition);
174 }
175
__anon68ed62490202null176 PLUGIN_DEFINITION(AudioServerSink, LicenseType::APACHE_V2, AudioServerSinkRegister, [] {});
177
ResetAudioRendererParams(OHOS::AudioStandard::AudioRendererParams & param)178 inline void ResetAudioRendererParams(OHOS::AudioStandard::AudioRendererParams& param)
179 {
180 using namespace OHOS::AudioStandard;
181 param.sampleFormat = INVALID_WIDTH;
182 param.sampleRate = SAMPLE_RATE_8000;
183 param.channelCount = MONO;
184 param.encodingType = ENCODING_INVALID;
185 }
186 } // namespace
187
188 namespace OHOS {
189 namespace Media {
190 namespace Plugin {
191 namespace AuSrSinkPlugin {
192 using namespace OHOS::Media::Plugin;
193
194
AudioRendererCallbackImpl(Callback * cb,bool & isPaused)195 AudioServerSinkPlugin::AudioRendererCallbackImpl::AudioRendererCallbackImpl(Callback* cb, bool& isPaused)
196 : callback_(cb), isPaused_(isPaused)
197 {
198 }
199
OnInterrupt(const OHOS::AudioStandard::InterruptEvent & interruptEvent)200 void AudioServerSinkPlugin::AudioRendererCallbackImpl::OnInterrupt(
201 const OHOS::AudioStandard::InterruptEvent& interruptEvent)
202 {
203 if (interruptEvent.forceType == OHOS::AudioStandard::INTERRUPT_FORCE) {
204 switch (interruptEvent.hintType) {
205 case OHOS::AudioStandard::INTERRUPT_HINT_PAUSE:
206 isPaused_ = true;
207 break;
208 default:
209 isPaused_ = false;
210 break;
211 }
212 }
213 callback_->OnEvent(PluginEvent{PluginEventType::AUDIO_INTERRUPT, interruptEvent, "Audio interrupt event"});
214 }
215
OnStateChange(const OHOS::AudioStandard::RendererState state,const OHOS::AudioStandard::StateChangeCmdType cmdType)216 void AudioServerSinkPlugin::AudioRendererCallbackImpl::OnStateChange(const OHOS::AudioStandard::RendererState state,
217 const OHOS::AudioStandard::StateChangeCmdType cmdType)
218 {
219 MEDIA_LOG_D("RenderState is " PUBLIC_LOG_U32, static_cast<uint32_t>(state));
220 if (cmdType == AudioStandard::StateChangeCmdType::CMD_FROM_SYSTEM) {
221 callback_->OnEvent(PluginEvent{PluginEventType::AUDIO_STATE_CHANGE, state});
222 }
223 }
224
AudioServerSinkPlugin(std::string name)225 AudioServerSinkPlugin::AudioServerSinkPlugin(std::string name)
226 : Plugin::AudioSinkPlugin(std::move(name)), audioRenderer_(nullptr)
227 {
228 }
229
~AudioServerSinkPlugin()230 AudioServerSinkPlugin::~AudioServerSinkPlugin()
231 {
232 MEDIA_LOG_I("~AudioServerSinkPlugin() entered.");
233 ReleaseRender();
234 }
235
Init()236 Status AudioServerSinkPlugin::Init()
237 {
238 MEDIA_LOG_I("Init entered.");
239 OSAL::ScopedLock lock(renderMutex_);
240 if (audioRenderer_ == nullptr) {
241 AudioStandard::AppInfo appInfo;
242 appInfo.appPid = appPid_;
243 appInfo.appUid = appUid_;
244 MEDIA_LOG_I("Create audio renderer for apppid_ " PUBLIC_LOG_D32 " appuid_ " PUBLIC_LOG_D32 " contentType "
245 PUBLIC_LOG_D32 " streamUsage " PUBLIC_LOG_D32 " rendererFlags " PUBLIC_LOG_D32 " audioInterruptMode_ "
246 PUBLIC_LOG_U32, appPid_, appUid_, audioRenderInfo_.contentType, audioRenderInfo_.streamUsage,
247 audioRenderInfo_.rendererFlags, static_cast<uint32_t>(audioInterruptMode_));
248 rendererOptions_.rendererInfo.contentType = static_cast<AudioStandard::ContentType>(
249 audioRenderInfo_.contentType);
250 rendererOptions_.rendererInfo.streamUsage = static_cast<AudioStandard::StreamUsage>(
251 audioRenderInfo_.streamUsage);
252 rendererOptions_.rendererInfo.rendererFlags = audioRenderInfo_.rendererFlags;
253 rendererOptions_.streamInfo.samplingRate = AudioStandard::SAMPLE_RATE_8000;
254 rendererOptions_.streamInfo.encoding = AudioStandard::ENCODING_PCM;
255 rendererOptions_.streamInfo.format = AudioStandard::SAMPLE_S16LE;
256 rendererOptions_.streamInfo.channels = AudioStandard::MONO;
257 audioRenderer_ = AudioStandard::AudioRenderer::Create(rendererOptions_, appInfo);
258 if (audioRenderer_ == nullptr) {
259 MEDIA_LOG_E("Create audioRenderer_ fail");
260 return Status::ERROR_UNKNOWN;
261 }
262 audioRenderer_->SetInterruptMode(audioInterruptMode_);
263 if (audioRendererCallback_ == nullptr) {
264 audioRendererCallback_ = std::make_shared<AudioRendererCallbackImpl>(callback_, isForcePaused_);
265 audioRenderer_->SetRendererCallback(audioRendererCallback_);
266 }
267 }
268 return Status::OK;
269 }
270
ReleaseRender()271 void AudioServerSinkPlugin::ReleaseRender()
272 {
273 OSAL::ScopedLock lock(renderMutex_);
274 if (audioRenderer_ != nullptr && audioRenderer_->GetStatus() != AudioStandard::RendererState::RENDERER_RELEASED) {
275 if (!audioRenderer_->Release()) {
276 MEDIA_LOG_W("release audio render failed");
277 return;
278 }
279 }
280 audioRenderer_.reset();
281 }
282
Deinit()283 Status AudioServerSinkPlugin::Deinit()
284 {
285 MEDIA_LOG_I("Deinit entered.");
286 ReleaseRender();
287 return Status::OK;
288 }
289
Prepare()290 Status AudioServerSinkPlugin::Prepare()
291 {
292 MEDIA_LOG_I("Prepare entered.");
293 FALSE_RETURN_V_MSG_E(fmtSupported_, Status::ERROR_INVALID_PARAMETER, "sample fmt is not supported");
294 if (bitsPerSample_ == 8 || bitsPerSample_ == 24) { // 8 24
295 needReformat_ = true;
296 rendererParams_.sampleFormat = reStdDestFmt_;
297 }
298 auto types = AudioStandard::AudioRenderer::GetSupportedEncodingTypes();
299 if (!CppExt::AnyOf(types.begin(), types.end(), [](AudioStandard::AudioEncodingType tmp) -> bool {
300 return tmp == AudioStandard::ENCODING_PCM;
301 })) {
302 MEDIA_LOG_E("audio renderer do not support pcm encoding");
303 return Status::ERROR_INVALID_PARAMETER;
304 }
305 rendererParams_.encodingType = AudioStandard::ENCODING_PCM;
306 MEDIA_LOG_I("set param with fmt " PUBLIC_LOG_D32 " sampleRate " PUBLIC_LOG_D32 " channel " PUBLIC_LOG_D32
307 " encode type " PUBLIC_LOG_D32,
308 rendererParams_.sampleFormat, rendererParams_.sampleRate, rendererParams_.channelCount,
309 rendererParams_.encodingType);
310 {
311 OSAL::ScopedLock lock(renderMutex_);
312 auto ret = audioRenderer_->SetParams(rendererParams_);
313 if (ret != AudioStandard::SUCCESS) {
314 MEDIA_LOG_E("audio renderer SetParams() fail with " PUBLIC_LOG_D32, ret);
315 return Status::ERROR_UNKNOWN;
316 }
317 }
318 if (needReformat_) {
319 resample_ = std::make_shared<Ffmpeg::Resample>();
320 Ffmpeg::ResamplePara resamplePara {
321 channels_,
322 sampleRate_,
323 bitsPerSample_,
324 static_cast<int64_t>(channelLayout_),
325 reSrcFfFmt_,
326 samplesPerFrame_,
327 reFfDestFmt_,
328 };
329 FALSE_RETURN_V_MSG(resample_->Init(resamplePara) == Status::OK, Status::ERROR_UNKNOWN, "Resample init error");
330 }
331 return Status::OK;
332 }
333
StopRender()334 bool AudioServerSinkPlugin::StopRender()
335 {
336 OSAL::ScopedLock lock(renderMutex_);
337 if (audioRenderer_) {
338 if (audioRenderer_->GetStatus() == AudioStandard::RendererState::RENDERER_STOPPED) {
339 MEDIA_LOG_I("AudioRenderer is already in stopped state.");
340 return true;
341 }
342 return audioRenderer_->Stop();
343 }
344 return true;
345 }
346
Reset()347 Status AudioServerSinkPlugin::Reset()
348 {
349 MEDIA_LOG_I("Reset entered.");
350 if (!StopRender()) {
351 MEDIA_LOG_E("stop render error");
352 return Status::ERROR_UNKNOWN;
353 }
354 ResetAudioRendererParams(rendererParams_);
355 fmtSupported_ = false;
356 reSrcFfFmt_ = AV_SAMPLE_FMT_NONE;
357 channels_ = 0;
358 bitRate_ = 0;
359 sampleRate_ = 0;
360 samplesPerFrame_ = 0;
361 needReformat_ = false;
362 if (resample_) {
363 resample_.reset();
364 }
365 return Status::OK;
366 }
367
Start()368 Status AudioServerSinkPlugin::Start()
369 {
370 MEDIA_LOG_I("Start entered.");
371 bool ret = false;
372 OSAL::ScopedLock lock(renderMutex_);
373 {
374 if (audioRenderer_ == nullptr) {
375 return Status::ERROR_WRONG_STATE;
376 }
377 ret = audioRenderer_->Start();
378 }
379 if (ret) {
380 MEDIA_LOG_I("audioRenderer_ Start() success");
381 return Status::OK;
382 } else {
383 MEDIA_LOG_E("audioRenderer_ Start() fail");
384 }
385 return Status::ERROR_UNKNOWN;
386 }
387
Stop()388 Status AudioServerSinkPlugin::Stop()
389 {
390 MEDIA_LOG_I("Stop entered.");
391 if (StopRender()) {
392 MEDIA_LOG_I("stop render success");
393 return Status::OK;
394 } else {
395 MEDIA_LOG_E("stop render failed");
396 }
397 return Status::ERROR_UNKNOWN;
398 }
399
GetParameter(Tag tag,ValueType & para)400 Status AudioServerSinkPlugin::GetParameter(Tag tag, ValueType& para)
401 {
402 MEDIA_LOG_I("GetParameter entered, key: " PUBLIC_LOG_S, Tag2String(tag));
403 AudioStandard::AudioRendererParams params;
404 OSAL::ScopedLock lock(renderMutex_);
405 switch (tag) {
406 case Tag::AUDIO_SAMPLE_RATE:
407 if (audioRenderer_ && audioRenderer_->GetParams(params) == AudioStandard::SUCCESS) {
408 if (params.sampleRate != rendererParams_.sampleRate) {
409 MEDIA_LOG_W("samplingRate has changed from " PUBLIC_LOG_U32 " to " PUBLIC_LOG_U32,
410 rendererParams_.sampleRate, params.sampleRate);
411 }
412 para = params.sampleRate;
413 }
414 break;
415 case Tag::AUDIO_OUTPUT_CHANNELS:
416 para = DEFAULT_OUTPUT_CHANNELS; // get the real output channels from audio server here
417 MEDIA_LOG_I("Get outputChannels: " PUBLIC_LOG_U32, DEFAULT_OUTPUT_CHANNELS);
418 break;
419 case Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT:
420 para = DEFAULT_OUTPUT_CHANNEL_LAYOUT; // get the real output channel layout from audio server here
421 MEDIA_LOG_I("Get outputChannelLayout: " PUBLIC_LOG_U64, DEFAULT_OUTPUT_CHANNEL_LAYOUT);
422 break;
423 case Tag::MEDIA_BITRATE:
424 para = bitRate_;
425 break;
426 case Tag::AUDIO_SAMPLE_FORMAT:
427 if (audioRenderer_ && audioRenderer_->GetParams(params) == AudioStandard::SUCCESS) {
428 if (params.sampleFormat != rendererParams_.sampleFormat) {
429 MEDIA_LOG_W("sampleFormat has changed from " PUBLIC_LOG_U32 " to " PUBLIC_LOG_U32,
430 rendererParams_.sampleFormat, params.sampleFormat);
431 }
432 para = params.sampleFormat;
433 }
434 break;
435 default:
436 MEDIA_LOG_I("Unknown key");
437 break;
438 }
439 return Status::OK;
440 }
441
AssignSampleRateIfSupported(uint32_t sampleRate)442 bool AudioServerSinkPlugin::AssignSampleRateIfSupported(uint32_t sampleRate)
443 {
444 sampleRate_ = sampleRate;
445 AudioStandard::AudioSamplingRate aRate = AudioStandard::SAMPLE_RATE_8000;
446 if (!SampleRateNum2Enum(sampleRate, aRate)) {
447 MEDIA_LOG_E("sample rate " PUBLIC_LOG_U32 "not supported", sampleRate);
448 return false;
449 }
450 auto supportedSampleRateList = OHOS::AudioStandard::AudioRenderer::GetSupportedSamplingRates();
451 if (supportedSampleRateList.empty()) {
452 MEDIA_LOG_E("GetSupportedSamplingRates() fail");
453 return false;
454 }
455 for (const auto& rate : supportedSampleRateList) {
456 if (rate == aRate) {
457 rendererParams_.sampleRate = rate;
458 MEDIA_LOG_D("sampleRate: " PUBLIC_LOG_U32, rendererParams_.sampleRate);
459 return true;
460 }
461 }
462 return false;
463 }
464
AssignChannelNumIfSupported(uint32_t channelNum)465 bool AudioServerSinkPlugin::AssignChannelNumIfSupported(uint32_t channelNum)
466 {
467 AudioStandard::AudioChannel aChannel = AudioStandard::MONO;
468 if (!ChannelNumNum2Enum(channelNum, aChannel)) {
469 MEDIA_LOG_E("channel num " PUBLIC_LOG_U32 "not supported", channelNum);
470 return false;
471 }
472 auto supportedChannelsList = OHOS::AudioStandard::AudioRenderer::GetSupportedChannels();
473 if (supportedChannelsList.empty()) {
474 MEDIA_LOG_E("GetSupportedChannels() fail");
475 return false;
476 }
477 for (const auto& channel : supportedChannelsList) {
478 if (channel == aChannel) {
479 rendererParams_.channelCount = channel;
480 MEDIA_LOG_D("channelCount: " PUBLIC_LOG_U32, rendererParams_.channelCount);
481 return true;
482 }
483 }
484 return false;
485 }
486
AssignSampleFmtIfSupported(Plugin::AudioSampleFormat sampleFormat)487 bool AudioServerSinkPlugin::AssignSampleFmtIfSupported(Plugin::AudioSampleFormat sampleFormat)
488 {
489 const auto& item = std::find_if(g_aduFmtMap.begin(), g_aduFmtMap.end(), [&sampleFormat] (const auto& tmp) -> bool {
490 return std::get<0>(tmp) == sampleFormat;
491 });
492 auto stdFmt = std::get<1>(*item);
493 if (stdFmt == OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH) {
494 if (std::get<2>(*item) == AV_SAMPLE_FMT_NONE) { // 2
495 fmtSupported_ = false;
496 } else {
497 fmtSupported_ = true;
498 needReformat_ = true;
499 reSrcFfFmt_ = std::get<2>(*item); // 2
500 rendererParams_.sampleFormat = reStdDestFmt_;
501 }
502 } else {
503 auto supportedFmts = OHOS::AudioStandard::AudioRenderer::GetSupportedFormats();
504 if (CppExt::AnyOf(supportedFmts.begin(), supportedFmts.end(), [&stdFmt](const auto& tmp) -> bool {
505 return tmp == stdFmt;
506 })) {
507 fmtSupported_ = true;
508 needReformat_ = false;
509 rendererParams_.sampleFormat = stdFmt;
510 } else {
511 fmtSupported_ = false;
512 needReformat_ = false;
513 }
514 }
515 return fmtSupported_;
516 }
517
SetInterruptMode(AudioStandard::InterruptMode interruptMode)518 void AudioServerSinkPlugin::SetInterruptMode(AudioStandard::InterruptMode interruptMode)
519 {
520 OSAL::ScopedLock lock(renderMutex_);
521 if (audioRenderer_) {
522 audioRenderer_->SetInterruptMode(interruptMode);
523 }
524 }
525
SetParameter(Tag tag,const ValueType & para)526 Status AudioServerSinkPlugin::SetParameter(Tag tag, const ValueType& para)
527 {
528 MEDIA_LOG_I("SetParameter entered, key: " PUBLIC_LOG_S, Tag2String(tag));
529 switch (tag) {
530 case Tag::AUDIO_SAMPLE_RATE:
531 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
532 "sample rate type should be uint32_t");
533 FALSE_RETURN_V_MSG_E(AssignSampleRateIfSupported(Plugin::AnyCast<uint32_t>(para)),
534 Status::ERROR_INVALID_PARAMETER, "sampleRate isn't supported");
535 break;
536 case Tag::AUDIO_OUTPUT_CHANNELS:
537 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
538 "channels type should be uint32_t");
539 channels_ = Plugin::AnyCast<uint32_t>(para);
540 MEDIA_LOG_I("Set outputChannels: " PUBLIC_LOG_U32, channels_);
541 FALSE_RETURN_V_MSG_E(AssignChannelNumIfSupported(channels_), Status::ERROR_INVALID_PARAMETER,
542 "channel isn't supported");
543 break;
544 case Tag::MEDIA_BITRATE:
545 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(int64_t)), Status::ERROR_MISMATCHED_TYPE,
546 "bit rate type should be int64_t");
547 bitRate_ = Plugin::AnyCast<int64_t>(para);
548 break;
549 case Tag::AUDIO_SAMPLE_FORMAT:
550 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioSampleFormat)), Status::ERROR_MISMATCHED_TYPE,
551 "AudioSampleFormat type should be AudioSampleFormat");
552 FALSE_RETURN_V_MSG_E(AssignSampleFmtIfSupported(Plugin::AnyCast<AudioSampleFormat>(para)),
553 Status::ERROR_INVALID_PARAMETER, "sampleFmt isn't supported by audio renderer or resample lib");
554 break;
555 case Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT:
556 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioChannelLayout)), Status::ERROR_MISMATCHED_TYPE,
557 "channel layout type should be AudioChannelLayout");
558 channelLayout_ = Plugin::AnyCast<AudioChannelLayout>(para);
559 MEDIA_LOG_I("Set outputChannelLayout: " PUBLIC_LOG_U64, channelLayout_);
560 break;
561 case Tag::AUDIO_SAMPLE_PER_FRAME:
562 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
563 "SAMPLE_PER_FRAME type should be uint32_t");
564 samplesPerFrame_ = Plugin::AnyCast<uint32_t>(para);
565 break;
566 case Tag::BITS_PER_CODED_SAMPLE:
567 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
568 "BITS_PER_CODED_SAMPLE type should be uint32_t");
569 bitsPerSample_ = Plugin::AnyCast<uint32_t>(para);
570 break;
571 case Tag::MEDIA_SEEKABLE:
572 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(Seekable)), Status::ERROR_MISMATCHED_TYPE,
573 "MEDIA_SEEKABLE type should be Seekable");
574 seekable_ = Plugin::AnyCast<Plugin::Seekable>(para);
575 break;
576 case Tag::APP_PID:
577 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(int32_t)), Status::ERROR_MISMATCHED_TYPE,
578 "APP_PID type should be int32_t");
579 appPid_ = Plugin::AnyCast<int32_t>(para);
580 break;
581 case Tag::APP_UID:
582 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(int32_t)), Status::ERROR_MISMATCHED_TYPE,
583 "APP_UID type should be int32_t");
584 appUid_ = Plugin::AnyCast<int32_t>(para);
585 break;
586 case Tag::AUDIO_RENDER_INFO:
587 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioRenderInfo)), Status::ERROR_MISMATCHED_TYPE,
588 "AUDIO_RENDER_INFO type should be AudioRenderInfo");
589 audioRenderInfo_ = Plugin::AnyCast<AudioRenderInfo>(para);
590 break;
591 case Tag::AUDIO_INTERRUPT_MODE:
592 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioInterruptMode)), Status::ERROR_MISMATCHED_TYPE,
593 "AUDIO_INTERRUPT_MODE type should be AudioInterruptMode");
594 AudioInterruptMode2InterruptMode(Plugin::AnyCast<AudioInterruptMode>(para), audioInterruptMode_);
595 SetInterruptMode(audioInterruptMode_);
596 break;
597 default:
598 MEDIA_LOG_I("Unknown key");
599 break;
600 }
601 return Status::OK;
602 }
603
GetVolume(float & volume)604 Status AudioServerSinkPlugin::GetVolume(float& volume)
605 {
606 MEDIA_LOG_I("GetVolume entered.");
607 OSAL::ScopedLock lock(renderMutex_);
608 if (audioRenderer_ != nullptr) {
609 volume = audioRenderer_->GetVolume();
610 return Status::OK;
611 }
612 return Status::ERROR_WRONG_STATE;
613 }
614
SetVolume(float volume)615 Status AudioServerSinkPlugin::SetVolume(float volume)
616 {
617 MEDIA_LOG_I("SetVolume entered.");
618 OSAL::ScopedLock lock(renderMutex_);
619 if (audioRenderer_ != nullptr) {
620 int32_t ret = audioRenderer_->SetVolume(volume);
621 if (ret != OHOS::AudioStandard::SUCCESS) {
622 MEDIA_LOG_E("set volume failed with code " PUBLIC_LOG_D32, ret);
623 return Status::ERROR_UNKNOWN;
624 }
625 return Status::OK;
626 }
627 return Status::ERROR_WRONG_STATE;
628 }
629
Resume()630 Status AudioServerSinkPlugin::Resume()
631 {
632 MEDIA_LOG_I("Resume entered.");
633 return Start();
634 }
635
Pause()636 Status AudioServerSinkPlugin::Pause()
637 {
638 MEDIA_LOG_I("Pause entered.");
639 OSAL::ScopedLock lock(renderMutex_);
640 if (audioRenderer_ && audioRenderer_->GetStatus() == OHOS::AudioStandard::RENDERER_RUNNING
641 && !audioRenderer_->Pause()) {
642 MEDIA_LOG_E("audio renderer pause fail");
643 return Status::ERROR_UNKNOWN;
644 }
645 MEDIA_LOG_I("audio renderer pause success");
646 return Status::OK;
647 }
648
GetLatency(uint64_t & hstTime)649 Status AudioServerSinkPlugin::GetLatency(uint64_t& hstTime)
650 {
651 hstTime = 0; // set latency as 0 since latency of audio system is not reliable
652 return Status::OK;
653 }
654
Write(const std::shared_ptr<Buffer> & input)655 Status AudioServerSinkPlugin::Write(const std::shared_ptr<Buffer>& input)
656 {
657 FALSE_RETURN_V_MSG_W(input != nullptr && !input->IsEmpty(), Status::OK, "Receive empty buffer."); // return ok
658 auto mem = input->GetMemory();
659 auto srcBuffer = mem->GetReadOnlyData();
660 auto destBuffer = const_cast<uint8_t*>(srcBuffer);
661 auto srcLength = mem->GetSize();
662 auto destLength = srcLength;
663 if (needReformat_ && resample_ && srcLength >0) {
664 FALSE_LOG(resample_->Convert(srcBuffer, srcLength, destBuffer, destLength) == Status::OK);
665 }
666 MEDIA_LOG_DD("write data size " PUBLIC_LOG_ZU, destLength);
667 while (isForcePaused_ && seekable_ == Seekable::SEEKABLE) {
668 OSAL::SleepFor(5); // 5ms
669 continue;
670 }
671 int32_t ret = 0;
672 OSAL::ScopedLock lock(renderMutex_);
673 FALSE_RETURN_V(audioRenderer_ != nullptr, Status::ERROR_WRONG_STATE);
674 for (; destLength > 0;) {
675 ret = audioRenderer_->Write(destBuffer, destLength);
676 if (ret < 0) {
677 MEDIA_LOG_E("Write data error ret is: " PUBLIC_LOG_D32, ret);
678 break;
679 } else if (static_cast<size_t>(ret) < destLength) {
680 OSAL::SleepFor(5); // 5ms
681 }
682 destBuffer += ret;
683 destLength -= ret;
684 MEDIA_LOG_DD("written data size " PUBLIC_LOG_D32, ret);
685 }
686 return ret >= 0 ? Status::OK : Status::ERROR_UNKNOWN;
687 }
688
Flush()689 Status AudioServerSinkPlugin::Flush()
690 {
691 MEDIA_LOG_I("Flush entered.");
692 OSAL::ScopedLock lock(renderMutex_);
693 if (audioRenderer_ == nullptr) {
694 return Status::ERROR_WRONG_STATE;
695 }
696 if (audioRenderer_->Flush()) {
697 MEDIA_LOG_I("audioRenderer_ Flush() success");
698 return Status::OK;
699 }
700 MEDIA_LOG_E("audioRenderer_ Flush() fail");
701 return Status::ERROR_UNKNOWN;
702 }
703
Drain()704 Status AudioServerSinkPlugin::Drain()
705 {
706 MEDIA_LOG_I("Drain entered.");
707 OSAL::ScopedLock lock(renderMutex_);
708 if (audioRenderer_ == nullptr) {
709 return Status::ERROR_WRONG_STATE;
710 }
711 if (!audioRenderer_->Drain()) {
712 uint64_t latency = 0;
713 audioRenderer_->GetLatency(latency);
714 latency /= 1000; // 1000 cast into ms
715 if (latency > 50) { // 50 latency too large
716 MEDIA_LOG_W("Drain failed and latency is too large, will sleep " PUBLIC_LOG_U64 " ms, aka. latency.",
717 latency);
718 OSAL::SleepFor(latency);
719 }
720 }
721 MEDIA_LOG_I("audioRenderer_ Drain() success");
722 return Status::OK;
723 }
724 } // namespace AuSrSinkPlugin
725 } // Plugin
726 } // namespace Media
727 } // namespace OHOS
728