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