1 /*
2 * Copyright (c) 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 #include "audio_renderer_adapter_impl.h"
17
18 #include <unordered_map>
19
20 #include "application_context.h"
21 #include "audio_errors.h"
22 #include "nweb_log.h"
23
24 namespace OHOS::NWeb {
25
26 const std::unordered_map<AudioAdapterSamplingRate, AudioSamplingRate> SAMPLING_RATE_MAP = {
27 { AudioAdapterSamplingRate::SAMPLE_RATE_8000, AudioSamplingRate::SAMPLE_RATE_8000 },
28 { AudioAdapterSamplingRate::SAMPLE_RATE_11025, AudioSamplingRate::SAMPLE_RATE_11025 },
29 { AudioAdapterSamplingRate::SAMPLE_RATE_12000, AudioSamplingRate::SAMPLE_RATE_12000 },
30 { AudioAdapterSamplingRate::SAMPLE_RATE_16000, AudioSamplingRate::SAMPLE_RATE_16000 },
31 { AudioAdapterSamplingRate::SAMPLE_RATE_22050, AudioSamplingRate::SAMPLE_RATE_22050 },
32 { AudioAdapterSamplingRate::SAMPLE_RATE_24000, AudioSamplingRate::SAMPLE_RATE_24000 },
33 { AudioAdapterSamplingRate::SAMPLE_RATE_32000, AudioSamplingRate::SAMPLE_RATE_32000 },
34 { AudioAdapterSamplingRate::SAMPLE_RATE_44100, AudioSamplingRate::SAMPLE_RATE_44100 },
35 { AudioAdapterSamplingRate::SAMPLE_RATE_48000, AudioSamplingRate::SAMPLE_RATE_48000 },
36 { AudioAdapterSamplingRate::SAMPLE_RATE_64000, AudioSamplingRate::SAMPLE_RATE_64000 },
37 { AudioAdapterSamplingRate::SAMPLE_RATE_96000, AudioSamplingRate::SAMPLE_RATE_96000 },
38 };
39
40 const std::unordered_map<AudioAdapterEncodingType, AudioEncodingType> ENCODING_TYPE_MAP = {
41 { AudioAdapterEncodingType::ENCODING_PCM, AudioEncodingType::ENCODING_PCM },
42 { AudioAdapterEncodingType::ENCODING_INVALID, AudioEncodingType::ENCODING_INVALID }
43 };
44
45 const std::unordered_map<AudioAdapterSampleFormat, AudioSampleFormat> SAMPLE_FORMAT_MAP = {
46 { AudioAdapterSampleFormat::SAMPLE_U8, AudioSampleFormat::SAMPLE_U8 },
47 { AudioAdapterSampleFormat::SAMPLE_S16LE, AudioSampleFormat::SAMPLE_S16LE },
48 { AudioAdapterSampleFormat::SAMPLE_S24LE, AudioSampleFormat::SAMPLE_S24LE },
49 { AudioAdapterSampleFormat::SAMPLE_S32LE, AudioSampleFormat::SAMPLE_S32LE },
50 { AudioAdapterSampleFormat::SAMPLE_F32LE, AudioSampleFormat::SAMPLE_F32LE },
51 };
52
53 const std::unordered_map<AudioAdapterChannel, AudioChannel> AUDIO_CHANNEL_MAP = {
54 { AudioAdapterChannel::MONO, AudioChannel::MONO },
55 { AudioAdapterChannel::STEREO, AudioChannel::STEREO },
56 { AudioAdapterChannel::CHANNEL_3, AudioChannel::CHANNEL_3 },
57 { AudioAdapterChannel::CHANNEL_4, AudioChannel::CHANNEL_4 },
58 { AudioAdapterChannel::CHANNEL_5, AudioChannel::CHANNEL_5 },
59 { AudioAdapterChannel::CHANNEL_6, AudioChannel::CHANNEL_6 },
60 { AudioAdapterChannel::CHANNEL_7, AudioChannel::CHANNEL_7 },
61 { AudioAdapterChannel::CHANNEL_8, AudioChannel::CHANNEL_8 },
62 };
63
64 const std::unordered_map<AudioAdapterContentType, ContentType> CONTENT_TYPE_MAP = {
65 { AudioAdapterContentType::CONTENT_TYPE_UNKNOWN, ContentType::CONTENT_TYPE_UNKNOWN },
66 { AudioAdapterContentType::CONTENT_TYPE_SPEECH, ContentType::CONTENT_TYPE_SPEECH },
67 { AudioAdapterContentType::CONTENT_TYPE_MUSIC, ContentType::CONTENT_TYPE_MUSIC },
68 { AudioAdapterContentType::CONTENT_TYPE_MOVIE, ContentType::CONTENT_TYPE_MOVIE },
69 { AudioAdapterContentType::CONTENT_TYPE_SONIFICATION, ContentType::CONTENT_TYPE_SONIFICATION },
70 { AudioAdapterContentType::CONTENT_TYPE_RINGTONE, ContentType::CONTENT_TYPE_RINGTONE },
71 };
72
73 const std::unordered_map<AudioAdapterStreamUsage, StreamUsage> STREAM_USAGE_MAP = {
74 { AudioAdapterStreamUsage::STREAM_USAGE_UNKNOWN, StreamUsage::STREAM_USAGE_UNKNOWN },
75 { AudioAdapterStreamUsage::STREAM_USAGE_MEDIA, StreamUsage::STREAM_USAGE_MEDIA },
76 { AudioAdapterStreamUsage::STREAM_USAGE_VOICE_COMMUNICATION, StreamUsage::STREAM_USAGE_VIDEO_COMMUNICATION },
77 { AudioAdapterStreamUsage::STREAM_USAGE_VOICE_ASSISTANT, StreamUsage::STREAM_USAGE_VOICE_ASSISTANT },
78 { AudioAdapterStreamUsage::STREAM_USAGE_NOTIFICATION_RINGTONE, StreamUsage::STREAM_USAGE_NOTIFICATION_RINGTONE },
79 };
80
81 const std::unordered_map<AudioStreamDeviceChangeReason, AudioAdapterDeviceChangeReason> CHANGE_REASON_MAP = {
82 { AudioStreamDeviceChangeReason::UNKNOWN, AudioAdapterDeviceChangeReason::UNKNOWN },
83 { AudioStreamDeviceChangeReason::NEW_DEVICE_AVAILABLE, AudioAdapterDeviceChangeReason::NEW_DEVICE_AVAILABLE },
84 { AudioStreamDeviceChangeReason::OLD_DEVICE_UNAVALIABLE, AudioAdapterDeviceChangeReason::OLD_DEVICE_UNAVALIABLE },
85 { AudioStreamDeviceChangeReason::OVERRODE, AudioAdapterDeviceChangeReason::OVERRODE },
86 };
87
88 const std::unordered_map<AudioAdapterConcurrencyMode, AudioConcurrencyMode> AUDIO_CONCURRENCY_MAP = {
89 { AudioAdapterConcurrencyMode::INVALID, AudioConcurrencyMode::INVALID },
90 { AudioAdapterConcurrencyMode::DEFAULT, AudioConcurrencyMode::DEFAULT },
91 { AudioAdapterConcurrencyMode::MIX_WITH_OTHERS, AudioConcurrencyMode::MIX_WITH_OTHERS },
92 { AudioAdapterConcurrencyMode::DUCK_OTHERS, AudioConcurrencyMode::DUCK_OTHERS },
93 { AudioAdapterConcurrencyMode::PAUSE_OTHERS, AudioConcurrencyMode::PAUSE_OTHERS },
94 { AudioAdapterConcurrencyMode::SLIENT, AudioConcurrencyMode::SLIENT },
95 };
96
AudioRendererCallbackImpl(std::shared_ptr<AudioRendererCallbackAdapter> cb)97 AudioRendererCallbackImpl::AudioRendererCallbackImpl(std::shared_ptr<AudioRendererCallbackAdapter> cb) : cb_(cb) {};
98
OnInterrupt(const InterruptEvent & interruptEvent)99 void AudioRendererCallbackImpl::OnInterrupt(const InterruptEvent& interruptEvent)
100 {
101 if (!cb_) {
102 return;
103 }
104 switch (interruptEvent.hintType) {
105 case InterruptHint::INTERRUPT_HINT_PAUSE:
106 cb_->OnSuspend();
107 break;
108 case InterruptHint::INTERRUPT_HINT_STOP:
109 cb_->OnSuspend();
110 break;
111 case InterruptHint::INTERRUPT_HINT_RESUME:
112 cb_->OnResume();
113 break;
114 default:
115 WVLOG_E("audio renderer interrupt hint not foud, code: %{public}d", interruptEvent.hintType);
116 break;
117 }
118 }
119
OnStateChange(const RendererState state,const StateChangeCmdType cmdType)120 void AudioRendererCallbackImpl::OnStateChange(const RendererState state, const StateChangeCmdType cmdType) {}
GetChangeReason(AudioStreamDeviceChangeReason reason)121 AudioAdapterDeviceChangeReason AudioOutputChangeCallbackImpl::GetChangeReason(AudioStreamDeviceChangeReason reason)
122 {
123 auto item = CHANGE_REASON_MAP.find(reason);
124 if (item == CHANGE_REASON_MAP.end()) {
125 WVLOG_E("device change reason not found");
126 return AudioAdapterDeviceChangeReason::UNKNOWN;
127 }
128 return item->second;
129 }
130
AudioOutputChangeCallbackImpl(std::shared_ptr<AudioOutputChangeCallbackAdapter> cb)131 AudioOutputChangeCallbackImpl::AudioOutputChangeCallbackImpl(std::shared_ptr<AudioOutputChangeCallbackAdapter> cb)
132 : cb_(cb) {};
OnOutputDeviceChange(const DeviceInfo & deviceInfo,const AudioStreamDeviceChangeReason reason)133 void AudioOutputChangeCallbackImpl::OnOutputDeviceChange(
134 const DeviceInfo& deviceInfo, const AudioStreamDeviceChangeReason reason)
135 {
136 if (!cb_) {
137 return;
138 }
139 AudioAdapterDeviceChangeReason reasonAdapter = GetChangeReason(reason);
140 WVLOG_I("OnOutputDeviceChange reason: %{public}d", (int32_t)reasonAdapter);
141 cb_->OnOutputDeviceChange((int32_t)reasonAdapter);
142 }
143
Create(const std::shared_ptr<AudioRendererOptionsAdapter> rendererOptions,std::string cachePath)144 int32_t AudioRendererAdapterImpl::Create(
145 const std::shared_ptr<AudioRendererOptionsAdapter> rendererOptions, std::string cachePath)
146 {
147 std::string audioCachePath = cachePath;
148 std::shared_ptr<AbilityRuntime::ApplicationContext> context =
149 AbilityRuntime::ApplicationContext::GetApplicationContext();
150 if (!context) {
151 WVLOG_E("application context get failed");
152 return AUDIO_ERROR;
153 }
154 if (audioCachePath.empty()) {
155 audioCachePath = context->GetCacheDir();
156 if (audioCachePath.empty()) {
157 WVLOG_E("application cache path get failed");
158 return AUDIO_ERROR;
159 }
160 }
161 if (!rendererOptions) {
162 WVLOG_E("rendererOptions is nullptr");
163 return AUDIO_ERROR;
164 }
165
166 AudioRendererOptions audioOptions;
167 TransformToAudioRendererOptions(audioOptions, rendererOptions);
168 audio_renderer_ = AudioRenderer::Create(audioCachePath, audioOptions);
169 if (audio_renderer_ == nullptr) {
170 WVLOG_E("audio rendderer create failed");
171 return AUDIO_NULL_ERROR;
172 }
173 audio_renderer_->SetOffloadAllowed(false);
174 return AUDIO_OK;
175 }
176
Start()177 bool AudioRendererAdapterImpl::Start()
178 {
179 if (audio_renderer_ == nullptr) {
180 WVLOG_E("audio rendderer is nullptr");
181 return false;
182 }
183 return audio_renderer_->Start();
184 }
185
Pause()186 bool AudioRendererAdapterImpl::Pause()
187 {
188 if (audio_renderer_ == nullptr) {
189 WVLOG_E("audio rendderer is nullptr");
190 return false;
191 }
192 return audio_renderer_->Pause();
193 }
194
Stop()195 bool AudioRendererAdapterImpl::Stop()
196 {
197 if (audio_renderer_ == nullptr) {
198 WVLOG_E("audio rendderer is nullptr");
199 return false;
200 }
201 return audio_renderer_->Stop();
202 }
203
Release()204 bool AudioRendererAdapterImpl::Release()
205 {
206 if (audio_renderer_ == nullptr) {
207 WVLOG_E("audio rendderer is nullptr");
208 return false;
209 }
210 return audio_renderer_->Release();
211 }
212
Write(uint8_t * buffer,size_t bufferSize)213 int32_t AudioRendererAdapterImpl::Write(uint8_t* buffer, size_t bufferSize)
214 {
215 if (audio_renderer_ == nullptr) {
216 WVLOG_E("audio rendderer is nullptr");
217 return AUDIO_NULL_ERROR;
218 }
219 return audio_renderer_->Write(buffer, bufferSize);
220 }
221
GetLatency(uint64_t & latency)222 int32_t AudioRendererAdapterImpl::GetLatency(uint64_t& latency)
223 {
224 if (audio_renderer_ == nullptr) {
225 WVLOG_E("audio rendderer is nullptr");
226 return AUDIO_NULL_ERROR;
227 }
228 return audio_renderer_->GetLatency(latency);
229 }
230
SetVolume(float volume)231 int32_t AudioRendererAdapterImpl::SetVolume(float volume)
232 {
233 if (audio_renderer_ == nullptr) {
234 WVLOG_E("audio rendderer is nullptr");
235 return AUDIO_NULL_ERROR;
236 }
237 return audio_renderer_->SetVolume(volume);
238 }
239
GetVolume()240 float AudioRendererAdapterImpl::GetVolume()
241 {
242 if (audio_renderer_ == nullptr) {
243 WVLOG_E("audio rendderer is nullptr");
244 return AUDIO_NULL_ERROR;
245 }
246 return audio_renderer_->GetVolume();
247 }
248
SetAudioRendererCallback(const std::shared_ptr<AudioRendererCallbackAdapter> & callback)249 int32_t AudioRendererAdapterImpl::SetAudioRendererCallback(
250 const std::shared_ptr<AudioRendererCallbackAdapter>& callback)
251 {
252 if (callback == nullptr) {
253 WVLOG_E("set audio manager interrupt callback is nullptr");
254 return AUDIO_NULL_ERROR;
255 }
256 callback_ = std::make_shared<AudioRendererCallbackImpl>(callback);
257
258 if (audio_renderer_ == nullptr) {
259 WVLOG_E("audio rendderer is nullptr");
260 return AUDIO_NULL_ERROR;
261 }
262 int32_t ret = audio_renderer_->SetRendererCallback(callback_);
263 if (ret != AudioStandard::SUCCESS) {
264 WVLOG_E("audio renderer set callback failed, code: %{public}d", ret);
265 return AUDIO_ERROR;
266 }
267 return AUDIO_OK;
268 }
269
SetAudioOutputChangeCallback(const std::shared_ptr<AudioOutputChangeCallbackAdapter> & callback)270 int32_t AudioRendererAdapterImpl::SetAudioOutputChangeCallback(
271 const std::shared_ptr<AudioOutputChangeCallbackAdapter>& callback)
272 {
273 WVLOG_I("AudioRendererAdapterImpl::SetAudioOutputChangeCallback");
274 if (callback == nullptr) {
275 WVLOG_E("set audio manager interrupt callback is nullptr");
276 return AUDIO_NULL_ERROR;
277 }
278 ouputChangeCallback_ = std::make_shared<AudioOutputChangeCallbackImpl>(callback);
279 if (audio_renderer_ == nullptr) {
280 WVLOG_E("audio rendderer is nullptr");
281 return AUDIO_NULL_ERROR;
282 }
283 int32_t ret = audio_renderer_->RegisterOutputDeviceChangeWithInfoCallback(ouputChangeCallback_);
284 if (ret != AudioStandard::SUCCESS) {
285 WVLOG_E("audio renderer set output device change callback failed, code: %{public}d", ret);
286 return AUDIO_ERROR;
287 }
288 return AUDIO_OK;
289 }
290
SetInterruptMode(bool audioExclusive)291 void AudioRendererAdapterImpl::SetInterruptMode(bool audioExclusive)
292 {
293 if (audio_renderer_ == nullptr) {
294 WVLOG_E("audio rendderer is nullptr");
295 return;
296 }
297 InterruptMode interruptMode = audioExclusive ? InterruptMode::INDEPENDENT_MODE : InterruptMode::SHARE_MODE;
298 WVLOG_D("AudioRendererAdapterImpl::SetInterruptMode audioExclusive: %{public}d", audioExclusive);
299 audio_renderer_->SetInterruptMode(interruptMode);
300 }
301
SetAudioSilentMode(bool isSilentMode)302 void AudioRendererAdapterImpl::SetAudioSilentMode(bool isSilentMode)
303 {
304 if (audio_renderer_ == nullptr) {
305 WVLOG_E("audio rendderer is nullptr");
306 return;
307 }
308 audio_renderer_->SetSilentModeAndMixWithOthers(isSilentMode);
309 WVLOG_D("AudioRendererAdapterImpl::SetAudioSilentMode isSilentMode: %{public}d", isSilentMode);
310 }
311
IsRendererStateRunning()312 bool AudioRendererAdapterImpl::IsRendererStateRunning()
313 {
314 if (audio_renderer_ == nullptr) {
315 WVLOG_E("audio rendderer is nullptr");
316 return false;
317 }
318 return audio_renderer_->GetStatus() == OHOS::AudioStandard::RendererState::RENDERER_RUNNING;
319 }
320
GetAudioSamplingRate(AudioAdapterSamplingRate samplingRate)321 AudioSamplingRate AudioRendererAdapterImpl::GetAudioSamplingRate(AudioAdapterSamplingRate samplingRate)
322 {
323 auto item = SAMPLING_RATE_MAP.find(samplingRate);
324 if (item == SAMPLING_RATE_MAP.end()) {
325 WVLOG_E("audio sampling rate not found");
326 return AudioSamplingRate::SAMPLE_RATE_44100;
327 }
328 return item->second;
329 }
330
GetAudioEncodingType(AudioAdapterEncodingType encodingType)331 AudioEncodingType AudioRendererAdapterImpl::GetAudioEncodingType(AudioAdapterEncodingType encodingType)
332 {
333 auto item = ENCODING_TYPE_MAP.find(encodingType);
334 if (item == ENCODING_TYPE_MAP.end()) {
335 WVLOG_E("audio encoding type not found");
336 return AudioEncodingType::ENCODING_INVALID;
337 }
338 return item->second;
339 }
340
GetAudioSampleFormat(AudioAdapterSampleFormat sampleFormat)341 AudioSampleFormat AudioRendererAdapterImpl::GetAudioSampleFormat(AudioAdapterSampleFormat sampleFormat)
342 {
343 auto item = SAMPLE_FORMAT_MAP.find(sampleFormat);
344 if (item == SAMPLE_FORMAT_MAP.end()) {
345 WVLOG_E("audio sample format not found");
346 return AudioSampleFormat::INVALID_WIDTH;
347 }
348 return item->second;
349 }
350
GetAudioChannel(AudioAdapterChannel channel)351 AudioChannel AudioRendererAdapterImpl::GetAudioChannel(AudioAdapterChannel channel)
352 {
353 auto item = AUDIO_CHANNEL_MAP.find(channel);
354 if (item == AUDIO_CHANNEL_MAP.end()) {
355 WVLOG_E("audio channel not found");
356 return AudioChannel::STEREO;
357 }
358 return item->second;
359 }
360
GetAudioContentType(AudioAdapterContentType contentType)361 ContentType AudioRendererAdapterImpl::GetAudioContentType(AudioAdapterContentType contentType)
362 {
363 auto item = CONTENT_TYPE_MAP.find(contentType);
364 if (item == CONTENT_TYPE_MAP.end()) {
365 WVLOG_E("audio content type not found");
366 return ContentType::CONTENT_TYPE_MUSIC;
367 }
368 return item->second;
369 }
370
GetAudioStreamUsage(AudioAdapterStreamUsage streamUsage)371 StreamUsage AudioRendererAdapterImpl::GetAudioStreamUsage(AudioAdapterStreamUsage streamUsage)
372 {
373 auto item = STREAM_USAGE_MAP.find(streamUsage);
374 if (item == STREAM_USAGE_MAP.end()) {
375 WVLOG_E("audio stream usage not found");
376 return StreamUsage::STREAM_USAGE_MEDIA;
377 }
378 return item->second;
379 }
380
GetAudioAudioStrategy(AudioAdapterConcurrencyMode concurrencyMode)381 AudioSessionStrategy AudioRendererAdapterImpl::GetAudioAudioStrategy(AudioAdapterConcurrencyMode concurrencyMode)
382 {
383 struct AudioSessionStrategy strategy;
384 auto item = AUDIO_CONCURRENCY_MAP.find(concurrencyMode);
385 if (item == AUDIO_CONCURRENCY_MAP.end()) {
386 WVLOG_E("audio concurrency mode not found");
387 strategy.concurrencyMode = AudioConcurrencyMode::INVALID;
388 return strategy;
389 }
390 strategy.concurrencyMode = item->second;
391 return strategy;
392 }
393
TransformToAudioRendererOptions(AudioRendererOptions & out,const std::shared_ptr<AudioRendererOptionsAdapter> & in)394 void AudioRendererAdapterImpl::TransformToAudioRendererOptions(
395 AudioRendererOptions& out, const std::shared_ptr<AudioRendererOptionsAdapter>& in)
396 {
397 out.streamInfo.samplingRate = GetAudioSamplingRate(in->GetSamplingRate());
398 out.streamInfo.encoding = GetAudioEncodingType(in->GetEncodingType());
399 out.streamInfo.format = GetAudioSampleFormat(in->GetSampleFormat());
400 out.streamInfo.channels = GetAudioChannel(in->GetChannel());
401 out.rendererInfo.contentType = GetAudioContentType(in->GetContentType());
402 out.rendererInfo.streamUsage = GetAudioStreamUsage(in->GetStreamUsage());
403 out.rendererInfo.rendererFlags = in->GetRenderFlags();
404 out.strategy = GetAudioAudioStrategy(in->GetConcurrencyMode());
405 }
406
407 } // namespace OHOS::NWeb
408