1 /*
2 * Copyright (c) 2023-2025 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 "PaRendererStreamImpl"
17 #endif
18
19 #ifdef FEATURE_POWER_MANAGER
20 #include "power_mgr_client.h"
21 #endif
22
23 #include "pa_renderer_stream_impl.h"
24
25 #include <chrono>
26
27 #include "safe_map.h"
28 #include "pa_adapter_tools.h"
29 #include "audio_effect_chain_manager.h"
30 #include "audio_errors.h"
31 #include "audio_service_log.h"
32 #include "common/hdi_adapter_info.h"
33 #include "manager/hdi_adapter_manager.h"
34 #include "sink/i_audio_render_sink.h"
35 #include "policy_handler.h"
36 #include "audio_volume.h"
37 #include "audio_limiter_manager.h"
38
39 namespace OHOS {
40 namespace AudioStandard {
41 static SafeMap<void *, std::weak_ptr<PaRendererStreamImpl>> rendererStreamInstanceMap_;
42 static const int32_t PA_STREAM_IMPL_TIMEOUT = 5; // 5s
43 const uint32_t DOUBLE_VALUE = 2;
44 const uint32_t MAX_LENGTH_OFFLOAD = 500;
45 const int32_t OFFLOAD_HDI_CACHE1 = 200; // ms, should equal with val in hdi_sink.c
46 const int32_t OFFLOAD_HDI_CACHE2 = 7000; // ms, should equal with val in hdi_sink.c
47 const int32_t OFFLOAD_HDI_CACHE3 = 500; // ms, should equal with val in hdi_sink.c for movie
48 const uint32_t OFFLOAD_BUFFER = 50;
49 const uint64_t AUDIO_CYCLE_TIME_US = 20000;
50 const uint64_t BUF_LENGTH_IN_MS = 20;
51 const uint64_t CAST_BUF_LENGTH_IN_MS = 10;
52
CheckReturnIfStreamInvalid(pa_stream * paStream,const int32_t retVal)53 static int32_t CheckReturnIfStreamInvalid(pa_stream *paStream, const int32_t retVal)
54 {
55 do {
56 if (!(paStream && PA_STREAM_IS_GOOD(pa_stream_get_state(paStream)))) {
57 return retVal;
58 }
59 } while (false);
60 return SUCCESS;
61 }
62
PaRendererStreamImpl(pa_stream * paStream,AudioProcessConfig processConfig,pa_threaded_mainloop * mainloop)63 PaRendererStreamImpl::PaRendererStreamImpl(pa_stream *paStream, AudioProcessConfig processConfig,
64 pa_threaded_mainloop *mainloop)
65 {
66 mainloop_ = mainloop;
67 paStream_ = paStream;
68 processConfig_ = processConfig;
69 effectMode_ = processConfig.rendererInfo.effectMode;
70 }
71
~PaRendererStreamImpl()72 PaRendererStreamImpl::~PaRendererStreamImpl()
73 {
74 AUDIO_DEBUG_LOG("~PaRendererStreamImpl");
75
76 PaLockGuard lock(mainloop_);
77 rendererStreamInstanceMap_.Erase(this);
78 if (paStream_) {
79 if (!releasedFlag_) {
80 pa_stream_set_state_callback(paStream_, nullptr, nullptr);
81 pa_stream_set_write_callback(paStream_, nullptr, nullptr);
82 pa_stream_set_latency_update_callback(paStream_, nullptr, nullptr);
83 pa_stream_set_underflow_callback(paStream_, nullptr, nullptr);
84 pa_stream_set_moved_callback(paStream_, nullptr, nullptr);
85 pa_stream_set_started_callback(paStream_, nullptr, nullptr);
86 pa_stream_disconnect(paStream_);
87 }
88 pa_stream_unref(paStream_);
89 paStream_ = nullptr;
90 }
91 }
92
InitParams()93 int32_t PaRendererStreamImpl::InitParams()
94 {
95 PaLockGuard lock(mainloop_);
96 rendererStreamInstanceMap_.Insert(this, weak_from_this());
97 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; }
98
99 sinkInputIndex_ = pa_stream_get_index(paStream_);
100 pa_stream_set_moved_callback(paStream_, PAStreamMovedCb,
101 reinterpret_cast<void *>(this)); // used to notify sink/source moved
102 pa_stream_set_write_callback(paStream_, PAStreamWriteCb, reinterpret_cast<void *>(this));
103 pa_stream_set_underflow_callback(paStream_, PAStreamUnderFlowCb, reinterpret_cast<void *>(this));
104 pa_stream_set_started_callback(paStream_, PAStreamSetStartedCb, reinterpret_cast<void *>(this));
105 pa_stream_set_underflow_ohos_callback(paStream_, PAStreamUnderFlowCountAddCb, reinterpret_cast<void *>(this));
106
107 // Get byte size per frame
108 const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
109 CHECK_AND_RETURN_RET_LOG(sampleSpec != nullptr, ERR_OPERATION_FAILED, "pa_sample_spec sampleSpec is nullptr");
110 AUDIO_INFO_LOG("sampleSpec: channels: %{public}u, formats: %{public}d, rate: %{public}d", sampleSpec->channels,
111 sampleSpec->format, sampleSpec->rate);
112
113 if (sampleSpec->channels != processConfig_.streamInfo.channels) {
114 AUDIO_WARNING_LOG("Unequal channels, in server: %{public}d, in client: %{public}d", sampleSpec->channels,
115 processConfig_.streamInfo.channels);
116 }
117 if (static_cast<uint8_t>(sampleSpec->format) != processConfig_.streamInfo.format) { // In plan
118 AUDIO_WARNING_LOG("Unequal format, in server: %{public}d, in client: %{public}d", sampleSpec->format,
119 processConfig_.streamInfo.format);
120 }
121 byteSizePerFrame_ = pa_frame_size(sampleSpec);
122
123 // Get min buffer size in frame
124 const pa_buffer_attr *bufferAttr = pa_stream_get_buffer_attr(paStream_);
125 if (bufferAttr == nullptr) {
126 int32_t count = ++bufferNullCount_;
127 AUDIO_ERR_LOG("pa_stream_get_buffer_attr returned nullptr count is %{public}d", count);
128 if (count >= 5) { // bufferAttr is nullptr 5 times, reboot audioserver
129 sleep(3); // sleep 3 seconds to dump stacktrace
130 AudioXCollie audioXCollie("AudioServer::Kill", 1, nullptr, nullptr, AUDIO_XCOLLIE_FLAG_RECOVERY);
131 sleep(2); // sleep 2 seconds to dump stacktrace
132 }
133 return ERR_OPERATION_FAILED;
134 }
135 bufferNullCount_ = 0;
136 minBufferSize_ = (size_t)bufferAttr->minreq;
137 if (byteSizePerFrame_ == 0) {
138 AUDIO_ERR_LOG("byteSizePerFrame_ should not be zero.");
139 return ERR_INVALID_PARAM;
140 }
141 spanSizeInFrame_ = minBufferSize_ / byteSizePerFrame_;
142
143 lock.Unlock();
144
145 AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, NO_FADE);
146 // In plan: Get data from xml
147 effectSceneName_ = processConfig_.rendererInfo.sceneType;
148
149 clientVolume_ = 1.0f;
150 ResetOffload();
151
152 return SUCCESS;
153 }
154
Start()155 int32_t PaRendererStreamImpl::Start()
156 {
157 AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
158 PaLockGuard lock(mainloop_);
159 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
160 return ERR_ILLEGAL_STATE;
161 }
162 pa_operation *operation = nullptr;
163
164 pa_stream_state_t state = pa_stream_get_state(paStream_);
165 if (state != PA_STREAM_READY) {
166 return ERR_OPERATION_FAILED;
167 }
168
169 streamCmdStatus_ = 0;
170 uint32_t oldFadeFlag = AudioVolume::GetInstance()->GetFadeoutState(sinkInputIndex_);
171 AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, NO_FADE);
172 if (oldFadeFlag != NO_FADE) {
173 AUDIO_INFO_LOG("SinkInput[%{public}u] fadeflag:%{public}u set to NO_FADE", sinkInputIndex_, oldFadeFlag);
174 }
175 operation = pa_stream_cork(paStream_, 0, PAStreamStartSuccessCb, reinterpret_cast<void *>(this));
176 CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
177 pa_operation_unref(operation);
178
179 std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
180 if (audioEffectVolume != nullptr) {
181 std::string sessionIDTemp = std::to_string(streamIndex_);
182 audioEffectVolume->SetStreamVolume(sessionIDTemp, clientVolume_);
183 }
184
185 return SUCCESS;
186 }
187
Pause(bool isStandby)188 int32_t PaRendererStreamImpl::Pause(bool isStandby)
189 {
190 AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
191 CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
192 "paStream[%{public}u] has been released", streamIndex_);
193 PaLockGuard palock(mainloop_, true);
194 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
195 return ERR_ILLEGAL_STATE;
196 }
197 pa_operation *operation = nullptr;
198 pa_stream_state_t state = pa_stream_get_state(paStream_);
199 if (state != PA_STREAM_READY) {
200 AUDIO_ERR_LOG("Stream Stop failed!");
201 return ERR_OPERATION_FAILED;
202 }
203
204 AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, DO_FADE);
205 if (!offloadEnable_) {
206 palock.Unlock();
207 {
208 std::unique_lock<std::mutex> lock(fadingMutex_);
209 const int32_t WAIT_TIME_MS = 40;
210 fadingCondition_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME_MS));
211 }
212 palock.Relock();
213 }
214
215 CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
216 "paStream[%{public}u] has been released", streamIndex_);
217 CHECK_AND_RETURN_RET_LOG(paStream_ != nullptr, ERR_ILLEGAL_STATE, "paStream[%{public}u] is null", streamIndex_);
218 isStandbyPause_ = isStandby;
219 operation = pa_stream_cork(paStream_, 1, PAStreamPauseSuccessCb, reinterpret_cast<void *>(this));
220 pa_operation_unref(operation);
221 CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
222 palock.Unlock();
223
224 if (effectMode_ == EFFECT_DEFAULT) {
225 AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
226 if (audioEffectChainManager == nullptr) {
227 AUDIO_INFO_LOG("audioEffectChainManager is null");
228 } else {
229 AUDIO_INFO_LOG("Pause make init effect buffer");
230 std::string sessionIDTemp = std::to_string(streamIndex_);
231 audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
232 }
233 }
234
235 std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
236 if (audioEffectVolume != nullptr) {
237 std::string sessionIDTemp = std::to_string(streamIndex_);
238 audioEffectVolume->StreamVolumeDelete(sessionIDTemp);
239 }
240 return SUCCESS;
241 }
242
Flush()243 int32_t PaRendererStreamImpl::Flush()
244 {
245 AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
246 PaLockGuard lock(mainloop_);
247 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
248 return ERR_ILLEGAL_STATE;
249 }
250
251 pa_operation *operation = nullptr;
252 pa_stream_state_t state = pa_stream_get_state(paStream_);
253 if (state != PA_STREAM_READY) {
254 AUDIO_ERR_LOG("Stream Flush failed!");
255 return ERR_OPERATION_FAILED;
256 }
257
258 streamFlushStatus_ = 0;
259 operation = pa_stream_flush(paStream_, PAStreamFlushSuccessCb, reinterpret_cast<void *>(this));
260 if (operation == nullptr) {
261 AUDIO_ERR_LOG("Stream Flush Operation failed!");
262 return ERR_OPERATION_FAILED;
263 }
264 Trace trace("PaRendererStreamImpl::InitAudioEffectChainDynamic");
265
266 if (effectMode_ == EFFECT_DEFAULT) {
267 AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
268 if (audioEffectChainManager == nullptr) {
269 AUDIO_INFO_LOG("audioEffectChainManager is null");
270 } else {
271 AUDIO_INFO_LOG("Flush make init effect buffer");
272 std::string sessionIDTemp = std::to_string(streamIndex_);
273 audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
274 }
275 }
276
277 pa_operation_unref(operation);
278 return SUCCESS;
279 }
280
Drain(bool stopFlag)281 int32_t PaRendererStreamImpl::Drain(bool stopFlag)
282 {
283 AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
284 PaLockGuard lock(mainloop_);
285 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
286 return ERR_ILLEGAL_STATE;
287 }
288 isDrain_ = true;
289
290 pa_operation *operation = nullptr;
291 pa_stream_state_t state = pa_stream_get_state(paStream_);
292 if (state != PA_STREAM_READY) {
293 AUDIO_ERR_LOG("Stream drain failed, state is not ready");
294 return ERR_OPERATION_FAILED;
295 }
296 streamDrainStatus_ = 0;
297 if (stopFlag && !offloadEnable_) {
298 AudioVolume::GetInstance()->SetStopFadeoutState(sinkInputIndex_, DO_FADE);
299 isDoFadeOut = true;
300 }
301 operation = pa_stream_drain(paStream_, PAStreamDrainSuccessCb, reinterpret_cast<void *>(this));
302 pa_operation_unref(operation);
303 return SUCCESS;
304 }
305
Stop()306 int32_t PaRendererStreamImpl::Stop()
307 {
308 AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
309 CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
310 "paStream[%{public}u] has been released", streamIndex_);
311 state_ = STOPPING;
312 PaLockGuard palock(mainloop_);
313
314 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
315 return ERR_ILLEGAL_STATE;
316 }
317
318 if (!isDoFadeOut && !offloadEnable_) {
319 AudioVolume::GetInstance()->SetFadeoutState(sinkInputIndex_, DO_FADE);
320 palock.Unlock();
321 {
322 std::unique_lock<std::mutex> lock(fadingMutex_);
323 const int32_t WAIT_TIME_MS = 20;
324 fadingCondition_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME_MS));
325 }
326 palock.Relock();
327 }
328 isDoFadeOut = false;
329 CHECK_AND_RETURN_RET_LOG(isReleased_ == false, ERR_ILLEGAL_STATE,
330 "paStream[%{public}u] has been released", streamIndex_);
331 CHECK_AND_RETURN_RET_LOG(paStream_ != nullptr, ERR_ILLEGAL_STATE, "paStream[%{public}u] is null", streamIndex_);
332
333 pa_operation *operation = pa_stream_cork(paStream_, 1, PaRendererStreamImpl::PAStreamAsyncStopSuccessCb,
334 reinterpret_cast<void *>(this));
335 CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
336 pa_operation_unref(operation);
337
338 if (effectMode_ == EFFECT_DEFAULT) {
339 AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
340 if (audioEffectChainManager == nullptr) {
341 AUDIO_INFO_LOG("audioEffectChainManager is null");
342 } else {
343 AUDIO_INFO_LOG("Stop make init effect buffer");
344 std::string sessionIDTemp = std::to_string(streamIndex_);
345 audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
346 }
347 }
348
349 std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
350 if (audioEffectVolume != nullptr) {
351 std::string sessionIDTemp = std::to_string(streamIndex_);
352 audioEffectVolume->StreamVolumeDelete(sessionIDTemp);
353 }
354
355 return SUCCESS;
356 }
357
Release()358 int32_t PaRendererStreamImpl::Release()
359 {
360 AUDIO_INFO_LOG("[%{public}u] Enter", streamIndex_);
361 isReleased_ = true;
362 if (state_ == RUNNING) {
363 PaLockGuard lock(mainloop_);
364 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
365 return ERR_ILLEGAL_STATE;
366 }
367 pa_operation *operation = pa_stream_cork(paStream_, 1, nullptr, nullptr);
368 CHECK_AND_RETURN_RET_LOG(operation != nullptr, ERR_OPERATION_FAILED, "pa_stream_cork operation is null");
369 pa_operation_unref(operation);
370 }
371
372 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
373 if (statusCallback != nullptr) {
374 statusCallback->OnStatusUpdate(OPERATION_RELEASED);
375 }
376 state_ = RELEASED;
377
378 if (effectMode_ == EFFECT_DEFAULT) {
379 AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
380 if (audioEffectChainManager == nullptr) {
381 AUDIO_INFO_LOG("audioEffectChainManager is null");
382 } else {
383 AUDIO_INFO_LOG("Release make init effect buffer");
384 std::string sessionIDTemp = std::to_string(streamIndex_);
385 audioEffectChainManager->InitEffectBuffer(sessionIDTemp);
386 }
387 }
388
389 std::shared_ptr<AudioEffectVolume> audioEffectVolume = AudioEffectVolume::GetInstance();
390 if (audioEffectVolume != nullptr) {
391 std::string sessionIDTemp = std::to_string(streamIndex_);
392 audioEffectVolume->StreamVolumeDelete(sessionIDTemp);
393 }
394
395 AudioVolume::GetInstance()->RemoveFadeoutState(sinkInputIndex_);
396 AudioVolume::GetInstance()->RemoveStopFadeoutState(sinkInputIndex_);
397 isDoFadeOut = false;
398
399 PaLockGuard lock(mainloop_);
400 if (paStream_) {
401 pa_stream_set_state_callback(paStream_, nullptr, nullptr);
402 pa_stream_set_write_callback(paStream_, nullptr, nullptr);
403 pa_stream_set_latency_update_callback(paStream_, nullptr, nullptr);
404 pa_stream_set_underflow_callback(paStream_, nullptr, nullptr);
405 pa_stream_set_moved_callback(paStream_, nullptr, nullptr);
406 pa_stream_set_started_callback(paStream_, nullptr, nullptr);
407
408 pa_stream_disconnect(paStream_);
409 releasedFlag_ = true;
410 }
411
412 return SUCCESS;
413 }
414
GetStreamFramesWritten(uint64_t & framesWritten)415 int32_t PaRendererStreamImpl::GetStreamFramesWritten(uint64_t &framesWritten)
416 {
417 CHECK_AND_RETURN_RET_LOG(byteSizePerFrame_ != 0, ERR_ILLEGAL_STATE, "Error frame size");
418 framesWritten = totalBytesWritten_ / byteSizePerFrame_;
419 return SUCCESS;
420 }
421
GetCurrentTimeStamp(uint64_t & timestamp)422 int32_t PaRendererStreamImpl::GetCurrentTimeStamp(uint64_t ×tamp)
423 {
424 PaLockGuard lock(mainloop_);
425 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
426 return ERR_ILLEGAL_STATE;
427 }
428 if (state_ == RELEASED) {
429 AUDIO_WARNING_LOG("stream is released, remain current timestamp unchanged");
430 return SUCCESS;
431 }
432 AudioXCollie audioXCollie("PaRendererStreamImpl::GetCurrentTimeStamp", PA_STREAM_IMPL_TIMEOUT,
433 [](void *) {
434 AUDIO_ERR_LOG("pulseAudio timeout");
435 }, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
436
437 UpdatePaTimingInfo();
438
439 const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
440 if (info == nullptr) {
441 AUDIO_ERR_LOG("pa_stream_get_timing_info failed");
442 return ERR_OPERATION_FAILED;
443 }
444
445 const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
446 timestamp = pa_bytes_to_usec(info->write_index, sampleSpec);
447 return SUCCESS;
448 }
449
GetCurrentPosition(uint64_t & framePosition,uint64_t & timestamp,uint64_t & latency,int32_t base)450 int32_t PaRendererStreamImpl::GetCurrentPosition(uint64_t &framePosition, uint64_t ×tamp, uint64_t &latency,
451 int32_t base)
452 {
453 Trace trace("PaRendererStreamImpl::GetCurrentPosition");
454 PaLockGuard lock(mainloop_);
455 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
456 return ERR_ILLEGAL_STATE;
457 }
458 if (state_ == RELEASED) {
459 AUDIO_WARNING_LOG("stream is released, remain current position unchanged");
460 return SUCCESS;
461 }
462 AudioXCollie audioXCollie("PaRendererStreamImpl::GetCurrentPosition", PA_STREAM_IMPL_TIMEOUT,
463 [](void *) { AUDIO_ERR_LOG("pulseAudio timeout"); }, nullptr,
464 AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
465
466 pa_usec_t curTimeGetLatency = pa_rtclock_now();
467 if (curTimeGetLatency - preTimeGetPaLatency_ > AUDIO_CYCLE_TIME_US || firstGetPaLatency_) { // 20000 cycle time
468 UpdatePaTimingInfo();
469 firstGetPaLatency_ = false;
470 preTimeGetPaLatency_ = curTimeGetLatency;
471 }
472
473 const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
474 CHECK_AND_RETURN_RET_LOG(info != nullptr, ERR_OPERATION_FAILED, "pa_stream_get_timing_info failed");
475 const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
476 uint64_t readIndex = pa_bytes_to_usec(info->read_index, sampleSpec);
477 framePosition = readIndex * sampleSpec->rate / AUDIO_US_PER_S;
478 latency = info->sink_usec * sampleSpec->rate / AUDIO_US_PER_S;
479 lock.Unlock();
480
481 // Processing data for algorithmic time delays
482 uint32_t algorithmLatency = GetEffectChainLatency();
483 if (!offloadEnable_) {
484 latency += algorithmLatency * sampleSpec->rate / AUDIO_MS_PER_S;
485 }
486 // Processing data for a2dpoffload time delays
487 uint32_t a2dpOffloadLatency = GetA2dpOffloadLatency();
488 latency += a2dpOffloadLatency * sampleSpec->rate / AUDIO_MS_PER_S;
489 // Processing data for nearlink time delays
490 uint32_t nearlinkLatency = GetNearlinkLatency();
491 latency += nearlinkLatency * sampleSpec->rate / AUDIO_MS_PER_S;
492
493 int64_t stamp = 0;
494 stamp = base == Timestamp::BOOTTIME ? ClockTime::GetBootNano() : ClockTime::GetCurNano();
495 timestamp = stamp >= 0 ? stamp : 0;
496
497 AUDIO_DEBUG_LOG("Latency info: framePosition: %{public}" PRIu64 ",readIndex %{public}" PRIu64
498 ", base %{public}d, timestamp %{public}" PRIu64
499 ", effect latency: %{public}u ms, a2dp offload latency: %{public}u ms, nearlink latency: %{public}u ms",
500 framePosition, readIndex, base, timestamp, algorithmLatency, a2dpOffloadLatency, nearlinkLatency);
501 return SUCCESS;
502 }
503
PAStreamUpdateTimingInfoSuccessCb(pa_stream * stream,int32_t success,void * userdata)504 void PaRendererStreamImpl::PAStreamUpdateTimingInfoSuccessCb(pa_stream *stream, int32_t success, void *userdata)
505 {
506 PaRendererStreamImpl *rendererStreamImpl = (PaRendererStreamImpl *)userdata;
507 pa_threaded_mainloop *mainLoop = (pa_threaded_mainloop *)rendererStreamImpl->mainloop_;
508 pa_threaded_mainloop_signal(mainLoop, 0);
509 }
510
GetLatency(uint64_t & latency)511 int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency)
512 {
513 Trace trace("PaRendererStreamImpl::GetLatency");
514 AudioXCollie audioXCollie("PaRendererStreamImpl::GetLatency", PA_STREAM_IMPL_TIMEOUT,
515 [](void *) {
516 AUDIO_ERR_LOG("pulseAudio timeout");
517 }, nullptr, AUDIO_XCOLLIE_FLAG_LOG | AUDIO_XCOLLIE_FLAG_RECOVERY);
518 pa_usec_t curTimeGetLatency = pa_rtclock_now();
519 if (curTimeGetLatency - preTimeGetLatency_ < AUDIO_CYCLE_TIME_US && !firstGetLatency_) { // 20000 cycle time
520 latency = preLatency_;
521 return SUCCESS;
522 }
523 PaLockGuard lock(mainloop_);
524 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
525 return ERR_ILLEGAL_STATE;
526 }
527 if (state_ == RELEASED) {
528 AUDIO_WARNING_LOG("stream is released, latency is 0");
529 latency = 0;
530 return SUCCESS;
531 }
532 pa_usec_t paLatency {0};
533
534 UpdatePaTimingInfo();
535 const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
536 CHECK_AND_RETURN_RET_LOG(info != nullptr, ERR_OPERATION_FAILED, "pa_stream_get_timing_info failed");
537 const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
538 uint64_t readIndex = pa_bytes_to_usec(info->read_index < 0 ? 0 : info->read_index, sampleSpec);
539 uint64_t writeIndex = pa_bytes_to_usec(info->write_index < 0 ? 0 : info->write_index, sampleSpec);
540 pa_usec_t usec = readIndex >= info->sink_usec ? readIndex - info->sink_usec : 0;
541 paLatency = writeIndex >= usec ? writeIndex - usec : 0;
542 lock.Unlock();
543
544 latency = paLatency;
545 uint32_t algorithmLatency = GetEffectChainLatency();
546 latency += offloadEnable_ ? 0 : algorithmLatency * AUDIO_US_PER_MS;
547 uint32_t a2dpOffloadLatency = GetA2dpOffloadLatency();
548 latency += a2dpOffloadLatency * AUDIO_US_PER_MS;
549 uint32_t nearlinkLatency = GetNearlinkLatency();
550 latency += nearlinkLatency * AUDIO_US_PER_MS;
551 uint32_t limiterLatency = GetLimiterLatency();
552 latency += limiterLatency * AUDIO_US_PER_MS;
553
554 AUDIO_DEBUG_LOG("total latency: %{public}" PRIu64 ", pa latency: %{public}" PRIu64 ", algo latency: %{public}u ms"
555 ", a2dp offload latency: %{public}u ms, nearlink latency: %{public}u ms, lmt latency: %{public}u ms"
556 ", write: %{public}" PRIu64 ", read: %{public}" PRIu64 ", sink:%{public}" PRIu64 "", latency, paLatency,
557 algorithmLatency, a2dpOffloadLatency, nearlinkLatency, limiterLatency, writeIndex, readIndex, info->sink_usec);
558
559 preLatency_ = latency;
560 preTimeGetLatency_ = curTimeGetLatency;
561 firstGetLatency_ = false;
562 return SUCCESS;
563 }
564
GetEffectChainLatency()565 uint32_t PaRendererStreamImpl::GetEffectChainLatency()
566 {
567 AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
568 uint32_t algorithmLatency = 0;
569 if (audioEffectChainManager != nullptr) {
570 algorithmLatency = audioEffectChainManager->GetLatency(std::to_string(streamIndex_));
571 }
572 return algorithmLatency;
573 }
574
GetA2dpOffloadLatency()575 uint32_t PaRendererStreamImpl::GetA2dpOffloadLatency()
576 {
577 Trace trace("PaRendererStreamImpl::GetA2dpOffloadLatency");
578 uint32_t a2dpOffloadLatency = 0;
579 uint64_t a2dpOffloadSendDataSize = 0;
580 uint32_t a2dpOffloadTimestamp = 0;
581 auto& handle = PolicyHandler::GetInstance();
582 int32_t ret = handle.OffloadGetRenderPosition(a2dpOffloadLatency, a2dpOffloadSendDataSize, a2dpOffloadTimestamp);
583 if (ret != SUCCESS) {
584 AUDIO_ERR_LOG("OffloadGetRenderPosition failed");
585 }
586 return a2dpOffloadLatency;
587 }
588
GetNearlinkLatency()589 uint32_t PaRendererStreamImpl::GetNearlinkLatency()
590 {
591 Trace trace("PaRendererStreamImpl::GetNearlinkLatency");
592 uint32_t nearlinkLatency = 0;
593 auto &handler = PolicyHandler::GetInstance();
594 int32_t ret = handler.NearlinkGetRenderPosition(nearlinkLatency);
595 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, 0, "NearlinkGetRenderPosition failed");
596
597 return nearlinkLatency;
598 }
599
GetLimiterLatency()600 uint32_t PaRendererStreamImpl::GetLimiterLatency()
601 {
602 AudioLmtManager *audioLmtManager = AudioLmtManager::GetInstance();
603 uint32_t limiterLatency = 0;
604 if (audioLmtManager != nullptr) {
605 int32_t sinkIndex = static_cast<int32_t>(pa_stream_get_device_index(paStream_));
606 limiterLatency = audioLmtManager->GetLatency(sinkIndex);
607 }
608 return limiterLatency;
609 }
610
SetRate(int32_t rate)611 int32_t PaRendererStreamImpl::SetRate(int32_t rate)
612 {
613 AUDIO_INFO_LOG("SetRate in");
614 PaLockGuard lock(mainloop_);
615 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
616 return ERR_ILLEGAL_STATE;
617 }
618 uint32_t currentRate = processConfig_.streamInfo.samplingRate;
619 switch (rate) {
620 case RENDER_RATE_NORMAL:
621 break;
622 case RENDER_RATE_DOUBLE:
623 currentRate *= DOUBLE_VALUE;
624 break;
625 case RENDER_RATE_HALF:
626 currentRate /= DOUBLE_VALUE;
627 break;
628 default:
629 return ERR_INVALID_PARAM;
630 }
631 renderRate_ = rate;
632
633 pa_operation *operation = pa_stream_update_sample_rate(paStream_, currentRate, nullptr, nullptr);
634 if (operation != nullptr) {
635 pa_operation_unref(operation);
636 } else {
637 AUDIO_ERR_LOG("SetRate: operation is nullptr!");
638 }
639 return SUCCESS;
640 }
641
SetAudioEffectMode(int32_t effectMode)642 int32_t PaRendererStreamImpl::SetAudioEffectMode(int32_t effectMode)
643 {
644 AUDIO_INFO_LOG("SetAudioEffectMode: %{public}d", effectMode);
645 PaLockGuard lock(mainloop_);
646 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
647 return ERR_ILLEGAL_STATE;
648 }
649
650 effectMode_ = effectMode;
651 const std::string effectModeName = GetEffectModeName(effectMode_);
652
653 pa_proplist *propList = pa_proplist_new();
654 if (propList == nullptr) {
655 AUDIO_ERR_LOG("pa_proplist_new failed");
656 return ERR_OPERATION_FAILED;
657 }
658
659 pa_proplist_sets(propList, "scene.mode", effectModeName.c_str());
660 pa_operation *updatePropOperation = pa_stream_proplist_update(paStream_, PA_UPDATE_REPLACE, propList,
661 nullptr, nullptr);
662 pa_proplist_free(propList);
663 CHECK_AND_RETURN_RET_LOG(updatePropOperation != nullptr, ERR_OPERATION_FAILED, "updatePropOperation is nullptr!");
664 pa_operation_unref(updatePropOperation);
665
666 return SUCCESS;
667 }
668
GetEffectModeName(int32_t effectMode)669 const std::string PaRendererStreamImpl::GetEffectModeName(int32_t effectMode)
670 {
671 std::string name;
672 switch (effectMode) {
673 case 0: // AudioEffectMode::EFFECT_NONE
674 name = "EFFECT_NONE";
675 break;
676 default:
677 name = "EFFECT_DEFAULT";
678 }
679
680 const std::string modeName = name;
681 return modeName;
682 }
683
GetAudioEffectMode(int32_t & effectMode)684 int32_t PaRendererStreamImpl::GetAudioEffectMode(int32_t &effectMode)
685 {
686 effectMode = effectMode_;
687 return SUCCESS;
688 }
689
SetPrivacyType(int32_t privacyType)690 int32_t PaRendererStreamImpl::SetPrivacyType(int32_t privacyType)
691 {
692 AUDIO_DEBUG_LOG("SetInnerCapturerState: %{public}d", privacyType);
693 privacyType_ = privacyType;
694 return SUCCESS;
695 }
696
GetPrivacyType(int32_t & privacyType)697 int32_t PaRendererStreamImpl::GetPrivacyType(int32_t &privacyType)
698 {
699 privacyType_ = privacyType;
700 return SUCCESS;
701 }
702
SetSpeed(float speed)703 int32_t PaRendererStreamImpl::SetSpeed(float speed)
704 {
705 AUDIO_WARNING_LOG("not support");
706 return ERR_NOT_SUPPORTED;
707 }
708
RegisterStatusCallback(const std::weak_ptr<IStatusCallback> & callback)709 void PaRendererStreamImpl::RegisterStatusCallback(const std::weak_ptr<IStatusCallback> &callback)
710 {
711 AUDIO_DEBUG_LOG("RegisterStatusCallback in");
712 statusCallback_ = callback;
713 }
714
RegisterWriteCallback(const std::weak_ptr<IWriteCallback> & callback)715 void PaRendererStreamImpl::RegisterWriteCallback(const std::weak_ptr<IWriteCallback> &callback)
716 {
717 AUDIO_DEBUG_LOG("RegisterWriteCallback in");
718 writeCallback_ = callback;
719 }
720
DequeueBuffer(size_t length)721 BufferDesc PaRendererStreamImpl::DequeueBuffer(size_t length)
722 {
723 BufferDesc bufferDesc;
724 bufferDesc.bufLength = length;
725 // DequeueBuffer is called in PAStreamWriteCb which is running in mainloop, so don't need lock mainloop.
726 pa_stream_begin_write(paStream_, reinterpret_cast<void **>(&bufferDesc.buffer), &bufferDesc.bufLength);
727 return bufferDesc;
728 }
729
EnqueueBuffer(const BufferDesc & bufferDesc)730 int32_t PaRendererStreamImpl::EnqueueBuffer(const BufferDesc &bufferDesc)
731 {
732 Trace trace("PaRendererStreamImpl::EnqueueBuffer " + std::to_string(bufferDesc.bufLength) + " totalBytesWritten" +
733 std::to_string(totalBytesWritten_));
734 int32_t error = 0;
735 if (offloadEnable_) {
736 error = OffloadUpdatePolicyInWrite();
737 CHECK_AND_RETURN_RET_LOG(error == SUCCESS, error, "OffloadUpdatePolicyInWrite failed");
738 }
739
740 // EnqueueBuffer is called in mainloop in most cases and don't need lock.
741 PaLockGuard palock(mainloop_, true);
742
743 if (paStream_ == nullptr) {
744 AUDIO_ERR_LOG("paStream is nullptr!");
745 return ERR_ILLEGAL_STATE;
746 }
747
748 error = pa_stream_write(paStream_, static_cast<void*>(bufferDesc.buffer), bufferDesc.bufLength, nullptr,
749 0LL, PA_SEEK_RELATIVE);
750 if (error < 0) {
751 AUDIO_ERR_LOG("Write stream failed");
752 pa_stream_cancel_write(paStream_);
753 }
754 totalBytesWritten_ += bufferDesc.bufLength;
755 return SUCCESS;
756 }
757
PAStreamWriteCb(pa_stream * stream,size_t length,void * userdata)758 void PaRendererStreamImpl::PAStreamWriteCb(pa_stream *stream, size_t length, void *userdata)
759 {
760 CHECK_AND_RETURN_LOG(userdata, "PAStreamWriteCb: userdata is null");
761
762 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
763 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
764 AUDIO_ERR_LOG("streamImpl is nullptr!");
765 return;
766 }
767 auto streamImpl = paRendererStreamWeakPtr.lock();
768 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
769
770 Trace trace("PaRendererStreamImpl::PAStreamWriteCb sink-input:" + std::to_string(streamImpl->sinkInputIndex_) +
771 " length:" + std::to_string(length));
772 std::shared_ptr<IWriteCallback> writeCallback = streamImpl->writeCallback_.lock();
773 if (writeCallback != nullptr) {
774 writeCallback->OnWriteData(length);
775 } else {
776 AUDIO_ERR_LOG("Write callback is nullptr!");
777 }
778 }
779
PAStreamMovedCb(pa_stream * stream,void * userdata)780 void PaRendererStreamImpl::PAStreamMovedCb(pa_stream *stream, void *userdata)
781 {
782 CHECK_AND_RETURN_LOG(userdata, "PAStreamMovedCb: userdata is null");
783
784 // get stream informations.
785 uint32_t deviceIndex = pa_stream_get_device_index(stream); // pa_context_get_sink_info_by_index
786 uint32_t streamIndex = pa_stream_get_index(stream); // get pa_stream index
787 const char *deviceName = pa_stream_get_device_name(stream);
788
789 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
790 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
791 AUDIO_ERR_LOG("streamImpl is nullptr!");
792 return;
793 }
794 auto streamImpl = paRendererStreamWeakPtr.lock();
795 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamMovedCb: userdata is null");
796
797 if (deviceName != nullptr && !strcmp(deviceName, REMOTE_CAST_INNER_CAPTURER_SINK_NAME)) {
798 streamImpl->remoteCastMovedFlag_ = true;
799 streamImpl->UpdateBufferSize(CAST_BUF_LENGTH_IN_MS);
800 } else if (streamImpl->remoteCastMovedFlag_) {
801 streamImpl->remoteCastMovedFlag_ = false;
802 streamImpl->UpdateBufferSize(BUF_LENGTH_IN_MS);
803 }
804
805 // Return 1 if the sink or source this stream is connected to has been suspended.
806 // This will return 0 if not, and a negative value on error.
807 int res = pa_stream_is_suspended(stream);
808 AUDIO_WARNING_LOG("PAstream:[%{public}d] moved to index:[%{public}d] suspended:[%{public}d]",
809 streamIndex, deviceIndex, res);
810 }
811
PAStreamUnderFlowCb(pa_stream * stream,void * userdata)812 void PaRendererStreamImpl::PAStreamUnderFlowCb(pa_stream *stream, void *userdata)
813 {
814 Trace trace("PaRendererStreamImpl::PAStreamUnderFlowCb");
815 CHECK_AND_RETURN_LOG(userdata, "userdata is null");
816
817 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
818 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
819 AUDIO_ERR_LOG("streamImpl is nullptr!");
820 return;
821 }
822 auto streamImpl = paRendererStreamWeakPtr.lock();
823 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
824
825 streamImpl->underFlowCount_++;
826 std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
827 if (statusCallback != nullptr) {
828 statusCallback->OnStatusUpdate(OPERATION_UNDERRUN);
829 }
830 AUDIO_WARNING_LOG("PaRendererStreamImpl underrun: %{public}d!", streamImpl->underFlowCount_);
831 }
832
PAStreamUnderFlowCountAddCb(pa_stream * stream,void * userdata)833 void PaRendererStreamImpl::PAStreamUnderFlowCountAddCb(pa_stream *stream, void *userdata)
834 {
835 Trace trace("PaRendererStreamImpl::PAStreamUnderFlowCountAddCb");
836 CHECK_AND_RETURN_LOG(userdata, "userdata is null");
837
838 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
839 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
840 AUDIO_ERR_LOG("streamImpl is nullptr");
841 return;
842 }
843 auto streamImpl = paRendererStreamWeakPtr.lock();
844 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
845
846 std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
847 if (statusCallback != nullptr) {
848 statusCallback->OnStatusUpdate(OPERATION_UNDERFLOW);
849 }
850 }
851
PAStreamSetStartedCb(pa_stream * stream,void * userdata)852 void PaRendererStreamImpl::PAStreamSetStartedCb(pa_stream *stream, void *userdata)
853 {
854 CHECK_AND_RETURN_LOG(userdata, "PAStreamSetStartedCb: userdata is null");
855 AUDIO_PRERELEASE_LOGI("PAStreamSetStartedCb");
856 Trace trace("PaRendererStreamImpl::PAStreamSetStartedCb");
857 }
858
PAStreamStartSuccessCb(pa_stream * stream,int32_t success,void * userdata)859 void PaRendererStreamImpl::PAStreamStartSuccessCb(pa_stream *stream, int32_t success, void *userdata)
860 {
861 AUDIO_INFO_LOG("PAStreamStartSuccessCb in");
862 CHECK_AND_RETURN_LOG(userdata, "PAStreamStartSuccessCb: userdata is null");
863
864 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
865 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
866 AUDIO_ERR_LOG("streamImpl is nullptr");
867 return;
868 }
869 auto streamImpl = paRendererStreamWeakPtr.lock();
870 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
871
872 streamImpl->state_ = RUNNING;
873 streamImpl->offloadTsLast_ = 0;
874 std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
875 if (statusCallback != nullptr) {
876 statusCallback->OnStatusUpdate(OPERATION_STARTED);
877 }
878 streamImpl->streamCmdStatus_ = success;
879 }
880
PAStreamPauseSuccessCb(pa_stream * stream,int32_t success,void * userdata)881 void PaRendererStreamImpl::PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata)
882 {
883 CHECK_AND_RETURN_LOG(userdata, "PAStreamPauseSuccessCb: userdata is null");
884
885 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
886 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
887 AUDIO_ERR_LOG("streamImpl is nullptr");
888 return;
889 }
890 auto streamImpl = paRendererStreamWeakPtr.lock();
891 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
892
893 streamImpl->state_ = PAUSED;
894 if (streamImpl->offloadEnable_ && !streamImpl->isStandbyPause_) {
895 streamImpl->offloadTsLast_ = 0;
896 streamImpl->ResetOffload();
897 }
898 std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
899 if (statusCallback != nullptr) {
900 statusCallback->OnStatusUpdate(OPERATION_PAUSED);
901 }
902 streamImpl->streamCmdStatus_ = success;
903 }
904
PAStreamFlushSuccessCb(pa_stream * stream,int32_t success,void * userdata)905 void PaRendererStreamImpl::PAStreamFlushSuccessCb(pa_stream *stream, int32_t success, void *userdata)
906 {
907 CHECK_AND_RETURN_LOG(userdata, "PAStreamFlushSuccessCb: userdata is null");
908 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
909 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
910 AUDIO_ERR_LOG("streamImpl is nullptr");
911 return;
912 }
913 auto streamImpl = paRendererStreamWeakPtr.lock();
914 CHECK_AND_RETURN_LOG(streamImpl, "Userdata is null");
915
916 std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
917 if (statusCallback != nullptr) {
918 statusCallback->OnStatusUpdate(OPERATION_FLUSHED);
919 }
920 streamImpl->streamFlushStatus_ = success;
921 }
922
PAStreamDrainSuccessCb(pa_stream * stream,int32_t success,void * userdata)923 void PaRendererStreamImpl::PAStreamDrainSuccessCb(pa_stream *stream, int32_t success, void *userdata)
924 {
925 CHECK_AND_RETURN_LOG(userdata, "PAStreamDrainSuccessCb: userdata is null");
926
927 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
928 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
929 AUDIO_ERR_LOG("streamImpl is nullptr");
930 return;
931 }
932 auto streamImpl = paRendererStreamWeakPtr.lock();
933 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
934
935 std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
936 if (statusCallback != nullptr) {
937 statusCallback->OnStatusUpdate(OPERATION_DRAINED);
938 }
939 streamImpl->streamDrainStatus_ = success;
940 streamImpl->isDrain_ = false;
941 }
942
PAStreamDrainInStopCb(pa_stream * stream,int32_t success,void * userdata)943 void PaRendererStreamImpl::PAStreamDrainInStopCb(pa_stream *stream, int32_t success, void *userdata)
944 {
945 CHECK_AND_RETURN_LOG(userdata, "PAStreamDrainInStopCb: userdata is null");
946
947 PaRendererStreamImpl *streamImpl = static_cast<PaRendererStreamImpl *>(userdata);
948 pa_operation *operation = pa_stream_cork(streamImpl->paStream_, 1,
949 PaRendererStreamImpl::PAStreamAsyncStopSuccessCb, userdata);
950
951 CHECK_AND_RETURN_LOG(operation != nullptr, "pa_stream_cork operation is null");
952
953 pa_operation_unref(operation);
954 streamImpl->streamDrainStatus_ = success;
955 }
956
PAStreamAsyncStopSuccessCb(pa_stream * stream,int32_t success,void * userdata)957 void PaRendererStreamImpl::PAStreamAsyncStopSuccessCb(pa_stream *stream, int32_t success, void *userdata)
958 {
959 AUDIO_DEBUG_LOG("PAStreamAsyncStopSuccessCb in");
960 CHECK_AND_RETURN_LOG(userdata, "PAStreamAsyncStopSuccessCb: userdata is null");
961 std::weak_ptr<PaRendererStreamImpl> paRendererStreamWeakPtr;
962 if (rendererStreamInstanceMap_.Find(userdata, paRendererStreamWeakPtr) == false) {
963 AUDIO_ERR_LOG("streamImpl is nullptr");
964 return;
965 }
966 auto streamImpl = paRendererStreamWeakPtr.lock();
967 CHECK_AND_RETURN_LOG(streamImpl, "PAStreamWriteCb: userdata is null");
968
969 streamImpl->state_ = STOPPED;
970 std::shared_ptr<IStatusCallback> statusCallback = streamImpl->statusCallback_.lock();
971
972 if (statusCallback != nullptr) {
973 statusCallback->OnStatusUpdate(OPERATION_STOPPED);
974 }
975 }
976
GetMinimumBufferSize(size_t & minBufferSize) const977 int32_t PaRendererStreamImpl::GetMinimumBufferSize(size_t &minBufferSize) const
978 {
979 minBufferSize = minBufferSize_;
980 return SUCCESS;
981 }
982
GetByteSizePerFrame(size_t & byteSizePerFrame) const983 void PaRendererStreamImpl::GetByteSizePerFrame(size_t &byteSizePerFrame) const
984 {
985 byteSizePerFrame = byteSizePerFrame_;
986 }
987
GetSpanSizePerFrame(size_t & spanSizeInFrame) const988 void PaRendererStreamImpl::GetSpanSizePerFrame(size_t &spanSizeInFrame) const
989 {
990 spanSizeInFrame = spanSizeInFrame_;
991 }
992
SetStreamIndex(uint32_t index)993 void PaRendererStreamImpl::SetStreamIndex(uint32_t index)
994 {
995 AUDIO_INFO_LOG("Using index/sessionId %{public}d", index);
996 streamIndex_ = index;
997 }
998
GetStreamIndex()999 uint32_t PaRendererStreamImpl::GetStreamIndex()
1000 {
1001 return streamIndex_;
1002 }
1003
1004 // offload
GetWritableSize()1005 size_t PaRendererStreamImpl::GetWritableSize()
1006 {
1007 PaLockGuard lock(mainloop_, true);
1008 if (paStream_ == nullptr) {
1009 return 0;
1010 }
1011 return pa_stream_writable_size(paStream_);
1012 }
1013
OffloadSetVolume(float volume)1014 int32_t PaRendererStreamImpl::OffloadSetVolume(float volume)
1015 {
1016 if (!offloadEnable_) {
1017 return ERR_OPERATION_FAILED;
1018 }
1019 uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1020 std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1021 CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1022 return sink->SetVolume(volume, volume);
1023 }
1024
SetOffloadDataCallbackState(int32_t state)1025 int32_t PaRendererStreamImpl::SetOffloadDataCallbackState(int32_t state)
1026 {
1027 AUDIO_INFO_LOG("SetOffloadDataCallbackState state: %{public}d", state);
1028 if (!offloadEnable_) {
1029 return ERR_OPERATION_FAILED;
1030 }
1031 uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1032 std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1033 CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1034 return sink->SetOffloadRenderCallbackType(static_cast<RenderCallbackType>(state));
1035 }
1036
UpdateSpatializationState(bool spatializationEnabled,bool headTrackingEnabled)1037 int32_t PaRendererStreamImpl::UpdateSpatializationState(bool spatializationEnabled, bool headTrackingEnabled)
1038 {
1039 PaLockGuard lock(mainloop_);
1040 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
1041 return ERR_ILLEGAL_STATE;
1042 }
1043
1044 pa_proplist *propList = pa_proplist_new();
1045 if (propList == nullptr) {
1046 AUDIO_ERR_LOG("pa_proplist_new failed");
1047 return ERR_OPERATION_FAILED;
1048 }
1049
1050 pa_proplist_sets(propList, "spatialization.enabled", std::to_string(spatializationEnabled).c_str());
1051 pa_proplist_sets(propList, "headtracking.enabled", std::to_string(headTrackingEnabled).c_str());
1052 pa_operation *updatePropOperation = pa_stream_proplist_update(paStream_, PA_UPDATE_REPLACE, propList,
1053 nullptr, nullptr);
1054 pa_proplist_free(propList);
1055 CHECK_AND_RETURN_RET_LOG(updatePropOperation != nullptr, ERR_OPERATION_FAILED, "updatePropOperation is nullptr");
1056 pa_operation_unref(updatePropOperation);
1057
1058 return SUCCESS;
1059 }
1060
OffloadGetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)1061 int32_t PaRendererStreamImpl::OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec)
1062 {
1063 uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1064 std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1065 CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1066 return sink->GetPresentationPosition(frames, timeSec, timeNanoSec);
1067 }
1068
OffloadSetBufferSize(uint32_t sizeMs)1069 int32_t PaRendererStreamImpl::OffloadSetBufferSize(uint32_t sizeMs)
1070 {
1071 uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD);
1072 std::shared_ptr<IAudioRenderSink> sink = HdiAdapterManager::GetInstance().GetRenderSink(id);
1073 CHECK_AND_RETURN_RET_LOG(sink != nullptr, ERROR, "Renderer is null.");
1074 return sink->SetBufferSize(sizeMs);
1075 }
1076
GetOffloadApproximatelyCacheTime(uint64_t & timestamp,uint64_t & paWriteIndex,uint64_t & cacheTimeDsp,uint64_t & cacheTimePa)1077 int32_t PaRendererStreamImpl::GetOffloadApproximatelyCacheTime(uint64_t ×tamp, uint64_t &paWriteIndex,
1078 uint64_t &cacheTimeDsp, uint64_t &cacheTimePa)
1079 {
1080 if (!offloadEnable_) {
1081 return ERR_OPERATION_FAILED;
1082 }
1083 PaLockGuard lock(mainloop_);
1084 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
1085 return ERR_ILLEGAL_STATE;
1086 }
1087
1088 pa_operation *operation = pa_stream_update_timing_info(paStream_, NULL, NULL);
1089 if (operation != nullptr) {
1090 pa_operation_unref(operation);
1091 } else {
1092 AUDIO_ERR_LOG("pa_stream_update_timing_info failed");
1093 }
1094
1095 const pa_timing_info *info = pa_stream_get_timing_info(paStream_);
1096 if (info == nullptr) {
1097 AUDIO_WARNING_LOG("pa_stream_get_timing_info failed");
1098 return SUCCESS;
1099 }
1100
1101 const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
1102 uint64_t readIndex = pa_bytes_to_usec(info->read_index, sampleSpec);
1103 uint64_t writeIndex = pa_bytes_to_usec(info->write_index, sampleSpec);
1104 timestamp = info->timestamp.tv_sec * AUDIO_US_PER_SECOND + info->timestamp.tv_usec;
1105 lock.Unlock();
1106
1107 uint64_t cacheTimeInPulse = writeIndex > readIndex ? writeIndex - readIndex : 0;
1108 cacheTimePa = cacheTimeInPulse;
1109 paWriteIndex = writeIndex;
1110
1111 bool first = offloadTsLast_ == 0;
1112 offloadTsLast_ = readIndex;
1113
1114 uint64_t frames = 0;
1115 int64_t timeSec = 0;
1116 int64_t timeNanoSec = 0;
1117 OffloadGetPresentationPosition(frames, timeSec, timeNanoSec);
1118 int64_t timeDelta = static_cast<int64_t>(timestamp) -
1119 static_cast<int64_t>(timeSec * AUDIO_US_PER_SECOND + timeNanoSec / AUDIO_NS_PER_US);
1120 int64_t framesInt = static_cast<int64_t>(frames) + timeDelta;
1121 framesInt = framesInt > 0 ? framesInt : 0;
1122 int64_t readIndexInt = static_cast<int64_t>(readIndex);
1123 if (framesInt + offloadTsOffset_ < readIndexInt - static_cast<int64_t>(
1124 (OFFLOAD_HDI_CACHE2 + MAX_LENGTH_OFFLOAD + OFFLOAD_BUFFER) * AUDIO_US_PER_MS) ||
1125 framesInt + offloadTsOffset_ > readIndexInt || first) {
1126 offloadTsOffset_ = readIndexInt - framesInt;
1127 }
1128 cacheTimeDsp = static_cast<uint64_t>(readIndexInt - (framesInt + offloadTsOffset_));
1129 return SUCCESS;
1130 }
1131
OffloadUpdatePolicyInWrite()1132 int32_t PaRendererStreamImpl::OffloadUpdatePolicyInWrite()
1133 {
1134 int error = 0;
1135 if ((lastOffloadUpdateFinishTime_ != 0) &&
1136 (std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) > lastOffloadUpdateFinishTime_)) {
1137 AUDIO_INFO_LOG("PaWriteStream switching curTime %{public}" PRIu64 ", switchTime %{public}" PRIu64,
1138 std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()), lastOffloadUpdateFinishTime_);
1139 error = OffloadUpdatePolicy(offloadNextStateTargetPolicy_, true);
1140 }
1141 return error;
1142 }
1143
SyncOffloadMode()1144 void PaRendererStreamImpl::SyncOffloadMode()
1145 {
1146 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
1147 if (statusCallback != nullptr) {
1148 if (offloadEnable_) {
1149 statusCallback->OnStatusUpdate(OPERATION_SET_OFFLOAD_ENABLE);
1150 } else {
1151 statusCallback->OnStatusUpdate(OPERATION_UNSET_OFFLOAD_ENABLE);
1152 }
1153 }
1154 }
1155
ResetOffload()1156 void PaRendererStreamImpl::ResetOffload()
1157 {
1158 offloadEnable_ = false;
1159 SyncOffloadMode();
1160 offloadTsOffset_ = 0;
1161 offloadTsLast_ = 0;
1162 OffloadUpdatePolicy(OFFLOAD_DEFAULT, true);
1163 }
1164
OffloadUpdatePolicy(AudioOffloadType statePolicy,bool force)1165 int32_t PaRendererStreamImpl::OffloadUpdatePolicy(AudioOffloadType statePolicy, bool force)
1166 {
1167 // if possible turn on the buffer immediately(long buffer -> short buffer), turn it at once.
1168 if (statePolicy < offloadStatePolicy_ || offloadStatePolicy_ == OFFLOAD_DEFAULT || force) {
1169 AUDIO_DEBUG_LOG("Update statePolicy immediately: %{public}d -> %{public}d, force(%d)",
1170 offloadStatePolicy_, statePolicy, force);
1171 lastOffloadUpdateFinishTime_ = 0;
1172 PaLockGuard lock(mainloop_, true);
1173 if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) {
1174 AUDIO_ERR_LOG("Set offload mode: invalid stream state, quit SetStreamOffloadMode due err");
1175 return ERR_ILLEGAL_STATE;
1176 }
1177 pa_proplist *propList = pa_proplist_new();
1178 CHECK_AND_RETURN_RET_LOG(propList != nullptr, ERR_OPERATION_FAILED, "pa_proplist_new failed");
1179 if (offloadEnable_) {
1180 pa_proplist_sets(propList, "stream.offload.enable", "1");
1181 } else {
1182 pa_proplist_sets(propList, "stream.offload.enable", "0");
1183 }
1184 AudioVolume::GetInstance()->SetOffloadType(sinkInputIndex_, statePolicy);
1185
1186 pa_operation *updatePropOperation =
1187 pa_stream_proplist_update(paStream_, PA_UPDATE_REPLACE, propList, nullptr, nullptr);
1188 if (updatePropOperation == nullptr) {
1189 AUDIO_ERR_LOG("pa_stream_proplist_update failed!");
1190 pa_proplist_free(propList);
1191 return ERR_OPERATION_FAILED;
1192 }
1193 pa_proplist_free(propList);
1194 pa_operation_unref(updatePropOperation);
1195
1196 if ((statePolicy != OFFLOAD_DEFAULT && offloadStatePolicy_ != OFFLOAD_DEFAULT) ||
1197 offloadStatePolicy_ == OFFLOAD_INACTIVE_BACKGROUND) {
1198 const uint32_t bufLenMs = processConfig_.streamType == STREAM_MOVIE ? OFFLOAD_HDI_CACHE3 :
1199 (statePolicy > 1 ? OFFLOAD_HDI_CACHE2 : OFFLOAD_HDI_CACHE1);
1200 OffloadSetBufferSize(bufLenMs);
1201 }
1202
1203 offloadStatePolicy_ = statePolicy;
1204 offloadNextStateTargetPolicy_ = statePolicy; // Fix here if sometimes can't cut into state 3
1205 } else {
1206 // Otherwise, hdi_sink.c's times detects the stateTarget change and switches later
1207 // this time is checked the PaWriteStream to check if the switch has been made
1208 AUDIO_DEBUG_LOG("Update statePolicy in 3 seconds: %{public}d -> %{public}d", offloadStatePolicy_, statePolicy);
1209 lastOffloadUpdateFinishTime_ = std::chrono::system_clock::to_time_t(
1210 std::chrono::system_clock::now() + std::chrono::seconds(3)); // add 3s latency to change offload state
1211 offloadNextStateTargetPolicy_ = statePolicy;
1212 }
1213
1214 return SUCCESS;
1215 }
1216
SetOffloadMode(int32_t state,bool isAppBack)1217 int32_t PaRendererStreamImpl::SetOffloadMode(int32_t state, bool isAppBack)
1218 {
1219 #ifdef FEATURE_POWER_MANAGER
1220 static const std::set<PowerMgr::PowerState> screenOffTable = {
1221 PowerMgr::PowerState::INACTIVE, PowerMgr::PowerState::STAND_BY,
1222 PowerMgr::PowerState::DOZE, PowerMgr::PowerState::SLEEP,
1223 PowerMgr::PowerState::HIBERNATE,
1224 };
1225 AudioOffloadType statePolicy = OFFLOAD_DEFAULT;
1226 auto powerState = static_cast<PowerMgr::PowerState>(state);
1227 if (screenOffTable.count(powerState)) {
1228 statePolicy = OFFLOAD_INACTIVE_BACKGROUND;
1229 } else {
1230 statePolicy = OFFLOAD_ACTIVE_FOREGROUND;
1231 }
1232
1233 if (statePolicy == OFFLOAD_DEFAULT) {
1234 AUDIO_ERR_LOG("impossible INPUT branch error");
1235 return ERR_OPERATION_FAILED;
1236 }
1237
1238 AUDIO_INFO_LOG("calling set stream offloadMode PowerState: %{public}d, isAppBack: %{public}d", state, isAppBack);
1239
1240 if (offloadNextStateTargetPolicy_ == statePolicy) {
1241 return SUCCESS;
1242 }
1243
1244 offloadEnable_ = true;
1245 SyncOffloadMode();
1246 if (OffloadUpdatePolicy(statePolicy, false) != SUCCESS) {
1247 return ERR_OPERATION_FAILED;
1248 }
1249 #else
1250 AUDIO_INFO_LOG("SetStreamOffloadMode not available, FEATURE_POWER_MANAGER no define");
1251 #endif
1252 return SUCCESS;
1253 }
1254
UnsetOffloadMode()1255 int32_t PaRendererStreamImpl::UnsetOffloadMode()
1256 {
1257 offloadEnable_ = false;
1258 SyncOffloadMode();
1259 return OffloadUpdatePolicy(OFFLOAD_DEFAULT, true);
1260 }
1261
UpdateMaxLength(uint32_t maxLength)1262 int32_t PaRendererStreamImpl::UpdateMaxLength(uint32_t maxLength)
1263 {
1264 uint32_t tlength = 4; // 4 is tlength of dup playback
1265 uint32_t prebuf = 2; // 2 is prebuf of dup playback
1266 uint32_t maxlength = maxLength;
1267 AUDIO_INFO_LOG("dup playback stream tlength: %{public}u, maxlength: %{public}u prebuf: %{public}u", tlength,
1268 maxlength, prebuf);
1269
1270 PaLockGuard lock(mainloop_);
1271 const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
1272 pa_buffer_attr bufferAttr;
1273 bufferAttr.fragsize = static_cast<uint32_t>(-1);
1274 bufferAttr.prebuf = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * prebuf, sampleSpec); // 20 buf len in ms
1275 bufferAttr.maxlength = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * maxlength, sampleSpec); // 20 buf len in ms
1276 bufferAttr.tlength = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * tlength, sampleSpec); // 20 buf len in ms
1277 bufferAttr.minreq = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC, sampleSpec); // 20 buf len in ms
1278
1279 pa_operation *operation = pa_stream_set_buffer_attr(paStream_, &bufferAttr, nullptr, nullptr);
1280 if (operation != nullptr) {
1281 pa_operation_unref(operation);
1282 }
1283 return SUCCESS;
1284 }
1285
UpdateBufferSize(uint32_t bufferLength)1286 int32_t PaRendererStreamImpl::UpdateBufferSize(uint32_t bufferLength)
1287 {
1288 uint32_t tlength = 4; // 4 is tlength of dup playback
1289 uint32_t prebuf = 1; // 1 is prebuf of dup playback
1290 uint32_t maxlength = 4; // 4 is maxlength of dup playback
1291
1292 const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_);
1293 pa_buffer_attr bufferAttr;
1294 bufferAttr.fragsize = static_cast<uint32_t>(-1);
1295 bufferAttr.prebuf = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * prebuf, sampleSpec); // 20 buf len in ms
1296 bufferAttr.maxlength = pa_usec_to_bytes(20 * PA_USEC_PER_MSEC * maxlength, sampleSpec); // 20 buf len in ms
1297 bufferAttr.tlength = pa_usec_to_bytes(bufferLength * PA_USEC_PER_MSEC * tlength, sampleSpec); // 20 buf len in ms
1298 bufferAttr.minreq = pa_usec_to_bytes(bufferLength * PA_USEC_PER_MSEC, sampleSpec); // 20 buf len in ms
1299
1300 pa_operation *operation = pa_stream_set_buffer_attr(paStream_, &bufferAttr, nullptr, nullptr);
1301 if (operation != nullptr) {
1302 pa_operation_unref(operation);
1303 }
1304 return SUCCESS;
1305 }
1306
GetAudioProcessConfig() const1307 AudioProcessConfig PaRendererStreamImpl::GetAudioProcessConfig() const noexcept
1308 {
1309 return processConfig_;
1310 }
1311
Peek(std::vector<char> * audioBuffer,int32_t & index)1312 int32_t PaRendererStreamImpl::Peek(std::vector<char> *audioBuffer, int32_t &index)
1313 {
1314 return SUCCESS;
1315 }
1316
ReturnIndex(int32_t index)1317 int32_t PaRendererStreamImpl::ReturnIndex(int32_t index)
1318 {
1319 return SUCCESS;
1320 }
1321
BlockStream()1322 void PaRendererStreamImpl::BlockStream() noexcept
1323 {
1324 return;
1325 }
1326 // offload end
1327
SetClientVolume(float clientVolume)1328 int32_t PaRendererStreamImpl::SetClientVolume(float clientVolume)
1329 {
1330 if (clientVolume < MIN_FLOAT_VOLUME || clientVolume > MAX_FLOAT_VOLUME) {
1331 AUDIO_ERR_LOG("SetClientVolume with invalid clientVolume %{public}f", clientVolume);
1332 return ERR_INVALID_PARAM;
1333 }
1334
1335 AudioEffectChainManager *audioEffectChainManager = AudioEffectChainManager::GetInstance();
1336 audioEffectChainManager->StreamVolumeUpdate(std::to_string(streamIndex_), clientVolume);
1337 AUDIO_PRERELEASE_LOGI("set client volume success");
1338
1339 return SUCCESS;
1340 }
1341
SetLoudnessGain(float loudnessGain)1342 int32_t PaRendererStreamImpl::SetLoudnessGain(float loudnessGain)
1343 {
1344 AUDIO_INFO_LOG("PA set loudnessGain: %{public}f", loudnessGain);
1345 return SUCCESS;
1346 }
1347
UpdatePaTimingInfo()1348 void PaRendererStreamImpl::UpdatePaTimingInfo()
1349 {
1350 pa_operation *operation = pa_stream_update_timing_info(paStream_, PAStreamUpdateTimingInfoSuccessCb, (void *)this);
1351 if (operation != nullptr) {
1352 auto start_time = std::chrono::steady_clock::now();
1353 while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) {
1354 auto update_time = std::chrono::steady_clock::now() - start_time;
1355 CHECK_AND_BREAK_LOG(update_time <= std::chrono::seconds(PA_STREAM_IMPL_TIMEOUT << 1),
1356 "pa_stream_update_timing_info timeout");
1357 pa_threaded_mainloop_wait(mainloop_);
1358 }
1359 pa_operation_unref(operation);
1360 } else {
1361 AUDIO_ERR_LOG("pa_stream_update_timing_info failed");
1362 }
1363 }
1364 } // namespace AudioStandard
1365 } // namespace OHOS
1366