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