sink, source: Add an avoid-processing mode

This generalises the avoid-resampling concept (don't resample for any
rate above the default/alternate sample rate) to include channel count
and sample format as well. The rationale for this is that users who wish
to send out their data untouched by processing in PulseAudio can do so.

In addition to this, there are opportunities for certain hardware (such
as systems with a DSP connected to a codec) to offload processing to the
DSP (providing potential cost savings).

Finally, this also enables modules that might be able to perform
transformations of (ANY -> sink format), and this allows us to implement
such transformations.
This commit is contained in:
Arun Raghavan 2018-09-24 13:51:23 +05:30 committed by Arun Raghavan
parent cbaf278f1e
commit 01c26546fa
14 changed files with 121 additions and 14 deletions

View file

@ -121,6 +121,13 @@ void pa_sink_new_data_set_avoid_resampling(pa_sink_new_data *data, bool avoid_re
data->avoid_resampling = avoid_resampling;
}
void pa_sink_new_data_set_avoid_processing(pa_sink_new_data *data, bool avoid_processing) {
pa_assert(data);
data->avoid_processing_is_set = true;
data->avoid_processing = avoid_processing;
}
void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
pa_assert(data);
@ -272,7 +279,7 @@ pa_sink* pa_sink_new(
s->sample_spec = data->sample_spec;
s->channel_map = data->channel_map;
s->default_sample_rate = s->sample_spec.rate;
s->default_sample_spec = s->sample_spec;
pa_sample_spec_init(&s->saved_spec);
pa_channel_map_init(&s->saved_map);
@ -286,6 +293,11 @@ pa_sink* pa_sink_new(
else
s->avoid_resampling = s->core->avoid_resampling;
if (data->avoid_processing_is_set)
s->avoid_processing = data->avoid_processing;
else
s->avoid_processing = s->core->avoid_processing;
s->inputs = pa_idxset_new(NULL, NULL);
s->n_corked = 0;
s->input_to_master = NULL;
@ -378,6 +390,7 @@ pa_sink* pa_sink_new(
pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
pa_source_new_data_set_alternate_sample_rate(&source_data, s->alternate_sample_rate);
pa_source_new_data_set_avoid_resampling(&source_data, s->avoid_resampling);
pa_source_new_data_set_avoid_processing(&source_data, s->avoid_processing);
source_data.name = pa_sprintf_malloc("%s.monitor", name);
source_data.driver = data->driver;
source_data.module = data->module;
@ -1484,13 +1497,16 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
int pa_sink_reconfigure(pa_sink *s, pa_sample_spec *spec, pa_channel_map *map, bool passthrough, bool restore) {
int ret = -1;
pa_sample_spec desired_spec;
uint32_t default_rate = s->default_sample_rate;
pa_sample_format_t default_format = s->default_sample_spec.format;
uint32_t default_rate = s->default_sample_spec.rate;
uint32_t alternate_rate = s->alternate_sample_rate;
uint8_t default_channels = s->default_sample_spec.channels;
uint32_t idx;
pa_sink_input *i;
bool default_rate_is_usable = false;
bool alternate_rate_is_usable = false;
bool avoid_resampling = s->avoid_resampling;
bool avoid_processing = s->avoid_processing;
pa_channel_map old_map, *new_map;
pa_assert(restore || (spec != NULL));
@ -1502,7 +1518,7 @@ int pa_sink_reconfigure(pa_sink *s, pa_sample_spec *spec, pa_channel_map *map, b
if (!s->reconfigure)
return -1;
if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough && !restore && !avoid_resampling)) {
if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough && !restore && !avoid_resampling && !avoid_processing)) {
pa_log_debug("Default and alternate sample rates are the same, so there is no point in switching.");
return -1;
}
@ -1541,13 +1557,22 @@ int pa_sink_reconfigure(pa_sink *s, pa_sample_spec *spec, pa_channel_map *map, b
/* We have to try to use the sink input spec */
desired_spec = *spec;
} else if (avoid_processing) {
desired_spec = s->sample_spec;
if (spec->rate >= default_rate || spec->rate >= alternate_rate)
desired_spec.rate = spec->rate;
if (spec->channels >= default_channels)
desired_spec.channels = spec->channels;
if (pa_sample_size_of_format(spec->format) >= pa_sample_size_of_format(default_format))
desired_spec.format = spec->format;
} else if (avoid_resampling) {
/* We just try to set the sink input's sample rate if it's not too low */
desired_spec = s->sample_spec;
if (spec->rate >= default_rate || spec->rate >= alternate_rate)
desired_spec.rate = spec->rate;
/* FIXME: don't set this if it's too low */
desired_spec.format = spec->format;
} else if (default_rate == spec->rate || alternate_rate == spec->rate) {
/* We can directly try to use this rate */