From: Arun Raghavan <git@xxxxxxxxxxxxxxxx> The drain reporting improvements that were added to alsa-sink were only being applied to directly connected sink inputs. This patch makes the same logic also recurse down the filter hierarchy, so drains are acknowledged more accurately (and not late) even if there is a filter sink in between. Also does some minor reorganisation of the code and sprinkles in some comments as documentation. --- src/pulsecore/sink.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 9ddb527..0b44fc7 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -950,18 +950,42 @@ size_t pa_sink_process_input_underruns(pa_sink *s, size_t left_to_play) { PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) { size_t uf = i->thread_info.underrun_for_sink; - if (uf == 0) - continue; - if (uf >= left_to_play) { - if (pa_sink_input_process_underrun(i)) - continue; + + /* Propagate down the filter tree */ + 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; } - else if (uf > result) + + if (uf == 0) { + /* No underrun here, move on */ + continue; + } else if (uf >= left_to_play) { + /* The sink has possibly consumed all the data the sink input provided */ + pa_sink_input_process_underrun(i); + } else if (uf > result) { + /* Remember the longest underrun so far */ result = uf; + } } if (result > 0) - pa_log_debug("Found underrun %ld bytes ago (%ld bytes ahead in playback buffer)", (long) result, (long) left_to_play - result); + pa_log_debug("%s: Found underrun %ld bytes ago (%ld bytes ahead in playback buffer)", s->name, + (long) result, (long) left_to_play - result); return left_to_play - result; } -- 2.5.0