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