• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19 
20 #undef LOG_TAG
21 #define LOG_TAG "ModuleSplitStreamSink"
22 
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <math.h>
29 #include "securec.h"
30 
31 #include <pulse/rtclock.h>
32 #include <pulse/timeval.h>
33 #include <pulse/util.h>
34 #include <pulse/xmalloc.h>
35 
36 #include <pulsecore/i18n.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/sink.h>
39 #include <pulsecore/module.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/modargs.h>
42 #include <pulsecore/log.h>
43 #include <pulsecore/thread.h>
44 #include <pulsecore/thread-mq.h>
45 #include <pulsecore/rtpoll.h>
46 #include <pulsecore/mix.h>
47 #include <pulsecore/memblockq.h>
48 #include <pulsecore/memblock.h>
49 
50 #include <pthread.h>
51 #include "audio_pulseaudio_log.h"
52 #include "audio_schedule.h"
53 #include "audio_utils_c.h"
54 #include "volume_tools_c.h"
55 #include "audio_volume_c.h"
56 #include "intf_def.h"
57 #include "sink/sink_intf.h"
58 
59 #define DEFAULT_SINK_NAME "hdi_output"
60 #define DEFAULT_DEVICE_CLASS "primary"
61 #define DEFAULT_DEVICE_NETWORKID "LocalDevice"
62 #define DEFAULT_BUFFER_SIZE 8192
63 #define MAX_SINK_VOLUME_LEVEL 1.0
64 #define MIX_BUFFER_LENGTH (pa_page_size())
65 #define MAX_REWIND (7000 * PA_USEC_PER_MSEC)
66 #define USEC_PER_SEC 1000000
67 #define SCENE_TYPE_NUM 7
68 #define PA_ERR (-1)
69 #define MAX_PARTS 10
70 #define EPSILON (1e-6f)
71 
72 #define STREAM_TYPE_MEDIA "1"
73 #define STREAM_TYPE_COMMUNICATION "2"
74 #define STREAM_TYPE_NAVIGATION "13"
75 #define STREAM_TYPE_VIDEO_COMMUNICATION "17"
76 
77 char *g_splitArr[MAX_PARTS];
78 int g_splitNums = 0;
79 
80 // count the num of empty chunk sent in each stream.
81 int16_t g_noDataCount[MAX_PARTS];
82 const int16_t MAX_EMPTY_CHUNK_NUM = 150;
83 bool g_needEmptyChunk = true;
84 
85 const char *SPLIT_MODE;
86 const uint32_t SPLIT_ONE_STREAM = 1;
87 const uint32_t SPLIT_TWO_STREAM = 2;
88 const uint32_t SPLIT_THREE_STREAM = 3;
89 
90 PA_MODULE_AUTHOR("OpenHarmony");
91 PA_MODULE_DESCRIPTION(_("Split Stream Sink"));
92 PA_MODULE_VERSION(PACKAGE_VERSION);
93 PA_MODULE_LOAD_ONCE(false);
94 PA_MODULE_USAGE(
95         "sink_name=<name of sink> "
96         "sink_properties=<properties for the sink> "
97         "format=<sample format> "
98         "rate=<sample rate> "
99         "channels=<number of channels> "
100         "channel_map=<channel map>"
101         "buffer_size=<custom buffer size>"
102         "formats=<semi-colon separated sink formats>");
103 
104 static ssize_t SplitRenderWrite(struct SinkAdapter *sinkAdapter, pa_memchunk *pchunk, char *streamType);
105 
106 struct userdata {
107     pa_core *core;
108     pa_module *module;
109     pa_sink *sink;
110     pa_thread *thread;
111     pa_thread_mq thread_mq;
112     pa_rtpoll *rtpoll;
113     uint32_t buffer_size;
114     pa_usec_t block_usec;
115     pa_usec_t timestamp;
116     pa_idxset *formats;
117     pa_thread *thread_split_hdi;
118     bool isHDISinkStarted;
119     struct SinkAdapter *sinkAdapter;
120     pa_asyncmsgq *dq;
121     pa_atomic_t dflag;
122     pa_usec_t writeTime;
123     pa_usec_t prewrite;
124     pa_sink_state_t previousState;
125     pa_usec_t timestampLastLog;
126     const char *deviceNetworkId;
127     const char *adapterName;
128     uint32_t open_mic_speaker;
129     pa_sample_spec ss;
130     pa_channel_map map;
131     int32_t deviceType;
132     size_t bytesDropped;
133     uint32_t writeCount;
134     uint32_t renderCount;
135     uint32_t fixed_latency;
136     pa_usec_t lastProcessDataTime;
137     uint32_t renderInIdleState;
138     uint32_t defaultAdapterEnable;
139 };
140 
141 struct NumPeekedInfo {
142     unsigned numAll;
143     unsigned numNotSilence;
144 };
145 
146 static const char * const VALID_MODARGS[] = {
147     "sink_name",
148     "device_class",
149     "sink_properties",
150     "format",
151     "rate",
152     "channels",
153     "channel_map",
154     "buffer_size",
155     "file_path",
156     "adapter_name",
157     "fixed_latency",
158     "sink_latency",
159     "render_in_idle_state",
160     "open_mic_speaker",
161     "test_mode_on",
162     "network_id",
163     "device_type",
164     "offload_enable",
165     "default_adapter_enable",
166     "split_mode",
167     "need_empty_chunk",
168     NULL
169 };
170 
171 char *const SCENE_TYPE_SET[SCENE_TYPE_NUM] = {"SCENE_MUSIC", "SCENE_GAME", "SCENE_MOVIE", "SCENE_SPEECH", "SCENE_RING",
172     "SCENE_OTHERS", "EFFECT_NONE"};
173 
174 enum {
175     HDI_INIT,
176     HDI_DEINIT,
177     HDI_START,
178     HDI_STOP,
179     HDI_RENDER,
180     QUIT,
181     HDI_RENDER_MEDIA,
182     HDI_RENDER_NAVIGATION,
183     HDI_RENDER_COMMUNICATION
184 };
185 
ConvertPaToHdiAdapterFormat(pa_sample_format_t format)186 static enum AudioSampleFormatIntf ConvertPaToHdiAdapterFormat(pa_sample_format_t format)
187 {
188     enum AudioSampleFormatIntf adapterFormat;
189     switch (format) {
190         case PA_SAMPLE_U8:
191             adapterFormat = SAMPLE_U8;
192             break;
193         case PA_SAMPLE_S16LE:
194             adapterFormat = SAMPLE_S16;
195             break;
196         case PA_SAMPLE_S24LE:
197             adapterFormat = SAMPLE_S24;
198             break;
199         case PA_SAMPLE_S32LE:
200             adapterFormat = SAMPLE_S32;
201             break;
202         default:
203             adapterFormat = INVALID_WIDTH;
204             break;
205     }
206 
207     return adapterFormat;
208 }
209 
ConvertToSplitArr(const char * str)210 static void ConvertToSplitArr(const char *str)
211 {
212     AUDIO_INFO_LOG("start ConvertToSplitArr");
213     g_splitNums = 0;
214     for (int i = 0; i < MAX_PARTS; ++i) {
215         g_splitArr[i] = NULL;
216     }
217     char *token;
218     char *copy = strdup(str);
219     CHECK_AND_RETURN_LOG(copy != NULL, "copy is null");
220     int count = 0;
221     token = strtok(copy, ":");
222     while (token != NULL && count < MAX_PARTS) {
223         g_splitArr[count] = (char *)malloc(strlen(token) + 1);
224         if (g_splitArr[count] != NULL) {
225             if (strcpy_s(g_splitArr[count], strlen(token) + 1, token) != 0) {
226                 AUDIO_ERR_LOG("strcpy_s failed.");
227             };
228             count++;
229         } else {
230             AUDIO_ERR_LOG("Memory allocation failed.\n");
231             break;
232         }
233         token = strtok(NULL, ":");
234     }
235     g_splitNums = count;
236     free(copy);
237 }
238 
SinkProcessMsg(pa_msgobject * o,int code,void * data,int64_t offset,pa_memchunk * chunk)239 static int SinkProcessMsg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk)
240 {
241     switch (code) {
242         case PA_SINK_MESSAGE_GET_LATENCY:
243             *((int64_t*) data) = 0;
244             return 0;
245         default:
246             break;
247     }
248 
249     return pa_sink_process_msg(o, code, data, offset, chunk);
250 }
251 
252 /* Called from the IO thread. */
SinkSetStateInIoThreadCb(pa_sink * s,pa_sink_state_t new_state,pa_suspend_cause_t new_suspend_cause)253 static int SinkSetStateInIoThreadCb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause)
254 {
255     struct userdata *u;
256 
257     CHECK_AND_RETURN_RET_LOG(s != NULL, -1, "s is null");
258     pa_assert_se(u = s->userdata);
259     CHECK_AND_RETURN_RET_LOG(u != NULL, -1, "u is null");
260 
261     if (s->thread_info.state == PA_SINK_SUSPENDED || s->thread_info.state == PA_SINK_INIT) {
262         if (PA_SINK_IS_OPENED(new_state)) {
263             u->timestamp = pa_rtclock_now();
264         }
265     }
266 
267     return 0;
268 }
269 
SinkUpdateRequestedLatencyCb(pa_sink * s)270 static void SinkUpdateRequestedLatencyCb(pa_sink *s)
271 {
272     struct userdata *u;
273     size_t nbytes;
274     CHECK_AND_RETURN_LOG(s != NULL, "s is null");
275     pa_sink_assert_ref(s);
276     pa_assert_se(u = s->userdata);
277     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
278 
279     u->block_usec = pa_sink_get_requested_latency_within_thread(s);
280 
281     if (u->block_usec == (pa_usec_t) -1) {
282         u->block_usec = s->thread_info.max_latency;
283     }
284 
285     nbytes = pa_usec_to_bytes(u->block_usec, &s->sample_spec);
286     pa_sink_set_max_rewind_within_thread(s, nbytes);
287     pa_sink_set_max_request_within_thread(s, nbytes);
288 }
289 
SinkReconfigureCb(pa_sink * s,pa_sample_spec * spec,bool passthrough)290 static void SinkReconfigureCb(pa_sink *s, pa_sample_spec *spec, bool passthrough)
291 {
292     CHECK_AND_RETURN_LOG(s != NULL, "s is null");
293     s->sample_spec = *spec;
294 }
295 
SinkSetFormatsCb(pa_sink * s,pa_idxset * formats)296 static bool SinkSetFormatsCb(pa_sink *s, pa_idxset *formats)
297 {
298     CHECK_AND_RETURN_RET_LOG(s != NULL, false, "s is null");
299     CHECK_AND_RETURN_RET_LOG(formats != NULL, false, "formats is null");
300     struct userdata *u = s->userdata;
301 
302     CHECK_AND_RETURN_RET_LOG(u != NULL, false, "u is null");
303 
304     pa_idxset_free(u->formats, (pa_free_cb_t) pa_format_info_free);
305     u->formats = pa_idxset_copy(formats, (pa_copy_func_t) pa_format_info_copy);
306 
307     return true;
308 }
309 
SinkGetFormatsCb(pa_sink * s)310 static pa_idxset* SinkGetFormatsCb(pa_sink *s)
311 {
312     CHECK_AND_RETURN_RET_LOG(s != NULL, NULL, "s is null");
313     struct userdata *u = s->userdata;
314 
315     CHECK_AND_RETURN_RET_LOG(u != NULL, NULL, "u is null");
316 
317     return pa_idxset_copy(u->formats, (pa_copy_func_t) pa_format_info_copy);
318 }
319 
ProcessRewind(struct userdata * u,pa_usec_t now)320 static void ProcessRewind(struct userdata *u, pa_usec_t now)
321 {
322     size_t rewindNbytes;
323     size_t inBuffer;
324     pa_usec_t delay;
325 
326     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
327     CHECK_AND_RETURN_LOG(u->sink != NULL, "sink is null");
328     rewindNbytes = u->sink->thread_info.rewind_nbytes;
329     if (!PA_SINK_IS_OPENED(u->sink->thread_info.state) || rewindNbytes == 0) {
330         goto do_nothing;
331     }
332     AUDIO_DEBUG_LOG("Requested to rewind %lu bytes.", (unsigned long) rewindNbytes);
333 
334     if (u->timestamp <= now) {
335         goto do_nothing;
336     }
337 
338     delay = u->timestamp - now;
339     inBuffer = pa_usec_to_bytes(delay, &u->sink->sample_spec);
340     if (inBuffer == 0) {
341         goto do_nothing;
342     }
343 
344     if (rewindNbytes > inBuffer) {
345         rewindNbytes = inBuffer;
346     }
347 
348     pa_sink_process_rewind(u->sink, rewindNbytes);
349     u->timestamp -= pa_bytes_to_usec(rewindNbytes, &u->sink->sample_spec);
350 
351     AUDIO_DEBUG_LOG("Rewound %lu bytes.", (unsigned long) rewindNbytes);
352     return;
353 
354 do_nothing:
355     pa_sink_process_rewind(u->sink, 0);
356 }
357 
StartSplitStreamHdiIfRunning(struct userdata * u)358 static void StartSplitStreamHdiIfRunning(struct userdata *u)
359 {
360     AUTO_CTRACE("split_stream_sink::StartPrimaryHdiIfRunning");
361     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
362     if (u->isHDISinkStarted) {
363         return;
364     }
365     CHECK_AND_RETURN_LOG(u->sinkAdapter != NULL, "sinkAdapter is null");
366     if (u->sinkAdapter->SinkAdapterStart(u->sinkAdapter)) {
367         AUDIO_ERR_LOG("split_stream_sink,audiorenderer control start failed!");
368         u->sinkAdapter->SinkAdapterDeInit(u->sinkAdapter);
369     } else {
370         u->isHDISinkStarted = true;
371         u->writeCount = 0;
372         u->renderCount = 0;
373         AUDIO_INFO_LOG("StartPrimaryHdiIfRunning, Successfully restarted HDI renderer");
374         u->renderInIdleState = 1;
375     }
376 }
377 
SplitSinkRenderInputsDrop(pa_sink * si,pa_mix_info * infoIn,unsigned n,pa_memchunk * chunkIn)378 static void SplitSinkRenderInputsDrop(pa_sink *si, pa_mix_info *infoIn, unsigned n, pa_memchunk *chunkIn)
379 {
380     CHECK_AND_RETURN_LOG(si != NULL, "s is null");
381     pa_sink_assert_io_context(si);
382     CHECK_AND_RETURN_LOG(chunkIn != NULL, "chunkIn is null");
383     CHECK_AND_RETURN_LOG(chunkIn->memblock != NULL, "chunkIn->memblock is null");
384     CHECK_AND_RETURN_LOG(chunkIn->length > 0, "chunkIn->length < 0");
385     AUTO_CTRACE("split_stream_sink::SplitSinkRenderInputsDrop:%u:len:%zu", n, chunkIn->length);
386 
387     /* We optimize for the case where the order of the inputs has not changed */
388 
389     pa_mix_info *infoCur = NULL;
390     pa_sink_input *sinkInput = NULL;
391     for (uint32_t k = 0; k < n; k++) {
392         sinkInput = infoIn[k].userdata;
393         pa_sink_input_assert_ref(sinkInput);
394         AUTO_CTRACE("hdi_sink::InnerCap:pa_sink_input_drop:%u:len:%zu", sinkInput->index, chunkIn->length);
395         pa_sink_input_drop(sinkInput, chunkIn->length);
396 
397         infoCur = infoIn + k;
398         if (infoCur) {
399             if (infoCur->chunk.memblock) {
400                 pa_memblock_unref(infoCur->chunk.memblock);
401                 pa_memchunk_reset(&infoCur->chunk);
402             }
403 
404             pa_sink_input_unref(infoCur->userdata);
405         }
406     }
407 }
408 
IsPeekCurrentSinkInput(char * streamType,const char * usageStr)409 static int IsPeekCurrentSinkInput(char *streamType, const char *usageStr)
410 {
411     CHECK_AND_RETURN_RET_LOG(usageStr != NULL, -1, "usageStr is null");
412     CHECK_AND_RETURN_RET_LOG(streamType != NULL, -1, "streamType is null");
413     int flag = 0;
414     if (g_splitNums == SPLIT_ONE_STREAM) {
415         flag = 1;
416     }
417 
418     if (g_splitNums == SPLIT_TWO_STREAM) {
419         if (strcmp(usageStr, STREAM_TYPE_NAVIGATION) && !strcmp(streamType, STREAM_TYPE_MEDIA)) {
420             flag = 1;
421         } else if (!strcmp(usageStr, STREAM_TYPE_NAVIGATION) && !strcmp(streamType, STREAM_TYPE_NAVIGATION)) {
422             flag = 1;
423         }
424     }
425 
426     if (g_splitNums == SPLIT_THREE_STREAM) {
427         if (strcmp(usageStr, STREAM_TYPE_NAVIGATION) && strcmp(usageStr, STREAM_TYPE_COMMUNICATION) &&
428             strcmp(usageStr, STREAM_TYPE_VIDEO_COMMUNICATION) && !strcmp(streamType, STREAM_TYPE_MEDIA)) {
429             flag = 1;
430         } else if (!strcmp(usageStr, STREAM_TYPE_NAVIGATION) && !strcmp(streamType, STREAM_TYPE_NAVIGATION)) {
431             flag = 1;
432         } else if ((!strcmp(usageStr, STREAM_TYPE_COMMUNICATION) ||
433             !strcmp(usageStr, STREAM_TYPE_VIDEO_COMMUNICATION)) &&
434             !strcmp(streamType, STREAM_TYPE_COMMUNICATION)) {
435             flag = 1;
436         }
437     }
438 
439     return flag;
440 }
441 
SafeProplistGets(const pa_proplist * p,const char * key,const char * defstr)442 static const char *SafeProplistGets(const pa_proplist *p, const char *key, const char *defstr)
443 {
444     const char *res = pa_proplist_gets(p, key);
445     if (res == NULL) {
446         return defstr;
447     }
448     return res;
449 }
450 
ProcessAudioVolume(pa_sink_input * sinkIn,size_t length,pa_memchunk * pchunk,pa_sink * si)451 static void ProcessAudioVolume(pa_sink_input *sinkIn, size_t length, pa_memchunk *pchunk, pa_sink *si)
452 {
453     AUTO_CTRACE("module_split_stream_sink::ProcessAudioVolume: len:%zu", length);
454     struct userdata *u;
455     CHECK_AND_RETURN_LOG(sinkIn != NULL, "sinkIn is null");
456     CHECK_AND_RETURN_LOG(pchunk != NULL, "pchunk is null");
457     CHECK_AND_RETURN_LOG(si != NULL, "si is null");
458     pa_assert_se(u = si->userdata);
459     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
460     const char *streamType = SafeProplistGets(sinkIn->proplist, "stream.type", "NULL");
461     const char *sessionIDStr = SafeProplistGets(sinkIn->proplist, "stream.sessionID", "NULL");
462     const char *deviceClass = u->sinkAdapter->deviceClass;
463     uint32_t sessionID = sessionIDStr != NULL ? (uint32_t)atoi(sessionIDStr) : 0;
464     struct VolumeValues volumes = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
465     float volumeEnd = GetCurVolume(sessionID, streamType, deviceClass, &volumes);
466     float volumeBeg = volumes.volumeHistory;
467     if (pa_memblock_is_silence(pchunk->memblock)) {
468         AUTO_CTRACE("module_split_stream_sink::ProcessAudioVolume: is_silence");
469         AUDIO_PRERELEASE_LOGI("pa_memblock_is_silence");
470     } else {
471         AudioRawFormat rawFormat;
472         rawFormat.format = (uint32_t)ConvertPaToHdiAdapterFormat(si->sample_spec.format);
473         rawFormat.channels = (uint32_t)si->sample_spec.channels;
474 
475         pa_memchunk_make_writable(pchunk, 0);
476         void *data = pa_memblock_acquire_chunk(pchunk);
477 
478         AUDIO_DEBUG_LOG("length:%{public}zu channels:%{public}d format:%{public}d"
479             " volumeBeg:%{public}f, volumeEnd:%{public}f",
480             length, rawFormat.channels, rawFormat.format, volumeBeg, volumeEnd);
481         int32_t ret = ProcessVol(data, length, rawFormat, volumeBeg, volumeEnd);
482         if (ret != 0) {
483             AUDIO_WARNING_LOG("ProcessVol failed:%{public}d", ret);
484         }
485         pa_memblock_release(pchunk->memblock);
486     }
487     if (fabs(volumeBeg - volumeEnd) > EPSILON) {
488         AUDIO_INFO_LOG("sessionID:%{public}u, volumeBeg:%{public}f, volumeEnd:%{public}f",
489             sessionID, volumeBeg, volumeEnd);
490         SetPreVolume(sessionID, volumeEnd);
491         MonitorVolume(sessionID, true);
492     }
493 }
494 
SplitFillMixInfo(pa_sink * s,size_t * length,pa_mix_info * info,unsigned maxInfo,char * streamType)495 static struct NumPeekedInfo SplitFillMixInfo(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxInfo,
496     char *streamType)
497 {
498     struct NumPeekedInfo resInfo = {0, 0};
499     CHECK_AND_RETURN_RET_LOG(s != NULL, resInfo, "s is null");
500     CHECK_AND_RETURN_RET_LOG(length != NULL, resInfo, "length is null");
501     AUTO_CTRACE("split_stream_sink::SplitFillMixInfo:len:%zu", *length);
502     pa_sink_input *i;
503     void *state = NULL;
504     size_t mixlength = *length;
505 
506     pa_sink_assert_ref(s);
507     pa_sink_assert_io_context(s);
508     CHECK_AND_RETURN_RET_LOG(info != NULL, resInfo, "info is null");
509 
510     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxInfo > 0) {
511         const char *usageStr = pa_proplist_gets(i->proplist, "stream.usage");
512         AUDIO_DEBUG_LOG("splitFillMixInfo usageStr = %{public}s, streamType = %{public}s", usageStr, streamType);
513         if (IsPeekCurrentSinkInput(streamType, usageStr) && i->thread_info.state == PA_SINK_INPUT_RUNNING) {
514             pa_sink_input_assert_ref(i);
515 
516             AUTO_CTRACE("module_split_stream_sink::splitFillMixInfo::pa_sink_input_peek:%u len:%zu", i->index, *length);
517             pa_sink_input_peek(i, *length, &info->chunk, &info->volume);
518 
519             if (mixlength == 0 || info->chunk.length < mixlength)
520                 mixlength = info->chunk.length;
521 
522             ProcessAudioVolume(i, mixlength, &info->chunk, s);
523 
524             if (!pa_memblock_is_silence(info->chunk.memblock)) {
525                 resInfo.numNotSilence++;
526             }
527 
528             info->userdata = pa_sink_input_ref(i);
529             pa_assert(info->chunk.memblock);
530             pa_assert(info->chunk.length > 0);
531 
532             info++;
533             resInfo.numAll++;
534             maxInfo--;
535         }
536     }
537 
538     if (mixlength > 0) {
539         *length = mixlength;
540     }
541     return resInfo;
542 }
543 
SplitSinkRenderMix(pa_sink * s,size_t length,pa_mix_info * info,unsigned n,pa_memchunk * result)544 static void SplitSinkRenderMix(pa_sink *s, size_t length, pa_mix_info *info, unsigned n, pa_memchunk *result)
545 {
546     CHECK_AND_RETURN_LOG(s != NULL, "s is null");
547     CHECK_AND_RETURN_LOG(info != NULL, "info is null");
548     CHECK_AND_RETURN_LOG(result != NULL, "result is null");
549     if (n == 0) {
550         *result = s->silence;
551         pa_memblock_ref(result->memblock);
552         if (result->length > length)
553             result->length = length;
554     } else if (n == 1) {
555         pa_cvolume volume;
556 
557         *result = info[0].chunk;
558         pa_memblock_ref(result->memblock);
559         if (result->length > length)
560             result->length = length;
561 
562         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
563 
564         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
565             pa_memblock_unref(result->memblock);
566             CHECK_AND_RETURN_LOG(s->core != NULL, "core is null");
567             pa_silence_memchunk_get(
568                 &s->core->silence_cache, s->core->mempool, result, &s->sample_spec, result->length);
569         } else if (!pa_cvolume_is_norm(&volume)) {
570             pa_memchunk_make_writable(result, 0);
571             pa_volume_memchunk(result, &s->sample_spec, &volume);
572         }
573     } else {
574         void *ptr;
575         CHECK_AND_RETURN_LOG(s->core != NULL, "core is null");
576         result->memblock = pa_memblock_new(s->core->mempool, length);
577 
578         ptr = pa_memblock_acquire(result->memblock);
579         result->length =
580             pa_mix(info, n, ptr, length, &s->sample_spec, &s->thread_info.soft_volume, s->thread_info.soft_muted);
581         pa_memblock_release(result->memblock);
582 
583         result->index = 0;
584     }
585 }
586 
SplitPaSinkRender(pa_sink * s,size_t length,pa_memchunk * result,char * streamType)587 static struct NumPeekedInfo SplitPaSinkRender(pa_sink *s, size_t length, pa_memchunk *result, char *streamType)
588 {
589     AUTO_CTRACE("module_split_stream_sink::SplitPaSinkRender:len:%zu", length);
590     pa_mix_info info[MAX_MIX_CHANNELS];
591     struct NumPeekedInfo resInfo = {0, 0};
592     size_t blockSizeMax;
593 
594     CHECK_AND_RETURN_RET_LOG(s != NULL, resInfo, "s is null");
595     pa_sink_assert_io_context(s);
596     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
597     pa_assert(pa_frame_aligned(length, &s->sample_spec));
598     CHECK_AND_RETURN_RET_LOG(result != NULL, resInfo, "result is null");
599 
600     pa_assert(!s->thread_info.rewind_requested);
601     pa_assert(s->thread_info.rewind_nbytes == 0);
602 
603     if (s->thread_info.state == PA_SINK_SUSPENDED) {
604         result->memblock = pa_memblock_ref(s->silence.memblock);
605         result->index = s->silence.index;
606         result->length = PA_MIN(s->silence.length, length);
607         return resInfo;
608     }
609 
610     pa_sink_ref(s);
611 
612     AUDIO_DEBUG_LOG("module_split_stream_sink, splitSinkRender in  length = %{public}zu", length);
613     if (length == 0) {
614         length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
615     }
616 
617     blockSizeMax = pa_mempool_block_size_max(s->core->mempool);
618     if (length > blockSizeMax)
619         length = pa_frame_align(blockSizeMax, &s->sample_spec);
620 
621     pa_assert(length > 0);
622 
623     resInfo = SplitFillMixInfo(s, &length, info, MAX_MIX_CHANNELS, streamType);
624     SplitSinkRenderMix(s, length, info, resInfo.numAll, result);
625 
626     SplitSinkRenderInputsDrop(s, info, resInfo.numAll, result);
627 
628     pa_sink_unref(s);
629     return resInfo;
630 }
631 
SplitSinkRenderIntoMix(pa_sink * s,size_t length,pa_mix_info * info,unsigned n,pa_memchunk * target)632 static void SplitSinkRenderIntoMix(pa_sink *s, size_t length, pa_mix_info *info, unsigned n, pa_memchunk *target)
633 {
634     CHECK_AND_RETURN_LOG(s != NULL, "s si null");
635     CHECK_AND_RETURN_LOG(target != NULL, "target si null");
636     if (n == 0) {
637         if (target->length > length)
638             target->length = length;
639 
640         pa_silence_memchunk(target, &s->sample_spec);
641     } else if (n == 1) {
642         pa_cvolume volume;
643 
644         if (target->length > length)
645             target->length = length;
646 
647         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
648 
649         if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) {
650             pa_silence_memchunk(target, &s->sample_spec);
651         } else {
652             pa_memchunk vChunk;
653 
654             vChunk = info[0].chunk;
655             pa_memblock_ref(vChunk.memblock);
656 
657             if (vChunk.length > length)
658                 vChunk.length = length;
659 
660             if (!pa_cvolume_is_norm(&volume)) {
661                 pa_memchunk_make_writable(&vChunk, 0);
662                 pa_volume_memchunk(&vChunk, &s->sample_spec, &volume);
663             }
664 
665             pa_memchunk_memcpy(target, &vChunk);
666             pa_memblock_unref(vChunk.memblock);
667         }
668     } else {
669         void *ptr;
670 
671         ptr = pa_memblock_acquire(target->memblock);
672 
673         target->length = pa_mix(info, n,
674                                 (uint8_t*) ptr + target->index, length,
675                                 &s->sample_spec,
676                                 &s->thread_info.soft_volume,
677                                 s->thread_info.soft_muted);
678 
679         pa_memblock_release(target->memblock);
680     }
681 }
682 
SplitPaSinkRenderInto(pa_sink * s,pa_memchunk * target,char * streamType)683 static void  SplitPaSinkRenderInto(pa_sink *s, pa_memchunk *target, char *streamType)
684 {
685     pa_mix_info info[MAX_MIX_CHANNELS];
686     size_t length;
687     size_t blockSizeMax;
688 
689     CHECK_AND_RETURN_LOG(s != NULL, "s si null");
690     pa_sink_assert_ref(s);
691     pa_sink_assert_io_context(s);
692     CHECK_AND_RETURN_LOG(target != NULL, "target si null");
693     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
694     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
695 
696     pa_assert(!s->thread_info.rewind_requested);
697     pa_assert(s->thread_info.rewind_nbytes == 0);
698 
699     if (s->thread_info.state == PA_SINK_SUSPENDED) {
700         pa_silence_memchunk(target, &s->sample_spec);
701         return;
702     }
703 
704     pa_sink_ref(s);
705 
706     length = target->length;
707     blockSizeMax = pa_mempool_block_size_max(s->core->mempool);
708     if (length > blockSizeMax)
709         length = pa_frame_align(blockSizeMax, &s->sample_spec);
710 
711     pa_assert(length > 0);
712 
713     struct NumPeekedInfo resInfo = SplitFillMixInfo(s, &length, info, MAX_MIX_CHANNELS, streamType);
714     SplitSinkRenderIntoMix(s, length, info, resInfo.numAll, target);
715 
716     SplitSinkRenderInputsDrop(s, info, resInfo.numAll, target);
717 
718     pa_sink_unref(s);
719 }
720 
SplitPaSinkRenderIntoFull(pa_sink * s,pa_memchunk * target,char * streamType)721 static void SplitPaSinkRenderIntoFull(pa_sink *s, pa_memchunk *target, char *streamType)
722 {
723     pa_memchunk chunk;
724     size_t l;
725     size_t d;
726 
727     CHECK_AND_RETURN_LOG(s != NULL, "s is null");
728     pa_sink_assert_io_context(s);
729     CHECK_AND_RETURN_LOG(target != NULL, "target is null");
730     CHECK_AND_RETURN_LOG(target->memblock != NULL, "target->memblock is null");
731     CHECK_AND_RETURN_LOG(target->length > 0, "target->length < 0");
732     pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
733 
734     if (s->thread_info.state == PA_SINK_SUSPENDED) {
735         pa_silence_memchunk(target, &s->sample_spec);
736         return;
737     }
738 
739     pa_sink_ref(s);
740 
741     l = target->length;
742     d = 0;
743     while (l > 0) {
744         chunk = *target;
745         chunk.index += d;
746         chunk.length -=d;
747 
748         SplitPaSinkRenderInto(s, &chunk, streamType);
749 
750         d += chunk.length;
751         l -= chunk.length;
752     }
753 
754     pa_sink_unref(s);
755 }
756 
SplitPaSinkRenderFull(pa_sink * s,size_t length,pa_memchunk * result,char * streamType)757 static struct NumPeekedInfo SplitPaSinkRenderFull(pa_sink *s, size_t length, pa_memchunk *result, char *streamType)
758 {
759     struct NumPeekedInfo resInfo = {0, 0};
760     pa_sink_assert_ref(s);
761     pa_sink_assert_io_context(s);
762     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
763     pa_assert(length > 0);
764     pa_assert(pa_frame_aligned(length, &s->sample_spec));
765     CHECK_AND_RETURN_RET_LOG(result != NULL, resInfo, "result is null");
766 
767     pa_assert(!s->thread_info.rewind_requested);
768     pa_assert(s->thread_info.rewind_nbytes == 0);
769 
770     if (s->thread_info.state == PA_SINK_SUSPENDED) {
771         result->memblock = pa_memblock_ref(s->silence.memblock);
772         result->index = s->silence.index;
773         result->length = PA_MIN(s->silence.length, length);
774         return resInfo;
775     }
776 
777     pa_sink_ref(s);
778 
779     AUDIO_DEBUG_LOG("module_split_stream_sink, splitSinkRender in  length = %{public}zu", length);
780     resInfo = SplitPaSinkRender(s, length, result, streamType);
781 
782     if (result->length < length) {
783         pa_memchunk chunk;
784 
785         pa_memchunk_make_writable(result, length);
786 
787         chunk.memblock = result->memblock;
788         chunk.index = result->index + result->length;
789         chunk.length = length - result->length;
790 
791         SplitPaSinkRenderIntoFull(s, &chunk, streamType);
792 
793         result->length = length;
794     }
795 
796     pa_sink_unref(s);
797     return resInfo;
798 }
799 
SendStreamData(struct userdata * u,int num,pa_memchunk chunk)800 static void SendStreamData(struct userdata *u, int num, pa_memchunk chunk)
801 {
802     if (num < 0 || num >= g_splitNums) {
803         return;
804     }
805     CHECK_AND_RETURN_LOG(u != NULL, "u si null");
806     // start hdi
807     StartSplitStreamHdiIfRunning(u);
808     // send msg post data
809     if (!strcmp(g_splitArr[num], STREAM_TYPE_NAVIGATION)) {
810         pa_asyncmsgq_post(u->dq, NULL, HDI_RENDER_NAVIGATION, NULL, 0, &chunk, NULL);
811     } else if (!strcmp(g_splitArr[num], STREAM_TYPE_COMMUNICATION)) {
812         pa_asyncmsgq_post(u->dq, NULL, HDI_RENDER_COMMUNICATION, NULL, 0, &chunk, NULL);
813     } else {
814         pa_asyncmsgq_post(u->dq, NULL, HDI_RENDER_MEDIA, NULL, 0, &chunk, NULL);
815     }
816 }
817 
ShouldSendChunk(int idx,unsigned numNotSilence)818 static bool ShouldSendChunk(int idx, unsigned numNotSilence)
819 {
820     if (numNotSilence == 0) {
821         if (!g_needEmptyChunk || g_noDataCount[idx] == -1) {
822             AUDIO_DEBUG_LOG("stream idx: %d, stream suspend, don't send", idx);
823             return false;
824         }
825         g_noDataCount[idx]++;
826         AUDIO_DEBUG_LOG("stream idx: %d, current empty count: %d, sending...", idx, g_noDataCount[idx]);
827         if (g_noDataCount[idx] >= MAX_EMPTY_CHUNK_NUM) {
828             g_noDataCount[idx] = -1;
829         }
830         return true;
831     } else {
832         AUDIO_DEBUG_LOG("stream idx: %d, not empty chunk, sending...", idx);
833         g_noDataCount[idx] = 0;
834         return true;
835     }
836 }
837 
ProcessRender(struct userdata * u,pa_usec_t now)838 static void ProcessRender(struct userdata *u, pa_usec_t now)
839 {
840     AUTO_CTRACE("module_split_stream_sink: ProcessRender");
841 
842     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
843 
844     /* Fill the buffer up the latency size */
845     for (int i = 0; i < g_splitNums; i++) {
846         AUTO_CTRACE("module_split_stream_sink::ProcessRender:streamType:%s", g_splitArr[i]);
847         AUDIO_DEBUG_LOG("module_split_stream_sink: ProcessRender:streamType:%{public}s", g_splitArr[i]);
848 
849         pa_memchunk chunk;
850         struct NumPeekedInfo resInfo = SplitPaSinkRenderFull(u->sink, u->sink->thread_info.max_request, &chunk,
851             g_splitArr[i]);
852         if (ShouldSendChunk(i, resInfo.numNotSilence)) {
853             SendStreamData(u, i, chunk);
854         } else {
855             AUDIO_DEBUG_LOG("chunk do not send, release chunk");
856             pa_memblock_unref(chunk.memblock);
857         }
858     }
859     u->timestamp += pa_bytes_to_usec(u->sink->thread_info.max_request, &u->sink->sample_spec);
860 }
861 
MonitorLinkedState(pa_sink * si,bool isRunning)862 static bool MonitorLinkedState(pa_sink *si, bool isRunning)
863 {
864     CHECK_AND_RETURN_RET_LOG(si != NULL, false, "si si null");
865     CHECK_AND_RETURN_RET_LOG(si->monitor_source != NULL, false, "monitor_source is null");
866     if (isRunning) {
867         return si->monitor_source && PA_SOURCE_IS_RUNNING(si->monitor_source->thread_info.state);
868     } else {
869         return si->monitor_source && PA_SOURCE_IS_LINKED(si->monitor_source->thread_info.state);
870     }
871 }
872 
HavePaSinkAction(struct userdata * u)873 static bool HavePaSinkAction(struct userdata *u)
874 {
875     CHECK_AND_RETURN_RET_LOG(u != NULL, false, "HavePaSinkAction: userdata ptr is null");
876     bool isIdle = u->sink->thread_info.state == PA_SINK_IDLE;
877     bool wasSuspended = u->previousState == PA_SINK_SUSPENDED;
878     bool wasInit = u->previousState == PA_SINK_INIT;
879 
880     return (((u->renderInIdleState && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ||
881         (!u->renderInIdleState && PA_SINK_IS_RUNNING(u->sink->thread_info.state))) &&
882         !(isIdle && wasSuspended) && !(isIdle && wasInit)) || (isIdle && MonitorLinkedState(u->sink, true));
883 }
884 
ThreadFunc(void * userdata)885 static void ThreadFunc(void *userdata)
886 {
887     ScheduleReportData(getpid(), gettid(), "audio_server");
888     struct userdata *u = userdata;
889     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
890     AUDIO_DEBUG_LOG("Thread starting up");
891     CHECK_AND_RETURN_LOG(u->core != NULL, "core is null");
892     if (u->core->realtime_scheduling) {
893         pa_thread_make_realtime(u->core->realtime_priority);
894     }
895     pa_thread_mq_install(&u->thread_mq);
896     u->timestamp = pa_rtclock_now();
897     for (;;) {
898         pa_usec_t now = 0;
899         int ret;
900 
901         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
902             now = pa_rtclock_now();
903         }
904         bool flag = HavePaSinkAction(u);
905         if (flag) {
906             now = pa_rtclock_now();
907         }
908 
909         if (PA_UNLIKELY(u->sink->thread_info.rewind_requested)) {
910             ProcessRewind(u, now);
911         }
912 
913         /* Render some data and drop it immediately */
914         if (flag) {
915             if (u->timestamp <= now) {
916                 ProcessRender(u, now);
917             }
918             pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp);
919         } else {
920             AUDIO_INFO_LOG("all stream suspend");
921             for (size_t i = 0; i < MAX_PARTS; i++) {
922                 g_noDataCount[i] = -1;
923             }
924             pa_rtpoll_set_timer_disabled(u->rtpoll);
925         }
926         /* Hmm, nothing to do. Let's sleep */
927         if ((ret = pa_rtpoll_run(u->rtpoll)) < 0) {
928             goto fail;
929         }
930         if (ret == 0) {
931             goto finish;
932         }
933     }
934 
935 fail:
936     /* If this was no regular exit from the loop we have to continue
937      * processing messages until we received PA_MESSAGE_SHUTDOWN */
938     pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core),
939         PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
940     pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
941 
942 finish:
943     AUDIO_DEBUG_LOG("Thread shutting down");
944 }
945 
ProcessSplitHdiRender(struct userdata * u,pa_memchunk * chunk,char * streamType)946 static void ProcessSplitHdiRender(struct userdata *u, pa_memchunk *chunk, char *streamType)
947 {
948     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
949     CHECK_AND_RETURN_LOG(chunk != NULL, "chunk is null");
950     pa_usec_t now = pa_rtclock_now();
951     if (!u->isHDISinkStarted && now - u->timestampLastLog > USEC_PER_SEC) {
952         u->timestampLastLog = now;
953         const char *deviceClass = u->sinkAdapter->deviceClass;
954         AUDIO_DEBUG_LOG("HDI not started, skip RenderWrite, wait sink[%s] suspend", deviceClass);
955         pa_memblock_unref(chunk->memblock);
956     } else if (!u->isHDISinkStarted) {
957         pa_memblock_unref(chunk->memblock);
958     } else if (SplitRenderWrite(u->sinkAdapter, chunk, streamType) < 0) {
959         u->bytesDropped += chunk->length;
960         AUDIO_ERR_LOG("RenderWrite failed");
961     }
962     if (pa_atomic_load(&u->dflag) == 1) {
963         pa_atomic_sub(&u->dflag, 1);
964     }
965     u->writeTime = pa_rtclock_now() - now;
966 }
967 
ThreadFuncWriteHDI(void * userdata)968 static void ThreadFuncWriteHDI(void *userdata)
969 {
970     // set audio thread priority
971     ScheduleReportData(getpid(), gettid(), "pulseaudio");
972 
973     struct userdata *u = userdata;
974     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
975 
976     int32_t quit = 0;
977 
978     do {
979         int32_t code = 0;
980         pa_memchunk chunk;
981 
982         pa_assert_se(pa_asyncmsgq_get(u->dq, NULL, &code, NULL, NULL, &chunk, 1) == 0);
983 
984         switch (code) {
985             case HDI_RENDER_MEDIA: {
986                 ProcessSplitHdiRender(u, &chunk, STREAM_TYPE_MEDIA);
987                 break;
988             }
989             case HDI_RENDER_COMMUNICATION: {
990                 ProcessSplitHdiRender(u, &chunk, STREAM_TYPE_COMMUNICATION);
991                 break;
992             }
993             case HDI_RENDER_NAVIGATION: {
994                 ProcessSplitHdiRender(u, &chunk, STREAM_TYPE_NAVIGATION);
995                 break;
996             }
997             case QUIT:
998                 quit = 1;
999                 break;
1000             default:
1001                 break;
1002         }
1003         pa_asyncmsgq_done(u->dq, 0);
1004     } while (!quit);
1005 }
1006 
SplitRenderWrite(struct SinkAdapter * sinkAdapter,pa_memchunk * pchunk,char * streamType)1007 static ssize_t SplitRenderWrite(struct SinkAdapter *sinkAdapter, pa_memchunk *pchunk, char *streamType)
1008 {
1009     size_t index;
1010     size_t length;
1011     ssize_t count = 0;
1012     void *p = NULL;
1013     CHECK_AND_RETURN_RET_LOG(sinkAdapter != NULL, 0, "sinkAdapter is null");
1014     CHECK_AND_RETURN_RET_LOG(pchunk != NULL, 0, "pchunk is null");
1015 
1016     index = pchunk->index;
1017     length = pchunk->length;
1018     p = pa_memblock_acquire(pchunk->memblock);
1019     CHECK_AND_RETURN_RET_LOG(p != NULL, 0, "p is null");
1020 
1021     while (true) {
1022         uint64_t writeLen = 0;
1023 
1024         int32_t ret = sinkAdapter->SinkAdapterSplitRenderFrame(sinkAdapter, ((char*)p + index),
1025             (uint64_t)length, &writeLen, streamType);
1026         if (writeLen > length) {
1027             AUDIO_ERR_LOG("Error writeLen > actual bytes. Length: %zu, Written: %" PRIu64 " bytes, %d ret",
1028                          length, writeLen, ret);
1029             count = -1 - count;
1030             break;
1031         }
1032         if (writeLen == 0) {
1033             AUDIO_ERR_LOG("Failed to render Length: %{public}zu, Written: %{public}" PRIu64 " bytes, %{public}d ret",
1034                 length, writeLen, ret);
1035             count = -1 - count;
1036             break;
1037         } else {
1038             count += (ssize_t)writeLen;
1039             index += writeLen;
1040             length -= writeLen;
1041             if (length == 0) {
1042                 break;
1043             }
1044         }
1045     }
1046     pa_memblock_release(pchunk->memblock);
1047     pa_memblock_unref(pchunk->memblock);
1048 
1049     return count;
1050 }
1051 
FillSinkFunc(struct userdata * u)1052 static void FillSinkFunc(struct userdata *u)
1053 {
1054     CHECK_AND_RETURN_LOG(u != NULL, "FillSinkFunc: userdata ptr is null");
1055     u->sink->parent.process_msg = SinkProcessMsg;
1056     u->sink->set_state_in_io_thread = SinkSetStateInIoThreadCb;
1057     u->sink->update_requested_latency = SinkUpdateRequestedLatencyCb;
1058     u->sink->reconfigure = SinkReconfigureCb;
1059     u->sink->get_formats = SinkGetFormatsCb;
1060     u->sink->set_formats = SinkSetFormatsCb;
1061     u->sink->userdata = u;
1062 }
1063 
CreateSink(pa_module * m,pa_modargs * ma,struct userdata * u)1064 static int CreateSink(pa_module *m, pa_modargs *ma, struct userdata *u)
1065 {
1066     AUDIO_DEBUG_LOG("CreateSink Start");
1067     for (size_t i = 0; i < MAX_PARTS; i++) {
1068         g_noDataCount[i] = -1;
1069     }
1070     pa_sample_spec ss;
1071     pa_channel_map map;
1072     pa_sink_new_data data;
1073     pa_format_info *format;
1074 
1075     CHECK_AND_RETURN_RET_LOG(m != NULL, -1, "m is null");
1076     CHECK_AND_RETURN_RET_LOG(m->core != NULL, -1, "core is null");
1077     ss = m->core->default_sample_spec;
1078     map = m->core->default_channel_map;
1079     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
1080         AUDIO_ERR_LOG("Invalid sample format specification or channel map");
1081         return PA_ERR;
1082     }
1083 
1084     pa_sink_new_data_init(&data);
1085     data.driver = __FILE__;
1086     data.module = m;
1087     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
1088     pa_sink_new_data_set_sample_spec(&data, &ss);
1089     pa_sink_new_data_set_channel_map(&data, &map);
1090     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Split Stream Output"));
1091     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, "splitStream");
1092     CHECK_AND_RETURN_RET_LOG(u != NULL, -1, "u is null");
1093     u->formats = pa_idxset_new(NULL, NULL);
1094     format = pa_format_info_new();
1095     format->encoding = PA_ENCODING_PCM;
1096     pa_idxset_put(u->formats, format, NULL);
1097 
1098     if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
1099         AUDIO_ERR_LOG("Invalid properties");
1100         pa_sink_new_data_done(&data);
1101         return PA_ERR;
1102     }
1103 
1104     u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY);
1105     pa_sink_new_data_done(&data);
1106 
1107     if (!u->sink) {
1108         AUDIO_ERR_LOG("Failed to create sink.");
1109         return PA_ERR;
1110     }
1111     FillSinkFunc(u);
1112     return 0;
1113 }
1114 
InitRemoteSink(struct userdata * u,const char * filePath)1115 static int32_t InitRemoteSink(struct userdata *u, const char *filePath)
1116 {
1117     CHECK_AND_RETURN_RET_LOG(u != NULL, -1, "u is null");
1118     struct SinkAdapterAttr sample_attrs;
1119     int32_t ret;
1120 
1121     sample_attrs.format = ConvertPaToHdiAdapterFormat(u->ss.format);
1122     sample_attrs.adapterName = u->adapterName;
1123     sample_attrs.openMicSpeaker = u->open_mic_speaker;
1124     sample_attrs.sampleRate = (uint32_t) u->ss.rate;
1125     sample_attrs.channel = u->ss.channels;
1126     sample_attrs.volume = MAX_SINK_VOLUME_LEVEL;
1127     sample_attrs.filePath = filePath;
1128     sample_attrs.deviceNetworkId = u->deviceNetworkId;
1129     sample_attrs.deviceType =  u->deviceType;
1130     sample_attrs.aux =  SPLIT_MODE;
1131 
1132     ret = u->sinkAdapter->SinkAdapterInit(u->sinkAdapter, &sample_attrs);
1133     if (ret != 0) {
1134         AUDIO_ERR_LOG("audiorenderer Init failed!");
1135         return -1;
1136     }
1137 
1138     return 0;
1139 }
1140 
UserdataFree(struct userdata * u)1141 static void UserdataFree(struct userdata *u)
1142 {
1143     AUDIO_INFO_LOG("start UserdataFree");
1144     CHECK_AND_RETURN_LOG(u != NULL, "u is null");
1145     if (u->sink) {
1146         pa_sink_unlink(u->sink);
1147     }
1148 
1149     if (u->thread) {
1150         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
1151         pa_thread_free(u->thread);
1152     }
1153 
1154     if (u->thread_split_hdi) {
1155         pa_asyncmsgq_post(u->dq, NULL, QUIT, NULL, 0, NULL, NULL);
1156         pa_thread_free(u->thread_split_hdi);
1157     }
1158 
1159     if (u->sinkAdapter) {
1160         u->sinkAdapter->SinkAdapterStop(u->sinkAdapter);
1161         u->sinkAdapter->SinkAdapterDeInit(u->sinkAdapter);
1162         ReleaseSinkAdapter(u->sinkAdapter);
1163         u->sinkAdapter = NULL;
1164     }
1165 
1166     pa_thread_mq_done(&u->thread_mq);
1167 
1168     if (u->sink) {
1169         pa_sink_unref(u->sink);
1170     }
1171 
1172     if (u->rtpoll) {
1173         pa_rtpoll_free(u->rtpoll);
1174     }
1175 
1176     if (u->formats) {
1177         pa_idxset_free(u->formats, (pa_free_cb_t)pa_format_info_free);
1178     }
1179 
1180     pa_xfree(u);
1181 
1182     // restore the arr ptr and len
1183     g_splitNums = 0;
1184     for (int32_t i = 0; i < MAX_PARTS; ++i) {
1185         if (g_splitArr[i] == NULL) {
1186             continue;
1187         }
1188         free(g_splitArr[i]);
1189         g_splitArr[i] = NULL;
1190     }
1191 }
1192 
InitFailed(pa_module * m,pa_modargs * ma)1193 static int InitFailed(pa_module *m, pa_modargs *ma)
1194 {
1195     AUDIO_ERR_LOG("Split Stream Sink Init Failed");
1196     CHECK_AND_RETURN_RET_LOG(m != NULL, -1, "m is null");
1197     UserdataFree(m->userdata);
1198     m->userdata = NULL;
1199     if (ma)
1200         pa_modargs_free(ma);
1201 
1202     pa__done(m);
1203 
1204     return PA_ERR;
1205 }
1206 
PaHdiSinkNewInit(pa_module * m,pa_modargs * ma,struct userdata * u)1207 static int32_t PaHdiSinkNewInit(pa_module *m, pa_modargs *ma, struct userdata *u)
1208 {
1209     CHECK_AND_RETURN_RET_LOG(u != NULL, -1, "u is null");
1210     size_t nbytes;
1211     int mg;
1212     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
1213     pa_sink_set_rtpoll(u->sink, u->rtpoll);
1214 
1215     u->buffer_size = DEFAULT_BUFFER_SIZE;
1216     CHECK_AND_RETURN_RET_LOG(ma != NULL, -1, "ma is null");
1217     mg = pa_modargs_get_value_u32(ma, "buffer_size", &u->buffer_size);
1218     CHECK_AND_RETURN_RET_LOG(mg >= 0, PA_ERR,
1219         "Failed to parse buffer_size arg in capturer sink");
1220 
1221     u->block_usec = pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec);
1222     CHECK_AND_RETURN_RET_LOG(u->sink != NULL, -1, "sink is null");
1223     nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
1224     pa_sink_set_max_rewind(u->sink, nbytes);
1225     pa_sink_set_max_request(u->sink, u->buffer_size);
1226 
1227     if (u->fixed_latency) {
1228         pa_sink_set_fixed_latency(u->sink, u->block_usec);
1229     } else {
1230         pa_sink_set_latency_range(u->sink, 0, u->block_usec);
1231     }
1232 
1233     const char *deviceClass = pa_modargs_get_value(ma, "device_class", DEFAULT_DEVICE_CLASS);
1234     u->sinkAdapter = GetSinkAdapter(deviceClass, pa_modargs_get_value(ma, "network_id", DEFAULT_DEVICE_NETWORKID));
1235     if (u->sinkAdapter == NULL) {
1236         AUDIO_ERR_LOG("Load adapter failed");
1237         return -1;
1238     }
1239 
1240     if (pa_modargs_get_value_s32(ma, "device_type", &u->deviceType) < 0) {
1241         AUDIO_ERR_LOG("Failed to parse deviceType argument.");
1242         return -1;
1243     }
1244 
1245     u->adapterName = pa_modargs_get_value(ma, "adapter_name", DEFAULT_DEVICE_CLASS);
1246     u->deviceNetworkId = pa_modargs_get_value(ma, "network_id", DEFAULT_DEVICE_NETWORKID);
1247     CHECK_AND_RETURN_RET_LOG(m != NULL, -1, "m is null");
1248     CHECK_AND_RETURN_RET_LOG(m->core != NULL, -1, "core is null");
1249     u->ss = m->core->default_sample_spec;
1250     u->map = m->core->default_channel_map;
1251     if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->ss, &u->map, PA_CHANNEL_MAP_DEFAULT) < 0) {
1252         AUDIO_ERR_LOG("Failed to parse sample specification and channel map");
1253         return -1;
1254     }
1255 
1256     if (InitRemoteSink(u, pa_modargs_get_value(ma, "file_path", "")) < 0) {
1257         AUDIO_ERR_LOG("Failed to init remote audio render sink.");
1258         return -1;
1259     }
1260 
1261     return 0;
1262 }
1263 
pa__init(pa_module * m)1264 int pa__init(pa_module *m)
1265 {
1266     AUDIO_INFO_LOG("module_split_stream_sink pa__init start");
1267     struct userdata *u = NULL;
1268     pa_modargs *ma = NULL;
1269     int mq;
1270 
1271     CHECK_AND_RETURN_RET_LOG(m != NULL, -1, "m is null");
1272 
1273     ma = pa_modargs_new(m->argument, VALID_MODARGS);
1274     CHECK_AND_RETURN_RET_LOG(ma != NULL, InitFailed(m, ma), "Failed to parse module arguments:%{public}s", m->argument);
1275 
1276     SPLIT_MODE = pa_modargs_get_value(ma, "split_mode", "1");
1277     AUDIO_INFO_LOG("module_split_stream_sink pa__init splitMode is %{public}s", SPLIT_MODE);
1278 
1279     bool defaultEmptyChunkMode = true;
1280     int getEmptyModeRet = pa_modargs_get_value_boolean(ma, "need_empty_chunk", &defaultEmptyChunkMode);
1281     g_needEmptyChunk = defaultEmptyChunkMode;
1282     AUDIO_INFO_LOG("module_split_stream_sink pa__init getEmptyModeRet: %{public}d, bool state: %{public}d",
1283         getEmptyModeRet, g_needEmptyChunk);
1284 
1285     ConvertToSplitArr(SPLIT_MODE);
1286 
1287     m->userdata = u = pa_xnew0(struct userdata, 1);
1288     u->core = m->core;
1289     u->module = m;
1290     u->rtpoll = pa_rtpoll_new();
1291 
1292     mq = pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
1293     CHECK_AND_RETURN_RET_LOG(mq >=0, InitFailed(m, ma), "pa_thread_mq_init() failed.");
1294 
1295     if (CreateSink(m, ma, u) != 0) {
1296         return InitFailed(m, ma);
1297     }
1298 
1299     if (PaHdiSinkNewInit(m, ma, u) < 0) {
1300         AUDIO_ERR_LOG("PaHdiSinkNewInit failed");
1301         return InitFailed(m, ma);
1302     }
1303 
1304     u->dq = pa_asyncmsgq_new(0);
1305 
1306     if (!(u->thread = pa_thread_new("OS_SplitStream", ThreadFunc, u))) {
1307         AUDIO_ERR_LOG("Failed to create thread.");
1308         return InitFailed(m, ma);
1309     }
1310 
1311     if (!(u->thread_split_hdi = pa_thread_new("OS_splitToHdi", ThreadFuncWriteHDI, u))) {
1312         AUDIO_ERR_LOG("Failed to create OS_splitToHdi.");
1313         return InitFailed(m, ma);
1314     }
1315 
1316     pa_sink_put(u->sink);
1317 
1318     pa_modargs_free(ma);
1319 
1320     return 0;
1321 }
1322 
pa__get_n_used(pa_module * m)1323 int pa__get_n_used(pa_module *m)
1324 {
1325     struct userdata *u;
1326 
1327     CHECK_AND_RETURN_RET_LOG(m != NULL, 0, "m is null");
1328     pa_assert_se(u = m->userdata);
1329 
1330     return pa_sink_linked_by(u->sink);
1331 }
1332 
pa__done(pa_module * m)1333 void pa__done(pa_module*m)
1334 {
1335     struct userdata *u;
1336 
1337     CHECK_AND_RETURN_LOG(m != NULL, "m is null");
1338 
1339     if (!(u = m->userdata)) {
1340         return;
1341     }
1342     UserdataFree(u);
1343     m->userdata = NULL;
1344 }
1345