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 "plugin/common/plugin_time.h"
26 #include "utils/constants.h"
27 #include "pipeline/core/plugin_attr_desc.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
__anon33df6dab0202null176 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 auto audioInterruptEvent = AudioInterruptEvent {
214 static_cast<uint32_t>(interruptEvent.eventType),
215 static_cast<uint32_t>(interruptEvent.forceType),
216 static_cast<uint32_t>(interruptEvent.hintType)
217 };
218 callback_->OnEvent(PluginEvent{PluginEventType::INTERRUPT, audioInterruptEvent, "Audio interrupt event"});
219 }
220
OnStateChange(const OHOS::AudioStandard::RendererState state,const AudioStandard::StateChangeCmdType cmdType)221 void AudioServerSinkPlugin::AudioRendererCallbackImpl::OnStateChange(const OHOS::AudioStandard::RendererState state,
222 const AudioStandard::StateChangeCmdType __attribute__((unused)) cmdType)
223 {
224 MEDIA_LOG_D("RenderState is " PUBLIC_LOG_U32, static_cast<uint32_t>(state));
225 }
226
AudioServerSinkPlugin(std::string name)227 AudioServerSinkPlugin::AudioServerSinkPlugin(std::string name)
228 : Plugin::AudioSinkPlugin(std::move(name)), audioRenderer_(nullptr)
229 {
230 rendererParams_.encodingType = AudioStandard::ENCODING_PCM;
231 }
232
~AudioServerSinkPlugin()233 AudioServerSinkPlugin::~AudioServerSinkPlugin()
234 {
235 MEDIA_LOG_I("~AudioServerSinkPlugin() entered.");
236 ReleaseRender();
237 }
238
Init()239 Status AudioServerSinkPlugin::Init()
240 {
241 MEDIA_LOG_I("Init entered.");
242 OSAL::ScopedLock lock(renderMutex_);
243 if (audioRenderer_ == nullptr) {
244 AudioStandard::AppInfo appInfo;
245 appInfo.appPid = appPid_;
246 appInfo.appUid = appUid_;
247 MEDIA_LOG_I("Create audio renderer for apppid_ " PUBLIC_LOG_D32 " appuid_ " PUBLIC_LOG_D32 " contentType "
248 PUBLIC_LOG_D32 " streamUsage " PUBLIC_LOG_D32 " rendererFlags " PUBLIC_LOG_D32 " audioInterruptMode_ "
249 PUBLIC_LOG_U32, appPid_, appUid_, audioRenderInfo_.contentType, audioRenderInfo_.streamUsage,
250 audioRenderInfo_.rendererFlags, static_cast<uint32_t>(audioInterruptMode_));
251 rendererOptions_.rendererInfo.contentType = static_cast<AudioStandard::ContentType>(
252 audioRenderInfo_.contentType);
253 rendererOptions_.rendererInfo.streamUsage = static_cast<AudioStandard::StreamUsage>(
254 audioRenderInfo_.streamUsage);
255 rendererOptions_.rendererInfo.rendererFlags = audioRenderInfo_.rendererFlags;
256 rendererOptions_.streamInfo.samplingRate = AudioStandard::SAMPLE_RATE_8000;
257 rendererOptions_.streamInfo.encoding = AudioStandard::ENCODING_PCM;
258 rendererOptions_.streamInfo.format = AudioStandard::SAMPLE_S16LE;
259 rendererOptions_.streamInfo.channels = AudioStandard::MONO;
260 audioRenderer_ = AudioStandard::AudioRenderer::Create(rendererOptions_, appInfo);
261 if (audioRenderer_ == nullptr) {
262 MEDIA_LOG_E("Create audioRenderer_ fail");
263 return Status::ERROR_UNKNOWN;
264 }
265 audioRenderer_->SetInterruptMode(audioInterruptMode_);
266 if (audioRendererCallback_ == nullptr) {
267 audioRendererCallback_ = std::make_shared<AudioRendererCallbackImpl>(callback_, isForcePaused_);
268 audioRenderer_->SetRendererCallback(audioRendererCallback_);
269 }
270 }
271 return Status::OK;
272 }
273
ReleaseRender()274 void AudioServerSinkPlugin::ReleaseRender()
275 {
276 OSAL::ScopedLock lock(renderMutex_);
277 if (audioRenderer_ != nullptr && audioRenderer_->GetStatus() != AudioStandard::RendererState::RENDERER_RELEASED) {
278 if (!audioRenderer_->Release()) {
279 MEDIA_LOG_W("release audio render failed");
280 return;
281 }
282 }
283 audioRenderer_.reset();
284 }
285
Deinit()286 Status AudioServerSinkPlugin::Deinit()
287 {
288 MEDIA_LOG_I("Deinit entered.");
289 ReleaseRender();
290 return Status::OK;
291 }
292
Prepare()293 Status AudioServerSinkPlugin::Prepare()
294 {
295 MEDIA_LOG_I("Prepare entered.");
296 FALSE_RETURN_V_MSG_E(fmtSupported_, Status::ERROR_INVALID_PARAMETER, "sample fmt is not supported");
297 if (bitsPerSample_ == 8 || bitsPerSample_ == 24) { // 8 24
298 needReformat_ = true;
299 rendererParams_.sampleFormat = reStdDestFmt_;
300 }
301 auto types = AudioStandard::AudioRenderer::GetSupportedEncodingTypes();
302 if (!CppExt::AnyOf(types.begin(), types.end(), [](AudioStandard::AudioEncodingType tmp) -> bool {
303 return tmp == AudioStandard::ENCODING_PCM;
304 })) {
305 MEDIA_LOG_E("audio renderer do not support pcm encoding");
306 return Status::ERROR_INVALID_PARAMETER;
307 }
308 MEDIA_LOG_I("set param with fmt " PUBLIC_LOG_D32 " sampleRate " PUBLIC_LOG_D32 " channel " PUBLIC_LOG_D32
309 " encode type " PUBLIC_LOG_D32,
310 rendererParams_.sampleFormat, rendererParams_.sampleRate, rendererParams_.channelCount,
311 rendererParams_.encodingType);
312 {
313 OSAL::ScopedLock lock(renderMutex_);
314 auto ret = audioRenderer_->SetParams(rendererParams_);
315 if (ret != AudioStandard::SUCCESS) {
316 MEDIA_LOG_E("audio renderer SetParams() fail with " PUBLIC_LOG_D32, ret);
317 return Status::ERROR_UNKNOWN;
318 }
319 }
320 if (needReformat_) {
321 resample_ = std::make_shared<Ffmpeg::Resample>();
322 Ffmpeg::ResamplePara resamplePara {
323 channels_,
324 sampleRate_,
325 bitsPerSample_,
326 static_cast<int64_t>(channelLayout_),
327 reSrcFfFmt_,
328 samplesPerFrame_,
329 reFfDestFmt_,
330 };
331 FALSE_RETURN_V_MSG(resample_->Init(resamplePara) == Status::OK, Status::ERROR_UNKNOWN, "Resample init error");
332 }
333 return Status::OK;
334 }
335
StopRender()336 bool AudioServerSinkPlugin::StopRender()
337 {
338 OSAL::ScopedLock lock(renderMutex_);
339 if (audioRenderer_) {
340 return audioRenderer_->Stop();
341 }
342 return true;
343 }
344
Reset()345 Status AudioServerSinkPlugin::Reset()
346 {
347 MEDIA_LOG_I("Reset entered.");
348 if (!StopRender()) {
349 MEDIA_LOG_E("stop render error");
350 return Status::ERROR_UNKNOWN;
351 }
352 ResetAudioRendererParams(rendererParams_);
353 fmtSupported_ = false;
354 reSrcFfFmt_ = AV_SAMPLE_FMT_NONE;
355 channels_ = 0;
356 bitRate_ = 0;
357 sampleRate_ = 0;
358 samplesPerFrame_ = 0;
359 needReformat_ = false;
360 if (resample_) {
361 resample_.reset();
362 }
363 return Status::OK;
364 }
365
Start()366 Status AudioServerSinkPlugin::Start()
367 {
368 MEDIA_LOG_I("Start entered.");
369 bool ret = false;
370 OSAL::ScopedLock lock(renderMutex_);
371 {
372 if (audioRenderer_ == nullptr) {
373 return Status::ERROR_WRONG_STATE;
374 }
375 ret = audioRenderer_->Start();
376 }
377 if (ret) {
378 MEDIA_LOG_I("audioRenderer_ Start() success");
379 return Status::OK;
380 } else {
381 MEDIA_LOG_E("audioRenderer_ Start() fail");
382 }
383 return Status::ERROR_UNKNOWN;
384 }
385
Stop()386 Status AudioServerSinkPlugin::Stop()
387 {
388 MEDIA_LOG_I("Stop entered.");
389 if (StopRender()) {
390 MEDIA_LOG_I("stop render success");
391 return Status::OK;
392 } else {
393 MEDIA_LOG_E("stop render failed");
394 }
395 return Status::ERROR_UNKNOWN;
396 }
397
GetParameter(Tag tag,ValueType & para)398 Status AudioServerSinkPlugin::GetParameter(Tag tag, ValueType& para)
399 {
400 MEDIA_LOG_I("GetParameter entered, key: " PUBLIC_LOG_S, Pipeline::Tag2String(tag));
401 AudioStandard::AudioRendererParams params;
402 OSAL::ScopedLock lock(renderMutex_);
403 switch (tag) {
404 case Tag::AUDIO_SAMPLE_RATE:
405 if (audioRenderer_ && audioRenderer_->GetParams(params) == AudioStandard::SUCCESS) {
406 if (params.sampleRate != rendererParams_.sampleRate) {
407 MEDIA_LOG_W("samplingRate has changed from " PUBLIC_LOG_U32 " to " PUBLIC_LOG_U32,
408 rendererParams_.sampleRate, params.sampleRate);
409 }
410 para = params.sampleRate;
411 }
412 break;
413 case Tag::AUDIO_OUTPUT_CHANNELS:
414 para = DEFAULT_OUTPUT_CHANNELS; // get the real output channels from audio server here
415 MEDIA_LOG_I("Get outputChannels: " PUBLIC_LOG_U32, DEFAULT_OUTPUT_CHANNELS);
416 break;
417 case Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT:
418 para = DEFAULT_OUTPUT_CHANNEL_LAYOUT; // get the real output channel layout from audio server here
419 MEDIA_LOG_I("Get outputChannelLayout: " PUBLIC_LOG_U64, DEFAULT_OUTPUT_CHANNEL_LAYOUT);
420 break;
421 case Tag::MEDIA_BITRATE:
422 para = bitRate_;
423 break;
424 case Tag::AUDIO_SAMPLE_FORMAT:
425 if (audioRenderer_ && audioRenderer_->GetParams(params) == AudioStandard::SUCCESS) {
426 if (params.sampleFormat != rendererParams_.sampleFormat) {
427 MEDIA_LOG_W("sampleFormat has changed from " PUBLIC_LOG_U32 " to " PUBLIC_LOG_U32,
428 rendererParams_.sampleFormat, params.sampleFormat);
429 }
430 para = params.sampleFormat;
431 }
432 break;
433 default:
434 MEDIA_LOG_I("Unknown key");
435 break;
436 }
437 return Status::OK;
438 }
439
AssignSampleRateIfSupported(uint32_t sampleRate)440 bool AudioServerSinkPlugin::AssignSampleRateIfSupported(uint32_t sampleRate)
441 {
442 sampleRate_ = sampleRate;
443 AudioStandard::AudioSamplingRate aRate = AudioStandard::SAMPLE_RATE_8000;
444 if (!SampleRateNum2Enum(sampleRate, aRate)) {
445 MEDIA_LOG_E("sample rate " PUBLIC_LOG_U32 "not supported", sampleRate);
446 return false;
447 }
448 auto supportedSampleRateList = OHOS::AudioStandard::AudioRenderer::GetSupportedSamplingRates();
449 if (supportedSampleRateList.empty()) {
450 MEDIA_LOG_E("GetSupportedSamplingRates() fail");
451 return false;
452 }
453 for (const auto& rate : supportedSampleRateList) {
454 if (rate == aRate) {
455 rendererParams_.sampleRate = rate;
456 MEDIA_LOG_D("sampleRate: " PUBLIC_LOG_U32, rendererParams_.sampleRate);
457 return true;
458 }
459 }
460 return false;
461 }
462
AssignChannelNumIfSupported(uint32_t channelNum)463 bool AudioServerSinkPlugin::AssignChannelNumIfSupported(uint32_t channelNum)
464 {
465 AudioStandard::AudioChannel aChannel = AudioStandard::MONO;
466 if (!ChannelNumNum2Enum(channelNum, aChannel)) {
467 MEDIA_LOG_E("channel num " PUBLIC_LOG_U32 "not supported", channelNum);
468 return false;
469 }
470 auto supportedChannelsList = OHOS::AudioStandard::AudioRenderer::GetSupportedChannels();
471 if (supportedChannelsList.empty()) {
472 MEDIA_LOG_E("GetSupportedChannels() fail");
473 return false;
474 }
475 for (const auto& channel : supportedChannelsList) {
476 if (channel == aChannel) {
477 rendererParams_.channelCount = channel;
478 MEDIA_LOG_D("channelCount: " PUBLIC_LOG_U32, rendererParams_.channelCount);
479 return true;
480 }
481 }
482 return false;
483 }
484
AssignSampleFmtIfSupported(Plugin::AudioSampleFormat sampleFormat)485 bool AudioServerSinkPlugin::AssignSampleFmtIfSupported(Plugin::AudioSampleFormat sampleFormat)
486 {
487 const auto& item = std::find_if(g_aduFmtMap.begin(), g_aduFmtMap.end(), [&sampleFormat] (const auto& tmp) -> bool {
488 return std::get<0>(tmp) == sampleFormat;
489 });
490 auto stdFmt = std::get<1>(*item);
491 if (stdFmt == OHOS::AudioStandard::AudioSampleFormat::INVALID_WIDTH) {
492 if (std::get<2>(*item) == AV_SAMPLE_FMT_NONE) { // 2
493 fmtSupported_ = false;
494 } else {
495 fmtSupported_ = true;
496 needReformat_ = true;
497 reSrcFfFmt_ = std::get<2>(*item); // 2
498 rendererParams_.sampleFormat = reStdDestFmt_;
499 }
500 } else {
501 auto supportedFmts = OHOS::AudioStandard::AudioRenderer::GetSupportedFormats();
502 if (CppExt::AnyOf(supportedFmts.begin(), supportedFmts.end(), [&stdFmt](const auto& tmp) -> bool {
503 return tmp == stdFmt;
504 })) {
505 fmtSupported_ = true;
506 needReformat_ = false;
507 rendererParams_.sampleFormat = stdFmt;
508 } else {
509 fmtSupported_ = false;
510 needReformat_ = false;
511 }
512 }
513 return fmtSupported_;
514 }
515
SetInterruptMode(AudioStandard::InterruptMode interruptMode)516 void AudioServerSinkPlugin::SetInterruptMode(AudioStandard::InterruptMode interruptMode)
517 {
518 OSAL::ScopedLock lock(renderMutex_);
519 if (audioRenderer_) {
520 audioRenderer_->SetInterruptMode(interruptMode);
521 }
522 }
523
SetParameter(Tag tag,const ValueType & para)524 Status AudioServerSinkPlugin::SetParameter(Tag tag, const ValueType& para)
525 {
526 MEDIA_LOG_I("SetParameter entered, key: " PUBLIC_LOG_S, Pipeline::Tag2String(tag));
527 switch (tag) {
528 case Tag::AUDIO_SAMPLE_RATE:
529 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
530 "sample rate type should be uint32_t");
531 FALSE_RETURN_V_MSG_E(AssignSampleRateIfSupported(Plugin::AnyCast<uint32_t>(para)),
532 Status::ERROR_INVALID_PARAMETER, "sampleRate isn't supported");
533 break;
534 case Tag::AUDIO_OUTPUT_CHANNELS:
535 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
536 "channels type should be uint32_t");
537 channels_ = Plugin::AnyCast<uint32_t>(para);
538 MEDIA_LOG_I("Set outputChannels: " PUBLIC_LOG_U32, channels_);
539 FALSE_RETURN_V_MSG_E(AssignChannelNumIfSupported(channels_), Status::ERROR_INVALID_PARAMETER,
540 "channel isn't supported");
541 break;
542 case Tag::MEDIA_BITRATE:
543 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(int64_t)), Status::ERROR_MISMATCHED_TYPE,
544 "bit rate type should be int64_t");
545 bitRate_ = Plugin::AnyCast<int64_t>(para);
546 break;
547 case Tag::AUDIO_SAMPLE_FORMAT:
548 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioSampleFormat)), Status::ERROR_MISMATCHED_TYPE,
549 "AudioSampleFormat type should be AudioSampleFormat");
550 FALSE_RETURN_V_MSG_E(AssignSampleFmtIfSupported(Plugin::AnyCast<AudioSampleFormat>(para)),
551 Status::ERROR_INVALID_PARAMETER, "sampleFmt isn't supported by audio renderer or resample lib");
552 break;
553 case Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT:
554 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioChannelLayout)), Status::ERROR_MISMATCHED_TYPE,
555 "channel layout type should be AudioChannelLayout");
556 channelLayout_ = Plugin::AnyCast<AudioChannelLayout>(para);
557 MEDIA_LOG_I("Set outputChannelLayout: " PUBLIC_LOG_U64, channelLayout_);
558 break;
559 case Tag::AUDIO_SAMPLE_PER_FRAME:
560 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
561 "SAMPLE_PER_FRAME type should be uint32_t");
562 samplesPerFrame_ = Plugin::AnyCast<uint32_t>(para);
563 break;
564 case Tag::BITS_PER_CODED_SAMPLE:
565 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(uint32_t)), Status::ERROR_MISMATCHED_TYPE,
566 "BITS_PER_CODED_SAMPLE type should be uint32_t");
567 bitsPerSample_ = Plugin::AnyCast<uint32_t>(para);
568 break;
569 case Tag::MEDIA_SEEKABLE:
570 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(Seekable)), Status::ERROR_MISMATCHED_TYPE,
571 "MEDIA_SEEKABLE type should be Seekable");
572 seekable_ = Plugin::AnyCast<Plugin::Seekable>(para);
573 break;
574 case Tag::APP_PID:
575 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(int32_t)), Status::ERROR_MISMATCHED_TYPE,
576 "APP_PID type should be int32_t");
577 appPid_ = Plugin::AnyCast<int32_t>(para);
578 break;
579 case Tag::APP_UID:
580 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(int32_t)), Status::ERROR_MISMATCHED_TYPE,
581 "APP_UID type should be int32_t");
582 appUid_ = Plugin::AnyCast<int32_t>(para);
583 break;
584 case Tag::AUDIO_RENDER_INFO:
585 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioRenderInfo)), Status::ERROR_MISMATCHED_TYPE,
586 "AUDIO_RENDER_INFO type should be AudioRenderInfo");
587 audioRenderInfo_ = Plugin::AnyCast<AudioRenderInfo>(para);
588 break;
589 case Tag::AUDIO_INTERRUPT_MODE:
590 FALSE_RETURN_V_MSG_E(para.SameTypeWith(typeid(AudioInterruptMode)), Status::ERROR_MISMATCHED_TYPE,
591 "AUDIO_INTERRUPT_MODE type should be AudioInterruptMode");
592 AudioInterruptMode2InterruptMode(Plugin::AnyCast<AudioInterruptMode>(para), audioInterruptMode_);
593 SetInterruptMode(audioInterruptMode_);
594 break;
595 default:
596 MEDIA_LOG_I("Unknown key");
597 break;
598 }
599 return Status::OK;
600 }
601
GetVolume(float & volume)602 Status AudioServerSinkPlugin::GetVolume(float& volume)
603 {
604 MEDIA_LOG_I("GetVolume entered.");
605 OSAL::ScopedLock lock(renderMutex_);
606 if (audioRenderer_ != nullptr) {
607 volume = audioRenderer_->GetVolume();
608 return Status::OK;
609 }
610 return Status::ERROR_WRONG_STATE;
611 }
612
SetVolume(float volume)613 Status AudioServerSinkPlugin::SetVolume(float volume)
614 {
615 MEDIA_LOG_I("SetVolume entered.");
616 OSAL::ScopedLock lock(renderMutex_);
617 if (audioRenderer_ != nullptr) {
618 int32_t ret = audioRenderer_->SetVolume(volume);
619 if (ret != OHOS::AudioStandard::SUCCESS) {
620 MEDIA_LOG_E("set volume failed with code " PUBLIC_LOG_D32, ret);
621 return Status::ERROR_UNKNOWN;
622 }
623 return Status::OK;
624 }
625 return Status::ERROR_WRONG_STATE;
626 }
627
Resume()628 Status AudioServerSinkPlugin::Resume()
629 {
630 MEDIA_LOG_I("Resume entered.");
631 return Start();
632 }
633
Pause()634 Status AudioServerSinkPlugin::Pause()
635 {
636 MEDIA_LOG_I("Pause entered.");
637 OSAL::ScopedLock lock(renderMutex_);
638 if (audioRenderer_ != nullptr) {
639 if (audioRenderer_->Pause()) {
640 MEDIA_LOG_I("audio renderer pause success");
641 return Status::OK;
642 } else {
643 MEDIA_LOG_E("audio renderer pause fail");
644 }
645 }
646 return Status::ERROR_WRONG_STATE;
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 auto res = audioRenderer_->Drain();
712 uint64_t latency = 0;
713 audioRenderer_->GetLatency(latency);
714 latency /= 1000; // 1000 cast into ms
715 if (!res || latency > 50) { // 50 latency too large
716 MEDIA_LOG_W("drain failed or latency is too large, will sleep " PUBLIC_LOG_U64 " ms, aka. latency", latency);
717 OSAL::SleepFor(latency);
718 }
719 MEDIA_LOG_I("audioRenderer_ Drain() success");
720 return Status::OK;
721 }
722 } // namespace AuSrSinkPlugin
723 } // Plugin
724 } // namespace Media
725 } // namespace OHOS
726