summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Chini <georg@chini.tk>2022-06-17 13:11:11 +0200
committerTanu Kaskinen <tanuk@iki.fi>2022-06-20 14:02:15 +0300
commit0e896eb51812dbee2076193145ca47516d243f4d (patch)
tree0bdbeacf1fc478815a82ab46d557cd56535b8dfe
parentca8c5242eb1d8efc7d09a7174eeb6f3a8417b0fe (diff)
downloadpulseaudio-0e896eb51812dbee2076193145ca47516d243f4d.tar.gz
combine-sink: Fix threading issue during underrun
A recent commit added i->origin sink for the sink inputs of the combine sinks. Therefore pa_sink_process_input_underruns() treated the combine sink like filter sinks. pa_sink_process_input_underruns() calls itself with the origin sink, which is only correct for filter sinks because they run in the thread context of the origin sink. The combine sink however has its own thread context, so pa_sink_process_input_underruns() was executed in the wrong context. This patch fixes the issue by skipping the section for module-combine-sink. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/722>
-rw-r--r--src/pulsecore/sink.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 3108ae765..0f0dc56fc 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1016,20 +1016,29 @@ size_t pa_sink_process_input_underruns(pa_sink *s, size_t left_to_play) {
if (i->origin_sink) {
size_t filter_result, left_to_play_origin;
- /* The recursive call works in the origin sink domain ... */
- left_to_play_origin = pa_convert_size(left_to_play, &i->sink->sample_spec, &i->origin_sink->sample_spec);
-
- /* .. and returns the time to sleep before waking up. We need the
- * underrun duration for comparisons, so we undo the subtraction on
- * the return value... */
- filter_result = left_to_play_origin - pa_sink_process_input_underruns(i->origin_sink, left_to_play_origin);
-
- /* ... and convert it back to the master sink domain */
- filter_result = pa_convert_size(filter_result, &i->origin_sink->sample_spec, &i->sink->sample_spec);
-
- /* Remember the longest underrun so far */
- if (filter_result > result)
- result = filter_result;
+ /* The combine sink sets i->origin sink but has a different threading model
+ * than the filter sinks. Therefore the recursion below may not be executed
+ * because pa_sink_process_input_underruns() was not called in the thread
+ * context of the origin sink.
+ * FIXME: It is unclear if some other kind of recursion would be necessary
+ * for the combine sink. */
+ if (!i->module || !pa_safe_streq(i->module->name, "module-combine-sink")) {
+
+ /* The recursive call works in the origin sink domain ... */
+ left_to_play_origin = pa_convert_size(left_to_play, &i->sink->sample_spec, &i->origin_sink->sample_spec);
+
+ /* .. and returns the time to sleep before waking up. We need the
+ * underrun duration for comparisons, so we undo the subtraction on
+ * the return value... */
+ filter_result = left_to_play_origin - pa_sink_process_input_underruns(i->origin_sink, left_to_play_origin);
+
+ /* ... and convert it back to the master sink domain */
+ filter_result = pa_convert_size(filter_result, &i->origin_sink->sample_spec, &i->sink->sample_spec);
+
+ /* Remember the longest underrun so far */
+ if (filter_result > result)
+ result = filter_result;
+ }
}
if (uf == 0) {