mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
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:
parent
cbaf278f1e
commit
01c26546fa
14 changed files with 121 additions and 14 deletions
|
|
@ -132,6 +132,16 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
|||
rates.</p>
|
||||
</option>
|
||||
|
||||
<option>
|
||||
<p><opt>avoid-processing=</opt> If set, try to configure the
|
||||
device to avoid resampling, sample format conversion and channel mixing. This only works on devices which
|
||||
support such reconfiguration, and when no other streams are
|
||||
already playing or capturing audio. The device will also not be
|
||||
configured to a rate less than the default and alternate sample
|
||||
rates, a channel count less than the default channels, or a sample
|
||||
format that is smaller than the default sample format.</p>
|
||||
</option>
|
||||
|
||||
<option>
|
||||
<p><opt>enable-remixing=</opt> If disabled never upmix or
|
||||
downmix channels to different channel maps. Instead, do a simple
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ static const pa_daemon_conf default_conf = {
|
|||
.log_time = false,
|
||||
.resample_method = PA_RESAMPLER_AUTO,
|
||||
.avoid_resampling = false,
|
||||
.avoid_processing = false,
|
||||
.disable_remixing = false,
|
||||
.remixing_use_all_sink_channels = true,
|
||||
.remixing_produce_lfe = false,
|
||||
|
|
@ -606,6 +607,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
|
|||
pa_config_parse_int, &c->deferred_volume_extra_delay_usec, NULL },
|
||||
{ "nice-level", parse_nice_level, c, NULL },
|
||||
{ "avoid-resampling", pa_config_parse_bool, &c->avoid_resampling, NULL },
|
||||
{ "avoid-processing", pa_config_parse_bool, &c->avoid_processing, NULL },
|
||||
{ "disable-remixing", pa_config_parse_bool, &c->disable_remixing, NULL },
|
||||
{ "enable-remixing", pa_config_parse_not_bool, &c->disable_remixing, NULL },
|
||||
{ "remixing-use-all-sink-channels",
|
||||
|
|
@ -819,6 +821,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
|
|||
pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
|
||||
pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
|
||||
pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(c->avoid_resampling));
|
||||
pa_strbuf_printf(s, "avoid-processing = %s\n", pa_yes_no(c->avoid_processing));
|
||||
pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
|
||||
pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels));
|
||||
pa_strbuf_printf(s, "remixing-produce-lfe = %s\n", pa_yes_no(c->remixing_produce_lfe));
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ typedef struct pa_daemon_conf {
|
|||
disable_shm,
|
||||
disable_memfd,
|
||||
avoid_resampling,
|
||||
avoid_processing,
|
||||
disable_remixing,
|
||||
remixing_use_all_sink_channels,
|
||||
remixing_produce_lfe,
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ ifelse(@HAVE_DBUS@, 1, [dnl
|
|||
|
||||
; resample-method = speex-float-1
|
||||
; avoid-resampling = false
|
||||
; avoid-processing = false
|
||||
; enable-remixing = yes
|
||||
; remixing-use-all-sink-channels = yes
|
||||
; remixing-produce-lfe = no
|
||||
|
|
|
|||
|
|
@ -1208,6 +1208,7 @@ int main(int argc, char *argv[]) {
|
|||
c->realtime_priority = conf->realtime_priority;
|
||||
c->realtime_scheduling = conf->realtime_scheduling;
|
||||
c->avoid_resampling = conf->avoid_resampling;
|
||||
c->avoid_processing = conf->avoid_processing;
|
||||
c->disable_remixing = conf->disable_remixing;
|
||||
c->remixing_use_all_sink_channels = conf->remixing_use_all_sink_channels;
|
||||
c->remixing_produce_lfe = conf->remixing_produce_lfe;
|
||||
|
|
|
|||
|
|
@ -2348,6 +2348,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
bool b;
|
||||
bool d;
|
||||
bool avoid_resampling;
|
||||
bool avoid_processing;
|
||||
pa_sink_new_data data;
|
||||
bool volume_is_set;
|
||||
bool mute_is_set;
|
||||
|
|
@ -2364,6 +2365,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
ss = m->core->default_sample_spec;
|
||||
map = m->core->default_channel_map;
|
||||
avoid_resampling = m->core->avoid_resampling;
|
||||
avoid_processing = m->core->avoid_processing;
|
||||
|
||||
/* Pick sample spec overrides from the mapping, if any */
|
||||
if (mapping) {
|
||||
|
|
@ -2640,6 +2642,13 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
}
|
||||
pa_sink_new_data_set_avoid_resampling(&data, avoid_resampling);
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "avoid_processing", &avoid_processing) < 0) {
|
||||
pa_log("Failed to parse avoid_processing argument.");
|
||||
pa_sink_new_data_done(&data);
|
||||
goto fail;
|
||||
}
|
||||
pa_sink_new_data_set_avoid_processing(&data, avoid_processing);
|
||||
|
||||
pa_sink_new_data_set_sample_spec(&data, &ss);
|
||||
pa_sink_new_data_set_channel_map(&data, &map);
|
||||
pa_sink_new_data_set_alternate_sample_rate(&data, alternate_sample_rate);
|
||||
|
|
|
|||
|
|
@ -2050,6 +2050,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
bool b;
|
||||
bool d;
|
||||
bool avoid_resampling;
|
||||
bool avoid_processing;
|
||||
pa_source_new_data data;
|
||||
bool volume_is_set;
|
||||
bool mute_is_set;
|
||||
|
|
@ -2062,6 +2063,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
ss = m->core->default_sample_spec;
|
||||
map = m->core->default_channel_map;
|
||||
avoid_resampling = m->core->avoid_resampling;
|
||||
avoid_processing = m->core->avoid_processing;
|
||||
|
||||
/* Pick sample spec overrides from the mapping, if any */
|
||||
if (mapping) {
|
||||
|
|
@ -2320,6 +2322,13 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
|
|||
}
|
||||
pa_source_new_data_set_avoid_resampling(&data, avoid_resampling);
|
||||
|
||||
if (pa_modargs_get_value_boolean(ma, "avoid_processing", &avoid_processing) < 0) {
|
||||
pa_log("Failed to parse avoid_processing argument.");
|
||||
pa_source_new_data_done(&data);
|
||||
goto fail;
|
||||
}
|
||||
pa_source_new_data_set_avoid_processing(&data, avoid_processing);
|
||||
|
||||
pa_source_new_data_set_sample_spec(&data, &ss);
|
||||
pa_source_new_data_set_channel_map(&data, &map);
|
||||
pa_source_new_data_set_alternate_sample_rate(&data, alternate_sample_rate);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ PA_MODULE_USAGE(
|
|||
"paths_dir=<directory containing the path configuration files> "
|
||||
"use_ucm=<load use case manager> "
|
||||
"avoid_resampling=<use stream original sample rate if possible?> "
|
||||
"avoid_processing=<use stream original sample spec if possible?> "
|
||||
"control=<name of mixer control> "
|
||||
);
|
||||
|
||||
|
|
@ -98,6 +99,7 @@ static const char* const valid_modargs[] = {
|
|||
"paths_dir",
|
||||
"use_ucm",
|
||||
"avoid_resampling",
|
||||
"avoid_processing",
|
||||
"control",
|
||||
NULL
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ PA_MODULE_USAGE(
|
|||
"ignore_dB=<ignore dB information from the device?> "
|
||||
"deferred_volume=<syncronize sw and hw volume changes in IO-thread?> "
|
||||
"use_ucm=<use ALSA UCM for card configuration?> "
|
||||
"avoid_resampling=<use stream original sample rate if possible?>");
|
||||
"avoid_resampling=<use stream original sample spec if possible?> "
|
||||
"avoid_processing=<use stream original sample spec if possible?>");
|
||||
|
||||
struct device {
|
||||
char *path;
|
||||
|
|
@ -70,6 +71,7 @@ struct userdata {
|
|||
bool deferred_volume:1;
|
||||
bool use_ucm:1;
|
||||
bool avoid_resampling:1;
|
||||
bool avoid_processing:1;
|
||||
|
||||
uint32_t tsched_buffer_size;
|
||||
|
||||
|
|
@ -89,6 +91,7 @@ static const char* const valid_modargs[] = {
|
|||
"deferred_volume",
|
||||
"use_ucm",
|
||||
"avoid_resampling",
|
||||
"avoid_processing",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -415,6 +418,7 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
|
|||
"deferred_volume=%s "
|
||||
"use_ucm=%s "
|
||||
"avoid_resampling=%s "
|
||||
"avoid_processing=%s "
|
||||
"card_properties=\"module-udev-detect.discovered=1\"",
|
||||
path_get_card_id(path),
|
||||
n,
|
||||
|
|
@ -424,7 +428,8 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
|
|||
pa_yes_no(u->ignore_dB),
|
||||
pa_yes_no(u->deferred_volume),
|
||||
pa_yes_no(u->use_ucm),
|
||||
pa_yes_no(u->avoid_resampling));
|
||||
pa_yes_no(u->avoid_resampling),
|
||||
pa_yes_no(u->avoid_processing));
|
||||
pa_xfree(n);
|
||||
|
||||
if (u->tsched_buffer_size_valid)
|
||||
|
|
@ -698,6 +703,7 @@ int pa__init(pa_module *m) {
|
|||
bool use_tsched = true, fixed_latency_range = false, ignore_dB = false, deferred_volume = m->core->deferred_volume;
|
||||
bool use_ucm = true;
|
||||
bool avoid_resampling;
|
||||
bool avoid_processing;
|
||||
|
||||
pa_assert(m);
|
||||
|
||||
|
|
@ -757,6 +763,13 @@ int pa__init(pa_module *m) {
|
|||
}
|
||||
u->avoid_resampling = avoid_resampling;
|
||||
|
||||
avoid_processing = m->core->avoid_processing;
|
||||
if (pa_modargs_get_value_boolean(ma, "avoid_processing", &avoid_processing) < 0) {
|
||||
pa_log("Failed to parse avoid_processing= argument.");
|
||||
goto fail;
|
||||
}
|
||||
u->avoid_processing = avoid_processing;
|
||||
|
||||
if (!(u->udev = udev_new())) {
|
||||
pa_log("Failed to initialize udev library.");
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ struct pa_core {
|
|||
bool running_as_daemon:1;
|
||||
bool realtime_scheduling:1;
|
||||
bool avoid_resampling:1;
|
||||
bool avoid_processing:1;
|
||||
bool disable_remixing:1;
|
||||
bool remixing_use_all_sink_channels:1;
|
||||
bool remixing_produce_lfe:1;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -81,9 +81,10 @@ struct pa_sink {
|
|||
|
||||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
uint32_t default_sample_rate;
|
||||
pa_sample_spec default_sample_spec;
|
||||
uint32_t alternate_sample_rate;
|
||||
bool avoid_resampling:1;
|
||||
bool avoid_processing:1;
|
||||
|
||||
pa_idxset *inputs;
|
||||
unsigned n_corked;
|
||||
|
|
@ -385,6 +386,7 @@ typedef struct pa_sink_new_data {
|
|||
pa_channel_map channel_map;
|
||||
uint32_t alternate_sample_rate;
|
||||
bool avoid_resampling:1;
|
||||
bool avoid_processing:1;
|
||||
pa_cvolume volume;
|
||||
bool muted:1;
|
||||
|
||||
|
|
@ -392,6 +394,7 @@ typedef struct pa_sink_new_data {
|
|||
bool channel_map_is_set:1;
|
||||
bool alternate_sample_rate_is_set:1;
|
||||
bool avoid_resampling_is_set:1;
|
||||
bool avoid_processing_is_set:1;
|
||||
bool volume_is_set:1;
|
||||
bool muted_is_set:1;
|
||||
|
||||
|
|
@ -408,6 +411,7 @@ void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_sp
|
|||
void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map);
|
||||
void pa_sink_new_data_set_alternate_sample_rate(pa_sink_new_data *data, const uint32_t alternate_sample_rate);
|
||||
void pa_sink_new_data_set_avoid_resampling(pa_sink_new_data *data, bool avoid_resampling);
|
||||
void pa_sink_new_data_set_avoid_processing(pa_sink_new_data *data, bool avoid_processing);
|
||||
void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume);
|
||||
void pa_sink_new_data_set_muted(pa_sink_new_data *data, bool mute);
|
||||
void pa_sink_new_data_set_port(pa_sink_new_data *data, const char *port);
|
||||
|
|
|
|||
|
|
@ -111,6 +111,13 @@ void pa_source_new_data_set_avoid_resampling(pa_source_new_data *data, bool avoi
|
|||
data->avoid_resampling = avoid_resampling;
|
||||
}
|
||||
|
||||
void pa_source_new_data_set_avoid_processing(pa_source_new_data *data, bool avoid_processing) {
|
||||
pa_assert(data);
|
||||
|
||||
data->avoid_processing_is_set = true;
|
||||
data->avoid_processing = avoid_processing;
|
||||
}
|
||||
|
||||
void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
|
||||
pa_assert(data);
|
||||
|
||||
|
|
@ -258,7 +265,7 @@ pa_source* pa_source_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);
|
||||
|
||||
|
|
@ -272,6 +279,11 @@ pa_source* pa_source_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->outputs = pa_idxset_new(NULL, NULL);
|
||||
s->n_corked = 0;
|
||||
s->monitor_of = NULL;
|
||||
|
|
@ -1050,11 +1062,14 @@ void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *
|
|||
int pa_source_reconfigure(pa_source *s, pa_sample_spec *spec, pa_channel_map *map, bool passthrough, bool restore) {
|
||||
int ret;
|
||||
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;
|
||||
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));
|
||||
|
|
@ -1066,7 +1081,7 @@ int pa_source_reconfigure(pa_source *s, pa_sample_spec *spec, pa_channel_map *ma
|
|||
if (!s->reconfigure && !s->monitor_of)
|
||||
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;
|
||||
}
|
||||
|
|
@ -1105,13 +1120,22 @@ int pa_source_reconfigure(pa_source *s, pa_sample_spec *spec, pa_channel_map *ma
|
|||
/* We have to try to use the source output 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 source output'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 */
|
||||
|
|
|
|||
|
|
@ -82,9 +82,10 @@ struct pa_source {
|
|||
|
||||
pa_sample_spec sample_spec;
|
||||
pa_channel_map channel_map;
|
||||
uint32_t default_sample_rate;
|
||||
pa_sample_spec default_sample_spec;
|
||||
uint32_t alternate_sample_rate;
|
||||
bool avoid_resampling:1;
|
||||
bool avoid_processing:1;
|
||||
|
||||
pa_idxset *outputs;
|
||||
unsigned n_corked;
|
||||
|
|
@ -319,6 +320,7 @@ typedef struct pa_source_new_data {
|
|||
pa_channel_map channel_map;
|
||||
uint32_t alternate_sample_rate;
|
||||
bool avoid_resampling:1;
|
||||
bool avoid_processing:1;
|
||||
pa_cvolume volume;
|
||||
bool muted:1;
|
||||
|
||||
|
|
@ -328,6 +330,7 @@ typedef struct pa_source_new_data {
|
|||
bool channel_map_is_set:1;
|
||||
bool alternate_sample_rate_is_set:1;
|
||||
bool avoid_resampling_is_set:1;
|
||||
bool avoid_processing_is_set:1;
|
||||
|
||||
bool namereg_fail:1;
|
||||
|
||||
|
|
@ -342,6 +345,7 @@ void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sampl
|
|||
void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map);
|
||||
void pa_source_new_data_set_alternate_sample_rate(pa_source_new_data *data, const uint32_t alternate_sample_rate);
|
||||
void pa_source_new_data_set_avoid_resampling(pa_source_new_data *data, bool avoid_resampling);
|
||||
void pa_source_new_data_set_avoid_processing(pa_source_new_data *data, bool avoid_processing);
|
||||
void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume);
|
||||
void pa_source_new_data_set_muted(pa_source_new_data *data, bool mute);
|
||||
void pa_source_new_data_set_port(pa_source_new_data *data, const char *port);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue