• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19 
20 #include <pulse/rtclock.h>
21 #include <pulse/timeval.h>
22 #include <pulse/xmalloc.h>
23 
24 #include <pulsecore/namereg.h>
25 #include <pulsecore/sink.h>
26 #include <pulsecore/module.h>
27 #include <pulsecore/core-util.h>
28 #include <pulsecore/modargs.h>
29 #include <pulsecore/log.h>
30 #include <pulsecore/rtpoll.h>
31 #include <pulsecore/thread.h>
32 #include <pulsecore/thread-mq.h>
33 
34 #include "securec.h"
35 #include "audio_log.h"
36 
37 PA_MODULE_AUTHOR("OpenHarmony");
38 PA_MODULE_DESCRIPTION("Virtual channel sink");
39 PA_MODULE_VERSION(PACKAGE_VERSION);
40 PA_MODULE_LOAD_ONCE(false);
41 PA_MODULE_USAGE(
42         "sink_name=<name for the sink> "
43         "master=<name of sink to remap> "
44 );
45 
46 #define DEFAULT_BUFFER_SIZE 8192
47 
48 struct userdata {
49     pa_module *module;
50 
51     pa_sink *sink;
52     pa_sink_input *sink_input;
53 
54     uint32_t buffer_size;
55     pa_core *core;
56 
57     pa_usec_t block_usec;
58     pa_usec_t timestamp;
59 
60     pa_rtpoll *rtpoll;
61     pa_thread *thread;
62     pa_thread_mq thread_mq;
63 
64     pa_sample_spec sampleSpec;
65     pa_channel_map sinkMap;
66 
67     bool auto_desc;
68 };
69 
70 static const char * const VALID_MODARGS[] = {
71     "sink_name",
72     "master",
73     "buffer_size",
74     NULL
75 };
76 
77 /* Called from I/O thread context */
SinkPorcessMsg(pa_msgobject * o,int code,void * data,int64_t offset,pa_memchunk * chunk)78 static int SinkPorcessMsg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk)
79 {
80     struct userdata *u = PA_SINK(o)->userdata;
81 
82     switch (code) {
83         case PA_SINK_MESSAGE_GET_LATENCY:
84             /* The sink is _put() before the sink input is, so let's
85              * make sure we don't access it yet */
86             if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
87                 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
88                 *((int64_t*) data) = 0;
89                 return 0;
90             }
91 
92             *((int64_t*) data) =
93                 /* Get the latency of the master sink */
94                 pa_sink_get_latency_within_thread(u->sink_input->sink, true) +
95 
96                 /* Add the latency internal to our sink input on top */
97                 pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq),
98                     &u->sink_input->sink->sample_spec);
99             return 0;
100         default:
101             break;
102     }
103     return pa_sink_process_msg(o, code, data, offset, chunk);
104 }
105 
106 /* Called from main context */
SinkSetStateInMainThread(pa_sink * s,pa_sink_state_t state,pa_suspend_cause_t suspend_cause)107 static int SinkSetStateInMainThread(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause)
108 {
109     struct userdata *u;
110 
111     pa_sink_assert_ref(s);
112     pa_assert_se(u = s->userdata);
113 
114     if (!PA_SINK_IS_LINKED(state) ||
115         !PA_SINK_INPUT_IS_LINKED(u->sink_input->state)) {
116         return 0;
117     }
118 
119     pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
120     return 0;
121 }
122 
123 /* Called from the IO thread. */
SinkSetStateInIoThreadCb(pa_sink * s,pa_sink_state_t new_state,pa_suspend_cause_t new_suspend_cause)124 static int SinkSetStateInIoThreadCb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause)
125 {
126     struct userdata *u;
127 
128     pa_assert(s);
129     pa_assert_se(u = s->userdata);
130 
131     /* When set to running or idle for the first time, request a rewind
132      * of the master sink to make sure we are heard immediately */
133     if (PA_SINK_IS_OPENED(new_state) && s->thread_info.state == PA_SINK_INIT) {
134         AUDIO_DEBUG_LOG("Requesting rewind due to state change.");
135         pa_sink_input_request_rewind(u->sink_input, 0, false, true, true);
136     }
137 
138     return 0;
139 }
140 
141 /* Called from I/O thread context */
SinkRequestRewind(pa_sink * s)142 static void SinkRequestRewind(pa_sink *s)
143 {
144     struct userdata *u;
145 
146     pa_sink_assert_ref(s);
147     pa_assert_se(u = s->userdata);
148 
149     if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
150         !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
151         return;
152     }
153 
154     pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, true, false, false);
155 }
156 
157 /* Called from I/O thread context */
SinkUpdateRequestedLatency(pa_sink * s)158 static void SinkUpdateRequestedLatency(pa_sink *s)
159 {
160     struct userdata *u;
161 
162     pa_sink_assert_ref(s);
163     pa_assert_se(u = s->userdata);
164 
165     if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
166         !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
167         return;
168     }
169 
170     /* Just hand this one over to the master sink */
171     pa_sink_input_set_requested_latency_within_thread(
172         u->sink_input, pa_sink_get_requested_latency_within_thread(s));
173 }
174 
175 /* Called from I/O thread context */
SinkInputPopCb(pa_sink_input * i,size_t nbytes,pa_memchunk * chunk)176 static int SinkInputPopCb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk)
177 {
178     struct userdata *u;
179 
180     pa_sink_input_assert_ref(i);
181     pa_assert(chunk);
182     pa_assert_se(u = i->userdata);
183 
184     if (!PA_SINK_IS_LINKED(u->sink->thread_info.state)) {
185         return -1;
186     }
187 
188     /* Hmm, process any rewind request that might be queued up */
189     pa_sink_process_rewind(u->sink, 0);
190 
191     pa_sink_render(u->sink, nbytes, chunk);
192     return 0;
193 }
194 
195 /* Called from I/O thread context */
SinkInputProcessRewindCb(pa_sink_input * i,size_t nbytes)196 static void SinkInputProcessRewindCb(pa_sink_input *i, size_t nbytes)
197 {
198     size_t amount = 0;
199     struct userdata *u;
200 
201     pa_sink_input_assert_ref(i);
202     pa_assert_se(u = i->userdata);
203 
204     /* If the sink is not yet linked, there is nothing to rewind */
205     if (!PA_SINK_IS_LINKED(u->sink->thread_info.state)) {
206         return;
207     }
208 
209     if (u->sink->thread_info.rewind_nbytes > 0) {
210         amount = PA_MIN(u->sink->thread_info.rewind_nbytes, nbytes);
211         u->sink->thread_info.rewind_nbytes = 0;
212     }
213 
214     pa_sink_process_rewind(u->sink, amount);
215 }
216 
217 /* Called from I/O thread context */
SinkInputUpdateMaxRewindCb(pa_sink_input * i,size_t nbytes)218 static void SinkInputUpdateMaxRewindCb(pa_sink_input *i, size_t nbytes)
219 {
220     struct userdata *u;
221 
222     pa_sink_input_assert_ref(i);
223     pa_assert_se(u = i->userdata);
224 
225     pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
226 }
227 
228 /* Called from I/O thread context */
SinkInputUpdateMaxRequestCb(pa_sink_input * i,size_t nbytes)229 static void SinkInputUpdateMaxRequestCb(pa_sink_input *i, size_t nbytes)
230 {
231     struct userdata *u;
232 
233     pa_sink_input_assert_ref(i);
234     pa_assert_se(u = i->userdata);
235 
236     pa_sink_set_max_request_within_thread(u->sink, nbytes);
237 }
238 
239 /* Called from I/O thread context */
SinkInputUpdateSinkLatencyRangeCb(pa_sink_input * i)240 static void SinkInputUpdateSinkLatencyRangeCb(pa_sink_input *i)
241 {
242     struct userdata *u;
243 
244     pa_sink_input_assert_ref(i);
245     pa_assert_se(u = i->userdata);
246 
247     pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency,
248         i->sink->thread_info.max_latency);
249 }
250 
251 /* Called from I/O thread context */
SinkInputUpdateSinkFixedLatencyCb(pa_sink_input * i)252 static void SinkInputUpdateSinkFixedLatencyCb(pa_sink_input *i)
253 {
254     struct userdata *u;
255 
256     pa_sink_input_assert_ref(i);
257     pa_assert_se(u = i->userdata);
258 
259     pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
260 }
261 
262 /* Called from I/O thread context */
SinkInputDetachCb(pa_sink_input * i)263 static void SinkInputDetachCb(pa_sink_input *i)
264 {
265     struct userdata *u;
266 
267     pa_sink_input_assert_ref(i);
268     pa_assert_se(u = i->userdata);
269 
270     if (PA_SINK_IS_LINKED(u->sink->thread_info.state)) {
271         pa_sink_detach_within_thread(u->sink);
272     }
273 
274     pa_sink_set_rtpoll(u->sink, NULL);
275 }
276 
277 /* Called from I/O thread context */
SinkInputAttachCb(pa_sink_input * i)278 static void SinkInputAttachCb(pa_sink_input *i)
279 {
280     struct userdata *u;
281 
282     pa_sink_input_assert_ref(i);
283     pa_assert_se(u = i->userdata);
284 
285     pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
286     pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency,
287         i->sink->thread_info.max_latency);
288     pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
289     pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i));
290     pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
291 
292     if (PA_SINK_IS_LINKED(u->sink->thread_info.state)) {
293         pa_sink_attach_within_thread(u->sink);
294     }
295 }
296 
297 /* Called from main context */
SinkInputKillCb(pa_sink_input * i)298 static void SinkInputKillCb(pa_sink_input *i)
299 {
300     struct userdata *u;
301 
302     pa_sink_input_assert_ref(i);
303     pa_assert_se(u = i->userdata);
304 
305     /* The order here matters! We first kill the sink so that streams
306      * can properly be moved away while the sink input is still connected
307      * to the master. */
308     pa_sink_input_cork(u->sink_input, true);
309     pa_sink_unlink(u->sink);
310     pa_sink_input_unlink(u->sink_input);
311 
312     pa_sink_input_unref(u->sink_input);
313     u->sink_input = NULL;
314 
315     pa_sink_unref(u->sink);
316     u->sink = NULL;
317 
318     pa_module_unload_request(u->module, true);
319 }
320 
321 /* Called from main context */
SinkInputMovingCb(pa_sink_input * i,pa_sink * dest)322 static void SinkInputMovingCb(pa_sink_input *i, pa_sink *dest)
323 {
324     struct userdata *u;
325 
326     pa_sink_input_assert_ref(i);
327     pa_assert_se(u = i->userdata);
328 
329     if (dest) {
330         pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
331         pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
332     } else {
333         pa_sink_set_asyncmsgq(u->sink, NULL);
334     }
335 
336     if (u->auto_desc && dest) {
337         const char *k;
338         pa_proplist *pl;
339 
340         pl = pa_proplist_new();
341         k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
342         pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name);
343 
344         pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
345         pa_proplist_free(pl);
346     }
347 }
348 
InitFail(pa_module * m,pa_modargs * ma)349 int InitFail(pa_module *m, pa_modargs *ma)
350 {
351     AUDIO_ERR_LOG("Receiver sink init failed.");
352     if (ma)
353         pa_modargs_free(ma);
354     pa__done(m);
355     return -1;
356 }
357 
CreateSink(pa_module * m,pa_modargs * ma,pa_sink * master,struct userdata * u)358 int CreateSink(pa_module *m, pa_modargs *ma, pa_sink *master, struct userdata *u)
359 {
360     pa_sample_spec ss;
361     pa_channel_map sinkMap;
362     pa_sink_new_data sinkData;
363 
364     ss = master->sample_spec;
365     sinkMap = master->channel_map;
366     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &sinkMap, PA_CHANNEL_MAP_DEFAULT) < 0) {
367         AUDIO_ERR_LOG("Invalid sample format specification or channel map");
368         return -1;
369     }
370 
371     pa_sink_new_data_init(&sinkData);
372     sinkData.driver = __FILE__;
373     sinkData.module = m;
374     if (!(sinkData.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
375         sinkData.name = pa_sprintf_malloc("%s.remapped", master->name);
376     pa_sink_new_data_set_sample_spec(&sinkData, &ss);
377     pa_sink_new_data_set_channel_map(&sinkData, &sinkMap);
378     pa_proplist_sets(sinkData.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
379     pa_proplist_sets(sinkData.proplist, PA_PROP_DEVICE_CLASS, "filter");
380     pa_proplist_sets(sinkData.proplist, PA_PROP_DEVICE_STRING, "receiver");
381 
382     if (pa_modargs_get_proplist(ma, "sink_properties", sinkData.proplist, PA_UPDATE_REPLACE) < 0) {
383         AUDIO_ERR_LOG("Invalid properties");
384         pa_sink_new_data_done(&sinkData);
385         return -1;
386     }
387 
388     if ((u->auto_desc = !pa_proplist_contains(sinkData.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
389         const char *k;
390 
391         k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
392         pa_proplist_setf(sinkData.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
393     }
394 
395     u->sink = pa_sink_new(m->core, &sinkData, master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY));
396     pa_sink_new_data_done(&sinkData);
397 
398     if (!u->sink) {
399         return -1;
400     }
401 
402     u->sink->parent.process_msg = SinkPorcessMsg;
403     u->sink->set_state_in_main_thread = SinkSetStateInMainThread;
404     u->sink->set_state_in_io_thread = SinkSetStateInIoThreadCb;
405     u->sink->update_requested_latency = SinkUpdateRequestedLatency;
406     u->sink->request_rewind = SinkRequestRewind;
407     u->sink->userdata = u;
408     u->sampleSpec = ss;
409     u->sinkMap = sinkMap;
410 
411     pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
412     return 0;
413 }
414 
CreateSinkInput(pa_module * m,pa_modargs * ma,pa_sink * master,struct userdata * u)415 int CreateSinkInput(pa_module *m, pa_modargs *ma, pa_sink *master, struct userdata *u)
416 {
417     pa_sink_input_new_data sinkInputData;
418     pa_resample_method_t resampleMethod = PA_RESAMPLER_SRC_SINC_FASTEST;
419 
420     if (pa_modargs_get_resample_method(ma, &resampleMethod) < 0) {
421         AUDIO_ERR_LOG("Invalid resampling method");
422         return -1;
423     }
424 
425     if (u->sinkMap.channels != u->sampleSpec.channels) {
426         AUDIO_ERR_LOG("Number of channels doesn't match");
427         return -1;
428     }
429 
430     if (pa_channel_map_equal(&u->sinkMap, &master->channel_map)) {
431         AUDIO_WARNING_LOG("Number of channels doesn't match of [%{public}s] and [%{public}s]",
432             u->sink->name, master->name);
433     }
434 
435     pa_sink_input_new_data_init(&sinkInputData);
436     sinkInputData.driver = __FILE__;
437     sinkInputData.module = m;
438     pa_sink_input_new_data_set_sink(&sinkInputData, master, false, true);
439     sinkInputData.origin_sink = u->sink;
440     pa_proplist_sets(sinkInputData.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream");
441     pa_proplist_sets(sinkInputData.proplist, PA_PROP_MEDIA_ROLE, "filter");
442     pa_sink_input_new_data_set_sample_spec(&sinkInputData, &u->sampleSpec);
443     pa_sink_input_new_data_set_channel_map(&sinkInputData, &u->sinkMap);
444     sinkInputData.flags = PA_SINK_INPUT_START_CORKED;
445     sinkInputData.resample_method = PA_RESAMPLER_SRC_SINC_FASTEST;
446 
447     pa_sink_input_new(&u->sink_input, m->core, &sinkInputData);
448     pa_sink_input_new_data_done(&sinkInputData);
449 
450     if (!u->sink_input) {
451         return -1;
452     }
453 
454     u->sink_input->pop = SinkInputPopCb;
455     u->sink_input->process_rewind = SinkInputProcessRewindCb;
456     u->sink_input->update_max_rewind = SinkInputUpdateMaxRewindCb;
457     u->sink_input->update_max_request = SinkInputUpdateMaxRequestCb;
458     u->sink_input->update_sink_latency_range = SinkInputUpdateSinkLatencyRangeCb;
459     u->sink_input->update_sink_fixed_latency = SinkInputUpdateSinkFixedLatencyCb;
460     u->sink_input->attach = SinkInputAttachCb;
461     u->sink_input->detach = SinkInputDetachCb;
462     u->sink_input->kill = SinkInputKillCb;
463     u->sink_input->moving = SinkInputMovingCb;
464     u->sink_input->userdata = u;
465 
466     u->sink->input_to_master = u->sink_input;
467     return 0;
468 }
469 
pa__init(pa_module * m)470 int pa__init(pa_module *m)
471 {
472     struct userdata *u;
473     pa_modargs *ma;
474     pa_sink *master;
475 
476     pa_assert(m);
477 
478     if (!(ma = pa_modargs_new(m->argument, VALID_MODARGS))) {
479         AUDIO_ERR_LOG("Failed to parse module arguments.");
480         return InitFail(m, ma);
481     }
482 
483     if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
484         pa_log("Master sink not found");
485         return InitFail(m, ma);
486     }
487 
488     u = pa_xnew0(struct userdata, 1);
489     u->core = m->core;
490     u->module = m;
491     m->userdata = u;
492     u->rtpoll = pa_rtpoll_new();
493 
494     if (pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll) < 0) {
495         AUDIO_ERR_LOG("pa_thread_mq_init failed.");
496         return InitFail(m, ma);
497     }
498 
499     /* Create sink */
500     if (CreateSink(m, ma, master, u) < 0) {
501         AUDIO_ERR_LOG("CreateSink failed.");
502         return InitFail(m, ma);
503     }
504     pa_sink_set_rtpoll(u->sink, u->rtpoll);
505     u->buffer_size = DEFAULT_BUFFER_SIZE;
506     if (pa_modargs_get_value_u32(ma, "buffer_size", &u->buffer_size) < 0) {
507         AUDIO_ERR_LOG("Failed to get buffer_size argument in effect sink");
508         return InitFail(m, ma);
509     }
510     u->block_usec = pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec);
511     pa_sink_set_latency_range(u->sink, 0, u->block_usec);
512     pa_sink_set_max_request(u->sink, u->buffer_size);
513 
514     /* Create sink input */
515     if (CreateSinkInput(m, ma, master, u) < 0) {
516         AUDIO_ERR_LOG("CreateSinkInput failed.");
517         return InitFail(m, ma);
518     }
519 
520     /* The order here is important. The input must be put first,
521      * otherwise streams might attach to the sink before the sink
522      * input is attached to the master. */
523     pa_sink_input_put(u->sink_input);
524     pa_sink_put(u->sink);
525     pa_sink_input_cork(u->sink_input, false);
526 
527     pa_modargs_free(ma);
528 
529     return 0;
530 }
531 
pa__get_n_used(pa_module * m)532 int pa__get_n_used(pa_module *m)
533 {
534     struct userdata *u;
535 
536     pa_assert(m);
537     pa_assert_se(u = m->userdata);
538 
539     return pa_sink_linked_by(u->sink);
540 }
541 
pa__done(pa_module * m)542 void pa__done(pa_module *m)
543 {
544     struct userdata *u;
545 
546     pa_assert(m);
547 
548     if (!(u = m->userdata)) {
549         return;
550     }
551 
552     /* See comments in SinkInputKillCb() above regarding
553      * destruction order! */
554 
555     if (u->sink_input) {
556         pa_sink_input_cork(u->sink_input, true);
557     }
558 
559     if (u->sink) {
560         pa_sink_unlink(u->sink);
561     }
562 
563     if (u->thread) {
564         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
565         pa_thread_free(u->thread);
566     }
567     pa_thread_mq_done(&u->thread_mq);
568 
569     if (u->sink_input) {
570         pa_sink_input_unlink(u->sink_input);
571         pa_sink_input_unref(u->sink_input);
572     }
573 
574     if (u->sink) {
575         pa_sink_unref(u->sink);
576     }
577 
578     if (u->rtpoll) {
579         pa_rtpoll_free(u->rtpoll);
580     }
581 
582     pa_xfree(u);
583 }
584