mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2026-03-02 01:40:27 -05:00
sink, source: Rework reconfiguration logic to apply to more than rate
This rejigs the update_rate() logic to encompass changes to the sample spec as a whole, as well as passthrough status. As a result, sinks/sources provide a reconfigure() method which allows reconfiguration as required. The behaviour itself is currently unchanged -- alsa-sink/-source do not actually implement anything other than rate updates for now (nor are they ever requested to). This can be modified in the future, to allow, for example 24-bit output when incoming media supports it, as well as channel count changes for passthrough sinks. Another related change is that passthrough status is now part of sink/source reconfiguration, and we can stop doing a suspend/unsuspend when entering/leaving passthrough state. So that part is now divided in two -- pa_sink_reconfigure() sets the sink in passthrough mode if required, and pa_sink_enter_passthrough() sets up everything else (this currently means only volumes, but could disable other processing) for passthrough mode.
This commit is contained in:
parent
4f1041c271
commit
7a7072557a
8 changed files with 90 additions and 94 deletions
|
|
@ -161,7 +161,7 @@ static void reset_callbacks(pa_sink *s) {
|
|||
s->set_port = NULL;
|
||||
s->get_formats = NULL;
|
||||
s->set_formats = NULL;
|
||||
s->update_rate = NULL;
|
||||
s->reconfigure = NULL;
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
@ -1411,9 +1411,9 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
|
|||
}
|
||||
|
||||
/* Called from main thread */
|
||||
int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
|
||||
int pa_sink_reconfigure(pa_sink *s, pa_sample_spec *spec, bool passthrough) {
|
||||
int ret = -1;
|
||||
uint32_t desired_rate;
|
||||
pa_sample_spec desired_spec;
|
||||
uint32_t default_rate = s->default_sample_rate;
|
||||
uint32_t alternate_rate = s->alternate_sample_rate;
|
||||
uint32_t idx;
|
||||
|
|
@ -1422,10 +1422,12 @@ int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
|
|||
bool alternate_rate_is_usable = false;
|
||||
bool avoid_resampling = s->core->avoid_resampling;
|
||||
|
||||
if (rate == s->sample_spec.rate)
|
||||
/* We currently only try to reconfigure the sample rate */
|
||||
|
||||
if (pa_sample_spec_equal(spec, &s->sample_spec))
|
||||
return 0;
|
||||
|
||||
if (!s->update_rate)
|
||||
if (!s->reconfigure)
|
||||
return -1;
|
||||
|
||||
if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough && !avoid_resampling)) {
|
||||
|
|
@ -1446,52 +1448,54 @@ int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
|
|||
}
|
||||
}
|
||||
|
||||
if (PA_UNLIKELY(!pa_sample_rate_valid(rate)))
|
||||
if (PA_UNLIKELY(!pa_sample_spec_valid(spec)))
|
||||
return -1;
|
||||
|
||||
desired_spec = s->sample_spec;
|
||||
|
||||
if (passthrough) {
|
||||
/* We have to try to use the sink input rate */
|
||||
desired_rate = rate;
|
||||
desired_spec.rate = spec->rate;
|
||||
|
||||
} else if (avoid_resampling && (rate >= default_rate || rate >= alternate_rate)) {
|
||||
} else if (avoid_resampling && (spec->rate >= default_rate || spec->rate >= alternate_rate)) {
|
||||
/* We just try to set the sink input's sample rate if it's not too low */
|
||||
desired_rate = rate;
|
||||
desired_spec.rate = spec->rate;
|
||||
|
||||
} else if (default_rate == rate || alternate_rate == rate) {
|
||||
} else if (default_rate == spec->rate || alternate_rate == spec->rate) {
|
||||
/* We can directly try to use this rate */
|
||||
desired_rate = rate;
|
||||
desired_spec.rate = spec->rate;
|
||||
|
||||
} else {
|
||||
/* See if we can pick a rate that results in less resampling effort */
|
||||
if (default_rate % 11025 == 0 && rate % 11025 == 0)
|
||||
if (default_rate % 11025 == 0 && spec->rate % 11025 == 0)
|
||||
default_rate_is_usable = true;
|
||||
if (default_rate % 4000 == 0 && rate % 4000 == 0)
|
||||
if (default_rate % 4000 == 0 && spec->rate % 4000 == 0)
|
||||
default_rate_is_usable = true;
|
||||
if (alternate_rate && alternate_rate % 11025 == 0 && rate % 11025 == 0)
|
||||
if (alternate_rate && alternate_rate % 11025 == 0 && spec->rate % 11025 == 0)
|
||||
alternate_rate_is_usable = true;
|
||||
if (alternate_rate && alternate_rate % 4000 == 0 && rate % 4000 == 0)
|
||||
if (alternate_rate && alternate_rate % 4000 == 0 && spec->rate % 4000 == 0)
|
||||
alternate_rate_is_usable = true;
|
||||
|
||||
if (alternate_rate_is_usable && !default_rate_is_usable)
|
||||
desired_rate = alternate_rate;
|
||||
desired_spec.rate = alternate_rate;
|
||||
else
|
||||
desired_rate = default_rate;
|
||||
desired_spec.rate = default_rate;
|
||||
}
|
||||
|
||||
if (desired_rate == s->sample_spec.rate)
|
||||
if (pa_sample_spec_equal(&desired_spec, &s->sample_spec) && passthrough == pa_sink_is_passthrough(s))
|
||||
return -1;
|
||||
|
||||
if (!passthrough && pa_sink_used_by(s) > 0)
|
||||
return -1;
|
||||
|
||||
pa_log_debug("Suspending sink %s due to changing the sample rate.", s->name);
|
||||
pa_log_debug("Suspending sink %s due to changing format.", s->name);
|
||||
pa_sink_suspend(s, true, PA_SUSPEND_INTERNAL);
|
||||
|
||||
if (s->update_rate(s, desired_rate) >= 0) {
|
||||
if (s->reconfigure(s, &desired_spec, passthrough) >= 0) {
|
||||
/* update monitor source as well */
|
||||
if (s->monitor_source && !passthrough)
|
||||
pa_source_update_rate(s->monitor_source, desired_rate, false);
|
||||
pa_log_info("Changed sampling rate successfully");
|
||||
pa_source_reconfigure(s->monitor_source, &desired_spec, false);
|
||||
pa_log_info("Changed format successfully");
|
||||
|
||||
PA_IDXSET_FOREACH(i, s->inputs, idx) {
|
||||
if (i->state == PA_SINK_INPUT_CORKED)
|
||||
|
|
@ -1626,10 +1630,9 @@ bool pa_sink_is_passthrough(pa_sink *s) {
|
|||
void pa_sink_enter_passthrough(pa_sink *s) {
|
||||
pa_cvolume volume;
|
||||
|
||||
if (s->is_passthrough_set) {
|
||||
pa_log_debug("Sink %s is already in passthrough mode, nothing to do", s->name);
|
||||
return;
|
||||
}
|
||||
/* The sink implementation is reconfigured for passthrough in
|
||||
* pa_sink_reconfigure(). This function sets the PA core objects to
|
||||
* passthrough mode. */
|
||||
|
||||
/* disable the monitor in passthrough mode */
|
||||
if (s->monitor_source) {
|
||||
|
|
@ -1645,21 +1648,10 @@ void pa_sink_enter_passthrough(pa_sink *s) {
|
|||
pa_sink_set_volume(s, &volume, true, false);
|
||||
|
||||
pa_log_debug("Suspending/Restarting sink %s to enter passthrough mode", s->name);
|
||||
|
||||
/* force sink to be resumed in passthrough mode */
|
||||
pa_sink_suspend(s, true, PA_SUSPEND_INTERNAL);
|
||||
s->is_passthrough_set = true;
|
||||
pa_sink_suspend(s, false, PA_SUSPEND_INTERNAL);
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
void pa_sink_leave_passthrough(pa_sink *s) {
|
||||
|
||||
if (!s->is_passthrough_set) {
|
||||
pa_log_debug("Sink %s is not in passthrough mode, nothing to do", s->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unsuspend monitor */
|
||||
if (s->monitor_source) {
|
||||
pa_log_debug("Resuming monitor source %s, because the sink is leaving the passthrough mode.", s->monitor_source->name);
|
||||
|
|
@ -1672,11 +1664,6 @@ void pa_sink_leave_passthrough(pa_sink *s) {
|
|||
pa_cvolume_init(&s->saved_volume);
|
||||
s->saved_save_volume = false;
|
||||
|
||||
/* force sink to be resumed in non-passthrough mode */
|
||||
pa_sink_suspend(s, true, PA_SUSPEND_INTERNAL);
|
||||
s->is_passthrough_set = false;
|
||||
pa_sink_suspend(s, false, PA_SUSPEND_INTERNAL);
|
||||
|
||||
}
|
||||
|
||||
/* Called from main context. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue