1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef LOG_TAG
16 #define LOG_TAG "HdiSink"
17 #endif
18
19 #include <config.h>
20 #include <pulse/rtclock.h>
21 #include <pulse/timeval.h>
22 #include <pulse/xmalloc.h>
23 #include <pulsecore/log.h>
24 #include <pulsecore/modargs.h>
25 #include <pulsecore/module.h>
26 #include <pulsecore/rtpoll.h>
27 #include <pulsecore/sink.h>
28 #include <pulsecore/thread-mq.h>
29 #include <pulsecore/thread.h>
30 #include <pulsecore/memblock.c>
31 #include <pulsecore/mix.h>
32 #include <pulse/volume.h>
33 #include <pulsecore/protocol-native.c>
34 #include <pulsecore/memblockq.c>
35
36 #include <stddef.h>
37 #include <stdint.h>
38 #include <stdbool.h>
39 #include <string.h>
40 #include <inttypes.h>
41 #include <sys/types.h>
42 #include <pthread.h>
43 #include <semaphore.h>
44
45 #include "securec.h"
46
47 #include "audio_hdi_log.h"
48 #include "audio_schedule.h"
49 #include "audio_utils_c.h"
50 #include "audio_hdiadapter_info.h"
51 #include "volume_tools_c.h"
52 #include "audio_volume_c.h"
53 #include "renderer_sink_adapter.h"
54 #include "audio_effect_chain_adapter.h"
55 #include "playback_capturer_adapter.h"
56 #include "sink_userdata.h"
57 #include "time.h"
58
59 #define DEFAULT_SINK_NAME "hdi_output"
60 #define DEFAULT_AUDIO_DEVICE_NAME "Speaker"
61 #define DEFAULT_DEVICE_CLASS "primary"
62 #define DEFAULT_DEVICE_NETWORKID "LocalDevice"
63 #define DEFAULT_BUFFER_SIZE 8192
64 #define MAX_SINK_VOLUME_LEVEL 1.0
65 #define DEFAULT_WRITE_TIME 1000
66 #define MIX_BUFFER_LENGTH (pa_page_size())
67 #define MAX_REWIND (7000 * PA_USEC_PER_MSEC)
68 #define USEC_PER_SEC 1000000
69 #define DEFAULT_IN_CHANNEL_NUM 2
70 #define PRIMARY_CHANNEL_NUM 2
71 #define IN_CHANNEL_NUM_MAX 16
72 #define OUT_CHANNEL_NUM_MAX 2
73 #define DEFAULT_FRAMELEN 2048
74 #define SCENE_TYPE_NUM 9
75 #define HDI_MIN_MS_MAINTAIN 40
76 #define OFFLOAD_HDI_CACHE1 200 // ms, should equal with val in client
77 #define OFFLOAD_HDI_CACHE2 7000 // ms, should equal with val in client
78 #define OFFLOAD_FRAME_SIZE 40
79 #define OFFLOAD_HDI_CACHE1_PLUS (OFFLOAD_HDI_CACHE1 + OFFLOAD_FRAME_SIZE + 5) // ms, add 1 frame and 5ms
80 #define OFFLOAD_HDI_CACHE2_PLUS (OFFLOAD_HDI_CACHE2 + OFFLOAD_FRAME_SIZE + 5) // to make sure get full
81 #define SPRINTF_STR_LEN 100
82 #define DEFAULT_MULTICHANNEL_NUM 6
83 #define DEFAULT_NUM_CHANNEL 2
84 #define DEFAULT_MULTICHANNEL_CHANNELLAYOUT 1551
85 #define DEFAULT_CHANNELLAYOUT 3
86 #define OFFLOAD_SET_BUFFER_SIZE_NUM 5
87 #define SPATIALIZATION_FADING_FRAMECOUNT 5
88 #define POSSIBLY_UNUSED __attribute__((unused))
89 #define MIN_SLEEP_FOR_USEC 2000
90 #define DEFAULT_BLOCK_USEC 20000
91 #define FADE_IN_BEGIN 0.0
92 #define FADE_IN_END 1.0
93 #define FADE_OUT_BEGIN 1.0
94 #define FADE_OUT_END 0.0
95 #define PRINT_INTERVAL_FRAME_COUNT 100
96
97 const int64_t LOG_LOOP_THRESHOLD = 50 * 60 * 9; // about 3 min
98 const uint64_t DEFAULT_GETLATENCY_LOG_THRESHOLD_MS = 100;
99
100 const char *DEVICE_CLASS_PRIMARY = "primary";
101 const char *DEVICE_CLASS_A2DP = "a2dp";
102 const char *DEVICE_CLASS_REMOTE = "remote";
103 const char *DEVICE_CLASS_OFFLOAD = "offload";
104 const char *DEVICE_CLASS_MULTICHANNEL = "multichannel";
105 const char *SINK_NAME_INNER_CAPTURER = "InnerCapturerSink";
106 const char *SINK_NAME_REMOTE_CAST_INNER_CAPTURER = "RemoteCastInnerCapturer";
107 const char *DUP_STEAM_NAME = "DupStream"; // should be same with DUP_STEAM in audio_info.h
108 const char *BT_SINK_NAME = "Bt_Speaker";
109 const char *MCH_SINK_NAME = "MCH_Speaker";
110 const char *OFFLOAD_SINK_NAME = "Offload_Speaker";
111 const char *DP_SINK_NAME = "DP_speaker";
112
113 const int32_t WAIT_CLOSE_PA_OR_EFFECT_TIME = 4; // secs
114 const int32_t MONITOR_CLOSE_PA_TIME_SEC = 5 * 60; // 5min
115 bool g_speakerPaAllStreamVolumeZero = false;
116 bool g_onlyPrimarySpeakerPaLoading = false;
117 bool g_paHaveDisabled = false;
118 time_t g_speakerPaAllStreamStartVolZeroTime = 0;
119 bool g_speakerPaHaveClosed = false;
120 time_t g_speakerPaClosedTime = 0;
121 bool g_effectAllStreamVolumeZeroMap[SCENE_TYPE_NUM] = {false};
122 bool g_effectHaveDisabledMap[SCENE_TYPE_NUM] = {false};
123 time_t g_effectStartVolZeroTimeMap[SCENE_TYPE_NUM] = {0};
124 char *const SCENE_TYPE_SET[SCENE_TYPE_NUM] = {"SCENE_DEFAULT", "SCENE_MUSIC", "SCENE_GAME", "SCENE_MOVIE",
125 "SCENE_SPEECH", "SCENE_RING", "SCENE_VOIP", "SCENE_OTHERS", "EFFECT_NONE"};
126 const int32_t COMMON_SCENE_TYPE_INDEX = 0;
127
128 enum HdiInputType { HDI_INPUT_TYPE_PRIMARY, HDI_INPUT_TYPE_OFFLOAD, HDI_INPUT_TYPE_MULTICHANNEL };
129
130 enum {
131 HDI_INIT,
132 HDI_DEINIT,
133 HDI_START,
134 HDI_STOP,
135 HDI_RENDER,
136 QUIT
137 };
138
139 enum AudioOffloadType {
140 /**
141 * Indicates audio offload state default.
142 */
143 OFFLOAD_DEFAULT = -1,
144 /**
145 * Indicates audio offload state : screen is active & app is foreground.
146 */
147 OFFLOAD_ACTIVE_FOREGROUND = 0,
148 /**
149 * Indicates audio offload state : screen is active & app is background.
150 */
151 OFFLOAD_ACTIVE_BACKGROUND = 1,
152 /**
153 * Indicates audio offload state : screen is inactive & app is background.
154 */
155 OFFLOAD_INACTIVE_BACKGROUND = 3,
156 };
157
158 static int32_t g_effectProcessFrameCount = 0;
159 static void UserdataFree(struct Userdata *u);
160 static int32_t PrepareDevice(struct Userdata *u, const char *filePath);
161
162 static int32_t PrepareDeviceOffload(struct Userdata *u);
163 static char *GetStateInfo(pa_sink_state_t state);
164 static char *GetInputStateInfo(pa_sink_input_state_t state);
165 static void PaInputStateChangeCb(pa_sink_input *i, pa_sink_input_state_t state);
166 static void OffloadLock(struct Userdata *u);
167 static void OffloadUnlock(struct Userdata *u);
168 static int32_t UpdatePresentationPosition(struct Userdata *u);
169 static bool InputIsPrimary(pa_sink_input *i);
170 static bool InputIsOffload(pa_sink_input *i);
171 static void GetSinkInputName(pa_sink_input *i, char *str, int len);
172 static const char *safeProplistGets(const pa_proplist *p, const char *key, const char *defstr);
173 static void StartOffloadHdi(struct Userdata *u, pa_sink_input *i);
174 static void StartPrimaryHdiIfRunning(struct Userdata *u);
175 static void StartMultiChannelHdiIfRunning(struct Userdata *u);
176 static void CheckInputChangeToOffload(struct Userdata *u, pa_sink_input *i);
177 static void ResetVolumeBySinkInputState(pa_sink_input *i, pa_sink_input_state_t state);
178 static void *AllocateBuffer(size_t size);
179 static bool AllocateEffectBuffer(struct Userdata *u);
180 static void FreeEffectBuffer(struct Userdata *u);
181 static void ResetBufferAttr(struct Userdata *u);
182
183 // BEGIN Utility functions
184 #define FLOAT_EPS 1e-9f
185 #define MEMBLOCKQ_MAXLENGTH (16*1024*16)
186 #define OFFSET_BIT_24 3
187 #define BIT_DEPTH_TWO 2
188 #define BIT_8 8
189 #define BIT_16 16
190 #define BIT_24 24
191 #define BIT_32 32
Read24Bit(const uint8_t * p)192 static uint32_t Read24Bit(const uint8_t *p)
193 {
194 return ((uint32_t) p[BIT_DEPTH_TWO] << BIT_16) | ((uint32_t) p[1] << BIT_8) | ((uint32_t) p[0]);
195 }
196
Write24Bit(uint8_t * p,uint32_t u)197 static void Write24Bit(uint8_t *p, uint32_t u)
198 {
199 p[BIT_DEPTH_TWO] = (uint8_t) (u >> BIT_16);
200 p[1] = (uint8_t) (u >> BIT_8);
201 p[0] = (uint8_t) u;
202 }
203
ConvertFrom16BitToFloat(unsigned n,const int16_t * a,float * b)204 static void ConvertFrom16BitToFloat(unsigned n, const int16_t *a, float *b)
205 {
206 for (; n > 0; n--) {
207 *(b++) = *(a++) * (1.0f / (1 << (BIT_16 - 1)));
208 }
209 }
210
ConvertFrom24BitToFloat(unsigned n,const uint8_t * a,float * b)211 static void ConvertFrom24BitToFloat(unsigned n, const uint8_t *a, float *b)
212 {
213 for (; n > 0; n--) {
214 int32_t s = Read24Bit(a) << BIT_8;
215 *b = s * (1.0f / (1U << (BIT_32 - 1)));
216 a += OFFSET_BIT_24;
217 b++;
218 }
219 }
220
ConvertFrom32BitToFloat(unsigned n,const int32_t * a,float * b)221 static void ConvertFrom32BitToFloat(unsigned n, const int32_t *a, float *b)
222 {
223 for (; n > 0; n--) {
224 *(b++) = *(a++) * (1.0f / (1U << (BIT_32 - 1)));
225 }
226 }
227
CapMax(float v)228 static float CapMax(float v)
229 {
230 float value = v;
231 if (v > 1.0f) {
232 value = 1.0f - FLOAT_EPS;
233 } else if (v < -1.0f) {
234 value = -1.0f + FLOAT_EPS;
235 }
236 return value;
237 }
238
ConvertFromFloatTo16Bit(unsigned n,const float * a,int16_t * b)239 static void ConvertFromFloatTo16Bit(unsigned n, const float *a, int16_t *b)
240 {
241 for (; n > 0; n--) {
242 float tmp = *a++;
243 float v = CapMax(tmp) * (1 << (BIT_16 - 1));
244 *(b++) = (int16_t) v;
245 }
246 }
247
ConvertFromFloatTo24Bit(unsigned n,const float * a,uint8_t * b)248 static void ConvertFromFloatTo24Bit(unsigned n, const float *a, uint8_t *b)
249 {
250 for (; n > 0; n--) {
251 float tmp = *a++;
252 float v = CapMax(tmp) * (1U << (BIT_32 - 1));
253 Write24Bit(b, ((int32_t) v) >> BIT_8);
254 b += OFFSET_BIT_24;
255 }
256 }
257
ConvertFromFloatTo32Bit(unsigned n,const float * a,int32_t * b)258 static void ConvertFromFloatTo32Bit(unsigned n, const float *a, int32_t *b)
259 {
260 for (; n > 0; n--) {
261 float tmp = *a++;
262 float v = CapMax(tmp) * (1U << (BIT_32 - 1));
263 *(b++) = (int32_t) v;
264 }
265 }
266
ConvertToFloat(pa_sample_format_t format,unsigned n,void * src,float * dst)267 static void ConvertToFloat(pa_sample_format_t format, unsigned n, void *src, float *dst)
268 {
269 pa_assert(src);
270 pa_assert(dst);
271 int32_t ret;
272 switch (format) {
273 case PA_SAMPLE_S16LE:
274 ConvertFrom16BitToFloat(n, src, dst);
275 break;
276 case PA_SAMPLE_S24LE:
277 ConvertFrom24BitToFloat(n, src, dst);
278 break;
279 case PA_SAMPLE_S32LE:
280 ConvertFrom32BitToFloat(n, src, dst);
281 break;
282 default:
283 ret = memcpy_s(dst, n, src, n);
284 if (ret != 0) {
285 float *srcFloat = (float *)src;
286 for (uint32_t i = 0; i < n; i++) {
287 dst[i] = srcFloat[i];
288 }
289 }
290 break;
291 }
292 }
293
ConvertFromFloat(pa_sample_format_t format,unsigned n,float * src,void * dst)294 static void ConvertFromFloat(pa_sample_format_t format, unsigned n, float *src, void *dst)
295 {
296 pa_assert(src);
297 pa_assert(dst);
298 int32_t ret;
299 switch (format) {
300 case PA_SAMPLE_S16LE:
301 ConvertFromFloatTo16Bit(n, src, dst);
302 break;
303 case PA_SAMPLE_S24LE:
304 ConvertFromFloatTo24Bit(n, src, dst);
305 break;
306 case PA_SAMPLE_S32LE:
307 ConvertFromFloatTo32Bit(n, src, dst);
308 break;
309 default:
310 ret = memcpy_s(dst, n, src, n);
311 if (ret != 0) {
312 float *dstFloat = (float *)dst;
313 for (uint32_t i = 0; i < n; i++) {
314 dstFloat[i] = src[i];
315 }
316 }
317 break;
318 }
319 }
320
updateResampler(pa_sink_input * sinkIn,const char * sceneType,bool mchFlag)321 static void updateResampler(pa_sink_input *sinkIn, const char *sceneType, bool mchFlag)
322 {
323 uint32_t processChannels = DEFAULT_NUM_CHANNEL;
324 uint64_t processChannelLayout = DEFAULT_CHANNELLAYOUT;
325 if (mchFlag) {
326 struct Userdata *u = sinkIn->sink->userdata;
327 processChannels = u->multiChannel.sinkChannel;
328 processChannelLayout = u->multiChannel.sinkChannelLayout;
329 } else {
330 EffectChainManagerReturnEffectChannelInfo(sceneType, &processChannels, &processChannelLayout);
331 }
332
333 pa_resampler *r;
334 pa_sample_spec ss = sinkIn->thread_info.resampler->o_ss;
335 pa_channel_map processCm;
336 ConvertChLayoutToPaChMap(processChannelLayout, &processCm);
337 processCm.channels = processChannels;
338 if (processChannels == sinkIn->thread_info.resampler->i_ss.channels) {
339 ss.channels = sinkIn->thread_info.resampler->i_ss.channels;
340 pa_channel_map cm = sinkIn->thread_info.resampler->i_cm;
341 if (pa_channel_map_equal(&sinkIn->thread_info.resampler->i_cm, &processCm)) {
342 return;
343 }
344 r = pa_resampler_new(sinkIn->thread_info.resampler->mempool,
345 &sinkIn->thread_info.resampler->i_ss,
346 &sinkIn->thread_info.resampler->i_cm,
347 &ss, &cm,
348 sinkIn->core->lfe_crossover_freq,
349 sinkIn->thread_info.resampler->method,
350 sinkIn->thread_info.resampler->flags);
351 } else {
352 ss.channels = processChannels;
353 if (ss.channels == sinkIn->thread_info.resampler->o_ss.channels) {
354 return;
355 }
356 r = pa_resampler_new(sinkIn->thread_info.resampler->mempool,
357 &sinkIn->thread_info.resampler->i_ss,
358 &sinkIn->thread_info.resampler->i_cm,
359 &ss, &processCm,
360 sinkIn->core->lfe_crossover_freq,
361 sinkIn->thread_info.resampler->method,
362 sinkIn->thread_info.resampler->flags);
363 }
364 pa_resampler_free(sinkIn->thread_info.resampler);
365 sinkIn->thread_info.resampler = r;
366 return;
367 }
368
RenderWrite(struct RendererSinkAdapter * sinkAdapter,pa_memchunk * pchunk)369 static ssize_t RenderWrite(struct RendererSinkAdapter *sinkAdapter, pa_memchunk *pchunk)
370 {
371 size_t index;
372 size_t length;
373 ssize_t count = 0;
374 void *p = NULL;
375
376 pa_assert(pchunk);
377
378 index = pchunk->index;
379 length = pchunk->length;
380 p = pa_memblock_acquire(pchunk->memblock);
381 pa_assert(p);
382
383 while (true) {
384 uint64_t writeLen = 0;
385
386 int32_t ret = sinkAdapter->RendererRenderFrame(sinkAdapter, ((char*)p + index),
387 (uint64_t)length, &writeLen);
388 if (writeLen > length) {
389 AUDIO_ERR_LOG("Error writeLen > actual bytes. Length: %zu, Written: %" PRIu64 " bytes, %d ret",
390 length, writeLen, ret);
391 count = -1 - count;
392 break;
393 }
394 if (writeLen == 0) {
395 AUDIO_ERR_LOG("Failed to render Length: %{public}zu, Written: %{public}" PRIu64 " bytes, %{public}d ret",
396 length, writeLen, ret);
397 count = -1 - count;
398 break;
399 } else {
400 count += (ssize_t)writeLen;
401 index += writeLen;
402 length -= writeLen;
403 if (length == 0) {
404 break;
405 }
406 }
407 }
408 pa_memblock_release(pchunk->memblock);
409 pa_memblock_unref(pchunk->memblock);
410
411 return count;
412 }
413
GetInputPolicyState(pa_sink_input * i)414 static enum AudioOffloadType GetInputPolicyState(pa_sink_input *i)
415 {
416 return atoi(safeProplistGets(i->proplist, "stream.offload.statePolicy", "0"));
417 }
418
OffloadSetHdiVolume(pa_sink_input * i)419 static void OffloadSetHdiVolume(pa_sink_input *i)
420 {
421 if (!InputIsOffload(i)) {
422 return;
423 }
424
425 struct Userdata *u = i->sink->userdata;
426 const char *streamType = safeProplistGets(i->proplist, "stream.type", "NULL");
427 const char *sessionIDStr = safeProplistGets(i->proplist, "stream.sessionID", "NULL");
428 const char *deviceClass = GetDeviceClass(u->offload.sinkAdapter->deviceClass);
429 uint32_t sessionID = sessionIDStr != NULL ? (uint32_t)atoi(sessionIDStr) : 0;
430 float volumeEnd = GetCurVolume(sessionID, streamType, deviceClass);
431 float volumeBeg = GetPreVolume(sessionID);
432 float fadeBeg = 1.0f;
433 float fadeEnd = 1.0f;
434 if (!pa_safe_streq(streamType, "ultrasonic")) {
435 GetStreamVolumeFade(sessionID, &fadeBeg, &fadeEnd);
436 }
437 if (volumeBeg != volumeEnd || fadeBeg != fadeEnd) {
438 AUDIO_INFO_LOG("sessionID:%{public}s, volumeBeg:%{public}f, volumeEnd:%{public}f"
439 ", fadeBeg:%{public}f, fadeEnd:%{public}f",
440 sessionIDStr, volumeBeg, volumeEnd, fadeBeg, fadeEnd);
441 if (volumeBeg != volumeEnd) {
442 SetPreVolume(sessionID, volumeEnd);
443 MonitorVolume(sessionID, true);
444 }
445 if (fadeBeg != fadeEnd) {
446 SetStreamVolumeFade(sessionID, fadeEnd, fadeEnd);
447 }
448 }
449 u->offload.sinkAdapter->RendererSinkSetVolume(u->offload.sinkAdapter, volumeEnd, volumeEnd);
450 }
451
OffloadSetHdiBufferSize(pa_sink_input * i)452 static void OffloadSetHdiBufferSize(pa_sink_input *i)
453 {
454 if (!InputIsOffload(i)) {
455 return;
456 }
457
458 struct Userdata *u = i->sink->userdata;
459 const uint32_t bufSize = (GetInputPolicyState(i) == OFFLOAD_INACTIVE_BACKGROUND ?
460 OFFLOAD_HDI_CACHE2 : OFFLOAD_HDI_CACHE1);
461 u->offload.sinkAdapter->RendererSinkSetBufferSize(u->offload.sinkAdapter, bufSize);
462 }
463
RenderWriteOffload(struct Userdata * u,pa_sink_input * i,pa_memchunk * pchunk)464 static int32_t RenderWriteOffload(struct Userdata *u, pa_sink_input *i, pa_memchunk *pchunk)
465 {
466 size_t index;
467 size_t length;
468 void *p = NULL;
469
470 pa_assert(pchunk);
471
472 index = pchunk->index;
473 length = pchunk->length;
474 p = pa_memblock_acquire(pchunk->memblock);
475 pa_assert(p);
476
477 uint64_t writeLen = 0;
478 uint64_t now = pa_rtclock_now();
479 if (!u->offload.isHDISinkStarted) {
480 AUDIO_DEBUG_LOG("StartOffloadHdi before write, because maybe sink switch");
481 StartOffloadHdi(u, i);
482 }
483 int32_t ret = u->offload.sinkAdapter->RendererRenderFrame(u->offload.sinkAdapter, ((char*)p + index),
484 (uint64_t)length, &writeLen);
485 pa_memblock_release(pchunk->memblock);
486 if (writeLen != length && writeLen != 0) {
487 AUDIO_ERR_LOG("Error writeLen != actual bytes. Length: %zu, Written: %" PRIu64 " bytes, %d ret",
488 length, writeLen, ret);
489 return -1;
490 }
491 if (ret == 0 && u->offload.firstWriteHdi && writeLen == length) {
492 u->offload.firstWriteHdi = false;
493 u->offload.hdiPosTs = now;
494 u->offload.hdiPos = 0;
495 // if the hdi is flushing, it will block the volume setting.
496 // so the render frame judge it.
497 OffloadSetHdiVolume(i);
498 }
499 if (ret == 0 && u->offload.setHdiBufferSizeNum > 0 && writeLen == length) {
500 u->offload.setHdiBufferSizeNum--;
501 OffloadSetHdiBufferSize(i);
502 }
503 if (ret == 0 && writeLen == 0 && !u->offload.firstWriteHdi) { // is full
504 AUDIO_DEBUG_LOG("RenderWriteOffload, hdi is full, break");
505 return 1; // 1 indicates full
506 } else if (writeLen == 0) {
507 AUDIO_ERR_LOG("Failed to render Length: %{public}zu, Written: %{public}" PRIu64 " bytes, %{public}d ret",
508 length, writeLen, ret);
509 return -1;
510 }
511 return 0;
512 }
513
OffloadCallback(const enum RenderCallbackType type,int8_t * userdata)514 static void OffloadCallback(const enum RenderCallbackType type, int8_t *userdata)
515 {
516 struct Userdata *u = (struct Userdata *)userdata;
517 switch (type) {
518 case CB_NONBLOCK_WRITE_COMPLETED: { //need more data
519 const int hdistate = pa_atomic_load(&u->offload.hdistate);
520 if (hdistate == 1) {
521 pa_atomic_store(&u->offload.hdistate, 0);
522 OffloadLock(u);
523 UpdatePresentationPosition(u);
524 }
525 if (u->thread_mq.inq) {
526 pa_asyncmsgq_post(u->thread_mq.inq, NULL, 0, NULL, 0, NULL, NULL);
527 }
528 break;
529 }
530 case CB_DRAIN_COMPLETED:
531 case CB_FLUSH_COMPLETED:
532 case CB_RENDER_FULL:
533 case CB_ERROR_OCCUR:
534 break;
535 default:
536 break;
537 }
538 }
539
RegOffloadCallback(struct Userdata * u)540 static void RegOffloadCallback(struct Userdata *u)
541 {
542 u->offload.sinkAdapter->RendererRegCallback(u->offload.sinkAdapter, (int8_t *)OffloadCallback, (int8_t *)u);
543 }
544
TestModeRenderWrite(struct Userdata * u,pa_memchunk * pchunk)545 static ssize_t TestModeRenderWrite(struct Userdata *u, pa_memchunk *pchunk)
546 {
547 size_t index;
548 size_t length;
549 ssize_t count = 0;
550 void *p = NULL;
551
552 pa_assert(pchunk);
553
554 index = pchunk->index;
555 length = pchunk->length;
556 p = pa_memblock_acquire(pchunk->memblock);
557 pa_assert(p);
558
559 if (*((int32_t*)p) > 0) {
560 AUDIO_DEBUG_LOG("RenderWrite Write: %{public}d", ++u->writeCount);
561 }
562 AUDIO_DEBUG_LOG("RenderWrite Write renderCount: %{public}d", ++u->renderCount);
563
564 while (true) {
565 uint64_t writeLen = 0;
566
567 int32_t ret = u->primary.sinkAdapter->RendererRenderFrame(u->primary.sinkAdapter, ((char *)p + index),
568 (uint64_t)length, &writeLen);
569 if (writeLen > length) {
570 AUDIO_ERR_LOG("Error writeLen > actual bytes. Length: %zu, Written: %" PRIu64 " bytes, %d ret",
571 length, writeLen, ret);
572 count = -1 - count;
573 break;
574 }
575 if (writeLen == 0) {
576 AUDIO_ERR_LOG("Failed to render Length: %zu, Written: %" PRIu64 " bytes, %d ret",
577 length, writeLen, ret);
578 count = -1 - count;
579 break;
580 } else {
581 count += (ssize_t)writeLen;
582 index += writeLen;
583 length -= writeLen;
584 if (length == 0) {
585 break;
586 }
587 }
588 }
589 pa_memblock_release(pchunk->memblock);
590 pa_memblock_unref(pchunk->memblock);
591
592 return count;
593 }
594
IsInnerCapturer(pa_sink_input * sinkIn)595 static bool IsInnerCapturer(pa_sink_input *sinkIn)
596 {
597 pa_sink_input_assert_ref(sinkIn);
598
599 if (!GetInnerCapturerState()) {
600 return false;
601 }
602
603 const char *usageStr = pa_proplist_gets(sinkIn->proplist, "stream.usage");
604 const char *privacyTypeStr = pa_proplist_gets(sinkIn->proplist, "stream.privacyType");
605 int32_t usage = -1;
606 int32_t privacyType = -1;
607 bool usageSupport = false;
608 bool privacySupport = true;
609
610 if (privacyTypeStr != NULL) {
611 pa_atoi(privacyTypeStr, &privacyType);
612 privacySupport = IsPrivacySupportInnerCapturer(privacyType);
613 }
614
615 if (usageStr != NULL) {
616 pa_atoi(usageStr, &usage);
617 usageSupport = IsStreamSupportInnerCapturer(usage);
618 }
619 return privacySupport && usageSupport;
620 }
621
safeProplistGets(const pa_proplist * p,const char * key,const char * defstr)622 static const char *safeProplistGets(const pa_proplist *p, const char *key, const char *defstr)
623 {
624 const char *res = pa_proplist_gets(p, key);
625 if (res == NULL) {
626 return defstr;
627 }
628 return res;
629 }
630
631 //modify from pa inputs_drop
632 static void InputsDropFromInputs(pa_mix_info *infoInputs, unsigned nInputs, pa_mix_info *info, unsigned n,
633 pa_memchunk *result);
634
635 static unsigned GetInputsInfo(enum HdiInputType type, bool isRun, pa_sink *s, pa_mix_info *info, unsigned maxinfo);
636
SinkRenderPrimaryClusterCap(pa_sink * si,size_t * length,pa_mix_info * infoIn,unsigned maxInfo)637 static unsigned SinkRenderPrimaryClusterCap(pa_sink *si, size_t *length, pa_mix_info *infoIn, unsigned maxInfo)
638 {
639 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryClusterCap:len:%zu", *length);
640 pa_sink_input *sinkIn;
641
642 pa_sink_assert_ref(si);
643 pa_sink_assert_io_context(si);
644 pa_assert(infoIn);
645
646 unsigned n = 0;
647 void *state = NULL;
648 size_t mixlength = *length;
649 while ((sinkIn = pa_hashmap_iterate(si->thread_info.inputs, &state, NULL)) && maxInfo > 0) {
650 if (IsInnerCapturer(sinkIn) && InputIsPrimary(sinkIn)) {
651 pa_sink_input_assert_ref(sinkIn);
652
653 // max_rewind is 0 by default, need change to at least u->buffer_size for InnerCapSinkInputsRewind.
654 if (pa_memblockq_get_maxrewind(sinkIn->thread_info.render_memblockq) == 0) {
655 AUTO_CTRACE("hdi_sink::pa_sink_input_update_max_rewind:%u len:%zu", sinkIn->index, *length);
656 pa_sink_input_update_max_rewind(sinkIn, *length);
657 }
658 AUTO_CTRACE("hdi_sink::ClusterCap::pa_sink_input_peek:%u len:%zu", sinkIn->index, *length);
659 pa_sink_input_peek(sinkIn, *length, &infoIn->chunk, &infoIn->volume);
660
661 if (mixlength == 0 || infoIn->chunk.length < mixlength)
662 mixlength = infoIn->chunk.length;
663
664 if (pa_memblock_is_silence(infoIn->chunk.memblock)) {
665 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryClusterCap::is_silence");
666 pa_memblock_unref(infoIn->chunk.memblock);
667 continue;
668 }
669
670 infoIn->userdata = pa_sink_input_ref(sinkIn);
671 pa_assert(infoIn->chunk.memblock);
672 pa_assert(infoIn->chunk.length > 0);
673
674 infoIn++;
675 n++;
676 maxInfo--;
677 }
678 }
679
680 if (mixlength > 0) {
681 *length = mixlength;
682 }
683
684 return n;
685 }
686
SinkRenderPrimaryMix(pa_sink * si,size_t length,pa_mix_info * infoIn,unsigned n,pa_memchunk * chunkIn)687 static void SinkRenderPrimaryMix(pa_sink *si, size_t length, pa_mix_info *infoIn, unsigned n, pa_memchunk *chunkIn)
688 {
689 if (n == 0) {
690 if (chunkIn->length > length)
691 chunkIn->length = length;
692
693 pa_silence_memchunk(chunkIn, &si->sample_spec);
694 } else if (n == 1) {
695 pa_cvolume volume;
696
697 if (chunkIn->length > length)
698 chunkIn->length = length;
699
700 pa_sw_cvolume_multiply(&volume, &si->thread_info.soft_volume, &infoIn[0].volume);
701
702 if (si->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
703 pa_silence_memchunk(chunkIn, &si->sample_spec);
704 } else {
705 pa_memchunk tmpChunk;
706
707 tmpChunk = infoIn[0].chunk;
708 pa_memblock_ref(tmpChunk.memblock);
709
710 if (tmpChunk.length > length)
711 tmpChunk.length = length;
712
713 if (!pa_cvolume_is_norm(&volume)) {
714 pa_memchunk_make_writable(&tmpChunk, 0);
715 pa_volume_memchunk(&tmpChunk, &si->sample_spec, &volume);
716 }
717
718 pa_memchunk_memcpy(chunkIn, &tmpChunk);
719 pa_memblock_unref(tmpChunk.memblock);
720 }
721 } else {
722 void *ptr;
723
724 ptr = pa_memblock_acquire(chunkIn->memblock);
725
726 chunkIn->length = pa_mix(infoIn, n,
727 (uint8_t*) ptr + chunkIn->index, length,
728 &si->sample_spec,
729 &si->thread_info.soft_volume,
730 si->thread_info.soft_muted);
731
732 pa_memblock_release(chunkIn->memblock);
733 }
734 }
735
SinkRenderPrimaryMixCap(pa_sink * si,size_t length,pa_mix_info * infoIn,unsigned n,pa_memchunk * chunkIn)736 static void SinkRenderPrimaryMixCap(pa_sink *si, size_t length, pa_mix_info *infoIn, unsigned n, pa_memchunk *chunkIn)
737 {
738 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryMixCap:%u:len:%zu", n, chunkIn->length);
739 if (n == 0) {
740 if (chunkIn->length > length) {
741 chunkIn->length = length;
742 }
743
744 pa_silence_memchunk(chunkIn, &si->sample_spec);
745 } else if (n == 1) {
746 pa_memchunk tmpChunk;
747 // If chunkIn is not full filled, we need re-call SinkRenderPrimaryPeekCap.
748 if (chunkIn->length > length) {
749 chunkIn->length = length;
750 }
751
752 tmpChunk = infoIn[0].chunk;
753 pa_memblock_ref(tmpChunk.memblock);
754
755 if (tmpChunk.length > length) {
756 tmpChunk.length = length;
757 }
758
759 pa_memchunk_memcpy(chunkIn, &tmpChunk);
760 pa_memblock_unref(tmpChunk.memblock);
761 } else {
762 void *ptr;
763
764 ptr = pa_memblock_acquire(chunkIn->memblock);
765
766 for (unsigned index = 0; index < n; index++) {
767 for (unsigned channel = 0; channel < si->sample_spec.channels; channel++) {
768 infoIn[index].volume.values[channel] = PA_VOLUME_NORM;
769 }
770 }
771
772 chunkIn->length = pa_mix(infoIn, n, (uint8_t*) ptr + chunkIn->index, length, &si->sample_spec, NULL, false);
773
774 pa_memblock_release(chunkIn->memblock);
775 }
776 }
777
SinkRenderPrimaryInputsDropCap(pa_sink * si,pa_mix_info * infoIn,unsigned n,pa_memchunk * chunkIn)778 static void SinkRenderPrimaryInputsDropCap(pa_sink *si, pa_mix_info *infoIn, unsigned n, pa_memchunk *chunkIn)
779 {
780 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryInputsDropCap:%u:len:%zu", n, chunkIn->length);
781 pa_sink_assert_ref(si);
782 pa_sink_assert_io_context(si);
783 pa_assert(chunkIn);
784 pa_assert(chunkIn->memblock);
785 pa_assert(chunkIn->length > 0);
786
787 /* We optimize for the case where the order of the inputs has not changed */
788
789 pa_mix_info *infoCur = NULL;
790 pa_sink_input *sceneSinkInput = NULL;
791 bool isCaptureSilently = IsCaptureSilently();
792 for (uint32_t k = 0; k < n; k++) {
793 sceneSinkInput = infoIn[k].userdata;
794 pa_sink_input_assert_ref(sceneSinkInput);
795 AUTO_CTRACE("hdi_sink::InnerCap:pa_sink_input_drop:%u:len:%zu", sceneSinkInput->index, chunkIn->length);
796 pa_sink_input_drop(sceneSinkInput, chunkIn->length);
797
798 infoCur = infoIn + k;
799 if (infoCur) {
800 if (infoCur->chunk.memblock) {
801 pa_memblock_unref(infoCur->chunk.memblock);
802 pa_memchunk_reset(&infoCur->chunk);
803 }
804
805 pa_sink_input_unref(infoCur->userdata);
806
807 if (isCaptureSilently) {
808 infoCur->userdata = NULL;
809 }
810 }
811 }
812 }
813
SinkRenderPrimaryPeekCap(pa_sink * si,pa_memchunk * chunkIn)814 static int32_t SinkRenderPrimaryPeekCap(pa_sink *si, pa_memchunk *chunkIn)
815 {
816 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryPeekCap:len:%zu", chunkIn->length);
817 pa_mix_info infoIn[MAX_MIX_CHANNELS];
818 unsigned n;
819 size_t length;
820 size_t blockSizeMax;
821
822 pa_sink_assert_ref(si);
823 pa_sink_assert_io_context(si);
824 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
825 pa_assert(chunkIn);
826 pa_assert(chunkIn->memblock);
827 pa_assert(chunkIn->length > 0);
828 pa_assert(pa_frame_aligned(chunkIn->length, &si->sample_spec));
829
830 pa_assert(!si->thread_info.rewind_requested);
831 pa_assert(si->thread_info.rewind_nbytes == 0);
832
833 if (si->thread_info.state == PA_SINK_SUSPENDED) {
834 pa_silence_memchunk(chunkIn, &si->sample_spec);
835 return 0;
836 }
837
838 pa_sink_ref(si);
839
840 length = chunkIn->length;
841 blockSizeMax = pa_mempool_block_size_max(si->core->mempool);
842 if (length > blockSizeMax)
843 length = pa_frame_align(blockSizeMax, &si->sample_spec);
844
845 pa_assert(length > 0);
846
847 n = SinkRenderPrimaryClusterCap(si, &length, infoIn, MAX_MIX_CHANNELS);
848 SinkRenderPrimaryMixCap(si, length, infoIn, n, chunkIn);
849
850 SinkRenderPrimaryInputsDropCap(si, infoIn, n, chunkIn);
851 pa_sink_unref(si);
852
853 return n;
854 }
855
SinkRenderPrimaryGetDataCap(pa_sink * si,pa_memchunk * chunkIn)856 static int32_t SinkRenderPrimaryGetDataCap(pa_sink *si, pa_memchunk *chunkIn)
857 {
858 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryGetDataCap:len:%zu", chunkIn->length);
859 pa_memchunk chunk;
860 size_t l;
861 size_t d;
862 pa_sink_assert_ref(si);
863 pa_sink_assert_io_context(si);
864 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
865 pa_assert(chunkIn);
866 pa_assert(chunkIn->memblock);
867 pa_assert(chunkIn->length > 0);
868 pa_assert(pa_frame_aligned(chunkIn->length, &si->sample_spec));
869
870 pa_assert(!si->thread_info.rewind_requested);
871 pa_assert(si->thread_info.rewind_nbytes == 0);
872
873 if (si->thread_info.state == PA_SINK_SUSPENDED) {
874 pa_silence_memchunk(chunkIn, &si->sample_spec);
875 return 0;
876 }
877
878 pa_sink_ref(si);
879
880 l = chunkIn->length;
881 d = 0;
882
883 int32_t nSinkInput = 0;
884 while (l > 0) {
885 chunk = *chunkIn;
886 chunk.index += d;
887 chunk.length -= d;
888
889 nSinkInput = SinkRenderPrimaryPeekCap(si, &chunk);
890
891 d += (size_t)chunk.length;
892 l -= (size_t)chunk.length;
893 }
894
895 pa_sink_unref(si);
896
897 return nSinkInput;
898 }
899
monitorLinked(pa_sink * si,bool isRunning)900 static bool monitorLinked(pa_sink *si, bool isRunning)
901 {
902 if (isRunning) {
903 return si->monitor_source && PA_SOURCE_IS_RUNNING(si->monitor_source->thread_info.state);
904 } else {
905 return si->monitor_source && PA_SOURCE_IS_LINKED(si->monitor_source->thread_info.state);
906 }
907 }
908
InnerCapSinkInputsRewind(pa_sink * si,size_t length)909 static void InnerCapSinkInputsRewind(pa_sink *si, size_t length)
910 {
911 AUTO_CTRACE("hdi_sink::InnerCapSinkInputsRewind:len:%zu", length);
912
913 pa_sink_assert_ref(si);
914 pa_sink_assert_io_context(si);
915
916 pa_sink_input *sinkIn = NULL;
917 void *state = NULL;
918 while ((sinkIn = pa_hashmap_iterate(si->thread_info.inputs, &state, NULL))) {
919 if (IsInnerCapturer(sinkIn) && InputIsPrimary(sinkIn)) {
920 pa_sink_input_assert_ref(sinkIn);
921 pa_sink_input_process_rewind(sinkIn, length); // will not work well if maxrewind = 0
922 }
923 }
924 }
925
SinkRenderCapProcess(pa_sink * si,size_t length,pa_memchunk * capResult)926 static void SinkRenderCapProcess(pa_sink *si, size_t length, pa_memchunk *capResult)
927 {
928 AUTO_CTRACE("hdi_sink::SinkRenderCapProcess:len:%zu", length);
929 capResult->memblock = pa_memblock_new(si->core->mempool, length);
930 capResult->index = 0;
931 capResult->length = length;
932 SinkRenderPrimaryGetDataCap(si, capResult);
933 if (monitorLinked(si, false)) {
934 AUTO_CTRACE("hdi_sink::pa_source_post:len:%zu", capResult->length);
935 pa_source_post(si->monitor_source, capResult);
936 }
937
938 //If not silent capture, we need to call rewind for Speak.
939 if (!IsCaptureSilently()) {
940 InnerCapSinkInputsRewind(si, capResult->length);
941 }
942 return;
943 }
944
SinkRenderPrimaryInputsDrop(pa_sink * si,pa_mix_info * infoIn,unsigned n,pa_memchunk * chunkIn)945 static void SinkRenderPrimaryInputsDrop(pa_sink *si, pa_mix_info *infoIn, unsigned n, pa_memchunk *chunkIn)
946 {
947 unsigned nUnreffed = 0;
948
949 pa_sink_assert_ref(si);
950 pa_sink_assert_io_context(si);
951 pa_assert(chunkIn);
952 pa_assert(chunkIn->memblock);
953 pa_assert(chunkIn->length > 0);
954
955 /* We optimize for the case where the order of the inputs has not changed */
956 pa_mix_info *infoCur = NULL;
957 pa_sink_input *sceneSinkInput = NULL;
958 for (uint32_t k = 0; k < n; k++) {
959 sceneSinkInput = infoIn[k].userdata;
960 pa_sink_input_assert_ref(sceneSinkInput);
961
962 /* Drop read data */
963 pa_sink_input_drop(sceneSinkInput, chunkIn->length);
964 infoCur = infoIn + k;
965 if (infoCur) {
966 if (infoCur->chunk.memblock) {
967 pa_memblock_unref(infoCur->chunk.memblock);
968 pa_memchunk_reset(&infoCur->chunk);
969 }
970
971 pa_sink_input_unref(infoCur->userdata);
972 infoCur->userdata = NULL;
973
974 nUnreffed += 1;
975 }
976 }
977 /* Now drop references to entries that are included in the
978 * pa_mix_info array but don't exist anymore */
979
980 if (nUnreffed < n) {
981 for (; n > 0; infoIn++, n--) {
982 if (infoIn->userdata)
983 pa_sink_input_unref(infoIn->userdata);
984 if (infoIn->chunk.memblock)
985 pa_memblock_unref(infoIn->chunk.memblock);
986 }
987 }
988 }
989
SinkRenderMultiChannelInputsDrop(pa_sink * si,pa_mix_info * infoIn,unsigned n,pa_memchunk * chunkIn)990 static void SinkRenderMultiChannelInputsDrop(pa_sink *si, pa_mix_info *infoIn, unsigned n, pa_memchunk *chunkIn)
991 {
992 AUDIO_DEBUG_LOG("mch inputs drop start");
993 unsigned nUnreffed = 0;
994
995 pa_sink_assert_ref(si);
996 pa_sink_assert_io_context(si);
997 pa_assert(chunkIn);
998 pa_assert(chunkIn->memblock);
999 pa_assert(chunkIn->length > 0);
1000
1001 /* We optimize for the case where the order of the inputs has not changed */
1002 pa_mix_info *infoCur = NULL;
1003 pa_sink_input *sceneSinkInput = NULL;
1004 for (uint32_t k = 0; k < n; k++) {
1005 sceneSinkInput = infoIn[k].userdata;
1006 pa_sink_input_assert_ref(sceneSinkInput);
1007
1008 /* Drop read data */
1009 pa_sink_input_drop(sceneSinkInput, chunkIn->length);
1010 infoCur = infoIn + k;
1011 if (infoCur) {
1012 if (infoCur->chunk.memblock) {
1013 pa_memblock_unref(infoCur->chunk.memblock);
1014 pa_memchunk_reset(&infoCur->chunk);
1015 }
1016
1017 pa_sink_input_unref(infoCur->userdata);
1018 infoCur->userdata = NULL;
1019
1020 nUnreffed += 1;
1021 }
1022 }
1023 /* Now drop references to entries that are included in the
1024 * pa_mix_info array but don't exist anymore */
1025
1026 if (nUnreffed < n) {
1027 for (; n > 0; infoIn++, n--) {
1028 if (infoIn->userdata)
1029 pa_sink_input_unref(infoIn->userdata);
1030 if (infoIn->chunk.memblock)
1031 pa_memblock_unref(infoIn->chunk.memblock);
1032 }
1033 }
1034 }
1035
CheckAndPushUidToArr(pa_sink_input * sinkIn,int32_t appsUid[MAX_MIX_CHANNELS],size_t * count)1036 static void CheckAndPushUidToArr(pa_sink_input *sinkIn, int32_t appsUid[MAX_MIX_CHANNELS], size_t *count)
1037 {
1038 const char *cstringClientUid = pa_proplist_gets(sinkIn->proplist, "stream.client.uid");
1039 if (cstringClientUid && (sinkIn->thread_info.state == PA_SINK_INPUT_RUNNING)) {
1040 appsUid[(*count)] = atoi(cstringClientUid);
1041 (*count)++;
1042 }
1043 }
1044
SafeRendererSinkUpdateAppsUid(struct RendererSinkAdapter * sinkAdapter,const int32_t appsUid[MAX_MIX_CHANNELS],const size_t count)1045 static void SafeRendererSinkUpdateAppsUid(struct RendererSinkAdapter *sinkAdapter,
1046 const int32_t appsUid[MAX_MIX_CHANNELS], const size_t count)
1047 {
1048 if (sinkAdapter) {
1049 sinkAdapter->RendererSinkUpdateAppsUid(sinkAdapter, appsUid, count);
1050 }
1051 }
1052
silenceData(pa_mix_info * infoIn,pa_sink * si)1053 static void silenceData(pa_mix_info *infoIn, pa_sink *si)
1054 {
1055 pa_memchunk_make_writable(&infoIn->chunk, 0);
1056 void *tmpdata = pa_memblock_acquire_chunk(&infoIn->chunk);
1057 memset_s(tmpdata, infoIn->chunk.length, 0, infoIn->chunk.length);
1058 pa_memblock_release(infoIn->chunk.memblock);
1059 }
1060
ConvertPaToHdiAdapterFormat(pa_sample_format_t format)1061 static enum HdiAdapterFormat ConvertPaToHdiAdapterFormat(pa_sample_format_t format)
1062 {
1063 enum HdiAdapterFormat adapterFormat;
1064 switch (format) {
1065 case PA_SAMPLE_U8:
1066 adapterFormat = SAMPLE_U8;
1067 break;
1068 case PA_SAMPLE_S16LE:
1069 adapterFormat = SAMPLE_S16;
1070 break;
1071 case PA_SAMPLE_S24LE:
1072 adapterFormat = SAMPLE_S24;
1073 break;
1074 case PA_SAMPLE_S32LE:
1075 adapterFormat = SAMPLE_S32;
1076 break;
1077 default:
1078 adapterFormat = INVALID_WIDTH;
1079 break;
1080 }
1081
1082 return adapterFormat;
1083 }
1084
DoFading(void * data,int32_t length,uint32_t format,uint32_t channel,int32_t fadeType)1085 static void DoFading(void *data, int32_t length, uint32_t format, uint32_t channel, int32_t fadeType)
1086 {
1087 AudioRawFormat rawFormat;
1088 rawFormat.format = format;
1089 rawFormat.channels = channel;
1090 AUDIO_INFO_LOG("length:%{public}d channels:%{public}d format:%{public}d fadeType:%{public}d",
1091 length, rawFormat.channels, rawFormat.format, fadeType);
1092 int32_t ret = 0;
1093 if (fadeType == 0) {
1094 ret = ProcessVol(data, length, rawFormat, FADE_IN_BEGIN, FADE_IN_END);
1095 } else {
1096 ret = ProcessVol(data, length, rawFormat, FADE_OUT_BEGIN, FADE_OUT_END);
1097 }
1098 if (ret != 0) {
1099 AUDIO_WARNING_LOG("ProcessVol failed:%{public}d", ret);
1100 }
1101 }
1102
PreparePrimaryFading(pa_sink_input * sinkIn,pa_mix_info * infoIn,pa_sink * si)1103 static void PreparePrimaryFading(pa_sink_input *sinkIn, pa_mix_info *infoIn, pa_sink *si)
1104 {
1105 struct Userdata *u;
1106 pa_assert_se(u = si->userdata);
1107
1108 const char *streamType = safeProplistGets(sinkIn->proplist, "stream.type", "NULL");
1109 if (pa_safe_streq(streamType, "ultrasonic")) {
1110 return;
1111 }
1112
1113 uint32_t streamIndex = sinkIn->index;
1114 uint32_t sinkFadeoutPause = GetFadeoutState(streamIndex);
1115 if (sinkFadeoutPause == DONE_FADE && (sinkIn->thread_info.state == PA_SINK_INPUT_RUNNING)) {
1116 silenceData(infoIn, si);
1117 AUDIO_PRERELEASE_LOGI("after pause fadeout done, silenceData");
1118 return;
1119 }
1120 uint32_t format = (uint32_t)ConvertPaToHdiAdapterFormat(u->format);
1121 if (pa_atomic_load(&u->primary.fadingFlagForPrimary) == 1 &&
1122 u->primary.primarySinkInIndex == (int32_t)sinkIn->index) {
1123 if (pa_memblock_is_silence(infoIn->chunk.memblock)) {
1124 AUDIO_PRERELEASE_LOGI("pa_memblock_is_silence");
1125 return;
1126 }
1127 //do fading in
1128 pa_memchunk_make_writable(&infoIn->chunk, 0);
1129 void *data = pa_memblock_acquire_chunk(&infoIn->chunk);
1130 DoFading(data, infoIn->chunk.length, format, (uint32_t)u->ss.channels, 0);
1131 u->primary.primaryFadingInDone = 1;
1132 pa_memblock_release(infoIn->chunk.memblock);
1133 }
1134 if (sinkFadeoutPause == DO_FADE) {
1135 //do fading out
1136 pa_memchunk_make_writable(&infoIn->chunk, 0);
1137 void *data = pa_memblock_acquire_chunk(&infoIn->chunk);
1138 DoFading(data, infoIn->chunk.length, format, (uint32_t)u->ss.channels, 1);
1139 SetFadeoutState(streamIndex, DONE_FADE);
1140 pa_memblock_release(infoIn->chunk.memblock);
1141 }
1142 }
1143
CheckPrimaryFadeinIsDone(pa_sink * si,pa_sink_input * sinkIn)1144 static void CheckPrimaryFadeinIsDone(pa_sink *si, pa_sink_input *sinkIn)
1145 {
1146 struct Userdata *u;
1147 pa_assert_se(u = si->userdata);
1148
1149 if (u->primary.primaryFadingInDone && u->primary.primarySinkInIndex == (int32_t)sinkIn->index) {
1150 pa_atomic_store(&u->primary.fadingFlagForPrimary, 0);
1151 }
1152 }
1153
RecordEffectChainStatus(bool existFlag,const char * sinkSceneType,const char * sinkSceneMode,bool actualSpatializationEnabled)1154 static void RecordEffectChainStatus(bool existFlag, const char *sinkSceneType, const char *sinkSceneMode,
1155 bool actualSpatializationEnabled)
1156 {
1157 if (g_effectProcessFrameCount == PRINT_INTERVAL_FRAME_COUNT) {
1158 AUDIO_DEBUG_LOG("Effect Chain Status is %{public}d, "
1159 "scene type is %{public}s, scene mode is %{public}s, spatializationEnabled is %{public}d.",
1160 existFlag, sinkSceneType, sinkSceneMode, actualSpatializationEnabled);
1161 }
1162 }
1163
GetExistFlag(pa_sink_input * sinkIn,const char * sinkSceneType,const char * sinkSceneMode,const char * spatializationEnabled)1164 static bool GetExistFlag(pa_sink_input *sinkIn, const char *sinkSceneType, const char *sinkSceneMode,
1165 const char *spatializationEnabled)
1166 {
1167 bool existFlag =
1168 EffectChainManagerExist(sinkSceneType, sinkSceneMode, spatializationEnabled ? "1" : "0");
1169 const char *deviceString = pa_proplist_gets(sinkIn->sink->proplist, PA_PROP_DEVICE_STRING);
1170 if (pa_safe_streq(deviceString, "remote")) {
1171 existFlag = false;
1172 }
1173
1174 return existFlag;
1175 }
1176
ProcessAudioVolume(pa_sink_input * sinkIn,size_t length,pa_memchunk * pchunk,pa_sink * si)1177 static void ProcessAudioVolume(pa_sink_input *sinkIn, size_t length, pa_memchunk *pchunk, pa_sink *si)
1178 {
1179 AUTO_CTRACE("hdi_sink::ProcessAudioVolume: len:%zu", length);
1180 struct Userdata *u;
1181 pa_assert_se(sinkIn);
1182 pa_assert_se(pchunk);
1183 pa_assert_se(si);
1184 pa_assert_se(u = si->userdata);
1185 const char *streamType = safeProplistGets(sinkIn->proplist, "stream.type", "NULL");
1186 const char *sessionIDStr = safeProplistGets(sinkIn->proplist, "stream.sessionID", "NULL");
1187 const char *deviceClass = GetDeviceClass(u->primary.sinkAdapter->deviceClass);
1188 uint32_t sessionID = sessionIDStr != NULL ? atoi(sessionIDStr) : 0;
1189 float volumeEnd = GetCurVolume(sessionID, streamType, deviceClass);
1190 float volumeBeg = GetPreVolume(sessionID);
1191 float fadeBeg = 1.0f;
1192 float fadeEnd = 1.0f;
1193 if (!pa_safe_streq(streamType, "ultrasonic")) {
1194 GetStreamVolumeFade(sessionID, &fadeBeg, &fadeEnd);
1195 }
1196 if (pa_memblock_is_silence(pchunk->memblock)) {
1197 AUTO_CTRACE("hdi_sink::ProcessAudioVolume: is_silence");
1198 AUDIO_PRERELEASE_LOGI("pa_memblock_is_silence");
1199 } else {
1200 AudioRawFormat rawFormat;
1201 rawFormat.format = (uint32_t)ConvertPaToHdiAdapterFormat(si->sample_spec.format);
1202 rawFormat.channels = (uint32_t)si->sample_spec.channels;
1203
1204 pa_memchunk_make_writable(pchunk, 0);
1205 void *data = pa_memblock_acquire_chunk(pchunk);
1206
1207 AUDIO_DEBUG_LOG("length:%{public}zu channels:%{public}d format:%{public}d"
1208 " volumeBeg:%{public}f, volumeEnd:%{public}f, fadeBeg:%{public}f, fadeEnd:%{public}f",
1209 length, rawFormat.channels, rawFormat.format, volumeBeg, volumeEnd, fadeBeg, fadeEnd);
1210 int32_t ret = ProcessVol(data, length, rawFormat, volumeBeg * fadeBeg, volumeEnd * fadeEnd);
1211 if (ret != 0) {
1212 AUDIO_WARNING_LOG("ProcessVol failed:%{public}d", ret);
1213 }
1214 pa_memblock_release(pchunk->memblock);
1215 }
1216 if (volumeBeg != volumeEnd || fadeBeg != fadeEnd) {
1217 AUDIO_INFO_LOG("sessionID:%{public}s, length:%{public}zu, volumeBeg:%{public}f, volumeEnd:%{public}f"
1218 ", fadeBeg:%{public}f, fadeEnd:%{public}f",
1219 sessionIDStr, length, volumeBeg, volumeEnd, fadeBeg, fadeEnd);
1220 if (volumeBeg != volumeEnd) {
1221 SetPreVolume(sessionID, volumeEnd);
1222 MonitorVolume(sessionID, true);
1223 }
1224 if (fadeBeg != fadeEnd) {
1225 SetStreamVolumeFade(sessionID, fadeEnd, fadeEnd);
1226 }
1227 }
1228 }
1229
HandleFading(pa_sink * si,size_t length,pa_sink_input * sinkIn,pa_mix_info * infoIn)1230 static void HandleFading(pa_sink *si, size_t length, pa_sink_input *sinkIn, pa_mix_info *infoIn)
1231 {
1232 struct Userdata *u;
1233 pa_assert_se(u = si->userdata);
1234
1235 infoIn->userdata = pa_sink_input_ref(sinkIn);
1236 pa_assert(infoIn->chunk.memblock);
1237 pa_assert(infoIn->chunk.length > 0);
1238 PreparePrimaryFading(sinkIn, infoIn, si);
1239 CheckPrimaryFadeinIsDone(si, sinkIn);
1240
1241 uint32_t sinkFadeoutPause = GetFadeoutState(sinkIn->index);
1242 if (!sinkFadeoutPause && (length <= infoIn->chunk.length)) {
1243 u->streamAvailable++;
1244 }
1245 }
1246
SinkRenderPrimaryCluster(pa_sink * si,size_t * length,pa_mix_info * infoIn,unsigned maxInfo,const char * sceneType)1247 static unsigned SinkRenderPrimaryCluster(pa_sink *si, size_t *length, pa_mix_info *infoIn,
1248 unsigned maxInfo, const char *sceneType)
1249 {
1250 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryCluster:%s len:%zu", sceneType, *length);
1251
1252 struct Userdata *u;
1253 pa_assert_se(u = si->userdata);
1254
1255 pa_sink_input *sinkIn;
1256 unsigned n = 0;
1257 void *state = NULL;
1258 size_t mixlength = *length;
1259
1260 pa_sink_assert_ref(si);
1261 pa_sink_assert_io_context(si);
1262 pa_assert(infoIn);
1263
1264 int32_t appsUid[MAX_MIX_CHANNELS];
1265 size_t count = 0;
1266 while ((sinkIn = pa_hashmap_iterate(si->thread_info.inputs, &state, NULL)) && maxInfo > 0) {
1267 CheckAndPushUidToArr(sinkIn, appsUid, &count);
1268 const char *sSceneType = pa_proplist_gets(sinkIn->proplist, "scene.type");
1269 const char *sSceneMode = pa_proplist_gets(sinkIn->proplist, "scene.mode");
1270 bool existFlag = GetExistFlag(sinkIn, sSceneType, sSceneMode, u->actualSpatializationEnabled ? "1" : "0");
1271 bool sceneTypeFlag = EffectChainManagerSceneCheck(sSceneType, sceneType);
1272 if ((IsInnerCapturer(sinkIn) && IsCaptureSilently()) || !InputIsPrimary(sinkIn)) {
1273 AUTO_CTRACE("hdi_sink::PrimaryCluster:InnerCapturer and CaptureSilently or not primary");
1274 continue;
1275 } else if ((sceneTypeFlag && existFlag) || (pa_safe_streq(sceneType, "EFFECT_NONE") && (!existFlag))) {
1276 RecordEffectChainStatus(existFlag, sSceneType, sSceneMode, u->actualSpatializationEnabled);
1277 pa_sink_input_assert_ref(sinkIn);
1278 updateResampler(sinkIn, sceneType, false);
1279
1280 AUTO_CTRACE("hdi_sink::PrimaryCluster:%u len:%zu", sinkIn->index, *length);
1281 pa_sink_input_peek(sinkIn, *length, &infoIn->chunk, &infoIn->volume);
1282
1283 if (mixlength == 0 || infoIn->chunk.length < mixlength) {mixlength = infoIn->chunk.length;}
1284
1285 ProcessAudioVolume(sinkIn, mixlength, &infoIn->chunk, si);
1286
1287 if (pa_memblock_is_silence(infoIn->chunk.memblock) && sinkIn->thread_info.state == PA_SINK_INPUT_RUNNING) {
1288 AUTO_CTRACE("hdi_sink::PrimaryCluster::is_silence");
1289 pa_sink_input_handle_ohos_underrun(sinkIn);
1290 } else {
1291 AUTO_CTRACE("hdi_sink::PrimaryCluster::is_not_silence");
1292 }
1293
1294 HandleFading(si, *length, sinkIn, infoIn);
1295
1296 infoIn++;
1297 n++;
1298 maxInfo--;
1299 }
1300 }
1301
1302 SafeRendererSinkUpdateAppsUid(u->primary.sinkAdapter, appsUid, count);
1303
1304 if (mixlength > 0) { *length = mixlength; }
1305
1306 return n;
1307 }
1308
PrepareMultiChannelFading(pa_sink_input * sinkIn,pa_mix_info * infoIn,pa_sink * si)1309 static void PrepareMultiChannelFading(pa_sink_input *sinkIn, pa_mix_info *infoIn, pa_sink *si)
1310 {
1311 struct Userdata *u;
1312 pa_assert_se(u = si->userdata);
1313
1314 uint32_t streamIndex = sinkIn->index;
1315 uint32_t sinkFadeoutPause = GetFadeoutState(streamIndex);
1316 if (sinkFadeoutPause == DONE_FADE) {
1317 silenceData(infoIn, si);
1318 AUDIO_PRERELEASE_LOGI("silenceData.");
1319 return;
1320 }
1321
1322 uint32_t format = (uint32_t)ConvertPaToHdiAdapterFormat(u->format);
1323 if (pa_atomic_load(&u->multiChannel.fadingFlagForMultiChannel) == 1 &&
1324 u->multiChannel.multiChannelSinkInIndex == (int32_t)sinkIn->index) {
1325 if (pa_memblock_is_silence(infoIn->chunk.memblock)) {
1326 AUDIO_DEBUG_LOG("pa_memblock_is_silence");
1327 return;
1328 }
1329 //do fading in
1330 pa_memchunk_make_writable(&infoIn->chunk, 0);
1331 void *data = pa_memblock_acquire_chunk(&infoIn->chunk);
1332 DoFading(data, infoIn->chunk.length, format, (uint32_t)u->ss.channels, 0);
1333 u->multiChannel.multiChannelFadingInDone = 1;
1334 pa_memblock_release(infoIn->chunk.memblock);
1335 }
1336 if (sinkFadeoutPause == DO_FADE) {
1337 //do fading out
1338 pa_memchunk_make_writable(&infoIn->chunk, 0);
1339 void *data = pa_memblock_acquire_chunk(&infoIn->chunk);
1340 DoFading(data, infoIn->chunk.length, format, (uint32_t)u->ss.channels, 1);
1341 SetFadeoutState(streamIndex, DONE_FADE);
1342 }
1343 }
1344
CheckMultiChannelFadeinIsDone(pa_sink * si,pa_sink_input * sinkIn)1345 static void CheckMultiChannelFadeinIsDone(pa_sink *si, pa_sink_input *sinkIn)
1346 {
1347 struct Userdata *u;
1348 pa_assert_se(u = si->userdata);
1349
1350 if (u->multiChannel.multiChannelFadingInDone &&
1351 u->multiChannel.multiChannelSinkInIndex == (int32_t)sinkIn->index) {
1352 pa_atomic_store(&u->multiChannel.fadingFlagForMultiChannel, 0);
1353 }
1354 }
1355
SinkRenderMultiChannelCluster(pa_sink * si,size_t * length,pa_mix_info * infoIn,unsigned maxInfo)1356 static unsigned SinkRenderMultiChannelCluster(pa_sink *si, size_t *length, pa_mix_info *infoIn,
1357 unsigned maxInfo)
1358 {
1359 pa_sink_input *sinkIn;
1360 unsigned n = 0;
1361 void *state = NULL;
1362 size_t mixlength = *length;
1363
1364 pa_sink_assert_ref(si);
1365 pa_sink_assert_io_context(si);
1366 pa_assert(infoIn);
1367
1368 struct Userdata *u;
1369 pa_assert_se(u = si->userdata);
1370
1371 int32_t appsUid[MAX_MIX_CHANNELS];
1372 size_t count = 0;
1373
1374 while ((sinkIn = pa_hashmap_iterate(si->thread_info.inputs, &state, NULL)) && maxInfo > 0) {
1375 CheckAndPushUidToArr(sinkIn, appsUid, &count);
1376 int32_t sinkChannels = sinkIn->sample_spec.channels;
1377 const char *sinkSceneType = pa_proplist_gets(sinkIn->proplist, "scene.type");
1378 const char *sinkSceneMode = pa_proplist_gets(sinkIn->proplist, "scene.mode");
1379 const char *sinkSpatializationEnabled = pa_proplist_gets(sinkIn->proplist, "spatialization.enabled");
1380 bool existFlag = EffectChainManagerExist(sinkSceneType, sinkSceneMode, sinkSpatializationEnabled);
1381 if (!existFlag && sinkChannels > PRIMARY_CHANNEL_NUM) {
1382 pa_sink_input_assert_ref(sinkIn);
1383 updateResampler(sinkIn, NULL, true);
1384 pa_sink_input_peek(sinkIn, *length, &infoIn->chunk, &infoIn->volume);
1385
1386 if (mixlength == 0 || infoIn->chunk.length < mixlength) {mixlength = infoIn->chunk.length;}
1387
1388 ProcessAudioVolume(sinkIn, mixlength, &infoIn->chunk, si);
1389
1390 if (pa_memblock_is_silence(infoIn->chunk.memblock) && sinkIn->thread_info.state == PA_SINK_INPUT_RUNNING) {
1391 AUTO_CTRACE("hdi_sink::SinkRenderMultiChannelCluster::is_silence");
1392 pa_sink_input_handle_ohos_underrun(sinkIn);
1393 }
1394
1395 infoIn->userdata = pa_sink_input_ref(sinkIn);
1396 pa_assert(infoIn->chunk.memblock);
1397 pa_assert(infoIn->chunk.length > 0);
1398
1399 if (pa_safe_streq(sinkSpatializationEnabled, "true")) {
1400 PrepareMultiChannelFading(sinkIn, infoIn, si);
1401 CheckMultiChannelFadeinIsDone(si, sinkIn);
1402 }
1403 infoIn++;
1404 n++;
1405 maxInfo--;
1406 }
1407 }
1408
1409 SafeRendererSinkUpdateAppsUid(u->multiChannel.sinkAdapter, appsUid, count);
1410
1411 if (mixlength > 0) { *length = mixlength; }
1412
1413 return n;
1414 }
1415
SinkRenderPrimaryPeek(pa_sink * si,pa_memchunk * chunkIn,const char * sceneType)1416 static int32_t SinkRenderPrimaryPeek(pa_sink *si, pa_memchunk *chunkIn, const char *sceneType)
1417 {
1418 pa_mix_info info[MAX_MIX_CHANNELS];
1419 unsigned n;
1420 size_t length;
1421 size_t blockSizeMax;
1422
1423 pa_sink_assert_ref(si);
1424 pa_sink_assert_io_context(si);
1425 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
1426 pa_assert(chunkIn);
1427 pa_assert(chunkIn->memblock);
1428 pa_assert(chunkIn->length > 0);
1429 pa_assert(pa_frame_aligned(chunkIn->length, &si->sample_spec));
1430
1431 pa_assert(!si->thread_info.rewind_requested);
1432 pa_assert(si->thread_info.rewind_nbytes == 0);
1433
1434 if (si->thread_info.state == PA_SINK_SUSPENDED) {
1435 AUTO_CTRACE("hdi_sink::Primary:PA_SINK_SUSPENDED");
1436 pa_silence_memchunk(chunkIn, &si->sample_spec);
1437 return 0;
1438 }
1439
1440 pa_sink_ref(si);
1441
1442 length = chunkIn->length;
1443 blockSizeMax = pa_mempool_block_size_max(si->core->mempool);
1444 if (length > blockSizeMax)
1445 length = pa_frame_align(blockSizeMax, &si->sample_spec);
1446
1447 pa_assert(length > 0);
1448 n = SinkRenderPrimaryCluster(si, &length, info, MAX_MIX_CHANNELS, sceneType);
1449
1450 AUTO_CTRACE("hdi_sink:Primary:SinkRenderPrimaryMix:%u len:%zu", n, length);
1451 SinkRenderPrimaryMix(si, length, info, n, chunkIn);
1452
1453 SinkRenderPrimaryInputsDrop(si, info, n, chunkIn);
1454 pa_sink_unref(si);
1455 return n;
1456 }
1457
SinkRenderMultiChannelPeek(pa_sink * si,pa_memchunk * chunkIn)1458 static int32_t SinkRenderMultiChannelPeek(pa_sink *si, pa_memchunk *chunkIn)
1459 {
1460 pa_mix_info info[MAX_MIX_CHANNELS];
1461 unsigned n;
1462 size_t length;
1463 size_t blockSizeMax;
1464
1465 pa_sink_assert_ref(si);
1466 pa_sink_assert_io_context(si);
1467 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
1468 pa_assert(chunkIn);
1469 pa_assert(chunkIn->memblock);
1470 pa_assert(chunkIn->length > 0);
1471 pa_assert(pa_frame_aligned(chunkIn->length, &si->sample_spec));
1472
1473 pa_assert(!si->thread_info.rewind_requested);
1474 pa_assert(si->thread_info.rewind_nbytes == 0);
1475
1476 if (si->thread_info.state == PA_SINK_SUSPENDED) {
1477 AUTO_CTRACE("hdi_sink::MultiCh:PA_SINK_SUSPENDED");
1478 pa_silence_memchunk(chunkIn, &si->sample_spec);
1479 return 0;
1480 }
1481
1482 pa_sink_ref(si);
1483
1484 length = chunkIn->length;
1485 blockSizeMax = pa_mempool_block_size_max(si->core->mempool);
1486 if (length > blockSizeMax)
1487 length = pa_frame_align(blockSizeMax, &si->sample_spec);
1488
1489 pa_assert(length > 0);
1490
1491 n = SinkRenderMultiChannelCluster(si, &length, info, MAX_MIX_CHANNELS);
1492
1493 AUTO_CTRACE("hdi_sink:MultiCh:SinkRenderPrimaryMix:%u len:%zu", n, length);
1494 SinkRenderPrimaryMix(si, length, info, n, chunkIn);
1495
1496 SinkRenderMultiChannelInputsDrop(si, info, n, chunkIn);
1497 pa_sink_unref(si);
1498
1499 return n;
1500 }
1501
SinkRenderPrimaryGetData(pa_sink * si,pa_memchunk * chunkIn,char * sceneType)1502 static int32_t SinkRenderPrimaryGetData(pa_sink *si, pa_memchunk *chunkIn, char *sceneType)
1503 {
1504 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryGetData:%s", sceneType);
1505 pa_memchunk chunk;
1506 size_t l;
1507 size_t d;
1508 pa_sink_assert_ref(si);
1509 pa_sink_assert_io_context(si);
1510 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
1511 pa_assert(chunkIn);
1512 pa_assert(chunkIn->memblock);
1513 pa_assert(chunkIn->length > 0);
1514 pa_assert(pa_frame_aligned(chunkIn->length, &si->sample_spec));
1515
1516 pa_assert(!si->thread_info.rewind_requested);
1517 pa_assert(si->thread_info.rewind_nbytes == 0);
1518
1519 if (si->thread_info.state == PA_SINK_SUSPENDED) {
1520 pa_silence_memchunk(chunkIn, &si->sample_spec);
1521 return 0;
1522 }
1523
1524 pa_sink_ref(si);
1525
1526 l = chunkIn->length;
1527 d = 0;
1528 int32_t nSinkInput = 0;
1529 while (l > 0) {
1530 chunk = *chunkIn;
1531 chunk.index += d;
1532 chunk.length -= d;
1533
1534 nSinkInput = SinkRenderPrimaryPeek(si, &chunk, sceneType);
1535
1536 d += chunk.length;
1537 l -= chunk.length;
1538 }
1539 pa_sink_unref(si);
1540
1541 return nSinkInput;
1542 }
1543
SinkRenderMultiChannelGetData(pa_sink * si,pa_memchunk * chunkIn)1544 static int32_t SinkRenderMultiChannelGetData(pa_sink *si, pa_memchunk *chunkIn)
1545 {
1546 pa_memchunk chunk;
1547 size_t l;
1548 size_t d;
1549 pa_sink_assert_ref(si);
1550 pa_sink_assert_io_context(si);
1551 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
1552 pa_assert(chunkIn);
1553 pa_assert(chunkIn->memblock);
1554 pa_assert(chunkIn->length > 0);
1555 pa_assert(pa_frame_aligned(chunkIn->length, &si->sample_spec));
1556
1557 pa_assert(!si->thread_info.rewind_requested);
1558 pa_assert(si->thread_info.rewind_nbytes == 0);
1559
1560 if (si->thread_info.state == PA_SINK_SUSPENDED) {
1561 pa_silence_memchunk(chunkIn, &si->sample_spec);
1562 return 0;
1563 }
1564
1565 pa_sink_ref(si);
1566
1567 l = chunkIn->length;
1568 d = 0;
1569
1570 int32_t nSinkInput = 0;
1571 while (l > 0) {
1572 chunk = *chunkIn;
1573 chunk.index += d;
1574 chunk.length -= d;
1575
1576 nSinkInput = SinkRenderMultiChannelPeek(si, &chunk);
1577
1578 d += chunk.length;
1579 l -= chunk.length;
1580 }
1581
1582 pa_sink_unref(si);
1583
1584 return nSinkInput;
1585 }
1586
PrepareSpatializationFading(int8_t * fadingState,int8_t * fadingCount,bool * actualSpatializationEnabled)1587 static void PrepareSpatializationFading(int8_t *fadingState, int8_t *fadingCount, bool *actualSpatializationEnabled)
1588 {
1589 (*fadingCount) = (*fadingCount) < 0 ? 0 : (*fadingCount);
1590 (*fadingCount) =
1591 (*fadingCount) > SPATIALIZATION_FADING_FRAMECOUNT ? SPATIALIZATION_FADING_FRAMECOUNT : (*fadingCount);
1592 // fading out if spatialization changed
1593 if (*fadingState >= 0 && *actualSpatializationEnabled != EffectChainManagerGetSpatializationEnabled()) {
1594 *fadingState = -1;
1595 }
1596 // fading in when fading out is done
1597 if (*fadingState < 0 && *fadingCount == 0) {
1598 *fadingState = 1;
1599 *actualSpatializationEnabled = EffectChainManagerGetSpatializationEnabled();
1600 EffectChainManagerFlush();
1601 }
1602 // no need to fade when fading out is done
1603 if (*fadingState > 0 && *fadingCount == SPATIALIZATION_FADING_FRAMECOUNT) {
1604 *fadingState = 0;
1605 }
1606 }
1607
DoSpatializationFading(float * buf,int8_t fadingState,int8_t * fadingCount,int32_t frameLen,int32_t channels)1608 static void DoSpatializationFading(float *buf, int8_t fadingState, int8_t *fadingCount, int32_t frameLen,
1609 int32_t channels)
1610 {
1611 // no need fading
1612 if (fadingState == 0) {
1613 return;
1614 }
1615 // fading out when fadingState equals -1, fading in when fadingState equals 1;
1616 for (int32_t i = 0; i < frameLen; i++) {
1617 for (int32_t j = 0; j < channels; j++) {
1618 buf[i * channels + j] *=
1619 ((*fadingCount) * frameLen + i * fadingState) / (float)(SPATIALIZATION_FADING_FRAMECOUNT * frameLen);
1620 }
1621 }
1622 (*fadingCount) += fadingState;
1623 }
1624
SinkRenderPrimaryAfterProcess(pa_sink * si,size_t length,pa_memchunk * chunkIn)1625 static void SinkRenderPrimaryAfterProcess(pa_sink *si, size_t length, pa_memchunk *chunkIn)
1626 {
1627 struct Userdata *u;
1628 pa_assert_se(u = si->userdata);
1629 int32_t bitSize = (int32_t)pa_sample_size_of_format(u->format);
1630 u->bufferAttr->numChanIn = DEFAULT_IN_CHANNEL_NUM;
1631 void *dst = pa_memblock_acquire_chunk(chunkIn);
1632 int32_t frameLen = bitSize > 0 ? ((int32_t)length / bitSize) : 0;
1633 DoSpatializationFading(u->bufferAttr->tempBufOut, u->spatializationFadingState, &u->spatializationFadingCount,
1634 frameLen / DEFAULT_IN_CHANNEL_NUM, DEFAULT_IN_CHANNEL_NUM);
1635 ConvertFromFloat(u->format, frameLen, u->bufferAttr->tempBufOut, dst);
1636
1637 chunkIn->index = 0;
1638 chunkIn->length = length;
1639 pa_memblock_release(chunkIn->memblock);
1640 }
1641
HandleSinkSceneType(struct Userdata * u,time_t currentTime,int32_t i)1642 static char *HandleSinkSceneType(struct Userdata *u, time_t currentTime, int32_t i)
1643 {
1644 char *sinkSceneType = SCENE_TYPE_SET[i];
1645 if (g_effectAllStreamVolumeZeroMap[i] && PA_SINK_IS_RUNNING(u->sink->thread_info.state) &&
1646 difftime(currentTime, g_effectStartVolZeroTimeMap[i]) > WAIT_CLOSE_PA_OR_EFFECT_TIME) {
1647 sinkSceneType = SCENE_TYPE_SET[SCENE_TYPE_NUM - 1]; // EFFECT_NONE
1648 if (!g_effectHaveDisabledMap[i]) {
1649 AUDIO_INFO_LOG("volume change to zero over %{public}ds, close effect:%{public}s success.",
1650 WAIT_CLOSE_PA_OR_EFFECT_TIME, SCENE_TYPE_SET[i]);
1651 g_effectHaveDisabledMap[i] = true;
1652 g_effectStartVolZeroTimeMap[i] = 0;
1653 }
1654 } else {
1655 sinkSceneType = SCENE_TYPE_SET[i];
1656 if (g_effectHaveDisabledMap[i]) {
1657 g_effectHaveDisabledMap[i] = false;
1658 AUDIO_INFO_LOG("volume change to non zero, open effect:%{public}s success. ", SCENE_TYPE_SET[i]);
1659 }
1660 }
1661 return sinkSceneType;
1662 }
1663
CheckAndDealEffectZeroVolume(struct Userdata * u,time_t currentTime,int32_t i)1664 static char *CheckAndDealEffectZeroVolume(struct Userdata *u, time_t currentTime, int32_t i)
1665 {
1666 void *state = NULL;
1667 pa_sink_input *input;
1668 g_effectAllStreamVolumeZeroMap[i] = true;
1669 while ((input = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL))) {
1670 pa_sink_input_assert_ref(input);
1671 if (input->thread_info.state != PA_SINK_INPUT_RUNNING) {
1672 continue;
1673 }
1674 const char *sinkSceneTypeTmp = pa_proplist_gets(input->proplist, "scene.type");
1675 const char *streamType = safeProplistGets(input->proplist, "stream.type", "NULL");
1676 const char *sessionIDStr = safeProplistGets(input->proplist, "stream.sessionID", "NULL");
1677 const char *deviceClass = GetDeviceClass(u->primary.sinkAdapter->deviceClass);
1678 uint32_t sessionID = sessionIDStr != NULL ? atoi(sessionIDStr) : 0;
1679 float volume = GetCurVolume(sessionID, streamType, deviceClass);
1680 bool isZeroVolume = IsSameVolume(volume, 0.0f);
1681 if (EffectChainManagerSceneCheck(sinkSceneTypeTmp, SCENE_TYPE_SET[i]) && !isZeroVolume) {
1682 g_effectAllStreamVolumeZeroMap[i] = false;
1683 g_effectStartVolZeroTimeMap[i] = 0;
1684 AUDIO_DEBUG_LOG("SCENE_TYPE_SET[%{public}d]:%{public}s for streamtype:[%{public}s]'s"
1685 " volume is non zero, this effect all streamtype is non zero volume.", i,
1686 SCENE_TYPE_SET[i], streamType);
1687 break;
1688 }
1689 }
1690
1691 if (g_effectAllStreamVolumeZeroMap[i] && !g_effectHaveDisabledMap[i] && (g_effectStartVolZeroTimeMap[i] == 0) &&
1692 PA_SINK_IS_RUNNING(u->sink->thread_info.state)) {
1693 AUDIO_INFO_LOG("Timing begins, will close [%{public}s] effect after [%{public}d]s", SCENE_TYPE_SET[i],
1694 WAIT_CLOSE_PA_OR_EFFECT_TIME);
1695 time(&g_effectStartVolZeroTimeMap[i]);
1696 }
1697
1698 char *handledSceneType = HandleSinkSceneType(u, currentTime, i);
1699 AUDIO_DEBUG_LOG("handle sink scene type:%{public}s", handledSceneType);
1700 return handledSceneType;
1701 }
1702
CheckOnlyPrimarySpeakerPaLoading(struct Userdata * u)1703 static void CheckOnlyPrimarySpeakerPaLoading(struct Userdata *u)
1704 {
1705 pa_sink *s;
1706 pa_core *c = u->core;
1707 uint32_t idx;
1708 PA_IDXSET_FOREACH(s, c->sinks, idx) {
1709 bool isHdiSink = !strncmp(s->driver, "module_hdi_sink", 15); // 15 cmp length
1710 if (isHdiSink && strcmp(s->name, "Speaker")) {
1711 AUDIO_DEBUG_LOG("Have new routing:[%{public}s] on primary, dont close it.", s->name);
1712 g_onlyPrimarySpeakerPaLoading = false;
1713 g_speakerPaAllStreamVolumeZero = false;
1714 g_speakerPaAllStreamStartVolZeroTime = 0;
1715 break;
1716 }
1717 }
1718
1719 if (strcmp(GetDeviceClass(u->primary.sinkAdapter->deviceClass), "primary")) {
1720 AUDIO_DEBUG_LOG("Sink[%{public}s] -- no primary, dont close it.",
1721 GetDeviceClass(u->primary.sinkAdapter->deviceClass));
1722 g_onlyPrimarySpeakerPaLoading = false;
1723 g_speakerPaAllStreamVolumeZero = false;
1724 g_speakerPaAllStreamStartVolZeroTime = 0;
1725 }
1726
1727 if (PA_SINK_IS_RUNNING(u->sink->thread_info.state) && !g_onlyPrimarySpeakerPaLoading && g_paHaveDisabled) {
1728 int32_t ret = u->primary.sinkAdapter->RendererSinkSetPaPower(u->primary.sinkAdapter, 1);
1729 AUDIO_INFO_LOG("sink running, open closed pa:[%{public}s] -- [%{public}s], ret:%{public}d", u->sink->name,
1730 (ret == 0 ? "success" : "failed"), ret);
1731 g_paHaveDisabled = false;
1732 g_speakerPaHaveClosed = false;
1733 }
1734 }
1735
HandleClosePa(struct Userdata * u)1736 static void HandleClosePa(struct Userdata *u)
1737 {
1738 if (!g_paHaveDisabled) {
1739 int32_t ret = u->primary.sinkAdapter->RendererSinkSetPaPower(u->primary.sinkAdapter, 0);
1740 AUDIO_INFO_LOG("Speaker pa volume change to zero over [%{public}d]s, close %{public}s pa [%{public}s], "
1741 "ret:%{public}d", WAIT_CLOSE_PA_OR_EFFECT_TIME, u->sink->name, (ret == 0 ? "success" : "failed"), ret);
1742 g_paHaveDisabled = true;
1743 g_speakerPaAllStreamStartVolZeroTime = 0;
1744 g_speakerPaHaveClosed = true;
1745 time(&g_speakerPaClosedTime);
1746 }
1747 }
1748
HandleOpenPa(struct Userdata * u)1749 static void HandleOpenPa(struct Userdata *u)
1750 {
1751 if (g_paHaveDisabled) {
1752 int32_t ret = u->primary.sinkAdapter->RendererSinkSetPaPower(u->primary.sinkAdapter, 1);
1753 AUDIO_INFO_LOG("volume change to non zero, open closed pa:[%{public}s] -- [%{public}s], ret:%{public}d",
1754 u->sink->name, (ret == 0 ? "success" : "failed"), ret);
1755 g_paHaveDisabled = false;
1756 g_speakerPaHaveClosed = false;
1757 }
1758 }
1759
CheckAndDealSpeakerPaZeroVolume(struct Userdata * u,time_t currentTime)1760 static void CheckAndDealSpeakerPaZeroVolume(struct Userdata *u, time_t currentTime)
1761 {
1762 if (!g_onlyPrimarySpeakerPaLoading) {
1763 AUDIO_DEBUG_LOG("Not only the speaker pa, dont deal speaker pa.");
1764 return;
1765 }
1766 void *state = NULL;
1767 pa_sink_input *input;
1768 while ((input = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL))) {
1769 pa_sink_input_assert_ref(input);
1770 if (input->thread_info.state != PA_SINK_INPUT_RUNNING) {
1771 continue;
1772 }
1773 const char *streamType = safeProplistGets(input->proplist, "stream.type", "NULL");
1774 const char *sessionIDStr = safeProplistGets(input->proplist, "stream.sessionID", "NULL");
1775 const char *deviceClass = GetDeviceClass(u->primary.sinkAdapter->deviceClass);
1776 uint32_t sessionID = sessionIDStr != NULL ? atoi(sessionIDStr) : 0;
1777 float volume = GetCurVolume(sessionID, streamType, deviceClass);
1778 bool isZeroVolume = IsSameVolume(volume, 0.0f);
1779 if (!strcmp(u->sink->name, "Speaker") && !isZeroVolume) {
1780 g_speakerPaAllStreamVolumeZero = false;
1781 g_speakerPaAllStreamStartVolZeroTime = 0;
1782 break;
1783 }
1784 }
1785
1786 if (g_speakerPaAllStreamVolumeZero && !g_paHaveDisabled && (g_speakerPaAllStreamStartVolZeroTime == 0) &&
1787 PA_SINK_IS_RUNNING(u->sink->thread_info.state)) {
1788 AUDIO_INFO_LOG("Timing begins, will close speaker after [%{public}d]s", WAIT_CLOSE_PA_OR_EFFECT_TIME);
1789 time(&g_speakerPaAllStreamStartVolZeroTime);
1790 }
1791 if (g_speakerPaAllStreamVolumeZero && PA_SINK_IS_RUNNING(u->sink->thread_info.state) &&
1792 difftime(currentTime, g_speakerPaAllStreamStartVolZeroTime) > WAIT_CLOSE_PA_OR_EFFECT_TIME) {
1793 HandleClosePa(u);
1794 } else {
1795 HandleOpenPa(u);
1796 }
1797
1798 if (g_speakerPaHaveClosed && difftime(currentTime, g_speakerPaClosedTime) >= MONITOR_CLOSE_PA_TIME_SEC) {
1799 time(&g_speakerPaClosedTime);
1800 AUDIO_INFO_LOG("Speaker pa have closed [%{public}d]s.", MONITOR_CLOSE_PA_TIME_SEC);
1801 }
1802 }
1803
UpdateStreamAvailableMap(struct Userdata * u,const char * sceneType)1804 static void UpdateStreamAvailableMap(struct Userdata *u, const char *sceneType)
1805 {
1806 if (u->streamAvailableMap == NULL) {
1807 AUDIO_ERR_LOG("streamAvailableMap is null");
1808 return;
1809 }
1810 uint32_t *num = (uint32_t *)pa_hashmap_get(u->streamAvailableMap, sceneType);
1811 if (num == NULL) {
1812 num = pa_xnew0(uint32_t, 1);
1813 (*num) = 0;
1814 }
1815 int32_t fadeDirection = (u->streamAvailable != 0) && ((*num) == 0) ? 0 :
1816 (u->streamAvailable == 0 && (*num) != 0) ? 1 : -1;
1817 int32_t outLength = u->bufferAttr->frameLen * u->bufferAttr->numChanOut * sizeof(float);
1818 if (fadeDirection != -1) {
1819 AUDIO_INFO_LOG("do %{public}s for MIXED DATA", fadeDirection ? "fade-out" : "fade-in");
1820 DoFading(u->bufferAttr->bufOut, outLength, (uint32_t)SAMPLE_F32, (uint32_t)u->ss.channels, fadeDirection);
1821 }
1822 if (u->streamAvailable == 0 && (*num) == 0) {
1823 memset_s(u->bufferAttr->bufOut, outLength, 0, outLength);
1824 }
1825
1826 if (pa_hashmap_get(u->streamAvailableMap, sceneType) != NULL) {
1827 (*num) = u->streamAvailable;
1828 } else {
1829 char *scene = strdup(sceneType);
1830 if (scene != NULL) {
1831 (*num) = u->streamAvailable;
1832 if (pa_hashmap_put(u->streamAvailableMap, scene, num) != 0) {
1833 AUDIO_ERR_LOG("pa_hashmap_put failed");
1834 free(scene);
1835 pa_xfree(num);
1836 }
1837 }
1838 }
1839 }
1840
PrimaryEffectProcess(struct Userdata * u,pa_memchunk * chunkIn,char * sinkSceneType)1841 static void PrimaryEffectProcess(struct Userdata *u, pa_memchunk *chunkIn, char *sinkSceneType)
1842 {
1843 AUTO_CTRACE("hdi_sink::EffectChainManagerProcess:%s", sinkSceneType);
1844 EffectChainManagerProcess(sinkSceneType, u->bufferAttr);
1845 UpdateStreamAvailableMap(u, sinkSceneType);
1846 for (int32_t k = 0; k < u->bufferAttr->frameLen * u->bufferAttr->numChanOut; k++) {
1847 u->bufferAttr->tempBufOut[k] += u->bufferAttr->bufOut[k];
1848 }
1849 pa_memblock_release(chunkIn->memblock);
1850 u->bufferAttr->numChanIn = DEFAULT_IN_CHANNEL_NUM;
1851 }
1852
AllocateBuffer(size_t size)1853 static void *AllocateBuffer(size_t size)
1854 {
1855 if (size > 0 && size <= sizeof(float) * DEFAULT_FRAMELEN * IN_CHANNEL_NUM_MAX) {
1856 return malloc(size);
1857 } else {
1858 return NULL;
1859 }
1860 }
1861
AllocateEffectBuffer(struct Userdata * u)1862 static bool AllocateEffectBuffer(struct Userdata *u)
1863 {
1864 if (u->bufferAttr == NULL) {
1865 return false;
1866 }
1867 float **buffers[] = { &u->bufferAttr->bufIn, &u->bufferAttr->bufOut,
1868 &u->bufferAttr->tempBufIn, &u->bufferAttr->tempBufOut };
1869 size_t numBuffers = sizeof(buffers) / sizeof(buffers[0]);
1870 for (size_t i = 0; i < numBuffers; i++) {
1871 *buffers[i] = (float *)AllocateBuffer(u->processSize);
1872 if (*buffers[i] == NULL) {
1873 AUDIO_ERR_LOG("failed to allocate effect buffer");
1874 FreeEffectBuffer(u);
1875 return false;
1876 }
1877 }
1878 return true;
1879 }
1880
FreeEffectBuffer(struct Userdata * u)1881 static void FreeEffectBuffer(struct Userdata *u)
1882 {
1883 if (u->bufferAttr == NULL) {
1884 return;
1885 }
1886 float **buffers[] = { &u->bufferAttr->bufIn, &u->bufferAttr->bufOut,
1887 &u->bufferAttr->tempBufIn, &u->bufferAttr->tempBufOut };
1888 size_t numBuffers = sizeof(buffers) / sizeof(buffers[0]);
1889 for (size_t i = 0; i < numBuffers; i++) {
1890 free(*buffers[i]);
1891 *buffers[i] = NULL;
1892 }
1893 }
1894
ResetBufferAttr(struct Userdata * u)1895 static void ResetBufferAttr(struct Userdata *u)
1896 {
1897 size_t memsetInLen = sizeof(float) * DEFAULT_FRAMELEN * IN_CHANNEL_NUM_MAX;
1898 size_t memsetOutLen = sizeof(float) * DEFAULT_FRAMELEN * OUT_CHANNEL_NUM_MAX;
1899 if (memset_s(u->bufferAttr->tempBufIn, u->processSize, 0, memsetInLen) != EOK) {
1900 AUDIO_WARNING_LOG("SinkRenderBufIn memset_s failed");
1901 }
1902 if (memset_s(u->bufferAttr->tempBufOut, u->processSize, 0, memsetOutLen) != EOK) {
1903 AUDIO_WARNING_LOG("SinkRenderBufOut memset_s failed");
1904 }
1905 }
1906
SinkRenderPrimaryProcess(pa_sink * si,size_t length,pa_memchunk * chunkIn)1907 static void SinkRenderPrimaryProcess(pa_sink *si, size_t length, pa_memchunk *chunkIn)
1908 {
1909 if (GetInnerCapturerState()) {
1910 pa_memchunk capResult;
1911 SinkRenderCapProcess(si, length, &capResult);
1912 pa_memblock_unref(capResult.memblock);
1913 }
1914
1915 struct Userdata *u;
1916 pa_assert_se(u = si->userdata);
1917
1918 ResetBufferAttr(u);
1919 int32_t bitSize = (int32_t)pa_sample_size_of_format(u->format);
1920 chunkIn->memblock = pa_memblock_new(si->core->mempool, length * IN_CHANNEL_NUM_MAX / DEFAULT_IN_CHANNEL_NUM);
1921 time_t currentTime = time(NULL);
1922 PrepareSpatializationFading(&u->spatializationFadingState, &u->spatializationFadingCount,
1923 &u->actualSpatializationEnabled);
1924 g_effectProcessFrameCount++;
1925 u->streamAvailable = 0;
1926 for (int32_t i = 0; i < SCENE_TYPE_NUM; i++) {
1927 uint32_t processChannels = DEFAULT_NUM_CHANNEL;
1928 uint64_t processChannelLayout = DEFAULT_CHANNELLAYOUT;
1929 EffectChainManagerReturnEffectChannelInfo(SCENE_TYPE_SET[i], &processChannels, &processChannelLayout);
1930 char *sinkSceneType = CheckAndDealEffectZeroVolume(u, currentTime, i);
1931 size_t tmpLength = length * processChannels / DEFAULT_IN_CHANNEL_NUM;
1932 chunkIn->index = 0;
1933 chunkIn->length = tmpLength;
1934 int32_t nSinkInput = SinkRenderPrimaryGetData(si, chunkIn, SCENE_TYPE_SET[i]);
1935 if (nSinkInput == 0) { continue; }
1936 chunkIn->index = 0;
1937 chunkIn->length = tmpLength;
1938 void *src = pa_memblock_acquire_chunk(chunkIn);
1939 int32_t frameLen = bitSize > 0 ? ((int32_t)tmpLength / bitSize) : 0;
1940
1941 ConvertToFloat(u->format, frameLen, src, u->bufferAttr->tempBufIn);
1942 memcpy_s(u->bufferAttr->bufIn, frameLen * sizeof(float), u->bufferAttr->tempBufIn, frameLen * sizeof(float));
1943 u->bufferAttr->numChanIn = (int32_t)processChannels;
1944 u->bufferAttr->frameLen = frameLen / u->bufferAttr->numChanIn;
1945 PrimaryEffectProcess(u, chunkIn, sinkSceneType);
1946 }
1947 if (g_effectProcessFrameCount == PRINT_INTERVAL_FRAME_COUNT) { g_effectProcessFrameCount = 0; }
1948 CheckAndDealSpeakerPaZeroVolume(u, currentTime);
1949 SinkRenderPrimaryAfterProcess(si, length, chunkIn);
1950 }
1951
SinkRenderPrimary(pa_sink * si,size_t length,pa_memchunk * chunkIn)1952 static void SinkRenderPrimary(pa_sink *si, size_t length, pa_memchunk *chunkIn)
1953 {
1954 pa_sink_ref(si);
1955
1956 size_t blockSizeMax;
1957
1958 pa_sink_assert_ref(si);
1959 pa_sink_assert_io_context(si);
1960 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
1961 pa_assert(length > 0);
1962 pa_assert(pa_frame_aligned(length, &si->sample_spec));
1963 pa_assert(chunkIn);
1964
1965 pa_assert(!si->thread_info.rewind_requested);
1966 pa_assert(si->thread_info.rewind_nbytes == 0);
1967
1968 if (si->thread_info.state == PA_SINK_SUSPENDED) {
1969 chunkIn->memblock = pa_memblock_ref(si->silence.memblock);
1970 chunkIn->index = si->silence.index;
1971 chunkIn->length = PA_MIN(si->silence.length, length);
1972 return;
1973 }
1974
1975 if (length == 0)
1976 length = pa_frame_align(MIX_BUFFER_LENGTH, &si->sample_spec);
1977
1978 blockSizeMax = pa_mempool_block_size_max(si->core->mempool);
1979 if (length > blockSizeMax)
1980 length = pa_frame_align(blockSizeMax, &si->sample_spec);
1981
1982 pa_assert(length > 0);
1983 AUTO_CTRACE("hdi_sink::SinkRenderPrimaryProcess:len:%zu", length);
1984 SinkRenderPrimaryProcess(si, length, chunkIn);
1985
1986 pa_sink_unref(si);
1987 }
1988
SetSinkVolumeByDeviceClass(pa_sink * s,const char * deviceClass)1989 static void SetSinkVolumeByDeviceClass(pa_sink *s, const char *deviceClass)
1990 {
1991 pa_assert(s);
1992 void *state = NULL;
1993 pa_sink_input *input;
1994 while ((input = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
1995 pa_sink_input_assert_ref(input);
1996 if (input->thread_info.state != PA_SINK_INPUT_RUNNING) {
1997 continue;
1998 }
1999 const char *streamType = safeProplistGets(input->proplist, "stream.type", "NULL");
2000 const char *sessionIDStr = safeProplistGets(input->proplist, "stream.sessionID", "NULL");
2001 uint32_t sessionID = sessionIDStr != NULL ? atoi(sessionIDStr) : 0;
2002 float volumeEnd = GetCurVolume(sessionID, streamType, deviceClass);
2003 float volumeBeg = GetPreVolume(sessionID);
2004 if (volumeBeg != volumeEnd) {
2005 AUDIO_INFO_LOG("sessionID:%{public}s, volumeBeg:%{public}f, volumeEnd:%{public}f",
2006 sessionIDStr, volumeBeg, volumeEnd);
2007 SetPreVolume(sessionID, volumeEnd);
2008 MonitorVolume(sessionID, true);
2009 }
2010 uint32_t volume = pa_sw_volume_from_linear(volumeEnd);
2011 pa_cvolume_set(&input->thread_info.soft_volume, input->thread_info.soft_volume.channels, volume);
2012 }
2013 }
2014
UnsetSinkVolume(pa_sink * s)2015 static void UnsetSinkVolume(pa_sink *s)
2016 {
2017 pa_assert(s);
2018 void *state = NULL;
2019 pa_sink_input *input;
2020 while ((input = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
2021 pa_sink_input_assert_ref(input);
2022 if (input->thread_info.state != PA_SINK_INPUT_RUNNING) {
2023 continue;
2024 }
2025 uint32_t volume = pa_sw_volume_from_linear(1.0f);
2026 pa_cvolume_set(&input->thread_info.soft_volume, input->thread_info.soft_volume.channels, volume);
2027 }
2028 }
2029
ProcessRenderUseTiming(struct Userdata * u,pa_usec_t now)2030 static void ProcessRenderUseTiming(struct Userdata *u, pa_usec_t now)
2031 {
2032 pa_assert(u);
2033
2034 // Fill the buffer up the latency size
2035 pa_memchunk chunk;
2036
2037 AUTO_CTRACE("hdi_sink::SinkRenderPrimary");
2038 // Change from pa_sink_render to pa_sink_render_full for alignment issue in 3516
2039
2040 if (!strcmp(u->sink->name, DP_SINK_NAME)) {
2041 // dp update volume
2042 SetSinkVolumeByDeviceClass(u->sink, GetDeviceClass(u->primary.sinkAdapter->deviceClass));
2043 pa_sink_render_full(u->sink, u->sink->thread_info.max_request, &chunk);
2044 UnsetSinkVolume(u->sink); // reset volume 1.0f
2045 } else {
2046 if (u->isEffectBufferAllocated || AllocateEffectBuffer(u)) {
2047 u->isEffectBufferAllocated = true;
2048 SinkRenderPrimary(u->sink, u->sink->thread_info.max_request, &chunk);
2049 }
2050 }
2051 pa_assert(chunk.length > 0);
2052
2053 StartPrimaryHdiIfRunning(u);
2054 pa_asyncmsgq_post(u->primary.dq, NULL, HDI_RENDER, NULL, 0, &chunk, NULL);
2055 u->primary.timestamp += pa_bytes_to_usec(chunk.length, &u->sink->sample_spec);
2056 }
2057
InputIsOffload(pa_sink_input * i)2058 static bool InputIsOffload(pa_sink_input *i)
2059 {
2060 if (monitorLinked(i->sink, true)) {
2061 return false;
2062 }
2063 if (strncmp(i->sink->driver, "module_hdi_sink", 15)) { // 15 cmp length
2064 return false;
2065 }
2066 struct Userdata *u = i->sink->userdata;
2067 if (!u->offload_enable || !u->offload.inited) {
2068 return false;
2069 }
2070 const char *offloadEnableStr = pa_proplist_gets(i->proplist, "stream.offload.enable");
2071 if (offloadEnableStr == NULL) {
2072 return false;
2073 }
2074 const bool offloadEnable = !strcmp(offloadEnableStr, "1");
2075 return offloadEnable;
2076 }
2077
InputIsMultiChannel(pa_sink_input * i)2078 static bool InputIsMultiChannel(pa_sink_input *i)
2079 {
2080 bool effectOffloadFlag = EffectChainManagerCheckEffectOffload();
2081 if (effectOffloadFlag) {
2082 int32_t sinkChannels = i->sample_spec.channels;
2083 const char *sinkSceneType = pa_proplist_gets(i->proplist, "scene.type");
2084 const char *sinkSceneMode = pa_proplist_gets(i->proplist, "scene.mode");
2085 const char *sinkSpatializationEnabled = pa_proplist_gets(i->proplist, "spatialization.enabled");
2086 bool existFlag = EffectChainManagerExist(sinkSceneType, sinkSceneMode, sinkSpatializationEnabled);
2087 if (!existFlag && sinkChannels > PRIMARY_CHANNEL_NUM) {
2088 return true;
2089 }
2090 }
2091 return false;
2092 }
2093
InputIsPrimary(pa_sink_input * i)2094 static bool InputIsPrimary(pa_sink_input *i)
2095 {
2096 const bool isOffload = InputIsOffload(i);
2097 const bool isRunning = i->thread_info.state == PA_SINK_INPUT_RUNNING;
2098 return !isOffload && isRunning;
2099 }
2100
GetInputsInfo(enum HdiInputType type,bool isRun,pa_sink * s,pa_mix_info * info,unsigned maxinfo)2101 static unsigned GetInputsInfo(enum HdiInputType type, bool isRun, pa_sink *s, pa_mix_info *info, unsigned maxinfo)
2102 {
2103 pa_sink_input *i;
2104 unsigned n = 0;
2105 void *state = NULL;
2106
2107 pa_sink_assert_ref(s);
2108 pa_sink_assert_io_context(s);
2109 pa_assert(s);
2110
2111 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) {
2112 pa_sink_input_assert_ref(i);
2113
2114 bool flag = false;
2115 const bool isOffload = InputIsOffload(i);
2116 const bool isHD = false; // add func is hd
2117 const bool isRunning = i->thread_info.state == PA_SINK_INPUT_RUNNING;
2118 if (isRun && !isRunning) {
2119 continue;
2120 }
2121 switch (type) {
2122 case HDI_INPUT_TYPE_PRIMARY:
2123 flag = !isOffload && !isHD;
2124 break;
2125 case HDI_INPUT_TYPE_OFFLOAD:
2126 flag = isOffload;
2127 break;
2128 case HDI_INPUT_TYPE_MULTICHANNEL:
2129 flag = isHD;
2130 break;
2131 default:
2132 break;
2133 }
2134 if (flag) {
2135 info->userdata = pa_sink_input_ref(i);
2136 } else {
2137 const char *sessionIDStr = safeProplistGets(i->proplist, "stream.sessionID", "NULL");
2138 AUDIO_PRERELEASE_LOGE("sink: %{public}s, sink_input: %{public}s, the type is not %{public}d",
2139 s->name, sessionIDStr, type);
2140 continue;
2141 }
2142
2143 info++;
2144 n++;
2145 maxinfo--;
2146 }
2147 return n;
2148 }
2149
GetInputsType(pa_sink * s,unsigned * nPrimary,unsigned * nOffload,unsigned * nMultiChannel,bool isRunning)2150 static int32_t GetInputsType(pa_sink *s, unsigned *nPrimary, unsigned *nOffload,
2151 unsigned *nMultiChannel, bool isRunning)
2152 {
2153 int ret;
2154 struct Userdata *u;
2155 pa_assert_se(u = s->userdata);
2156 if ((ret = pthread_mutex_lock(&u->mutexPa2)) != 0) {
2157 AUDIO_WARNING_LOG("GetInputsType pthread_mutex_lock ret %d", ret);
2158 }
2159 pa_sink_input *i;
2160 void *state = NULL;
2161 *nPrimary = 0;
2162 *nOffload = 0;
2163 *nMultiChannel = 0;
2164 int n = 0;
2165
2166 pa_sink_assert_ref(s);
2167 pa_sink_assert_io_context(s);
2168 pa_assert(s);
2169 while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
2170 pa_sink_input_assert_ref(i);
2171 if (isRunning && i->thread_info.state != PA_SINK_INPUT_RUNNING) {
2172 continue;
2173 }
2174 n++;
2175 if (InputIsOffload(i)) {
2176 (*nOffload)++;
2177 } else if (!strcmp(u->sink->name, MCH_SINK_NAME) && InputIsMultiChannel(i)) {
2178 (*nMultiChannel)++;
2179 } else {
2180 (*nPrimary)++;
2181 }
2182 }
2183 if ((ret = pthread_mutex_unlock(&u->mutexPa2)) != 0) {
2184 AUDIO_WARNING_LOG("GetInputsType pthread_mutex_unlock ret %d", ret);
2185 }
2186 return n;
2187 }
2188
GetOffloadRenderLength(struct Userdata * u,pa_sink_input * i,bool * wait)2189 static size_t GetOffloadRenderLength(struct Userdata *u, pa_sink_input *i, bool *wait)
2190 {
2191 size_t length;
2192 playback_stream *ps = i->userdata;
2193 const bool b = (bool)ps->sink_input->thread_info.resampler;
2194 const pa_sample_spec sampleSpecIn = b ? ps->sink_input->thread_info.resampler->i_ss : ps->sink_input->sample_spec;
2195 const pa_sample_spec sampleSpecOut = b ? ps->sink_input->thread_info.resampler->o_ss : ps->sink_input->sample_spec;
2196 const int statePolicy = GetInputPolicyState(i);
2197 u->offload.prewrite = (statePolicy == OFFLOAD_INACTIVE_BACKGROUND ?
2198 OFFLOAD_HDI_CACHE2_PLUS : OFFLOAD_HDI_CACHE1_PLUS) * PA_USEC_PER_MSEC;
2199 size_t sizeFrame = pa_frame_align(pa_usec_to_bytes(OFFLOAD_FRAME_SIZE * PA_USEC_PER_MSEC, &sampleSpecOut),
2200 &sampleSpecOut);
2201 size_t tlengthHalfResamp = pa_frame_align(pa_usec_to_bytes(pa_bytes_to_usec(pa_memblockq_get_tlength(
2202 ps->memblockq) / 1.5, &sampleSpecIn), &sampleSpecOut), &sampleSpecOut); // 1.5 for half
2203 size_t sizeTgt = PA_MIN(sizeFrame, tlengthHalfResamp);
2204 const size_t bql = pa_memblockq_get_length(ps->memblockq);
2205 const size_t bqlResamp = pa_usec_to_bytes(pa_bytes_to_usec(bql, &sampleSpecIn), &sampleSpecOut);
2206 const size_t bqlRend = pa_memblockq_get_length(i->thread_info.render_memblockq);
2207 const size_t bqlAlin = pa_frame_align(bqlResamp + bqlRend, &sampleSpecOut);
2208
2209 if (ps->drain_request) {
2210 if (i->thread_info.render_memblockq->maxrewind != 0) {
2211 pa_sink_input_update_max_rewind(i, 0);
2212 }
2213 const uint64_t hdiPos = u->offload.hdiPos + (pa_rtclock_now() - u->offload.hdiPosTs);
2214 *wait = u->offload.pos > hdiPos + HDI_MIN_MS_MAINTAIN * PA_USEC_PER_MSEC ? true : false;
2215 length = u->offload.pos > hdiPos + HDI_MIN_MS_MAINTAIN * PA_USEC_PER_MSEC ? 0 : sizeFrame;
2216 } else {
2217 bool waitable = false;
2218 const uint64_t hdiPos = u->offload.hdiPos + (pa_rtclock_now() - u->offload.hdiPosTs);
2219 if (u->offload.pos > hdiPos + 60 * PA_USEC_PER_MSEC) { // if hdi cache < 60ms, indicate no enough data
2220 // hdi left 100ms is triggered process_complete_msg, it leads to kartun. Could be stating time leads it.
2221 waitable = true;
2222 }
2223 length = PA_MIN(bqlAlin, sizeTgt);
2224 *wait = false;
2225 if (length < sizeTgt) {
2226 *wait = waitable || length == 0;
2227 length = waitable ? 0 : length;
2228 if (ps->memblockq->missing > 0) {
2229 playback_stream_request_bytes(ps);
2230 }
2231 }
2232 }
2233 return length;
2234 }
2235
InputsDropFromInputs2(pa_mix_info * info,unsigned n)2236 static void InputsDropFromInputs2(pa_mix_info *info, unsigned n)
2237 {
2238 for (; n > 0; info++, n--) {
2239 if (info->userdata) {
2240 pa_sink_input_unref(info->userdata);
2241 info->userdata = NULL;
2242 }
2243 if (info->chunk.memblock) {
2244 pa_memblock_unref(info->chunk.memblock);
2245 }
2246 }
2247 }
2248
InputsDropFromInputs(pa_mix_info * infoInputs,unsigned nInputs,pa_mix_info * info,unsigned n,pa_memchunk * result)2249 static void InputsDropFromInputs(pa_mix_info *infoInputs, unsigned nInputs, pa_mix_info *info, unsigned n,
2250 pa_memchunk *result)
2251 {
2252 unsigned p = 0;
2253 unsigned ii = 0;
2254 unsigned nUnreffed = 0;
2255 pa_assert(result && result->memblock && result->length > 0);
2256 /* We optimize for the case where the order of the inputs has not changed */
2257
2258 for (ii = 0; ii < nInputs; ++ii) {
2259 pa_sink_input *i = infoInputs[ii].userdata;
2260 unsigned j;
2261 pa_mix_info *m = NULL;
2262
2263 pa_sink_input_assert_ref(i);
2264
2265 /* Let's try to find the matching entyr info the pa_mix_info array */
2266 for (j = 0; j < n; j++) {
2267 if (info[p].userdata == i) {
2268 m = info + p;
2269 break;
2270 }
2271
2272 p++;
2273 if (p >= n) {
2274 p = 0;
2275 }
2276 }
2277
2278 /* Drop read data */
2279 pa_sink_input_drop(i, result->length);
2280
2281 if (m) {
2282 if (m->chunk.memblock) {
2283 pa_memblock_unref(m->chunk.memblock);
2284 pa_memchunk_reset(&m->chunk);
2285 }
2286
2287 pa_sink_input_unref(m->userdata);
2288 m->userdata = NULL;
2289
2290 nUnreffed += 1;
2291 }
2292 }
2293
2294 /* Now drop references to entries that are included in the
2295 * pa_mix_info array but don't exist anymore */
2296
2297 if (nUnreffed < n) {
2298 for (; n > 0; info++, n--) {
2299 if (info->userdata)
2300 pa_sink_input_unref(info->userdata);
2301 if (info->chunk.memblock) {
2302 pa_memblock_unref(info->chunk.memblock);
2303 }
2304 }
2305 }
2306 }
2307
PaSinkRenderIntoOffload(pa_sink * s,pa_mix_info * infoInputs,unsigned nInputs,pa_memchunk * target)2308 static void PaSinkRenderIntoOffload(pa_sink *s, pa_mix_info *infoInputs, unsigned nInputs, pa_memchunk *target)
2309 {
2310 unsigned n = 0;
2311 unsigned ii = 0;
2312 pa_mix_info info[MAX_MIX_CHANNELS];
2313 pa_sink_assert_ref(s);
2314 pa_sink_assert_io_context(s);
2315
2316 size_t length = target->length;
2317 size_t mixlength = length;
2318 size_t blockSizeMax = pa_mempool_block_size_max(s->core->mempool);
2319 if (length > blockSizeMax)
2320 length = pa_frame_align(blockSizeMax, &s->sample_spec);
2321
2322 pa_assert(length > 0);
2323
2324 for (ii = 0; ii < nInputs; ++ii) {
2325 pa_sink_input *i = infoInputs[ii].userdata;
2326 pa_sink_input_assert_ref(i);
2327 AUTO_CTRACE("hdi_sink::Offload:pa_sink_input_peek:%u len:%zu", i->index, length);
2328 pa_sink_input_peek(i, length, &info[n].chunk, &info[n].volume);
2329 if (mixlength == 0 || info[n].chunk.length < mixlength)
2330 mixlength = info[n].chunk.length;
2331
2332 if (pa_memblock_is_silence(info[n].chunk.memblock)) {
2333 AUTO_CTRACE("hdi_sink::Offload::is_silence");
2334 pa_memblock_unref(info[n].chunk.memblock);
2335 continue;
2336 }
2337
2338 info[n].userdata = pa_sink_input_ref(i);
2339
2340 pa_assert(info[n].chunk.memblock);
2341 pa_assert(info[n].chunk.length > 0);
2342
2343 n++;
2344 }
2345 length = mixlength > 0 ? mixlength : length;
2346
2347 pa_assert(n == 1 || n == 0);
2348 if (n == 0) {
2349 if (target->length > length)
2350 target->length = length;
2351
2352 pa_silence_memchunk(target, &s->sample_spec);
2353 } else if (n == 1) {
2354 if (target->length > length)
2355 target->length = length;
2356
2357 pa_memchunk vchunk;
2358 vchunk = info[0].chunk;
2359
2360 if (vchunk.length > length)
2361 vchunk.length = length;
2362 // if target lead pa_memblock_new memory leak, fixed chunk length can solve it.
2363 pa_memchunk_memcpy(target, &vchunk);
2364 }
2365
2366 InputsDropFromInputs(infoInputs, nInputs, info, n, target);
2367 }
2368
OffloadReset(struct Userdata * u)2369 static void OffloadReset(struct Userdata *u)
2370 {
2371 u->offload.sessionID = -1;
2372 u->offload.pos = 0;
2373 u->offload.hdiPos = 0;
2374 u->offload.hdiPosTs = pa_rtclock_now();
2375 u->offload.prewrite = OFFLOAD_HDI_CACHE1_PLUS * PA_USEC_PER_MSEC;
2376 u->offload.firstWriteHdi = true;
2377 u->offload.setHdiBufferSizeNum = OFFLOAD_SET_BUFFER_SIZE_NUM;
2378 pa_atomic_store(&u->offload.hdistate, 0);
2379 u->offload.fullTs = 0;
2380 }
2381
RenderWriteOffloadFunc(struct Userdata * u,size_t length,pa_mix_info * infoInputs,unsigned nInputs,int32_t * writen)2382 static int32_t RenderWriteOffloadFunc(struct Userdata *u, size_t length, pa_mix_info *infoInputs, unsigned nInputs,
2383 int32_t *writen)
2384 {
2385 pa_sink_input *i = infoInputs[0].userdata;
2386
2387 pa_assert(length != 0);
2388 pa_memchunk *chunk = &(u->offload.chunk);
2389 chunk->index = 0;
2390 chunk->length = length;
2391 int64_t l;
2392 int64_t d;
2393 l = (int64_t)chunk->length;
2394 size_t blockSize = pa_memblock_get_length(u->offload.chunk.memblock);
2395 blockSize = PA_MAX(blockSize, pa_usec_to_bytes(0.6 * OFFLOAD_HDI_CACHE1 * PA_USEC_PER_MSEC, // 0.6 40% is hdi limit
2396 &u->sink->sample_spec));
2397 d = 0;
2398 while (l > 0) {
2399 pa_memchunk tchunk;
2400 tchunk = *chunk;
2401 tchunk.index += (size_t)d;
2402 tchunk.length = PA_MIN((size_t)l, blockSize - tchunk.index);
2403
2404 PaSinkRenderIntoOffload(i->sink, infoInputs, nInputs, &tchunk);
2405 d += (int64_t)tchunk.length;
2406 l -= (int64_t)tchunk.length;
2407 }
2408 if (l < 0) {
2409 chunk->length += (size_t)-l;
2410 }
2411
2412 int32_t appsUid[MAX_MIX_CHANNELS];
2413 size_t count = 0;
2414
2415 const char *cstringClientUid = pa_proplist_gets(i->proplist, "stream.client.uid");
2416 if (cstringClientUid && (i->thread_info.state == PA_SINK_INPUT_RUNNING)) {
2417 appsUid[count++] = atoi(cstringClientUid);
2418 }
2419
2420 SafeRendererSinkUpdateAppsUid(u->offload.sinkAdapter, appsUid, count);
2421
2422 int ret = RenderWriteOffload(u, i, chunk);
2423 *writen = ret == 0 ? (int32_t)chunk->length : 0;
2424 if (ret == 1) { // 1 indicates full
2425 const int hdistate = pa_atomic_load(&u->offload.hdistate);
2426 if (hdistate == 0) {
2427 pa_atomic_store(&u->offload.hdistate, 1);
2428 }
2429 if (GetInputPolicyState(i) == OFFLOAD_INACTIVE_BACKGROUND) {
2430 u->offload.fullTs = pa_rtclock_now();
2431 }
2432 pa_memblockq_rewind(i->thread_info.render_memblockq, chunk->length);
2433 } else if (ret < 0) {
2434 pa_memblockq_rewind(i->thread_info.render_memblockq, chunk->length);
2435 }
2436
2437 u->offload.pos += pa_bytes_to_usec(*writen, &u->sink->sample_spec);
2438 InputsDropFromInputs2(infoInputs, nInputs);
2439 return ret;
2440 }
2441
ProcessRenderUseTimingOffload(struct Userdata * u,bool * wait,int32_t * nInput,int32_t * writen)2442 static int32_t ProcessRenderUseTimingOffload(struct Userdata *u, bool *wait, int32_t *nInput, int32_t *writen)
2443 {
2444 *wait = true;
2445 pa_sink *s = u->sink;
2446 pa_mix_info infoInputs[MAX_MIX_CHANNELS];
2447 unsigned nInputs;
2448
2449 pa_sink_assert_ref(s);
2450 pa_sink_assert_io_context(s);
2451 pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
2452
2453 pa_assert(s->thread_info.rewind_nbytes == 0);
2454
2455 if (s->thread_info.state == PA_SINK_SUSPENDED) {
2456 return 0;
2457 }
2458
2459 pa_sink_ref(s);
2460
2461 nInputs = GetInputsInfo(HDI_INPUT_TYPE_OFFLOAD, true, s, infoInputs, MAX_MIX_CHANNELS);
2462 *nInput = (int32_t)nInputs;
2463
2464 if (nInputs == 0) {
2465 pa_sink_unref(s);
2466 return 0;
2467 } else if (nInputs > 1) {
2468 AUDIO_WARNING_LOG("GetInputsInfo offload input != 1");
2469 }
2470
2471 pa_sink_input *i = infoInputs[0].userdata;
2472 if (GetFadeoutState(i->index) != NO_FADE) {
2473 InputsDropFromInputs2(infoInputs, nInputs);
2474 pa_sink_unref(s);
2475 AUDIO_WARNING_LOG("stream is croked, do not need peek");
2476 return 0;
2477 }
2478 CheckInputChangeToOffload(u, i);
2479 size_t length = GetOffloadRenderLength(u, i, wait);
2480 if (*wait && length == 0) {
2481 InputsDropFromInputs2(infoInputs, nInputs);
2482 AUTO_CTRACE("hdi_sink::ProcessRenderUseTimingOffload::underrun");
2483 pa_sink_input_handle_ohos_underrun(i);
2484 pa_sink_unref(s);
2485 return 0;
2486 }
2487 int ret = RenderWriteOffloadFunc(u, length, infoInputs, nInputs, writen);
2488 pa_sink_unref(s);
2489 return ret;
2490 }
2491
UpdatePresentationPosition(struct Userdata * u)2492 static int32_t UpdatePresentationPosition(struct Userdata *u)
2493 {
2494 uint64_t frames;
2495 int64_t timeSec;
2496 int64_t timeNanoSec;
2497 int ret = u->offload.sinkAdapter->RendererSinkGetPresentationPosition(
2498 u->offload.sinkAdapter, &frames, &timeSec, &timeNanoSec);
2499 if (ret != 0) {
2500 AUDIO_ERR_LOG("RendererSinkGetPresentationPosition fail, ret %d", ret);
2501 return ret;
2502 }
2503 u->offload.hdiPos = frames;
2504 u->offload.hdiPosTs = (uint64_t)timeSec * USEC_PER_SEC + (uint64_t)timeNanoSec / PA_NSEC_PER_USEC;
2505 return 0;
2506 }
2507
OffloadRewindAndFlush(struct Userdata * u,pa_sink_input * i,bool afterRender)2508 static void OffloadRewindAndFlush(struct Userdata *u, pa_sink_input *i, bool afterRender)
2509 {
2510 pa_sink_input_assert_ref(i);
2511 playback_stream *ps = i->userdata;
2512 pa_assert(ps);
2513
2514 OffloadLock(u); // flush will interrupt the offload callback, may be offload unlock.
2515 int ret = UpdatePresentationPosition(u);
2516 u->offload.sinkAdapter->RendererSinkFlush(u->offload.sinkAdapter);
2517 if (ret == 0) {
2518 uint64_t offloadFade = 180000; // 180000 us fade out
2519 uint64_t cacheLenInHdi =
2520 u->offload.pos > u->offload.hdiPos + offloadFade ? u->offload.pos - u->offload.hdiPos - offloadFade : 0;
2521 uint64_t bufSizeInRender = pa_usec_to_bytes(cacheLenInHdi, &i->sink->sample_spec);
2522 const pa_sample_spec sampleSpecIn = i->thread_info.resampler ? i->thread_info.resampler->i_ss
2523 : i->sample_spec;
2524 uint64_t bufSizeInInput = pa_usec_to_bytes(cacheLenInHdi, &sampleSpecIn);
2525 bufSizeInInput += pa_usec_to_bytes(pa_bytes_to_usec(
2526 pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec), &sampleSpecIn);
2527 uint64_t rewindSize = afterRender ? bufSizeInRender : bufSizeInInput;
2528 uint64_t maxRewind = afterRender ? i->thread_info.render_memblockq->maxrewind : ps->memblockq->maxrewind;
2529 if (rewindSize > maxRewind) {
2530 AUDIO_WARNING_LOG("OffloadRewindAndFlush, rewindSize(%" PRIu64 ") > maxrewind(%u), afterRender(%d)",
2531 rewindSize, (uint32_t)(afterRender ? i->thread_info.render_memblockq->maxrewind :
2532 ps->memblockq->maxrewind), afterRender);
2533 rewindSize = maxRewind;
2534 }
2535
2536 if (afterRender) {
2537 pa_memblockq_rewind(i->thread_info.render_memblockq, rewindSize);
2538 } else {
2539 pa_memblockq_rewind(ps->memblockq, rewindSize);
2540 pa_memblockq_flush_read(i->thread_info.render_memblockq);
2541 }
2542 }
2543 OffloadReset(u);
2544 }
2545
GetSinkInputName(pa_sink_input * i,char * str,int len)2546 static void GetSinkInputName(pa_sink_input *i, char *str, int len)
2547 {
2548 const char *streamUid = safeProplistGets(i->proplist, "stream.client.uid", "NULL");
2549 const char *streamPid = safeProplistGets(i->proplist, "stream.client.pid", "NULL");
2550 const char *streamType = safeProplistGets(i->proplist, "stream.type", "NULL");
2551 const char *sessionID = safeProplistGets(i->proplist, "stream.sessionID", "NULL");
2552 int ret = sprintf_s(str, len, "%s_%s_%s_%s_of%d", streamType, streamUid, streamPid, sessionID, InputIsOffload(i));
2553 if (ret < 0) {
2554 AUDIO_ERR_LOG("sprintf_s fail! ret %d", ret);
2555 }
2556 }
2557
getSinkInputSessionID(pa_sink_input * i)2558 static int32_t getSinkInputSessionID(pa_sink_input *i)
2559 {
2560 const char *res = pa_proplist_gets(i->proplist, "stream.sessionID");
2561 if (res == NULL) {
2562 return -1;
2563 } else {
2564 return atoi(res);
2565 }
2566 }
2567
OffloadLock(struct Userdata * u)2568 static void OffloadLock(struct Userdata *u)
2569 {
2570 if (!u->offload.runninglocked) {
2571 u->offload.sinkAdapter->RendererSinkOffloadRunningLockLock(u->offload.sinkAdapter);
2572 u->offload.runninglocked = true;
2573 } else {
2574 }
2575 }
2576
OffloadUnlock(struct Userdata * u)2577 static void OffloadUnlock(struct Userdata *u)
2578 {
2579 if (u->offload.runninglocked) {
2580 u->offload.sinkAdapter->RendererSinkOffloadRunningLockUnlock(u->offload.sinkAdapter);
2581 u->offload.runninglocked = false;
2582 } else {
2583 }
2584 }
2585
offloadSetMaxRewind(struct Userdata * u,pa_sink_input * i)2586 static void offloadSetMaxRewind(struct Userdata *u, pa_sink_input *i)
2587 {
2588 pa_sink_input_assert_ref(i);
2589 pa_sink_input_assert_io_context(i);
2590 pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
2591
2592 size_t blockSize = pa_memblock_get_length(u->offload.chunk.memblock);
2593 pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, blockSize);
2594
2595 size_t nbytes = pa_usec_to_bytes(MAX_REWIND, &i->sink->sample_spec);
2596
2597 if (i->update_max_rewind) {
2598 i->update_max_rewind(i, i->thread_info.resampler ?
2599 pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
2600 }
2601 }
2602
CheckInputChangeToOffload(struct Userdata * u,pa_sink_input * i)2603 static void CheckInputChangeToOffload(struct Userdata *u, pa_sink_input *i)
2604 {
2605 // if maxrewind is set to buffer_size while inner-cap, reset it to 0 for offload.
2606 if (pa_memblockq_get_maxrewind(i->thread_info.render_memblockq) == u->buffer_size) {
2607 AUDIO_INFO_LOG("Reset maxwind to 0 to enable offload for sink-input:%{public}u", i->index);
2608 pa_sink_input_update_max_rewind(i, 0);
2609 }
2610 if (InputIsOffload(i) && pa_memblockq_get_maxrewind(i->thread_info.render_memblockq) == 0) {
2611 offloadSetMaxRewind(u, i);
2612 pa_sink_input *it;
2613 void *state = NULL;
2614 while ((it = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL))) {
2615 if (it != i && pa_memblockq_get_maxrewind(it->thread_info.render_memblockq) != 0) {
2616 pa_sink_input_update_max_rewind(it, 0);
2617 drop_backlog(it->thread_info.render_memblockq);
2618 playback_stream *ps = it->userdata;
2619 drop_backlog(ps->memblockq);
2620 }
2621 }
2622 }
2623 }
2624
StartOffloadHdi(struct Userdata * u,pa_sink_input * i)2625 static void StartOffloadHdi(struct Userdata *u, pa_sink_input *i)
2626 {
2627 CheckInputChangeToOffload(u, i);
2628 int32_t sessionID = getSinkInputSessionID(i);
2629 if (u->offload.isHDISinkStarted) {
2630 AUDIO_INFO_LOG("StartOffloadHdi, sessionID : %{public}d -> %{public}d", u->offload.sessionID, sessionID);
2631 if (sessionID != u->offload.sessionID) {
2632 if (u->offload.sessionID != -1) {
2633 u->offload.sinkAdapter->RendererSinkReset(u->offload.sinkAdapter);
2634 OffloadReset(u);
2635 }
2636 u->offload.sessionID = sessionID;
2637 }
2638 OffloadLock(u);
2639 } else {
2640 AUDIO_INFO_LOG("StartOffloadHdi, Restart offload with rate:%{public}d, channels:%{public}d",
2641 u->ss.rate, u->ss.channels);
2642 if (u->offload.sinkAdapter->RendererSinkStart(u->offload.sinkAdapter)) {
2643 AUDIO_WARNING_LOG("StartOffloadHdi, audiorenderer control start failed!");
2644 } else {
2645 RegOffloadCallback(u);
2646 u->offload.isHDISinkStarted = true;
2647 AUDIO_INFO_LOG("StartOffloadHdi, Successfully restarted offload HDI renderer");
2648 OffloadLock(u);
2649 u->offload.sessionID = sessionID;
2650 OffloadSetHdiVolume(i);
2651 }
2652 }
2653 }
2654
PaInputStateChangeCbOffload(struct Userdata * u,pa_sink_input * i,pa_sink_input_state_t state)2655 static void POSSIBLY_UNUSED PaInputStateChangeCbOffload(struct Userdata *u, pa_sink_input *i,
2656 pa_sink_input_state_t state)
2657 {
2658 const bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED;
2659 const bool starting = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2660 const bool stopping = state == PA_SINK_INPUT_UNLINKED;
2661
2662 if (!u->offload.inited && PrepareDeviceOffload(u) == 0) {
2663 u->offload.inited = true;
2664 }
2665 if (starting) {
2666 StartOffloadHdi(u, i);
2667 } else if (corking) {
2668 pa_atomic_store(&u->offload.hdistate, 2); // 2 indicates corking
2669 OffloadRewindAndFlush(u, i, false);
2670 } else if (stopping) {
2671 u->offload.sinkAdapter->RendererSinkFlush(u->offload.sinkAdapter);
2672 OffloadReset(u);
2673 g_speakerPaAllStreamStartVolZeroTime = 0;
2674 }
2675 ResetVolumeBySinkInputState(i, state);
2676 }
2677
ResetVolumeBySinkInputState(pa_sink_input * i,pa_sink_input_state_t state)2678 static void ResetVolumeBySinkInputState(pa_sink_input *i, pa_sink_input_state_t state)
2679 {
2680 pa_assert(i);
2681 const bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED;
2682 if (corking) {
2683 const char *sessionIDStr = safeProplistGets(i->proplist, "stream.sessionID", "NULL");
2684 uint32_t sessionID = sessionIDStr != NULL ? atoi(sessionIDStr) : 0;
2685 SetPreVolume(sessionID, 0.0f);
2686 }
2687 }
2688
2689 // call from IO thread(OS_ProcessData)
PaInputStateChangeCbPrimary(struct Userdata * u,pa_sink_input * i,pa_sink_input_state_t state)2690 static void PaInputStateChangeCbPrimary(struct Userdata *u, pa_sink_input *i, pa_sink_input_state_t state)
2691 {
2692 const bool starting = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2693 const bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED;
2694 uint32_t streamIndex = i->index;
2695 if (corking) {
2696 SetFadeoutState(streamIndex, NO_FADE);
2697 }
2698
2699 if (starting) {
2700 u->primary.timestamp = pa_rtclock_now();
2701 if (pa_atomic_load(&u->primary.isHDISinkStarted) == 1) {
2702 pa_atomic_store(&u->primary.fadingFlagForPrimary, 1);
2703 AUDIO_INFO_LOG("store fadingFlagForPrimary for 1");
2704 SetFadeoutState(streamIndex, NO_FADE);
2705 u->primary.primaryFadingInDone = 0;
2706 u->primary.primarySinkInIndex = (int32_t)(i->index);
2707 AUDIO_INFO_LOG("PaInputStateChangeCb, HDI renderer already started");
2708 return;
2709 }
2710 AUDIO_INFO_LOG("PaInputStateChangeCb, Restart with rate:%{public}d,channels:%{public}d, format:%{public}d",
2711 u->ss.rate, u->ss.channels, (int)pa_sample_size_of_format(u->format));
2712 if (pa_asyncmsgq_send(u->primary.dq, NULL, HDI_START, NULL, 0, NULL)) {
2713 AUDIO_ERR_LOG("audiorenderer control start failed!");
2714 u->primary.sinkAdapter->RendererSinkDeInit(u->primary.sinkAdapter);
2715 } else {
2716 pa_atomic_store(&u->primary.isHDISinkStarted, 1);
2717 u->writeCount = 0;
2718 u->renderCount = 0;
2719 pa_atomic_store(&u->primary.fadingFlagForPrimary, 1);
2720 AUDIO_INFO_LOG("store fadingFlagForPrimary for 1");
2721 SetFadeoutState(streamIndex, NO_FADE);
2722 u->primary.primaryFadingInDone = 0;
2723 u->primary.primarySinkInIndex = (int32_t)(i->index);
2724 AUDIO_INFO_LOG("PaInputStateChangeCb, Successfully restarted HDI renderer");
2725 }
2726 }
2727 ResetVolumeBySinkInputState(i, state);
2728 }
2729
2730 // call from IO thread(OS_ProcessData)
StartPrimaryHdiIfRunning(struct Userdata * u)2731 static void StartPrimaryHdiIfRunning(struct Userdata *u)
2732 {
2733 AUTO_CTRACE("hdi_sink::StartPrimaryHdiIfRunning");
2734 if (pa_atomic_load(&u->primary.isHDISinkStarted) == 1) {
2735 return;
2736 }
2737
2738 unsigned nPrimary = 0;
2739 unsigned nOffload = 0;
2740 unsigned nMultiChannel = 0;
2741 GetInputsType(u->sink, &nPrimary, &nOffload, &nMultiChannel, true);
2742 if (nPrimary == 0) {
2743 return;
2744 }
2745
2746 if (pa_asyncmsgq_send(u->primary.dq, NULL, HDI_START, NULL, 0, NULL)) {
2747 AUDIO_ERR_LOG("audiorenderer control start failed!");
2748 u->primary.sinkAdapter->RendererSinkDeInit(u->primary.sinkAdapter);
2749 } else {
2750 pa_atomic_store(&u->primary.isHDISinkStarted, 1);
2751 u->writeCount = 0;
2752 u->renderCount = 0;
2753 AUDIO_INFO_LOG("StartPrimaryHdiIfRunning, Successfully restarted HDI renderer");
2754 }
2755 }
2756
ResetMultiChannelHdiState(struct Userdata * u)2757 static void ResetMultiChannelHdiState(struct Userdata *u)
2758 {
2759 if (u->multiChannel.sinkAdapter == NULL) {
2760 return;
2761 }
2762 if (u->multiChannel.isHDISinkInited) {
2763 if (u->multiChannel.sample_attrs.channel != (uint32_t)u->multiChannel.sinkChannel) {
2764 u->multiChannel.sinkAdapter->RendererSinkStop(u->multiChannel.sinkAdapter);
2765 u->multiChannel.isHDISinkStarted = false;
2766 u->multiChannel.sinkAdapter->RendererSinkDeInit(u->multiChannel.sinkAdapter);
2767 u->multiChannel.isHDISinkInited = false;
2768 u->multiChannel.sample_attrs.adapterName = "primary";
2769 u->multiChannel.sample_attrs.channel = (uint32_t)u->multiChannel.sinkChannel;
2770 u->multiChannel.sample_attrs.channelLayout = u->multiChannel.sinkChannelLayout;
2771 u->multiChannel.sinkAdapter->RendererSinkInit(u->multiChannel.sinkAdapter, &u->multiChannel.sample_attrs);
2772 u->multiChannel.isHDISinkInited = true;
2773 } else {
2774 if (u->multiChannel.isHDISinkStarted) {
2775 pa_atomic_store(&u->multiChannel.fadingFlagForMultiChannel, 1);
2776 u->multiChannel.multiChannelFadingInDone = 0;
2777 u->multiChannel.multiChannelSinkInIndex = u->multiChannel.multiChannelTmpSinkInIndex;
2778 return;
2779 }
2780 }
2781 } else {
2782 u->multiChannel.sample_attrs.adapterName = "primary";
2783 u->multiChannel.sample_attrs.channel = (uint32_t)u->multiChannel.sinkChannel;
2784 u->multiChannel.sample_attrs.channelLayout = u->multiChannel.sinkChannelLayout;
2785 u->multiChannel.sinkAdapter->RendererSinkInit(u->multiChannel.sinkAdapter, &u->multiChannel.sample_attrs);
2786 u->multiChannel.isHDISinkInited = true;
2787 }
2788 if (u->multiChannel.sinkAdapter->RendererSinkStart(u->multiChannel.sinkAdapter)) {
2789 u->multiChannel.isHDISinkStarted = false;
2790 u->multiChannel.sinkAdapter->RendererSinkDeInit(u->multiChannel.sinkAdapter);
2791 u->multiChannel.isHDISinkInited = false;
2792 AUDIO_INFO_LOG("ResetMultiChannelHdiState deinit success");
2793 } else {
2794 u->multiChannel.isHDISinkStarted = true;
2795 AUDIO_INFO_LOG("ResetMultiChannelHdiState start success");
2796 u->writeCount = 0;
2797 u->renderCount = 0;
2798 pa_atomic_store(&u->multiChannel.fadingFlagForMultiChannel, 1);
2799 u->multiChannel.multiChannelFadingInDone = 0;
2800 u->multiChannel.multiChannelSinkInIndex = u->multiChannel.multiChannelTmpSinkInIndex;
2801 }
2802 }
2803
StartMultiChannelHdiIfRunning(struct Userdata * u)2804 static void StartMultiChannelHdiIfRunning(struct Userdata *u)
2805 {
2806 ResetMultiChannelHdiState(u);
2807 }
2808
PaInputStateChangeCbMultiChannel(struct Userdata * u,pa_sink_input * i,pa_sink_input_state_t state)2809 static void PaInputStateChangeCbMultiChannel(struct Userdata *u, pa_sink_input *i, pa_sink_input_state_t state)
2810 {
2811 const bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED;
2812 const bool starting = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2813 const bool stopping = state == PA_SINK_INPUT_UNLINKED;
2814 if (corking) {
2815 SetFadeoutState(i->index, NO_FADE);
2816 }
2817 if (starting) {
2818 u->multiChannel.timestamp = pa_rtclock_now();
2819 u->multiChannel.multiChannelTmpSinkInIndex = (int32_t)(i->index);
2820 } else if (stopping) {
2821 // Continuously dropping data clear counter on entering suspended state.
2822 if (u->bytes_dropped != 0) {
2823 AUDIO_INFO_LOG("PaInputStateChangeCbMultiChannel, HDI-sink continuously dropping data - clear statistics "
2824 "(%zu -> 0 bytes dropped)", u->bytes_dropped);
2825 u->bytes_dropped = 0;
2826 }
2827 g_speakerPaAllStreamStartVolZeroTime = 0;
2828 }
2829 ResetVolumeBySinkInputState(i, state);
2830 }
2831
ResetFadeoutPause(pa_sink_input * i,pa_sink_input_state_t state)2832 static void ResetFadeoutPause(pa_sink_input *i, pa_sink_input_state_t state)
2833 {
2834 bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED;
2835 bool starting = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2836 if (corking || starting) {
2837 AUDIO_INFO_LOG("set fadeoutPause to 0");
2838 SetFadeoutState(i->index, NO_FADE);
2839 }
2840 }
2841
RendererSinkSetPriPaPower(pa_sink_input * i,pa_sink_input_state_t state,struct Userdata * u)2842 static void RendererSinkSetPriPaPower(pa_sink_input *i, pa_sink_input_state_t state, struct Userdata *u)
2843 {
2844 if (state == PA_SINK_INPUT_RUNNING) {
2845 if (u->primary.sinkAdapter == NULL) {
2846 return;
2847 }
2848 const char *streamType = safeProplistGets(i->proplist, "stream.type", "NULL");
2849 const char *sessionIDStr = safeProplistGets(i->proplist, "stream.sessionID", "NULL");
2850 const char *deviceClass = GetDeviceClass(u->primary.sinkAdapter->deviceClass);
2851 uint32_t sessionID = sessionIDStr != NULL ? (uint32_t)atoi(sessionIDStr) : 0;
2852 float volume = GetCurVolume(sessionID, streamType, deviceClass);
2853 bool isZeroVolume = IsSameVolume(volume, 0.0f);
2854 AUDIO_INFO_LOG(
2855 "session %{public}u, stream %{public}s, zerovol %{public}d", sessionID, streamType, isZeroVolume);
2856 if (!isZeroVolume) {
2857 u->primary.sinkAdapter->RendererSinkSetPriPaPower(u->primary.sinkAdapter);
2858 }
2859 }
2860 }
2861
PaInputStateChangeCb(pa_sink_input * i,pa_sink_input_state_t state)2862 static void PaInputStateChangeCb(pa_sink_input *i, pa_sink_input_state_t state)
2863 {
2864 struct Userdata *u = NULL;
2865
2866 pa_assert(i);
2867 pa_sink_input_assert_ref(i);
2868 pa_assert(i->sink);
2869
2870 const bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED;
2871 const bool starting = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING;
2872 const bool stopping = state == PA_SINK_INPUT_UNLINKED;
2873
2874 corking ? pa_atomic_store(&i->isFirstReaded, 0) : (void)0;
2875 starting ? pa_atomic_store(&i->isFirstReaded, 1) : (void)0;
2876
2877 if (!strcmp(i->sink->name, SINK_NAME_INNER_CAPTURER) ||
2878 !strcmp(i->sink->name, SINK_NAME_REMOTE_CAST_INNER_CAPTURER) ||
2879 !strcmp(i->sink->driver, "module_split_stream_sink.c")) {
2880 ResetFadeoutPause(i, state);
2881 AUDIO_INFO_LOG("PaInputStateChangeCb inner_cap return");
2882 return;
2883 }
2884 pa_assert_se(u = i->sink->userdata);
2885
2886 RendererSinkSetPriPaPower(i, state, u);
2887
2888 char str[SPRINTF_STR_LEN] = {0};
2889 GetSinkInputName(i, str, SPRINTF_STR_LEN);
2890 AUDIO_INFO_LOG(
2891 "PaInputStateChangeCb, Sink[%{public}s]->SinkInput[%{public}s] state change:[%{public}s]-->[%{public}s]",
2892 GetDeviceClass(u->primary.sinkAdapter->deviceClass), str, GetInputStateInfo(i->thread_info.state),
2893 GetInputStateInfo(state));
2894
2895 if (i->thread_info.state == state) {
2896 return;
2897 }
2898
2899 if (!corking && !starting && !stopping) {
2900 AUDIO_WARNING_LOG("PaInputStateChangeCb, input state change: invalid");
2901 return;
2902 }
2903
2904 if (u->offload_enable && !strcmp(i->sink->name, OFFLOAD_SINK_NAME)) {
2905 ResetFadeoutPause(i, state);
2906 PaInputStateChangeCbOffload(u, i, state);
2907 } else if (u->multichannel_enable && !strcmp(i->sink->name, MCH_SINK_NAME)) {
2908 PaInputStateChangeCbMultiChannel(u, i, state);
2909 } else {
2910 PaInputStateChangeCbPrimary(u, i, state);
2911 }
2912 }
2913
ThreadFuncRendererTimerOffloadProcess(struct Userdata * u,pa_usec_t now,int64_t * sleepForUsec)2914 static void ThreadFuncRendererTimerOffloadProcess(struct Userdata *u, pa_usec_t now, int64_t *sleepForUsec)
2915 {
2916 static uint32_t timeWait = 1; // 1ms init
2917 const uint64_t pos = u->offload.pos;
2918 const uint64_t hdiPos = u->offload.hdiPos + (pa_rtclock_now() - u->offload.hdiPosTs);
2919 const uint64_t pw = u->offload.prewrite;
2920 int64_t blockTime = (int64_t)pa_bytes_to_usec(u->sink->thread_info.max_request, &u->sink->sample_spec);
2921
2922 int32_t nInput = -1;
2923 const int hdistate = (int)pa_atomic_load(&u->offload.hdistate);
2924 if (pos <= hdiPos + pw && hdistate == 0) {
2925 bool wait;
2926 int32_t writen = -1;
2927 int ret = ProcessRenderUseTimingOffload(u, &wait, &nInput, &writen);
2928 if (ret < 0) {
2929 blockTime = 20 * PA_USEC_PER_MSEC; // 20ms for render write error
2930 } else if (wait) {
2931 blockTime = (int64_t)(timeWait * PA_USEC_PER_MSEC); // timeWait ms for first write no data
2932 if (timeWait < 20) { // 20ms max wait no data
2933 timeWait++;
2934 }
2935 } else {
2936 timeWait = 1; // 1ms have data reset timeWait
2937 blockTime = 1 * PA_USEC_PER_MSEC; // 1ms for min wait
2938 }
2939 } else if (hdistate == 1) {
2940 blockTime = (int64_t)(pos - hdiPos - HDI_MIN_MS_MAINTAIN * PA_USEC_PER_MSEC);
2941 if (blockTime < 0) {
2942 blockTime = OFFLOAD_FRAME_SIZE * PA_USEC_PER_MSEC; // block for one frame
2943 }
2944 }
2945 if (pos < hdiPos) {
2946 if (pos != 0) {
2947 AUDIO_DEBUG_LOG("ThreadFuncRendererTimerOffload hdiPos wrong need sync, pos %" PRIu64 ", hdiPos %" PRIu64,
2948 pos, hdiPos);
2949 }
2950 if (u->offload.hdiPosTs + 300 * PA_USEC_PER_MSEC < now) { // 300ms for update pos
2951 UpdatePresentationPosition(u);
2952 }
2953 }
2954 if (blockTime != -1) {
2955 *sleepForUsec = PA_MAX(blockTime, 0) - (int64_t)(pa_rtclock_now() - now);
2956 *sleepForUsec = PA_MAX(*sleepForUsec, 0);
2957 }
2958 }
2959
ThreadFuncRendererTimerOffloadFlag(struct Userdata * u,pa_usec_t now,bool * flagOut,int64_t * sleepForUsec)2960 static void ThreadFuncRendererTimerOffloadFlag(struct Userdata *u, pa_usec_t now, bool *flagOut, int64_t *sleepForUsec)
2961 {
2962 bool flag = PA_SINK_IS_RUNNING(u->sink->thread_info.state);
2963 if (!flag && !PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
2964 OffloadUnlock(u);
2965 }
2966 *flagOut = flag;
2967 }
2968
SinkRenderMultiChannelProcess(pa_sink * si,size_t length,pa_memchunk * chunkIn)2969 static void SinkRenderMultiChannelProcess(pa_sink *si, size_t length, pa_memchunk *chunkIn)
2970 {
2971 struct Userdata *u;
2972 pa_assert_se(u = si->userdata);
2973
2974 EffectChainManagerReturnMultiChannelInfo(&u->multiChannel.sinkChannel, &u->multiChannel.sinkChannelLayout);
2975
2976 chunkIn->memblock = pa_memblock_new(si->core->mempool, length * IN_CHANNEL_NUM_MAX / DEFAULT_IN_CHANNEL_NUM);
2977 size_t tmpLength = length * u->multiChannel.sinkChannel / DEFAULT_IN_CHANNEL_NUM;
2978 chunkIn->index = 0;
2979 chunkIn->length = tmpLength;
2980 SinkRenderMultiChannelGetData(si, chunkIn);
2981 chunkIn->index = 0;
2982 chunkIn->length = tmpLength;
2983 }
2984
SinkRenderMultiChannel(pa_sink * si,size_t length,pa_memchunk * chunkIn)2985 static void SinkRenderMultiChannel(pa_sink *si, size_t length, pa_memchunk *chunkIn)
2986 {
2987 pa_sink_ref(si);
2988
2989 size_t blockSizeMax;
2990
2991 pa_sink_assert_ref(si);
2992 pa_sink_assert_io_context(si);
2993 pa_assert(PA_SINK_IS_LINKED(si->thread_info.state));
2994 pa_assert(length > 0);
2995 pa_assert(pa_frame_aligned(length, &si->sample_spec));
2996 pa_assert(chunkIn);
2997
2998 pa_assert(!si->thread_info.rewind_requested);
2999 pa_assert(si->thread_info.rewind_nbytes == 0);
3000
3001 if (si->thread_info.state == PA_SINK_SUSPENDED) {
3002 chunkIn->memblock = pa_memblock_ref(si->silence.memblock);
3003 chunkIn->index = si->silence.index;
3004 chunkIn->length = PA_MIN(si->silence.length, length);
3005 return;
3006 }
3007
3008 if (length == 0)
3009 length = pa_frame_align(MIX_BUFFER_LENGTH, &si->sample_spec);
3010
3011 blockSizeMax = pa_mempool_block_size_max(si->core->mempool);
3012 if (length > blockSizeMax)
3013 length = pa_frame_align(blockSizeMax, &si->sample_spec);
3014
3015 pa_assert(length > 0);
3016
3017 SinkRenderMultiChannelProcess(si, length, chunkIn);
3018
3019 pa_sink_unref(si);
3020 }
3021
ProcessRenderUseTimingMultiChannel(struct Userdata * u,pa_usec_t now)3022 static void ProcessRenderUseTimingMultiChannel(struct Userdata *u, pa_usec_t now)
3023 {
3024 pa_assert(u);
3025
3026 // Fill the buffer up the latency size
3027 pa_memchunk chunk;
3028
3029 // Change from pa_sink_render to pa_sink_render_full for alignment issue in 3516
3030 SinkRenderMultiChannel(u->sink, u->sink->thread_info.max_request, &chunk);
3031 pa_assert(chunk.length > 0);
3032
3033 StartMultiChannelHdiIfRunning(u);
3034
3035 if (!chunk.memblock) {
3036 if (pa_atomic_load(&u->multiChannel.dflag) == 1) {
3037 pa_atomic_sub(&u->multiChannel.dflag, 1);
3038 }
3039 return;
3040 }
3041 pa_asyncmsgq_post(u->multiChannel.dq, NULL, HDI_RENDER, NULL, 0, &chunk, NULL);
3042 u->multiChannel.timestamp += pa_bytes_to_usec(u->sink->thread_info.max_request, &u->sink->sample_spec);
3043 }
3044
ThreadFuncRendererTimerMultiChannelFlagJudge(struct Userdata * u)3045 static bool POSSIBLY_UNUSED ThreadFuncRendererTimerMultiChannelFlagJudge(struct Userdata *u)
3046 {
3047 pa_assert(u);
3048 bool flag = (u->render_in_idle_state && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ||
3049 (!u->render_in_idle_state && PA_SINK_IS_RUNNING(u->sink->thread_info.state)) ||
3050 (u->sink->thread_info.state == PA_SINK_IDLE && u->sink->monitor_source &&
3051 PA_SOURCE_IS_RUNNING(u->sink->monitor_source->thread_info.state));
3052 pa_sink_input *i;
3053 void *state = NULL;
3054 int nMultiChannel = 0;
3055 while ((i = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL))) {
3056 pa_sink_input_assert_ref(i);
3057 if (InputIsMultiChannel(i)) {
3058 nMultiChannel++;
3059 }
3060 }
3061 flag &= nMultiChannel > 0;
3062 return flag;
3063 }
3064
ProcessNormalData(struct Userdata * u)3065 static void ProcessNormalData(struct Userdata *u)
3066 {
3067 AUTO_CTRACE("ProcessNormalData");
3068 int64_t sleepForUsec = -1;
3069 pa_usec_t now = 0;
3070
3071 if (u->sink->thread_info.state == PA_SINK_SUSPENDED && u->isEffectBufferAllocated == true) {
3072 FreeEffectBuffer(u);
3073 u->isEffectBufferAllocated = false;
3074 }
3075
3076 bool flag = (((u->render_in_idle_state && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ||
3077 (!u->render_in_idle_state && PA_SINK_IS_RUNNING(u->sink->thread_info.state))) &&
3078 !(u->sink->thread_info.state == PA_SINK_IDLE && u->primary.previousState == PA_SINK_SUSPENDED) &&
3079 !(u->sink->thread_info.state == PA_SINK_IDLE && u->primary.previousState == PA_SINK_INIT)) ||
3080 (u->sink->thread_info.state == PA_SINK_IDLE && monitorLinked(u->sink, true));
3081 if (flag) {
3082 now = pa_rtclock_now();
3083 }
3084
3085 if (PA_UNLIKELY(u->sink->thread_info.rewind_requested)) {
3086 pa_sink_process_rewind(u->sink, 0);
3087 }
3088
3089 if (flag) {
3090 pa_usec_t frameUsec = pa_bytes_to_usec(u->sink->thread_info.max_request, &u->sink->sample_spec);
3091 pa_usec_t blockTime = u->primary.timestamp + frameUsec - now;
3092 if (blockTime > frameUsec) { blockTime = frameUsec; }
3093 if (pa_atomic_load(&u->primary.dflag) == 1) {
3094 sleepForUsec = (int64_t)blockTime -
3095 ((int64_t)pa_rtclock_now() - (int64_t)(u->primary.lastProcessDataTime));
3096 if (sleepForUsec < MIN_SLEEP_FOR_USEC) {
3097 sleepForUsec = MIN_SLEEP_FOR_USEC;
3098 }
3099 } else {
3100 if (u->primary.timestamp <= now + u->primary.prewrite || !strcmp(u->sink->name, DP_SINK_NAME)) {
3101 pa_atomic_add(&u->primary.dflag, 1);
3102 u->primary.lastProcessDataTime = pa_rtclock_now();
3103 ProcessRenderUseTiming(u, now);
3104 }
3105 sleepForUsec = (int64_t)blockTime - ((int64_t)pa_rtclock_now() - (int64_t)now);
3106 if (u->primary.timestamp <= now + u->primary.prewrite) {
3107 sleepForUsec = PA_MIN(sleepForUsec, (int64_t)u->primary.writeTime);
3108 }
3109 }
3110 sleepForUsec = PA_MAX(sleepForUsec, 0);
3111 }
3112
3113 if (sleepForUsec != -1) {
3114 if (u->timestampSleep == -1) {
3115 u->timestampSleep = (int64_t)pa_rtclock_now() + sleepForUsec;
3116 } else {
3117 u->timestampSleep = PA_MIN(u->timestampSleep, (int64_t)pa_rtclock_now() + sleepForUsec);
3118 }
3119 }
3120 }
3121
ProcessMCHData(struct Userdata * u)3122 static void ProcessMCHData(struct Userdata *u)
3123 {
3124 AUTO_CTRACE("ProcessMCHData");
3125 const uint64_t pw = u->multiChannel.prewrite;
3126
3127 pa_usec_t now = 0;
3128
3129 int64_t sleepForUsec = -1;
3130
3131 now = pa_rtclock_now();
3132
3133 if (PA_UNLIKELY(u->sink->thread_info.rewind_requested)) {
3134 pa_sink_process_rewind(u->sink, 0);
3135 }
3136
3137 if (!ThreadFuncRendererTimerMultiChannelFlagJudge(u)) {
3138 return;
3139 }
3140
3141 if (u->multiChannel.timestamp <= now + pw && pa_atomic_load(&u->multiChannel.dflag) == 0) {
3142 pa_atomic_add(&u->multiChannel.dflag, 1);
3143 ProcessRenderUseTimingMultiChannel(u, now);
3144 }
3145 pa_usec_t blockTime = pa_bytes_to_usec(u->sink->thread_info.max_request, &u->sink->sample_spec);
3146 sleepForUsec = PA_MIN((int64_t)blockTime - ((int64_t)pa_rtclock_now() - (int64_t)now),
3147 (int64_t)(u->multiChannel.writeTime));
3148 sleepForUsec = PA_MAX(sleepForUsec, 0);
3149 if (sleepForUsec != -1) {
3150 if (u->timestampSleep == -1) {
3151 u->timestampSleep = (int64_t)pa_rtclock_now() + sleepForUsec;
3152 } else {
3153 u->timestampSleep = PA_MIN(u->timestampSleep, (int64_t)pa_rtclock_now() + sleepForUsec);
3154 }
3155 }
3156 }
3157
ProcessOffloadData(struct Userdata * u)3158 static void ProcessOffloadData(struct Userdata *u)
3159 {
3160 AUTO_CTRACE("ProcessOffloadData");
3161 pa_usec_t now = pa_rtclock_now();
3162 int64_t sleepForUsec = -1;
3163 bool flag;
3164 ThreadFuncRendererTimerOffloadFlag(u, now, &flag, &sleepForUsec);
3165
3166 if (flag) {
3167 ThreadFuncRendererTimerOffloadProcess(u, now, &sleepForUsec);
3168 sleepForUsec = PA_MAX(sleepForUsec, 0);
3169 }
3170
3171 if (u->offload.fullTs != 0) {
3172 if (u->offload.fullTs + 10 * PA_USEC_PER_MSEC > now) { // 10 is min checking size
3173 const int64_t s = ((int64_t)(u->offload.fullTs) + 10 * PA_USEC_PER_MSEC) - (int64_t)now;
3174 sleepForUsec = sleepForUsec == -1 ? s : PA_MIN(s, sleepForUsec);
3175 } else if (pa_atomic_load(&u->offload.hdistate) == 1) {
3176 u->offload.fullTs = 0;
3177 OffloadUnlock(u);
3178 } else {
3179 u->offload.fullTs = 0;
3180 }
3181 }
3182
3183 if (sleepForUsec != -1) {
3184 if (u->timestampSleep == -1) {
3185 u->timestampSleep = (int64_t)pa_rtclock_now() + sleepForUsec;
3186 } else {
3187 u->timestampSleep = PA_MIN(u->timestampSleep, (int64_t)pa_rtclock_now() + sleepForUsec);
3188 }
3189 }
3190 }
3191
ThreadFuncRendererTimerProcessData(struct Userdata * u)3192 static void ThreadFuncRendererTimerProcessData(struct Userdata *u)
3193 {
3194 if (u->timestampSleep < (int64_t)pa_rtclock_now()) {
3195 u->timestampSleep = -1;
3196 }
3197
3198 pthread_rwlock_unlock(&u->rwlockSleep);
3199
3200 static int64_t logCnt = 0;
3201 if (logCnt == 0) {
3202 AUDIO_INFO_LOG("Bus thread still running");
3203 }
3204 ++logCnt;
3205 if (logCnt > LOG_LOOP_THRESHOLD) {
3206 logCnt = 0;
3207 }
3208
3209 g_onlyPrimarySpeakerPaLoading = true;
3210 g_speakerPaAllStreamVolumeZero = true;
3211 CheckOnlyPrimarySpeakerPaLoading(u);
3212 if (!strcmp(u->sink->name, MCH_SINK_NAME)) {
3213 ProcessMCHData(u);
3214 } else if (!strcmp(u->sink->name, OFFLOAD_SINK_NAME) && u->offload_enable && u->offload.msgq) {
3215 ProcessOffloadData(u);
3216 } else {
3217 ProcessNormalData(u);
3218 }
3219 }
3220
ThreadFuncRendererTimerBus(void * userdata)3221 static void ThreadFuncRendererTimerBus(void *userdata)
3222 {
3223 // set audio thread priority
3224 ScheduleThreadInServer(getpid(), gettid());
3225
3226 struct Userdata *u = userdata;
3227
3228 pa_assert(u);
3229
3230 const char *deviceClass = GetDeviceClass(u->primary.sinkAdapter->deviceClass);
3231 AUDIO_INFO_LOG("Thread %s(use timing bus) starting up, pid %d, tid %d", deviceClass, getpid(), gettid());
3232 pa_thread_mq_install(&u->thread_mq);
3233
3234 if (!strcmp(u->sink->name, OFFLOAD_SINK_NAME)) {
3235 OffloadReset(u);
3236 CHECK_AND_RETURN_LOG(u->offload.sinkAdapter != NULL, "offload.sinkAdapter is NULL");
3237 u->offload.sinkAdapter->RendererSinkOffloadRunningLockInit(u->offload.sinkAdapter);
3238 }
3239 while (true) {
3240 int ret;
3241 pthread_rwlock_wrlock(&u->rwlockSleep);
3242
3243 int64_t sleepForUsec = 0;
3244
3245 if (u->timestampSleep == -1) {
3246 pa_rtpoll_set_timer_disabled(u->rtpoll); // sleep forever
3247 } else if ((sleepForUsec = u->timestampSleep - (int64_t)(pa_rtclock_now())) <= 0) {
3248 pa_rtpoll_set_timer_relative(u->rtpoll, 0);
3249 } else {
3250 pa_rtpoll_set_timer_relative(u->rtpoll, sleepForUsec);
3251 }
3252
3253 AUTO_CTRACE("ProcessDataLoop %s sleep:%lld us", deviceClass, sleepForUsec);
3254 // Hmm, nothing to do. Let's sleep
3255 if ((ret = pa_rtpoll_run(u->rtpoll)) < 0) {
3256 AUDIO_ERR_LOG("Thread %{public}s(use timing bus) shutting down, error %{public}d, "
3257 "pid %{public}d, tid %{public}d", deviceClass, ret, getpid(), gettid());
3258 if (!strcmp(deviceClass, DEVICE_CLASS_PRIMARY)) {
3259 AUDIO_ERR_LOG("Primary sink's pa_rtpoll_run error, exit");
3260 _Exit(0);
3261 }
3262
3263 // If this was no regular exit from the loop we have to continue
3264 // processing messages until we received PA_MESSAGE_SHUTDOWN
3265 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE,
3266 u->module, 0, NULL, NULL);
3267 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
3268 pthread_rwlock_unlock(&u->rwlockSleep);
3269 break;
3270 }
3271
3272 if (ret == 0) {
3273 AUDIO_INFO_LOG("Thread %{public}s(use timing bus) shutting down, pid %{public}d, tid %{public}d",
3274 deviceClass, getpid(), gettid());
3275 pthread_rwlock_unlock(&u->rwlockSleep);
3276 break;
3277 }
3278
3279 ThreadFuncRendererTimerProcessData(u);
3280 }
3281 UnscheduleThreadInServer(getpid(), gettid());
3282 }
3283
ThreadFuncWriteHDIMultiChannel(void * userdata)3284 static void ThreadFuncWriteHDIMultiChannel(void *userdata)
3285 {
3286 AUDIO_DEBUG_LOG("ThreadFuncWriteHDIMultiChannel start");
3287 // set audio thread priority
3288 ScheduleThreadInServer(getpid(), gettid());
3289
3290 struct Userdata *u = userdata;
3291 pa_assert(u);
3292
3293 int32_t quit = 0;
3294
3295 do {
3296 int32_t code = 0;
3297 pa_memchunk chunk;
3298
3299 pa_assert_se(pa_asyncmsgq_get(u->multiChannel.dq, NULL, &code, NULL, NULL, &chunk, 1) == 0);
3300
3301 switch (code) {
3302 case HDI_RENDER: {
3303 pa_usec_t now = pa_rtclock_now();
3304 if (RenderWrite(u->multiChannel.sinkAdapter, &chunk) < 0) {
3305 AUDIO_DEBUG_LOG("ThreadFuncWriteHDIMultiChannel RenderWrite");
3306 u->bytes_dropped += chunk.length;
3307 }
3308 if (pa_atomic_load(&u->multiChannel.dflag) == 1) {
3309 pa_atomic_sub(&u->multiChannel.dflag, 1);
3310 }
3311 u->multiChannel.writeTime = pa_rtclock_now() - now;
3312 break;
3313 }
3314 case QUIT:
3315 quit = 1;
3316 break;
3317 default:
3318 break;
3319 }
3320 pa_asyncmsgq_done(u->multiChannel.dq, 0);
3321 } while (!quit);
3322 UnscheduleThreadInServer(getpid(), gettid());
3323 }
3324
ProcessHdiRendererPrimary(struct Userdata * u,pa_memchunk * pChunk)3325 static void ProcessHdiRendererPrimary(struct Userdata *u, pa_memchunk *pChunk)
3326 {
3327 pa_usec_t now = pa_rtclock_now();
3328 if (pa_atomic_load(&u->primary.isHDISinkStarted) != 1 && now - u->timestampLastLog > USEC_PER_SEC) {
3329 u->timestampLastLog = now;
3330 const char *deviceClass = GetDeviceClass(u->primary.sinkAdapter->deviceClass);
3331 AUDIO_DEBUG_LOG("HDI not started, skip RenderWrite, wait sink[%s] suspend", deviceClass);
3332 pa_memblock_unref(pChunk->memblock);
3333 } else if (pa_atomic_load(&u->primary.isHDISinkStarted) != 1) {
3334 pa_memblock_unref(pChunk->memblock);
3335 } else if (RenderWrite(u->primary.sinkAdapter, pChunk) < 0) {
3336 u->bytes_dropped += pChunk->length;
3337 AUDIO_ERR_LOG("RenderWrite failed");
3338 }
3339 if (pa_atomic_load(&u->primary.dflag) == 1) {
3340 pa_atomic_sub(&u->primary.dflag, 1);
3341 }
3342 u->primary.writeTime = pa_rtclock_now() - now;
3343 }
3344
ThreadFuncWriteHDI(void * userdata)3345 static void ThreadFuncWriteHDI(void *userdata)
3346 {
3347 // set audio thread priority
3348 ScheduleThreadInServer(getpid(), gettid());
3349
3350 struct Userdata *u = userdata;
3351 pa_assert(u);
3352
3353 int32_t quit = 0;
3354
3355 do {
3356 int32_t code = 0;
3357 pa_memchunk chunk;
3358
3359 CHECK_AND_RETURN_LOG(u->primary.dq != NULL, "u->primary.dq is NULL");
3360 pa_assert_se(pa_asyncmsgq_get(u->primary.dq, NULL, &code, NULL, NULL, &chunk, 1) == 0);
3361
3362 int ret = 0;
3363 AUTO_CTRACE("hdi_sink::ThreadFuncWriteHDI code: %d", code);
3364 switch (code) {
3365 case HDI_RENDER: {
3366 ProcessHdiRendererPrimary(u, &chunk);
3367 break;
3368 }
3369 case HDI_STOP: {
3370 if (pa_atomic_load(&u->primary.isHDISinkStarted) == 1) {
3371 u->primary.sinkAdapter->RendererSinkStop(u->primary.sinkAdapter);
3372 AUDIO_INFO_LOG("Stopped HDI renderer");
3373 pa_atomic_store(&u->primary.isHDISinkStarted, 0);
3374 }
3375 break;
3376 }
3377 case HDI_START: {
3378 ret = u->primary.sinkAdapter->RendererSinkStart(u->primary.sinkAdapter);
3379 break;
3380 }
3381 case QUIT:
3382 quit = 1;
3383 break;
3384 default:
3385 break;
3386 }
3387 AUTO_CTRACE("hdi_sink::ThreadFuncWriteHDI done ret: %d", ret);
3388 pa_asyncmsgq_done(u->primary.dq, ret);
3389 } while (!quit);
3390 UnscheduleThreadInServer(getpid(), gettid());
3391 }
3392
TestModeThreadFuncWriteHDI(void * userdata)3393 static void TestModeThreadFuncWriteHDI(void *userdata)
3394 {
3395 // set audio thread priority
3396 ScheduleThreadInServer(getpid(), gettid());
3397
3398 struct Userdata *u = userdata;
3399 pa_assert(u);
3400
3401 int32_t quit = 0;
3402
3403 do {
3404 int32_t code = 0;
3405 pa_memchunk chunk;
3406
3407 pa_assert_se(pa_asyncmsgq_get(u->primary.dq, NULL, &code, NULL, NULL, &chunk, 1) == 0);
3408
3409 switch (code) {
3410 case HDI_RENDER:
3411 if (TestModeRenderWrite(u, &chunk) < 0) {
3412 u->bytes_dropped += chunk.length;
3413 AUDIO_ERR_LOG("TestModeRenderWrite failed");
3414 }
3415 if (pa_atomic_load(&u->primary.dflag) == 1) {
3416 pa_atomic_sub(&u->primary.dflag, 1);
3417 }
3418 break;
3419 case QUIT:
3420 quit = 1;
3421 break;
3422 default:
3423 break;
3424 }
3425 pa_asyncmsgq_done(u->primary.dq, 0);
3426 } while (!quit);
3427 UnscheduleThreadInServer(getpid(), gettid());
3428 }
3429
SinkUpdateRequestedLatencyCb(pa_sink * s)3430 static void SinkUpdateRequestedLatencyCb(pa_sink *s)
3431 {
3432 struct Userdata *u = NULL;
3433 size_t nbytes;
3434
3435 pa_sink_assert_ref(s);
3436 pa_assert_se(u = s->userdata);
3437
3438 u->block_usec = pa_sink_get_requested_latency_within_thread(s);
3439
3440 if (u->block_usec == (pa_usec_t) - 1)
3441 u->block_usec = s->thread_info.max_latency;
3442
3443 if (u->block_usec < DEFAULT_BLOCK_USEC) {
3444 AUDIO_WARNING_LOG("block_usec is less than 20000, block_usec: %{public}" PRIu64, u->block_usec);
3445 u->block_usec = DEFAULT_BLOCK_USEC;
3446 }
3447 nbytes = pa_usec_to_bytes(u->block_usec, &s->sample_spec);
3448 pa_sink_set_max_request_within_thread(s, nbytes);
3449 }
3450
CheckAndPrintLatency(uint64_t lastRecodedLatency,uint64_t latency,bool getLatencyFromHdiSucess,uint32_t continuesGetLatencyErrCount,uint64_t logThreshold)3451 static void CheckAndPrintLatency(uint64_t lastRecodedLatency, uint64_t latency, bool getLatencyFromHdiSucess,
3452 uint32_t continuesGetLatencyErrCount, uint64_t logThreshold)
3453 {
3454 uint64_t latencyDifference = (latency > lastRecodedLatency)
3455 ? (latency - lastRecodedLatency) : (lastRecodedLatency - latency);
3456 if (latencyDifference > logThreshold) {
3457 AUDIO_INFO_LOG("lastLatency: %{public}" PRIu64 " latency: %{public}" PRIu64 ""
3458 " getLatencyFromHdiSucess: %{public}d continuesGetLatencyErrCount: %{public}u",
3459 lastRecodedLatency, latency, getLatencyFromHdiSucess, continuesGetLatencyErrCount);
3460 }
3461 }
3462
SinkProcessMsg(pa_msgobject * o,int32_t code,void * data,int64_t offset,pa_memchunk * chunk)3463 static int32_t SinkProcessMsg(pa_msgobject *o, int32_t code, void *data, int64_t offset,
3464 pa_memchunk *chunk)
3465 {
3466 AUDIO_DEBUG_LOG("SinkProcessMsg: code: %{public}d", code);
3467 AUTO_CTRACE("hdi_sink::SinkProcessMsg code: %d", code);
3468 struct Userdata *u = PA_SINK(o)->userdata;
3469 pa_assert(u);
3470
3471 switch (code) {
3472 case PA_SINK_MESSAGE_GET_LATENCY: {
3473 if (!strcmp(GetDeviceClass(u->primary.sinkAdapter->deviceClass), DEVICE_CLASS_OFFLOAD)) {
3474 uint64_t pos = u->offload.pos;
3475 pa_usec_t now = pa_rtclock_now();
3476 uint64_t time = now > u->offload.hdiPosTs ? (now - u->offload.hdiPosTs) / PA_USEC_PER_MSEC : 0;
3477 uint64_t hdiPos = u->offload.hdiPos + time * PA_USEC_PER_MSEC;
3478 *((uint64_t *)data) = pos > hdiPos ? (pos - hdiPos) : 0;
3479 AUDIO_DEBUG_LOG("offload latency: %{public}" PRIu64 " write pos: %{public}" PRIu64
3480 " hdi pos: %{public}" PRIu64 " time: %{public}" PRIu64,
3481 *((uint64_t *)data), pos, u->offload.hdiPos, time * PA_USEC_PER_MSEC);
3482 } else if (u->sink_latency) {
3483 *((uint64_t *)data) = u->sink_latency * PA_USEC_PER_MSEC;
3484 } else {
3485 uint64_t latency;
3486 uint32_t hdiLatency;
3487 bool getLatencyFromHdiSucess = true;
3488 // Tries to fetch latency from HDI else will make an estimate based
3489 // on samples to be rendered based on the timestamp and current time
3490 if (u->primary.sinkAdapter->RendererSinkGetLatency(u->primary.sinkAdapter, &hdiLatency) == 0) {
3491 latency = (PA_USEC_PER_MSEC * hdiLatency);
3492 } else {
3493 pa_usec_t now = pa_rtclock_now();
3494 latency = (now - u->primary.timestamp);
3495 getLatencyFromHdiSucess = false;
3496 }
3497
3498 *((uint64_t *)data) = latency;
3499 CheckAndPrintLatency(u->lastRecodedLatency, latency, getLatencyFromHdiSucess,
3500 u->continuesGetLatencyErrCount, DEFAULT_GETLATENCY_LOG_THRESHOLD_MS);
3501 u->lastRecodedLatency = latency;
3502 u->continuesGetLatencyErrCount = getLatencyFromHdiSucess ? 0 : (u->continuesGetLatencyErrCount + 1);
3503 }
3504 return 0;
3505 }
3506 default:
3507 break;
3508 }
3509 return pa_sink_process_msg(o, code, data, offset, chunk);
3510 }
3511
GetStateInfo(pa_sink_state_t state)3512 static char *GetStateInfo(pa_sink_state_t state)
3513 {
3514 switch (state) {
3515 case PA_SINK_INVALID_STATE:
3516 return "INVALID";
3517 case PA_SINK_RUNNING:
3518 return "RUNNING";
3519 case PA_SINK_IDLE:
3520 return "IDLE";
3521 case PA_SINK_SUSPENDED:
3522 return "SUSPENDED";
3523 case PA_SINK_INIT:
3524 return "INIT";
3525 case PA_SINK_UNLINKED:
3526 return "UNLINKED";
3527 default:
3528 return "error state";
3529 }
3530 }
3531
GetInputStateInfo(pa_sink_input_state_t state)3532 static char *GetInputStateInfo(pa_sink_input_state_t state)
3533 {
3534 switch (state) {
3535 case PA_SINK_INPUT_INIT:
3536 return "INIT";
3537 case PA_SINK_INPUT_RUNNING:
3538 return "RUNNING";
3539 case PA_SINK_INPUT_CORKED:
3540 return "CORKED";
3541 case PA_SINK_INPUT_UNLINKED:
3542 return "UNLINKED";
3543 default:
3544 return "UNKNOWN";
3545 }
3546 }
3547
3548 // call from IO thread(OS_ProcessData)
RemoteSinkStateChange(pa_sink * s,pa_sink_state_t newState)3549 static int32_t RemoteSinkStateChange(pa_sink *s, pa_sink_state_t newState)
3550 {
3551 struct Userdata *u = s->userdata;
3552 if (s->thread_info.state == PA_SINK_INIT || newState == PA_SINK_INIT) {
3553 u->isFirstStarted = false;
3554 }
3555
3556 if (!u->isFirstStarted && (newState == PA_SINK_RUNNING)) {
3557 u->primary.timestamp = pa_rtclock_now();
3558 u->isFirstStarted = true;
3559 }
3560
3561 if (s->thread_info.state == PA_SINK_INIT && newState == PA_SINK_IDLE) {
3562 AUDIO_INFO_LOG("First start.");
3563 }
3564
3565 if (s->thread_info.state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(newState)) {
3566 u->primary.timestamp = pa_rtclock_now();
3567 if (pa_atomic_load(&u->primary.isHDISinkStarted) == 1) {
3568 return 0;
3569 }
3570
3571 if (pa_asyncmsgq_send(u->primary.dq, NULL, HDI_START, NULL, 0, NULL)) {
3572 AUDIO_ERR_LOG("audiorenderer control start failed!");
3573 } else {
3574 pa_atomic_store(&u->primary.isHDISinkStarted, 1);
3575 u->render_in_idle_state = 1; // enable to reduce noise from idle to running.
3576 u->writeCount = 0;
3577 u->renderCount = 0;
3578 AUDIO_INFO_LOG("Successfully restarted remote renderer");
3579 }
3580 }
3581 if (PA_SINK_IS_OPENED(s->thread_info.state) && newState == PA_SINK_SUSPENDED) {
3582 // Continuously dropping data (clear counter on entering suspended state.
3583 if (u->bytes_dropped != 0) {
3584 AUDIO_INFO_LOG("HDI-sink continuously dropping data - clear statistics (%zu -> 0 bytes dropped)",
3585 u->bytes_dropped);
3586 u->bytes_dropped = 0;
3587 }
3588
3589 if (pa_atomic_load(&u->primary.isHDISinkStarted) == 1) {
3590 pa_asyncmsgq_post(u->primary.dq, NULL, HDI_STOP, NULL, 0, NULL, NULL);
3591 }
3592 }
3593
3594 return 0;
3595 }
3596
3597 // call from IO thread(OS_ProcessData)
SinkSetStateInIoThreadCbStartPrimary(struct Userdata * u,pa_sink_state_t newState)3598 static int32_t SinkSetStateInIoThreadCbStartPrimary(struct Userdata *u, pa_sink_state_t newState)
3599 {
3600 if (!PA_SINK_IS_OPENED(newState)) {
3601 return 0;
3602 }
3603
3604 u->primary.timestamp = pa_rtclock_now();
3605 if (pa_atomic_load(&u->primary.isHDISinkStarted) == 1) {
3606 return 0;
3607 }
3608
3609 if (u->sink->thread_info.state == PA_SINK_SUSPENDED && newState == PA_SINK_IDLE) {
3610 AUDIO_INFO_LOG("Primary sink from suspend to idle");
3611 return 0;
3612 }
3613
3614 if (pa_asyncmsgq_send(u->primary.dq, NULL, HDI_START, NULL, 0, NULL)) {
3615 AUDIO_ERR_LOG("audiorenderer control start failed!");
3616 u->primary.sinkAdapter->RendererSinkDeInit(u->primary.sinkAdapter);
3617 } else {
3618 pa_atomic_store(&u->primary.isHDISinkStarted, 1);
3619 u->writeCount = 0;
3620 u->renderCount = 0;
3621 AUDIO_INFO_LOG("SinkSetStateInIoThreadCbStartPrimary, Successfully restarted HDI renderer");
3622 }
3623 return 0;
3624 }
3625
SinkSetStateInIoThreadCbStartMultiChannel(struct Userdata * u,pa_sink_state_t newState)3626 static int32_t SinkSetStateInIoThreadCbStartMultiChannel(struct Userdata *u, pa_sink_state_t newState)
3627 {
3628 if (!PA_SINK_IS_OPENED(newState)) {
3629 return 0;
3630 }
3631
3632 u->multiChannel.timestamp = pa_rtclock_now();
3633
3634 EffectChainManagerReturnMultiChannelInfo(&u->multiChannel.sinkChannel, &u->multiChannel.sinkChannelLayout);
3635 ResetMultiChannelHdiState(u);
3636 return 0;
3637 }
3638
OffloadSinkStateChangeCb(pa_sink * sink,pa_sink_state_t newState)3639 static void OffloadSinkStateChangeCb(pa_sink *sink, pa_sink_state_t newState)
3640 {
3641 struct Userdata *u = (struct Userdata *)(sink->userdata);
3642 const bool starting = PA_SINK_IS_OPENED(newState);
3643 const bool stopping = newState == PA_SINK_SUSPENDED;
3644 AUDIO_INFO_LOG("starting: %{public}d, stopping: %{public}d, offload_enable: %{public}d",
3645 starting, stopping, u->offload_enable);
3646 if (starting && u->offload_enable && !u->offload.inited && PrepareDeviceOffload(u) == 0) {
3647 u->offload.inited = true;
3648 } else if (stopping && u->offload_enable) {
3649 if (u->offload.isHDISinkStarted) {
3650 u->offload.sinkAdapter->RendererSinkStop(u->offload.sinkAdapter);
3651 AUDIO_INFO_LOG("Stopped Offload HDI renderer, DeInit later");
3652 u->offload.isHDISinkStarted = false;
3653 }
3654 OffloadReset(u);
3655 OffloadUnlock(u);
3656 if (u->offload.inited) {
3657 u->offload.inited = false;
3658 u->offload.sinkAdapter->RendererSinkDeInit(u->offload.sinkAdapter);
3659 AUDIO_INFO_LOG("DeInited Offload HDI renderer");
3660 }
3661 g_speakerPaAllStreamStartVolZeroTime = 0;
3662 }
3663 }
3664
3665 // Called from the IO thread.
SinkSetStateInIoThreadCb(pa_sink * s,pa_sink_state_t newState,pa_suspend_cause_t newSuspendCause)3666 static int32_t SinkSetStateInIoThreadCb(pa_sink *s, pa_sink_state_t newState, pa_suspend_cause_t newSuspendCause)
3667 {
3668 struct Userdata *u = NULL;
3669
3670 pa_assert(s);
3671 pa_assert_se(u = s->userdata);
3672
3673 AUDIO_INFO_LOG("Sink[%{public}s] state change:[%{public}s]-->[%{public}s]",
3674 GetDeviceClass(u->primary.sinkAdapter->deviceClass), GetStateInfo(s->thread_info.state),
3675 GetStateInfo(newState));
3676 u->primary.previousState = u->sink->thread_info.state;
3677
3678 if (!strcmp(GetDeviceClass(u->primary.sinkAdapter->deviceClass), DEVICE_CLASS_REMOTE)) {
3679 return RemoteSinkStateChange(s, newState);
3680 }
3681
3682 if (!strcmp(u->sink->name, OFFLOAD_SINK_NAME)) {
3683 OffloadSinkStateChangeCb(s, newState);
3684 return 0;
3685 }
3686
3687 if (s->thread_info.state == PA_SINK_SUSPENDED || s->thread_info.state == PA_SINK_INIT ||
3688 newState == PA_SINK_RUNNING) {
3689 if (EffectChainManagerCheckEffectOffload() && (!strcmp(u->sink->name, "Speaker"))) {
3690 SinkSetStateInIoThreadCbStartMultiChannel(u, newState);
3691 }
3692 if (strcmp(u->sink->name, BT_SINK_NAME) || newState == PA_SINK_RUNNING) {
3693 return SinkSetStateInIoThreadCbStartPrimary(u, newState);
3694 }
3695 } else if (PA_SINK_IS_OPENED(s->thread_info.state)) {
3696 if (newState != PA_SINK_SUSPENDED) {
3697 return 0;
3698 }
3699 // Continuously dropping data (clear counter on entering suspended state.
3700 if (u->bytes_dropped != 0) {
3701 AUDIO_INFO_LOG("HDI-sink continuously dropping data - clear statistics (%zu -> 0 bytes dropped)",
3702 u->bytes_dropped);
3703 u->bytes_dropped = 0;
3704 }
3705
3706 if (pa_atomic_load(&u->primary.isHDISinkStarted) == 1) {
3707 pa_asyncmsgq_post(u->primary.dq, NULL, HDI_STOP, NULL, 0, NULL, NULL);
3708 }
3709
3710 if (u->multiChannel.isHDISinkStarted) {
3711 u->multiChannel.sinkAdapter->RendererSinkStop(u->multiChannel.sinkAdapter);
3712 AUDIO_INFO_LOG("MultiChannel Stopped HDI renderer");
3713 u->multiChannel.isHDISinkStarted = false;
3714 }
3715 }
3716
3717 return 0;
3718 }
3719
SinkInputMoveStartCb(pa_core * core,pa_sink_input * i,struct Userdata * u)3720 static pa_hook_result_t SinkInputMoveStartCb(pa_core *core, pa_sink_input *i, struct Userdata *u)
3721 {
3722 pa_sink_input_assert_ref(i);
3723 char str[SPRINTF_STR_LEN] = {0};
3724 GetSinkInputName(i, str, SPRINTF_STR_LEN);
3725 AUDIO_INFO_LOG("SinkInputMoveStartCb sink[%{public}s] - %{public}s", i->sink->name, str);
3726 if (u->offload_enable && !strcmp(i->sink->name, OFFLOAD_SINK_NAME) &&
3727 i->thread_info.state == PA_SINK_INPUT_RUNNING) {
3728 const bool maybeOffload = pa_memblockq_get_maxrewind(i->thread_info.render_memblockq) != 0;
3729 if (maybeOffload || InputIsOffload(i)) {
3730 OffloadRewindAndFlush(u, i, false);
3731 pa_sink_input_update_max_rewind(i, 0);
3732 }
3733 }
3734 return PA_HOOK_OK;
3735 }
3736
SinkInputStateChangedCb(pa_core * core,pa_sink_input * i,struct Userdata * u)3737 static pa_hook_result_t SinkInputStateChangedCb(pa_core *core, pa_sink_input *i, struct Userdata *u)
3738 {
3739 pa_sink_input_assert_ref(i);
3740 char str[SPRINTF_STR_LEN] = {0};
3741 GetSinkInputName(i, str, SPRINTF_STR_LEN);
3742 AUDIO_INFO_LOG("SinkInputStateChangedCb sink[%{public}s] - %{public}s", i->sink->name, str);
3743 if (u->offload_enable && !strcmp(i->sink->name, OFFLOAD_SINK_NAME)) {
3744 if (i->thread_info.state == PA_SINK_INPUT_CORKED) {
3745 pa_atomic_store(&u->offload.hdistate, 0);
3746 }
3747 }
3748 return PA_HOOK_OK;
3749 }
3750
SinkInputPutCb(pa_core * core,pa_sink_input * i,struct Userdata * u)3751 static pa_hook_result_t SinkInputPutCb(pa_core *core, pa_sink_input *i, struct Userdata *u)
3752 {
3753 pa_sink_input_assert_ref(i);
3754 const char *streamMode = pa_proplist_gets(i->proplist, "stream.mode");
3755 if (streamMode != NULL && !strcmp(streamMode, DUP_STEAM_NAME)) {
3756 AUDIO_INFO_LOG("Dup stream is dismissed:%{public}u", i->index);
3757 return PA_HOOK_OK;
3758 }
3759 i->state_change = PaInputStateChangeCb;
3760 return PA_HOOK_OK;
3761 }
3762
PrepareDevice(struct Userdata * u,const char * filePath)3763 static int32_t PrepareDevice(struct Userdata *u, const char *filePath)
3764 {
3765 SinkAttr sample_attrs;
3766 int32_t ret;
3767
3768 sample_attrs.format = ConvertPaToHdiAdapterFormat(u->ss.format);
3769 sample_attrs.adapterName = u->adapterName;
3770 sample_attrs.openMicSpeaker = u->open_mic_speaker;
3771 sample_attrs.sampleRate = (uint32_t)u->ss.rate;
3772 sample_attrs.channel = u->ss.channels;
3773 sample_attrs.volume = MAX_SINK_VOLUME_LEVEL;
3774 sample_attrs.filePath = filePath;
3775 sample_attrs.deviceNetworkId = u->deviceNetworkId;
3776 sample_attrs.deviceType = u->deviceType;
3777
3778 if (!strcmp(GetDeviceClass(u->primary.sinkAdapter->deviceClass), DEVICE_CLASS_MULTICHANNEL)) {
3779 sample_attrs.channel = DEFAULT_MULTICHANNEL_NUM;
3780 sample_attrs.channelLayout = DEFAULT_MULTICHANNEL_CHANNELLAYOUT;
3781 }
3782
3783 ret = u->primary.sinkAdapter->RendererSinkInit(u->primary.sinkAdapter, &sample_attrs);
3784 if (ret != 0) {
3785 AUDIO_ERR_LOG("audiorenderer Init failed!");
3786 return -1;
3787 }
3788
3789 if (ret != 0) {
3790 AUDIO_ERR_LOG("audiorenderer control start failed!");
3791 u->primary.sinkAdapter->RendererSinkDeInit(u->primary.sinkAdapter);
3792 return -1;
3793 }
3794
3795 return 0;
3796 }
3797
PrepareDeviceOffload(struct Userdata * u)3798 static int32_t PrepareDeviceOffload(struct Userdata *u)
3799 {
3800 const char *adapterName = safeProplistGets(u->sink->proplist, PA_PROP_DEVICE_STRING, "");
3801 const char *filePath = safeProplistGets(u->sink->proplist, "filePath", "");
3802 const char *deviceNetworkId = safeProplistGets(u->sink->proplist, "NetworkId", "");
3803 AUDIO_INFO_LOG("PrepareDeviceOffload enter, deviceClass %d, filePath %s",
3804 u->offload.sinkAdapter->deviceClass, filePath);
3805 SinkAttr sample_attrs;
3806 int32_t ret;
3807
3808 enum HdiAdapterFormat format = ConvertPaToHdiAdapterFormat(u->ss.format);
3809 sample_attrs.format = format;
3810 AUDIO_INFO_LOG("PrepareDeviceOffload audiorenderer format: %d ,adapterName %s",
3811 sample_attrs.format, GetDeviceClass(u->offload.sinkAdapter->deviceClass));
3812 sample_attrs.adapterName = adapterName;
3813 sample_attrs.openMicSpeaker = u->open_mic_speaker;
3814 sample_attrs.sampleRate = u->ss.rate;
3815 sample_attrs.channel = u->ss.channels;
3816 sample_attrs.volume = MAX_SINK_VOLUME_LEVEL;
3817 sample_attrs.filePath = filePath;
3818 sample_attrs.deviceNetworkId = deviceNetworkId;
3819 sample_attrs.deviceType = u->deviceType;
3820
3821 ret = u->offload.sinkAdapter->RendererSinkInit(u->offload.sinkAdapter, &sample_attrs);
3822 if (ret != 0) {
3823 AUDIO_ERR_LOG("PrepareDeviceOffload audiorenderer Init failed!");
3824 return -1;
3825 }
3826
3827 return 0;
3828 }
3829
PrepareDeviceMultiChannel(struct Userdata * u,struct RendererSinkAdapter * sinkAdapter,const char * filePath)3830 static int32_t PrepareDeviceMultiChannel(struct Userdata *u, struct RendererSinkAdapter *sinkAdapter,
3831 const char *filePath)
3832 {
3833 int32_t ret;
3834
3835 enum HdiAdapterFormat format = ConvertPaToHdiAdapterFormat(u->ss.format);
3836
3837 u->multiChannel.sample_attrs.format = format;
3838 u->multiChannel.sample_attrs.sampleRate = u->ss.rate;
3839 AUDIO_INFO_LOG("PrepareDeviceMultiChannel format: %d ,adapterName %s",
3840 u->multiChannel.sample_attrs.format, GetDeviceClass(sinkAdapter->deviceClass));
3841 u->multiChannel.sample_attrs.adapterName = u->adapterName;
3842 u->multiChannel.sample_attrs.openMicSpeaker = u->open_mic_speaker;
3843 u->multiChannel.sample_attrs.sampleRate = u->ss.rate;
3844 u->multiChannel.sample_attrs.channel = DEFAULT_MULTICHANNEL_NUM;
3845 u->multiChannel.sample_attrs.channelLayout = DEFAULT_MULTICHANNEL_CHANNELLAYOUT;
3846 u->multiChannel.sinkChannel = DEFAULT_MULTICHANNEL_NUM;
3847 u->multiChannel.sinkChannelLayout = DEFAULT_MULTICHANNEL_CHANNELLAYOUT;
3848 u->multiChannel.sample_attrs.volume = MAX_SINK_VOLUME_LEVEL;
3849 u->multiChannel.sample_attrs.filePath = filePath;
3850 u->multiChannel.sample_attrs.deviceNetworkId = u->deviceNetworkId;
3851 u->multiChannel.sample_attrs.deviceType = u->deviceType;
3852
3853 ret = sinkAdapter->RendererSinkInit(sinkAdapter, &u->multiChannel.sample_attrs);
3854 if (ret != 0) {
3855 AUDIO_ERR_LOG("PrepareDeviceMultiChannel Init failed!");
3856 return -1;
3857 }
3858 u->multiChannel.isHDISinkInited = true;
3859 AUDIO_DEBUG_LOG("PrepareDeviceMultiChannel init success");
3860 return 0;
3861 }
3862
PaHdiSinkUserdataInit(struct Userdata * u)3863 static void PaHdiSinkUserdataInit(struct Userdata *u)
3864 {
3865 u->format = u->ss.format;
3866 u->processLen = IN_CHANNEL_NUM_MAX * DEFAULT_FRAMELEN;
3867 u->processSize = (uint32_t)u->processLen * sizeof(float);
3868 u->bufferAttr = pa_xnew0(BufferAttr, 1);
3869 u->bufferAttr->samplingRate = (int32_t)u->ss.rate;
3870 u->bufferAttr->frameLen = DEFAULT_FRAMELEN;
3871 u->bufferAttr->numChanIn = u->ss.channels;
3872 u->bufferAttr->numChanOut = u->ss.channels;
3873 u->bufferAttr->bufOutUsed = true;
3874 u->sinkSceneMode = -1;
3875 u->sinkSceneType = -1;
3876 }
3877
PaHdiSinkInit(struct Userdata * u,pa_modargs * ma,const char * driver)3878 static pa_sink *PaHdiSinkInit(struct Userdata *u, pa_modargs *ma, const char *driver)
3879 {
3880 pa_sink_new_data data;
3881 pa_module *m;
3882 pa_sink *sink = NULL;
3883
3884 m = u->module;
3885 u->ss = m->core->default_sample_spec;
3886 u->map = m->core->default_channel_map;
3887 if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->ss, &u->map, PA_CHANNEL_MAP_DEFAULT) < 0) {
3888 AUDIO_ERR_LOG("Failed to parse sample specification and channel map");
3889 goto fail;
3890 }
3891
3892 AUDIO_INFO_LOG("Initializing HDI rendering device with rate: %{public}d, channels: %{public}d",
3893 u->ss.rate, u->ss.channels);
3894 if (PrepareDevice(u, pa_modargs_get_value(ma, "file_path", "")) < 0) { goto fail; }
3895
3896 u->primary.prewrite = 0;
3897 if (u->offload_enable && !strcmp(GetDeviceClass(u->primary.sinkAdapter->deviceClass), DEVICE_CLASS_PRIMARY)) {
3898 u->primary.prewrite = u->block_usec * 7; // 7 frame, set cache len in hdi, avoid pop
3899 }
3900
3901 AUDIO_DEBUG_LOG("Initialization of HDI rendering device[%{public}s] completed", u->adapterName);
3902 pa_sink_new_data_init(&data);
3903 data.driver = driver;
3904 data.module = m;
3905
3906 PaHdiSinkUserdataInit(u);
3907 pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
3908 pa_sink_new_data_set_sample_spec(&data, &u->ss);
3909 pa_sink_new_data_set_channel_map(&data, &u->map);
3910 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING,
3911 (u->adapterName ? u->adapterName : DEFAULT_AUDIO_DEVICE_NAME));
3912 pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "HDI sink is %s",
3913 (u->adapterName ? u->adapterName : DEFAULT_AUDIO_DEVICE_NAME));
3914 pa_proplist_sets(data.proplist, "filePath", pa_modargs_get_value(ma, "file_path", ""));
3915 pa_proplist_sets(data.proplist, "networkId", pa_modargs_get_value(ma, "network_id", DEFAULT_DEVICE_NETWORKID));
3916
3917 if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
3918 AUDIO_ERR_LOG("Invalid properties");
3919 pa_sink_new_data_done(&data);
3920 goto fail;
3921 }
3922
3923 if (u->fixed_latency) {
3924 sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE | PA_SINK_LATENCY);
3925 } else {
3926 sink = pa_sink_new(m->core, &data,
3927 PA_SINK_HARDWARE | PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY);
3928 }
3929 pa_sink_new_data_done(&data);
3930
3931 return sink;
3932
3933 fail:
3934 AUDIO_ERR_LOG("PaHdiSinkInit fail");
3935 return NULL;
3936 }
3937
PaHdiSinkNewInitThreadMultiChannel(pa_module * m,pa_modargs * ma,struct Userdata * u)3938 static int32_t PaHdiSinkNewInitThreadMultiChannel(pa_module *m, pa_modargs *ma, struct Userdata *u)
3939 {
3940 int ret;
3941 pa_atomic_store(&u->multiChannel.dflag, 0);
3942 u->multiChannel.msgq = pa_asyncmsgq_new(0);
3943 u->multiChannel.dq = pa_asyncmsgq_new(0);
3944 ret = LoadSinkAdapter(DEVICE_CLASS_MULTICHANNEL, "LocalDevice", &u->multiChannel.sinkAdapter);
3945 if (ret) {
3946 AUDIO_ERR_LOG("Load mch adapter failed");
3947 return -1;
3948 }
3949 if (PrepareDeviceMultiChannel(u, u->multiChannel.sinkAdapter, pa_modargs_get_value(ma, "file_path", "")) < 0) {
3950 return -1;
3951 }
3952
3953 u->multiChannel.used = true;
3954
3955 u->multiChannel.chunk.memblock = pa_memblock_new(u->sink->core->mempool, -1); // -1 == pa_mempool_block_size_max
3956
3957 return 0;
3958 }
3959
PaHdiSinkNewInitThread(pa_module * m,pa_modargs * ma,struct Userdata * u)3960 static int32_t PaHdiSinkNewInitThread(pa_module *m, pa_modargs *ma, struct Userdata *u)
3961 {
3962 char *paThreadName = NULL;
3963
3964 // offload
3965 const char *deviceClass = GetDeviceClass(u->primary.sinkAdapter->deviceClass);
3966 if (!strcmp(u->sink->name, OFFLOAD_SINK_NAME) && u->offload_enable) {
3967 AUDIO_DEBUG_LOG("PaHdiSinkNew device[%s] sink[%s] init offload thread", deviceClass, u->sink->name);
3968 int32_t ret = LoadSinkAdapter(DEVICE_CLASS_OFFLOAD, "LocalDevice", &u->offload.sinkAdapter);
3969 if (ret) {
3970 AUDIO_ERR_LOG("Load adapter failed");
3971 return -1;
3972 }
3973 u->offload.msgq = pa_asyncmsgq_new(0);
3974 pa_atomic_store(&u->offload.hdistate, 0);
3975 u->offload.chunk.memblock = pa_memblock_new(u->sink->core->mempool,
3976 pa_usec_to_bytes(200 * PA_USEC_PER_MSEC, &u->sink->sample_spec)); // 200ms for max len once offload render
3977 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_LATE,
3978 (pa_hook_cb_t)SinkInputMoveStartCb, u);
3979 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], PA_HOOK_NORMAL,
3980 (pa_hook_cb_t)SinkInputStateChangedCb, u);
3981 } else {
3982 AUDIO_INFO_LOG("PaHdiSinkNew device[%s] sink[%s] skip offload thread", deviceClass, u->sink->name);
3983 }
3984
3985 if (!strcmp(u->sink->name, MCH_SINK_NAME)) {
3986 PaHdiSinkNewInitThreadMultiChannel(m, ma, u);
3987 u->multichannel_enable = true;
3988 } else {
3989 u->multichannel_enable = false;
3990 }
3991
3992 if (!strcmp(u->sink->name, "Speaker") || !strcmp(u->sink->name, MCH_SINK_NAME)
3993 || !strcmp(u->sink->name, OFFLOAD_SINK_NAME)) {
3994 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_EARLY,
3995 (pa_hook_cb_t)SinkInputPutCb, u);
3996 }
3997
3998 paThreadName = "OS_ProcessData";
3999 if (!(u->thread = pa_thread_new(paThreadName, ThreadFuncRendererTimerBus, u))) {
4000 AUDIO_ERR_LOG("Failed to create bus thread.");
4001 return -1;
4002 }
4003
4004 return 0;
4005 }
4006
PaHdiSinkNewInitUserData(pa_module * m,pa_modargs * ma,struct Userdata * u)4007 static int32_t PaHdiSinkNewInitUserData(pa_module *m, pa_modargs *ma, struct Userdata *u)
4008 {
4009 u->core = m->core;
4010 u->module = m;
4011
4012 pa_memchunk_reset(&u->memchunk);
4013 u->rtpoll = pa_rtpoll_new();
4014 u->primary.msgq = pa_asyncmsgq_new(0);
4015 pthread_rwlock_init(&u->rwlockSleep, NULL);
4016 pthread_mutex_init(&u->mutexPa, NULL);
4017 pthread_mutex_init(&u->mutexPa2, NULL);
4018
4019 if (pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll) < 0) {
4020 AUDIO_ERR_LOG("pa_thread_mq_init() failed.");
4021 return -1;
4022 }
4023
4024 AUDIO_DEBUG_LOG("Load sink adapter");
4025 int32_t ret = LoadSinkAdapter(pa_modargs_get_value(ma, "device_class", DEFAULT_DEVICE_CLASS),
4026 pa_modargs_get_value(ma, "network_id", DEFAULT_DEVICE_NETWORKID), &u->primary.sinkAdapter);
4027 if (ret) {
4028 AUDIO_ERR_LOG("Load adapter failed");
4029 return -1;
4030 }
4031 if (pa_modargs_get_value_u32(ma, "fixed_latency", &u->fixed_latency) < 0) {
4032 AUDIO_ERR_LOG("Failed to parse fixed latency argument.");
4033 return -1;
4034 }
4035 if (pa_modargs_get_value_s32(ma, "device_type", &u->deviceType) < 0) {
4036 AUDIO_ERR_LOG("Failed to parse deviceType argument.");
4037 return -1;
4038 }
4039
4040 u->adapterName = pa_modargs_get_value(ma, "adapter_name", DEFAULT_DEVICE_CLASS);
4041 u->sink_latency = 0;
4042 if (pa_modargs_get_value_u32(ma, "sink_latency", &u->sink_latency) < 0) {
4043 AUDIO_ERR_LOG("No sink_latency argument.");
4044 }
4045
4046 u->deviceNetworkId = pa_modargs_get_value(ma, "network_id", DEFAULT_DEVICE_NETWORKID);
4047
4048 if (pa_modargs_get_value_u32(ma, "render_in_idle_state", &u->render_in_idle_state) < 0) {
4049 AUDIO_ERR_LOG("Failed to parse render_in_idle_state argument.");
4050 return -1;
4051 }
4052
4053 if (pa_modargs_get_value_u32(ma, "open_mic_speaker", &u->open_mic_speaker) < 0) {
4054 AUDIO_ERR_LOG("Failed to parse open_mic_speaker argument.");
4055 return -1;
4056 }
4057
4058 u->test_mode_on = false;
4059 if (pa_modargs_get_value_boolean(ma, "test_mode_on", &u->test_mode_on) < 0) {
4060 AUDIO_INFO_LOG("No test_mode_on arg. Normal mode it is.");
4061 }
4062
4063 return 0;
4064 }
4065
PaHdiSinkNewInitUserDataAndSink(pa_module * m,pa_modargs * ma,const char * driver,struct Userdata * u)4066 static int32_t PaHdiSinkNewInitUserDataAndSink(pa_module *m, pa_modargs *ma, const char *driver, struct Userdata *u)
4067 {
4068 if (pa_modargs_get_value_boolean(ma, "offload_enable", &u->offload_enable) < 0) {
4069 AUDIO_ERR_LOG("Failed to parse offload_enable argument.");
4070 return -1;
4071 }
4072
4073 pa_atomic_store(&u->primary.dflag, 0);
4074 u->primary.dq = pa_asyncmsgq_new(0);
4075 CHECK_AND_RETURN_RET_LOG(u->primary.dq, -1, "Failed to create u->primary.dq");
4076
4077 u->sink = PaHdiSinkInit(u, ma, driver);
4078 if (!u->sink) {
4079 AUDIO_ERR_LOG("Failed to create sink object");
4080 return -1;
4081 }
4082
4083 u->sink->parent.process_msg = SinkProcessMsg;
4084 u->sink->set_state_in_io_thread = SinkSetStateInIoThreadCb;
4085 if (!u->fixed_latency) {
4086 u->sink->update_requested_latency = SinkUpdateRequestedLatencyCb;
4087 }
4088 u->sink->userdata = u;
4089
4090 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
4091 pa_sink_set_rtpoll(u->sink, u->rtpoll);
4092
4093 u->bytes_dropped = 0;
4094 u->buffer_size = DEFAULT_BUFFER_SIZE;
4095 if (pa_modargs_get_value_u32(ma, "buffer_size", &u->buffer_size) < 0) {
4096 AUDIO_ERR_LOG("Failed to parse buffer_size argument.");
4097 return -1;
4098 }
4099
4100 u->block_usec = pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec);
4101
4102 u->lastRecodedLatency = 0;
4103 u->continuesGetLatencyErrCount = 0;
4104 u->lastStreamAvailable = 0;
4105 u->streamAvailable = 0;
4106
4107 if (u->fixed_latency) {
4108 pa_sink_set_fixed_latency(u->sink, u->block_usec);
4109 } else {
4110 pa_sink_set_latency_range(u->sink, 0, u->block_usec);
4111 }
4112
4113 pa_sink_set_max_request(u->sink, u->buffer_size);
4114
4115 u->streamAvailableMap = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
4116 pa_xfree, pa_xfree);
4117
4118 return 0;
4119 }
4120
PaHdiSinkNew(pa_module * m,pa_modargs * ma,const char * driver)4121 pa_sink *PaHdiSinkNew(pa_module *m, pa_modargs *ma, const char *driver)
4122 {
4123 struct Userdata *u = NULL;
4124 char *hdiThreadName = NULL;
4125 char *hdiThreadNameMch = NULL;
4126
4127 pa_assert(m);
4128 pa_assert(ma);
4129
4130 u = pa_xnew0(struct Userdata, 1);
4131 pa_assert(u);
4132
4133 if (PaHdiSinkNewInitUserData(m, ma, u) < 0) {
4134 goto fail;
4135 }
4136
4137 if (PaHdiSinkNewInitUserDataAndSink(m, ma, driver, u) < 0) {
4138 goto fail;
4139 }
4140
4141 int32_t ret = PaHdiSinkNewInitThread(m, ma, u);
4142 if (ret) {
4143 AUDIO_ERR_LOG("PaHdiSinkNewInitThread failed");
4144 goto fail;
4145 }
4146
4147 if (u->test_mode_on) {
4148 u->writeCount = 0;
4149 u->renderCount = 0;
4150 hdiThreadName = "OS_WriteHdiTest";
4151 if (!(u->primary.thread_hdi = pa_thread_new(hdiThreadName, TestModeThreadFuncWriteHDI, u))) {
4152 AUDIO_ERR_LOG("Failed to test-mode-write-hdi thread.");
4153 goto fail;
4154 }
4155 } else {
4156 hdiThreadName = "OS_WriteHdi";
4157 if (!(u->primary.thread_hdi = pa_thread_new(hdiThreadName, ThreadFuncWriteHDI, u))) {
4158 AUDIO_ERR_LOG("Failed to write-hdi-primary2 thread.");
4159 goto fail;
4160 }
4161
4162 if (!strcmp(u->sink->name, MCH_SINK_NAME)) {
4163 hdiThreadNameMch = "OS_WriteHdiMch";
4164 if (!(u->multiChannel.thread_hdi = pa_thread_new(hdiThreadNameMch, ThreadFuncWriteHDIMultiChannel, u))) {
4165 AUDIO_ERR_LOG("Failed to write-hdi-multichannel thread.");
4166 goto fail;
4167 }
4168 }
4169 }
4170
4171 u->primary.writeTime = DEFAULT_WRITE_TIME;
4172 u->multiChannel.writeTime = DEFAULT_WRITE_TIME;
4173 pa_sink_put(u->sink);
4174
4175 return u->sink;
4176 fail:
4177 AUDIO_ERR_LOG("PaHdiSinkNew failed, free userdata");
4178 UserdataFree(u);
4179
4180 return NULL;
4181 }
4182
UserdataFreeOffload(struct Userdata * u)4183 static void UserdataFreeOffload(struct Userdata *u)
4184 {
4185 if (u->offload.msgq) {
4186 pa_asyncmsgq_unref(u->offload.msgq);
4187 }
4188
4189 if (u->offload.sinkAdapter) {
4190 u->offload.sinkAdapter->RendererSinkStop(u->offload.sinkAdapter);
4191 OffloadUnlock(u);
4192 u->offload.sinkAdapter->RendererSinkDeInit(u->offload.sinkAdapter);
4193 UnLoadSinkAdapter(u->offload.sinkAdapter);
4194 }
4195
4196 if (u->offload.chunk.memblock) {
4197 pa_memblock_unref(u->offload.chunk.memblock);
4198 }
4199 }
4200
UserdataFreeMultiChannel(struct Userdata * u)4201 static void UserdataFreeMultiChannel(struct Userdata *u)
4202 {
4203 if (u->multiChannel.msgq) {
4204 pa_asyncmsgq_unref(u->multiChannel.msgq);
4205 }
4206
4207 if (u->multiChannel.dq) {
4208 pa_asyncmsgq_unref(u->multiChannel.dq);
4209 }
4210
4211 if (u->multiChannel.sinkAdapter) {
4212 u->multiChannel.sinkAdapter->RendererSinkStop(u->multiChannel.sinkAdapter);
4213 u->multiChannel.sinkAdapter->RendererSinkDeInit(u->multiChannel.sinkAdapter);
4214 UnLoadSinkAdapter(u->multiChannel.sinkAdapter);
4215 }
4216
4217 if (u->multiChannel.chunk.memblock) {
4218 pa_memblock_unref(u->multiChannel.chunk.memblock);
4219 }
4220 }
4221
UserdataFreeThread(struct Userdata * u)4222 static void UserdataFreeThread(struct Userdata *u)
4223 {
4224 if (u->thread) {
4225 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
4226 pa_thread_free(u->thread);
4227 }
4228
4229 if (u->offload.thread) {
4230 pa_asyncmsgq_send(u->offload.msgq, NULL, QUIT, NULL, 0, NULL);
4231 pa_thread_free(u->offload.thread);
4232 }
4233
4234 if (u->multiChannel.thread) {
4235 pa_asyncmsgq_send(u->multiChannel.msgq, NULL, QUIT, NULL, 0, NULL);
4236 pa_thread_free(u->multiChannel.thread);
4237 }
4238
4239 if (u->multiChannel.thread_hdi) {
4240 pa_asyncmsgq_post(u->multiChannel.dq, NULL, QUIT, NULL, 0, NULL, NULL);
4241 pa_thread_free(u->multiChannel.thread_hdi);
4242 }
4243
4244 if (u->primary.thread) {
4245 pa_asyncmsgq_send(u->primary.msgq, NULL, QUIT, NULL, 0, NULL);
4246 pa_thread_free(u->primary.thread);
4247 }
4248
4249 if (u->primary.thread_hdi) {
4250 pa_asyncmsgq_post(u->primary.dq, NULL, QUIT, NULL, 0, NULL, NULL);
4251 pa_thread_free(u->primary.thread_hdi);
4252 }
4253
4254 pa_thread_mq_done(&u->thread_mq);
4255 }
4256
FreeBufferAttr(struct Userdata * u)4257 static bool FreeBufferAttr(struct Userdata *u)
4258 {
4259 // free heap allocated in userdata init
4260 if (u->bufferAttr == NULL) {
4261 pa_xfree(u);
4262 AUDIO_DEBUG_LOG("buffer attr is null, free done");
4263 return false;
4264 }
4265 FreeEffectBuffer(u);
4266
4267 pa_xfree(u->bufferAttr);
4268 u->bufferAttr = NULL;
4269 return true;
4270 }
4271
UserdataFree(struct Userdata * u)4272 static void UserdataFree(struct Userdata *u)
4273 {
4274 if (u == NULL) {
4275 AUDIO_INFO_LOG("Userdata is null, free done");
4276 return;
4277 }
4278
4279 if (u->sink) {
4280 pa_sink_unlink(u->sink);
4281 }
4282
4283 UserdataFreeThread(u);
4284
4285 if (u->sink) {
4286 pa_sink_unref(u->sink);
4287 }
4288
4289 if (u->memchunk.memblock) {
4290 pa_memblock_unref(u->memchunk.memblock);
4291 }
4292
4293 if (u->rtpoll) {
4294 pa_rtpoll_free(u->rtpoll);
4295 }
4296
4297 UserdataFreeOffload(u);
4298 UserdataFreeMultiChannel(u);
4299
4300 if (u->primary.msgq) {
4301 pa_asyncmsgq_unref(u->primary.msgq);
4302 }
4303
4304 if (u->primary.dq) {
4305 pa_asyncmsgq_unref(u->primary.dq);
4306 }
4307
4308 if (u->primary.sinkAdapter) {
4309 u->primary.sinkAdapter->RendererSinkStop(u->primary.sinkAdapter);
4310 u->primary.sinkAdapter->RendererSinkDeInit(u->primary.sinkAdapter);
4311 UnLoadSinkAdapter(u->primary.sinkAdapter);
4312 }
4313
4314 if (!FreeBufferAttr(u)) {
4315 return;
4316 }
4317
4318 if (u->streamAvailableMap) {
4319 pa_hashmap_free(u->streamAvailableMap);
4320 }
4321
4322 pa_xfree(u);
4323
4324 AUDIO_DEBUG_LOG("UserdataFree done");
4325 }
4326
PaHdiSinkFree(pa_sink * s)4327 void PaHdiSinkFree(pa_sink *s)
4328 {
4329 AUTO_CTRACE("PaHdiSinkFree");
4330 AUDIO_INFO_LOG("PaHdiSinkFree, free userdata");
4331 struct Userdata *u = NULL;
4332
4333 pa_sink_assert_ref(s);
4334 pa_assert_se(u = s->userdata);
4335
4336 UserdataFree(u);
4337 }
4338