• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef LOG_TAG
16 #define LOG_TAG "NoneMixEngine"
17 #endif
18 
19 #include "audio_common_converter.h"
20 #include "audio_errors.h"
21 #include "audio_service_log.h"
22 #include "audio_utils.h"
23 #include "common/hdi_adapter_info.h"
24 #include "manager/hdi_adapter_manager.h"
25 #include "sink/i_audio_render_sink.h"
26 #include "none_mix_engine.h"
27 #include "audio_performance_monitor.h"
28 #include "audio_volume.h"
29 #include "format_converter.h"
30 #include "audio_service.h"
31 
32 namespace OHOS {
33 namespace AudioStandard {
34 constexpr int32_t DELTA_TIME = 4000000; // 4ms
35 constexpr int32_t PERIOD_NS = 20000000; // 20ms
36 constexpr int32_t AUDIO_US_PER_MS = 1000;
37 constexpr int32_t AUDIO_DEFAULT_LATENCY_US = 160000;
38 constexpr int32_t AUDIO_FRAME_WORK_LATENCY_US = 40000;
39 constexpr int32_t FADING_MS = 20; // 20ms
40 constexpr int32_t MAX_ERROR_COUNT = 50;
41 constexpr int16_t STEREO_CHANNEL_COUNT = 2;
42 constexpr int16_t HDI_STEREO_CHANNEL_LAYOUT = 3;
43 constexpr int16_t HDI_MONO_CHANNEL_LAYOUT = 4;
44 constexpr int32_t DIRECT_STOP_TIMEOUT_IN_SEC = 8; // 8S
45 constexpr int32_t DIRECT_SINK_STANDBY_TIMES = 8; // 8
46 const std::string THREAD_NAME = "noneMixThread";
47 const std::string VOIP_SINK_NAME = "voip";
48 const std::string DIRECT_SINK_NAME = "direct";
49 const char *SINK_ADAPTER_NAME = "primary";
50 
NoneMixEngine()51 NoneMixEngine::NoneMixEngine()
52     : isVoip_(false),
53       isStart_(false),
54       isInit_(false),
55       failedCount_(0),
56       writeCount_(0),
57       fwkSyncTime_(0),
58       latency_(0),
59       stream_(nullptr),
60       startFadein_(false),
61       startFadeout_(false),
62       uChannel_(0),
63       uFormat_(sizeof(int32_t)),
64       uSampleRate_(0),
65       firstSetVolume_(true)
66 {
67     AUDIO_INFO_LOG("Constructor");
68 }
69 
~NoneMixEngine()70 NoneMixEngine::~NoneMixEngine()
71 {
72     writeCount_ = 0;
73     failedCount_ = 0;
74     fwkSyncTime_ = 0;
75     if (playbackThread_) {
76         playbackThread_->Stop();
77         playbackThread_ = nullptr;
78     }
79     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
80     if (sink && sink->IsInited()) {
81         sink->Stop();
82         sink->DeInit();
83     }
84     HdiAdapterManager::GetInstance().ReleaseId(renderId_);
85     isStart_ = false;
86     startFadein_ = false;
87     startFadeout_ = false;
88 }
89 
Init(const AudioDeviceDescriptor & type,bool isVoip)90 int32_t NoneMixEngine::Init(const AudioDeviceDescriptor &type, bool isVoip)
91 {
92     if (!isInit_) {
93         isVoip_ = isVoip;
94         device_ = type;
95         return SUCCESS;
96     }
97     if (type.deviceType_ != device_.deviceType_ || isVoip_ != isVoip) {
98         isVoip_ = isVoip;
99         device_ = type;
100         std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
101         if (sink && sink->IsInited()) {
102             sink->Stop();
103             sink->DeInit();
104         }
105         HdiAdapterManager::GetInstance().ReleaseId(renderId_);
106     }
107     return SUCCESS;
108 }
109 
Start()110 int32_t NoneMixEngine::Start()
111 {
112     AUDIO_INFO_LOG("Enter in");
113     int32_t ret = SUCCESS;
114     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
115     CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERR_INVALID_HANDLE, "null sink");
116     CHECK_AND_RETURN_RET_LOG(sink->IsInited(), ERR_NOT_STARTED, "sink Not Inited! Init the sink first");
117     fwkSyncTime_ = static_cast<uint64_t>(ClockTime::GetCurNano());
118     writeCount_ = 0;
119     failedCount_ = 0;
120     if (!playbackThread_) {
121         playbackThread_ = std::make_unique<AudioThreadTask>(THREAD_NAME);
122         playbackThread_->RegisterJob([this] { this->MixStreams(); });
123     }
124     latency_ = 0;
125     if (!isStart_) {
126         startFadeout_ = false;
127         startFadein_ = true;
128         ret = sink->Start();
129         isStart_ = true;
130     }
131     if (!playbackThread_->CheckThreadIsRunning()) {
132         playbackThread_->Start();
133     }
134     return ret;
135 }
136 
Stop()137 int32_t NoneMixEngine::Stop()
138 {
139     AUDIO_INFO_LOG("Enter");
140     int32_t ret = SUCCESS;
141     if (!isStart_) {
142         AUDIO_INFO_LOG("already stopped");
143         return ret;
144     }
145     AudioXCollie audioXCollie(
146         "NoneMixEngine::Stop", DIRECT_STOP_TIMEOUT_IN_SEC,
147         [this](void *) { AUDIO_ERR_LOG("%{public}d stop timeout", isVoip_); }, nullptr,
148         AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
149 
150     writeCount_ = 0;
151     failedCount_ = 0;
152     if (playbackThread_) {
153         startFadein_ = false;
154         startFadeout_ = true;
155         // wait until fadeout complete
156         std::unique_lock fadingLock(fadingMutex_);
157         cvFading_.wait_for(
158             fadingLock, std::chrono::milliseconds(FADING_MS), [this] { return (!(startFadein_ || startFadeout_)); });
159         playbackThread_->Stop();
160         playbackThread_ = nullptr;
161     }
162     ClockTime::RelativeSleep(PERIOD_NS * DIRECT_SINK_STANDBY_TIMES);
163     ret = StopAudioSink();
164     isStart_ = false;
165     return ret;
166 }
167 
PauseAsync()168 void NoneMixEngine::PauseAsync()
169 {
170     // stop thread when failed 5 times,do not add logic inside.
171     if (playbackThread_ && playbackThread_->CheckThreadIsRunning()) {
172         playbackThread_->PauseAsync();
173     }
174     int32_t ret = StopAudioSink();
175     if (ret != SUCCESS) {
176         AUDIO_ERR_LOG("sink stop failed.ret:%{public}d", ret);
177     }
178     isStart_ = false;
179 }
180 
StopAudioSink()181 int32_t NoneMixEngine::StopAudioSink()
182 {
183     int32_t ret = SUCCESS;
184     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
185     if (sink && sink->IsInited()) {
186         ret = sink->Stop();
187     } else {
188         AUDIO_ERR_LOG("sink is null or not init");
189     }
190     return ret;
191 }
192 
Pause()193 int32_t NoneMixEngine::Pause()
194 {
195     AUDIO_INFO_LOG("Enter");
196     if (!isStart_) {
197         AUDIO_INFO_LOG("already stopped");
198         return SUCCESS;
199     }
200     AudioXCollie audioXCollie(
201         "NoneMixEngine::Pause", DIRECT_STOP_TIMEOUT_IN_SEC,
202         [this](void *) { AUDIO_ERR_LOG("%{public}d stop timeout", isVoip_); }, nullptr,
203         AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
204 
205     writeCount_ = 0;
206     failedCount_ = 0;
207     if (playbackThread_) {
208         startFadein_ = false;
209         startFadeout_ = true;
210         // wait until fadeout complete
211         std::unique_lock fadingLock(fadingMutex_);
212         cvFading_.wait_for(
213             fadingLock, std::chrono::milliseconds(FADING_MS), [this] { return (!(startFadein_ || startFadeout_)); });
214         playbackThread_->Pause();
215     }
216     ClockTime::RelativeSleep(PERIOD_NS * DIRECT_SINK_STANDBY_TIMES);
217     int32_t ret = StopAudioSink();
218     isStart_ = false;
219     return ret;
220 }
221 
Flush()222 int32_t NoneMixEngine::Flush()
223 {
224     AUDIO_INFO_LOG("Enter");
225     return SUCCESS;
226 }
227 
228 template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
DoFadeInOut(T * dest,size_t count,bool isFadeOut,uint32_t channel)229 static void DoFadeInOut(T *dest, size_t count, bool isFadeOut, uint32_t channel)
230 {
231     if (count <= 0) {
232         return;
233     }
234     float fadeStep = 1.0f / count;
235     for (size_t i = 0; i < count; i++) {
236         float fadeFactor;
237         if (isFadeOut) {
238             fadeFactor = 1.0f - ((i + 1) * fadeStep);
239         } else {
240             fadeFactor = (i + 1) * fadeStep;
241         }
242         for (uint32_t j = 0; j < channel; j++) {
243             dest[i * channel + j] *= fadeFactor;
244         }
245     }
246 }
247 
DoFadeinOut(bool isFadeOut,char * pBuffer,size_t bufferSize)248 void NoneMixEngine::DoFadeinOut(bool isFadeOut, char *pBuffer, size_t bufferSize)
249 {
250     CHECK_AND_RETURN_LOG(pBuffer != nullptr && bufferSize > 0 && uChannel_ > 0, "buffer is null.");
251     size_t dataLength = bufferSize / (static_cast<uint32_t>(uFormat_) * uChannel_);
252     if (uFormat_ == sizeof(int16_t)) {
253         AUDIO_INFO_LOG("int16 fading frame length:%{public}zu", dataLength);
254         DoFadeInOut(reinterpret_cast<int16_t *>(pBuffer), dataLength, isFadeOut, uChannel_);
255     } else if (uFormat_ == sizeof(int32_t)) {
256         AUDIO_INFO_LOG("int32 fading frame length:%{public}zu", dataLength);
257         DoFadeInOut(reinterpret_cast<int32_t *>(pBuffer), dataLength, isFadeOut, uChannel_);
258     }
259     if (isFadeOut) {
260         startFadeout_.store(false);
261     } else {
262         startFadein_.store(false);
263     }
264 }
265 
AdjustVoipVolume()266 void NoneMixEngine::AdjustVoipVolume()
267 {
268     if (isVoip_) {
269         uint32_t streamIndx = stream_->GetStreamIndex();
270         AudioProcessConfig config = stream_->GetAudioProcessConfig();
271         AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(config.streamType);
272         float volumeBg = AudioVolume::GetInstance()->GetHistoryVolume(streamIndx);
273         float volumeEd = AudioVolume::GetInstance()->GetVolume(streamIndx, volumeType, std::string(SINK_ADAPTER_NAME));
274         if ((!firstSetVolume_ && volumeBg != volumeEd) || firstSetVolume_) {
275             AUDIO_INFO_LOG("Adjust voip volume");
276             AudioVolume::GetInstance()->SetHistoryVolume(streamIndx, volumeEd);
277             AudioVolume::GetInstance()->Monitor(streamIndx, true);
278             std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
279             CHECK_AND_RETURN(sink != nullptr);
280             sink->SetVolume(volumeEd, volumeEd);
281             firstSetVolume_ = false;
282         }
283     }
284 }
285 
DoRenderFrame(std::vector<char> & audioBufferConverted,int32_t index,int32_t appUid)286 void NoneMixEngine::DoRenderFrame(std::vector<char> &audioBufferConverted, int32_t index, int32_t appUid)
287 {
288     uint64_t written = 0;
289     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
290     CHECK_AND_RETURN(sink != nullptr);
291     sink->RenderFrame(*audioBufferConverted.data(), audioBufferConverted.size(), written);
292     stream_->ReturnIndex(index);
293     sink->UpdateAppsUid({appUid});
294 }
295 
MixStreams()296 void NoneMixEngine::MixStreams()
297 {
298     if (stream_ == nullptr) {
299         StandbySleep();
300         return;
301     }
302     if (failedCount_ >= MAX_ERROR_COUNT) {
303         AUDIO_WARNING_LOG("failed count is overflow.");
304         PauseAsync();
305         return;
306     }
307     std::vector<char> audioBuffer;
308     int32_t appUid = stream_->GetAudioProcessConfig().appInfo.appUid;
309     int32_t index = -1;
310     int32_t result = stream_->Peek(&audioBuffer, index);
311 
312     uint32_t sessionId = stream_->GetStreamIndex();
313     writeCount_++;
314     if (index < 0) {
315         AUDIO_WARNING_LOG("peek buffer failed.result:%{public}d,buffer size:%{public}d", result, index);
316         AudioPerformanceMonitor::GetInstance().RecordSilenceState(sessionId, true, PIPE_TYPE_DIRECT_OUT);
317         stream_->ReturnIndex(index);
318         failedCount_++;
319         if (startFadeout_) {
320             startFadeout_.store(false);
321             cvFading_.notify_all();
322             return;
323         }
324         ClockTime::RelativeSleep(PERIOD_NS);
325         return;
326     }
327     AudioPerformanceMonitor::GetInstance().RecordSilenceState(sessionId, false, PIPE_TYPE_DIRECT_OUT);
328     AdjustVoipVolume();
329     failedCount_ = 0;
330     // fade in or fade out
331     if (startFadeout_ || startFadein_) {
332         if (startFadeout_) {
333             stream_->BlockStream();
334         }
335         DoFadeinOut(startFadeout_, audioBuffer.data(), audioBuffer.size());
336         cvFading_.notify_all();
337     }
338     DoRenderFrame(audioBuffer, index, appUid);
339     StandbySleep();
340 }
341 
AddRenderer(const std::shared_ptr<IRendererStream> & stream)342 int32_t NoneMixEngine::AddRenderer(const std::shared_ptr<IRendererStream> &stream)
343 {
344     AUDIO_INFO_LOG("Enter add");
345     if (!stream_) {
346         AudioProcessConfig config = stream->GetAudioProcessConfig();
347         int32_t result = InitSink(config.streamInfo);
348         if (result == SUCCESS) {
349             stream_ = stream;
350             isInit_ = true;
351         }
352         return result;
353     } else if (stream->GetStreamIndex() != stream_->GetStreamIndex()) {
354         return ERROR_UNSUPPORTED;
355     }
356     return SUCCESS;
357 }
358 
RemoveRenderer(const std::shared_ptr<IRendererStream> & stream)359 void NoneMixEngine::RemoveRenderer(const std::shared_ptr<IRendererStream> &stream)
360 {
361     AUDIO_INFO_LOG("step in remove");
362     if (stream_ == nullptr) {
363         AUDIO_INFO_LOG("stream already removed.");
364         return;
365     }
366     if (stream->GetStreamIndex() == stream_->GetStreamIndex()) {
367         Stop();
368         stream_ = nullptr;
369     }
370 }
371 
IsPlaybackEngineRunning() const372 bool NoneMixEngine::IsPlaybackEngineRunning() const noexcept
373 {
374     return isStart_;
375 }
376 
StandbySleep()377 void NoneMixEngine::StandbySleep()
378 {
379     int64_t writeTime = static_cast<int64_t>(fwkSyncTime_) + static_cast<int64_t>(writeCount_) * PERIOD_NS + DELTA_TIME;
380     ClockTime::AbsoluteSleep(writeTime);
381 }
382 
GetDirectSampleRate(AudioSamplingRate sampleRate)383 AudioSamplingRate NoneMixEngine::GetDirectSampleRate(AudioSamplingRate sampleRate)
384 {
385     AudioSamplingRate result = sampleRate;
386     switch (sampleRate) {
387         case AudioSamplingRate::SAMPLE_RATE_44100:
388             result = AudioSamplingRate::SAMPLE_RATE_48000;
389             break;
390         case AudioSamplingRate::SAMPLE_RATE_88200:
391             result = AudioSamplingRate::SAMPLE_RATE_96000;
392             break;
393         case AudioSamplingRate::SAMPLE_RATE_176400:
394             result = AudioSamplingRate::SAMPLE_RATE_192000;
395             break;
396         default:
397             break;
398     }
399     AUDIO_INFO_LOG("GetDirectSampleRate: sampleRate: %{public}d, result: %{public}d", sampleRate, result);
400     return result;
401 }
402 
GetDirectVoipSampleRate(AudioSamplingRate sampleRate)403 AudioSamplingRate NoneMixEngine::GetDirectVoipSampleRate(AudioSamplingRate sampleRate)
404 {
405     AudioSamplingRate result = sampleRate;
406     if (sampleRate <= AudioSamplingRate::SAMPLE_RATE_16000) {
407         result = AudioSamplingRate::SAMPLE_RATE_16000;
408     } else {
409         result = AudioSamplingRate::SAMPLE_RATE_48000;
410     }
411     AUDIO_INFO_LOG("GetDirectVoipSampleRate: sampleRate: %{public}d, result: %{public}d", sampleRate, result);
412     return result;
413 }
414 
GetDirectDeviceFormat(AudioSampleFormat format)415 AudioSampleFormat NoneMixEngine::GetDirectDeviceFormat(AudioSampleFormat format)
416 {
417     switch (format) {
418         case AudioSampleFormat::SAMPLE_U8:
419         case AudioSampleFormat::SAMPLE_S16LE:
420             return AudioSampleFormat::SAMPLE_S16LE;
421         case AudioSampleFormat::SAMPLE_S24LE:
422         case AudioSampleFormat::SAMPLE_S32LE:
423             return AudioSampleFormat::SAMPLE_S32LE;
424         case AudioSampleFormat::SAMPLE_F32LE:
425             return AudioSampleFormat::SAMPLE_F32LE;
426         default:
427             return AudioSampleFormat::SAMPLE_S16LE;
428     }
429 }
430 
431 // replaced by using xml configuration later
GetDirectVoipDeviceFormat(AudioSampleFormat format)432 AudioSampleFormat NoneMixEngine::GetDirectVoipDeviceFormat(AudioSampleFormat format)
433 {
434     switch (format) {
435         case AudioSampleFormat::SAMPLE_U8:
436         case AudioSampleFormat::SAMPLE_S16LE:
437         case AudioSampleFormat::SAMPLE_F32LE:
438             return AudioSampleFormat::SAMPLE_S16LE;
439         case AudioSampleFormat::SAMPLE_S24LE:
440         case AudioSampleFormat::SAMPLE_S32LE:
441             return AudioSampleFormat::SAMPLE_S32LE;
442         default:
443             return AudioSampleFormat::SAMPLE_S16LE;
444     }
445 }
446 
GetDirectFormatByteSize(AudioSampleFormat format)447 int32_t NoneMixEngine::GetDirectFormatByteSize(AudioSampleFormat format)
448 {
449     switch (format) {
450         case AudioSampleFormat::SAMPLE_S16LE:
451             return sizeof(int16_t);
452         case AudioSampleFormat::SAMPLE_S32LE:
453         case AudioSampleFormat::SAMPLE_F32LE:
454             return sizeof(int32_t);
455         default:
456             return sizeof(int32_t);
457     }
458 }
459 
GetTargetSinkStreamInfo(const AudioStreamInfo & clientStreamInfo,uint32_t & targetSampleRate,uint32_t & targetChannel,AudioSampleFormat & targetFormat,bool & isVoip)460 void NoneMixEngine::GetTargetSinkStreamInfo(const AudioStreamInfo &clientStreamInfo, uint32_t &targetSampleRate,
461     uint32_t &targetChannel, AudioSampleFormat &targetFormat, bool &isVoip)
462 {
463     targetChannel = clientStreamInfo.channels >= STEREO_CHANNEL_COUNT ? STEREO_CHANNEL_COUNT : 1;
464 
465     if (isVoip) {
466         targetSampleRate = GetDirectVoipSampleRate(clientStreamInfo.samplingRate);
467         targetFormat = GetDirectVoipDeviceFormat(clientStreamInfo.format);
468     } else {
469         targetSampleRate = GetDirectSampleRate(clientStreamInfo.samplingRate);
470         targetFormat = GetDirectDeviceFormat(clientStreamInfo.format);
471     }
472 }
473 
InitSink(const AudioStreamInfo & clientStreamInfo)474 int32_t NoneMixEngine::InitSink(const AudioStreamInfo &clientStreamInfo)
475 {
476     uint32_t targetSampleRate;
477     uint32_t targetChannel;
478     AudioSampleFormat targetFormat;
479     GetTargetSinkStreamInfo(clientStreamInfo, targetSampleRate, targetChannel, targetFormat, isVoip_);
480 
481     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
482     if (isInit_ && sink) {
483         if (uChannel_ != targetChannel || uFormat_ != targetFormat || targetSampleRate != uSampleRate_) {
484             if (sink && sink->IsInited()) {
485                 sink->Stop();
486                 sink->DeInit();
487             }
488         } else {
489             return SUCCESS;
490         }
491     }
492     HdiAdapterManager::GetInstance().ReleaseId(renderId_);
493     return InitSink(targetChannel, targetFormat, targetSampleRate);
494 }
495 
InitSink(uint32_t channel,AudioSampleFormat format,uint32_t rate)496 int32_t NoneMixEngine::InitSink(uint32_t channel, AudioSampleFormat format, uint32_t rate)
497 {
498     std::string sinkName = DIRECT_SINK_NAME;
499     if (isVoip_) {
500         sinkName = VOIP_SINK_NAME;
501     }
502     renderId_ = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, sinkName, true);
503     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_, true);
504     if (sink == nullptr) {
505         AUDIO_ERR_LOG("get render fail, sinkName: %{public}s", sinkName.c_str());
506         HdiAdapterManager::GetInstance().ReleaseId(renderId_);
507         return ERR_INVALID_HANDLE;
508     }
509     IAudioSinkAttr attr = {};
510     bool isDefaultAdapterEnable = AudioService::GetInstance()->GetDefaultAdapterEnable();
511     attr.adapterName = isDefaultAdapterEnable ? "dp" : SINK_ADAPTER_NAME;
512     attr.sampleRate = rate;
513     attr.channel = channel;
514     attr.format = format;
515     attr.channelLayout = channel >= STEREO_CHANNEL_COUNT ? HDI_STEREO_CHANNEL_LAYOUT : HDI_MONO_CHANNEL_LAYOUT;
516     attr.deviceType = device_.deviceType_;
517     attr.volume = 1.0f;
518     attr.openMicSpeaker = 1;
519     AUDIO_INFO_LOG("sinkName:%{public}s,device:%{public}d,sample rate:%{public}d,format:%{public}d,channel:%{public}d",
520         sinkName.c_str(), attr.deviceType, attr.sampleRate, attr.format, attr.channel);
521     int32_t ret = sink->Init(attr);
522     if (ret != SUCCESS) {
523         return ret;
524     }
525     float volume = 1.0f;
526     ret = sink->SetVolume(volume, volume);
527     uChannel_ = attr.channel;
528     uSampleRate_ = attr.sampleRate;
529     uFormat_ = GetDirectFormatByteSize(attr.format);
530 
531     return ret;
532 }
533 
SwitchSink(const AudioStreamInfo & streamInfo,bool isVoip)534 int32_t NoneMixEngine::SwitchSink(const AudioStreamInfo &streamInfo, bool isVoip)
535 {
536     Stop();
537     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
538     if (sink != nullptr) {
539         sink->DeInit();
540     }
541     isVoip_ = isVoip;
542     return InitSink(streamInfo);
543 }
544 
GetLatency()545 uint64_t NoneMixEngine::GetLatency() noexcept
546 {
547     if (!isStart_) {
548         return 0;
549     }
550     if (latency_ > 0) {
551         return latency_;
552     }
553     uint32_t latency = 0;
554     std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(renderId_);
555     CHECK_AND_RETURN_RET(sink != nullptr, 0);
556     if (sink->GetLatency(latency) == 0) {
557         latency_ = latency * AUDIO_US_PER_MS + AUDIO_FRAME_WORK_LATENCY_US;
558     } else {
559         AUDIO_INFO_LOG("get latency failed,use default");
560         latency_ = AUDIO_DEFAULT_LATENCY_US;
561     }
562     AUDIO_INFO_LOG("latency value:%{public}" PRId64 " ns", latency_);
563     return latency_;
564 }
565 } // namespace AudioStandard
566 } // namespace OHOS
567