sink-input: Limit rewinding to max_rewind for virtual sinks

This patch is in preparation of allowing virtual sinks to specify their own
max_rewind limit.
Currently, virtual sinks cannot specify their max_rewind limit, but just copy
the value from the master sink. This may not be correct, if the DSP code of the
virtual sink has limited (or no) rewinding capability.
Because the DSP code of the virtual sink is rewound in the process_rewind()
callback of the sink input, it must be ensured, that rewinding a sink input
to the master of a virtual sink is limited similar to rewinding a sink.
There are two remaining exceptions:

1) If an underrun is detected. In that case, the filter should be reset anyway.
2) When the sink input of the filter is moved and attached to the destination
sink.

The move case is handled without involvement of the implementer, so the implementer
can only receive a rewind larger than max_rewind when the filter should be reset
anyway.

All existing virtual sinks do not distinguish between reset and rewind of the
filter.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/120>
This commit is contained in:
Georg Chini 2021-01-01 00:31:32 +01:00 committed by PulseAudio Marge Bot
parent f121779f88
commit 5c6d91a97c
3 changed files with 50 additions and 5 deletions

View file

@ -1657,6 +1657,27 @@ bool pa_sink_flat_volume_enabled(pa_sink *s) {
return false;
}
/* Check if the sink has a virtual sink attached.
* Called from the IO thread. */
bool pa_sink_has_filter_attached(pa_sink *s) {
bool vsink_attached = false;
void *state = NULL;
pa_sink_input *i;
pa_assert(s);
if (PA_SINK_IS_LINKED(s->thread_info.state)) {
PA_HASHMAP_FOREACH(i, s->thread_info.inputs, state) {
if (!i->origin_sink)
continue;
vsink_attached = true;
break;
}
}
return vsink_attached;
}
/* Called from the main thread (and also from the IO thread while the main
* thread is waiting). */
pa_sink *pa_sink_get_master(pa_sink *s) {
@ -2669,8 +2690,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
}
pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
pa_sink_invalidate_requested_latency(s, true);
pa_sink_request_rewind(s, (size_t) -1);
pa_sink_invalidate_requested_latency(s, true);
/* In flat volume mode we need to update the volume as
* well */
@ -2709,11 +2730,13 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
/* Let's remove the sink input ...*/
pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
pa_sink_invalidate_requested_latency(s, true);
/* The rewind must be requested before invalidating the latency, otherwise
* the max_rewind value of the sink may change before the rewind. */
pa_log_debug("Requesting rewind due to started move");
pa_sink_request_rewind(s, (size_t) -1);
pa_sink_invalidate_requested_latency(s, true);
/* In flat volume mode we need to update the volume as
* well */
return o->process_msg(o, PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL);