[pulseaudio-commits] Branch 'next' - 2 commits - src/modules
Georg Chini
gchini at kemper.freedesktop.org
Tue Feb 20 20:37:42 UTC 2018
src/modules/module-loopback.c | 174 ++++++++++++++++++++++++------------------
1 file changed, 100 insertions(+), 74 deletions(-)
New commits:
commit 8e4053905f9078fd80c2a381dfc1f20a998cdeb8
Author: Raman Shyshniou <rommer at ibuffed.com>
Date: Tue Feb 20 21:32:57 2018 +0100
loopback: use source sample spec and channel map by default
Currently the loopback module uses sample spec and channel map of the
sink by default. It leads to double resample if source and sink sample
specs are different and no rate/format specified in arguments. This
patch causes the source sample spec and channel map to be used by
default.
diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index 19005e8e..31702e32 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -1300,15 +1300,15 @@ int pa__init(pa_module *m) {
goto fail;
}
- if (sink) {
- ss = sink->sample_spec;
- map = sink->channel_map;
+ if (source) {
+ ss = source->sample_spec;
+ map = source->channel_map;
format_set = true;
rate_set = true;
channels_set = true;
- } else if (source) {
- ss = source->sample_spec;
- map = source->channel_map;
+ } else if (sink) {
+ ss = sink->sample_spec;
+ map = sink->channel_map;
format_set = true;
rate_set = true;
channels_set = true;
@@ -1389,6 +1389,70 @@ int pa__init(pa_module *m) {
u->real_adjust_time = u->adjust_time;
+ pa_source_output_new_data_init(&source_output_data);
+ source_output_data.driver = __FILE__;
+ source_output_data.module = m;
+ if (source)
+ pa_source_output_new_data_set_source(&source_output_data, source, false, true);
+
+ if (pa_modargs_get_proplist(ma, "source_output_properties", source_output_data.proplist, PA_UPDATE_REPLACE) < 0) {
+ pa_log("Failed to parse the source_output_properties value.");
+ pa_source_output_new_data_done(&source_output_data);
+ goto fail;
+ }
+
+ if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ROLE))
+ pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
+
+ pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
+ pa_source_output_new_data_set_channel_map(&source_output_data, &map);
+ source_output_data.flags = PA_SOURCE_OUTPUT_START_CORKED;
+
+ if (!remix)
+ source_output_data.flags |= PA_SOURCE_OUTPUT_NO_REMIX;
+
+ if (!format_set)
+ source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_FORMAT;
+
+ if (!rate_set)
+ source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_RATE;
+
+ if (!channels_set)
+ source_output_data.flags |= PA_SOURCE_OUTPUT_FIX_CHANNELS;
+
+ source_dont_move = false;
+ if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) {
+ pa_log("source_dont_move= expects a boolean argument.");
+ goto fail;
+ }
+
+ if (source_dont_move)
+ source_output_data.flags |= PA_SOURCE_OUTPUT_DONT_MOVE;
+
+ pa_source_output_new(&u->source_output, m->core, &source_output_data);
+ pa_source_output_new_data_done(&source_output_data);
+
+ if (!u->source_output)
+ goto fail;
+
+ u->source_output->parent.process_msg = source_output_process_msg_cb;
+ u->source_output->push = source_output_push_cb;
+ u->source_output->process_rewind = source_output_process_rewind_cb;
+ u->source_output->kill = source_output_kill_cb;
+ u->source_output->attach = source_output_attach_cb;
+ u->source_output->detach = source_output_detach_cb;
+ u->source_output->may_move_to = source_output_may_move_to_cb;
+ u->source_output->moving = source_output_moving_cb;
+ u->source_output->suspend = source_output_suspend_cb;
+ u->source_output->update_source_latency_range = update_source_latency_range_cb;
+ u->source_output->update_source_fixed_latency = update_source_latency_range_cb;
+ u->source_output->userdata = u;
+
+ /* If format, rate or channels were originally unset, they are set now
+ * after the pa_source_output_new() call. */
+ ss = u->source_output->sample_spec;
+ map = u->source_output->channel_map;
+
pa_sink_input_new_data_init(&sink_input_data);
sink_input_data.driver = __FILE__;
sink_input_data.module = m;
@@ -1412,15 +1476,6 @@ int pa__init(pa_module *m) {
if (!remix)
sink_input_data.flags |= PA_SINK_INPUT_NO_REMIX;
- if (!format_set)
- sink_input_data.flags |= PA_SINK_INPUT_FIX_FORMAT;
-
- if (!rate_set)
- sink_input_data.flags |= PA_SINK_INPUT_FIX_RATE;
-
- if (!channels_set)
- sink_input_data.flags |= PA_SINK_INPUT_FIX_CHANNELS;
-
sink_dont_move = false;
if (pa_modargs_get_value_boolean(ma, "sink_dont_move", &sink_dont_move) < 0) {
pa_log("sink_dont_move= expects a boolean argument.");
@@ -1436,11 +1491,6 @@ int pa__init(pa_module *m) {
if (!u->sink_input)
goto fail;
- /* If format, rate or channels were originally unset, they are set now
- * after the pa_sink_input_new() call. */
- ss = u->sink_input->sample_spec;
- map = u->sink_input->channel_map;
-
u->sink_input->parent.process_msg = sink_input_process_msg_cb;
u->sink_input->pop = sink_input_pop_cb;
u->sink_input->process_rewind = sink_input_process_rewind_cb;
@@ -1457,56 +1507,6 @@ int pa__init(pa_module *m) {
u->sink_input->update_sink_fixed_latency = update_sink_latency_range_cb;
u->sink_input->userdata = u;
- pa_source_output_new_data_init(&source_output_data);
- source_output_data.driver = __FILE__;
- source_output_data.module = m;
- if (source)
- pa_source_output_new_data_set_source(&source_output_data, source, false, true);
-
- if (pa_modargs_get_proplist(ma, "source_output_properties", source_output_data.proplist, PA_UPDATE_REPLACE) < 0) {
- pa_log("Failed to parse the source_output_properties value.");
- pa_source_output_new_data_done(&source_output_data);
- goto fail;
- }
-
- if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ROLE))
- pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
-
- pa_source_output_new_data_set_sample_spec(&source_output_data, &ss);
- pa_source_output_new_data_set_channel_map(&source_output_data, &map);
- source_output_data.flags = PA_SOURCE_OUTPUT_START_CORKED;
-
- if (!remix)
- source_output_data.flags |= PA_SOURCE_OUTPUT_NO_REMIX;
-
- source_dont_move = false;
- if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) {
- pa_log("source_dont_move= expects a boolean argument.");
- goto fail;
- }
-
- if (source_dont_move)
- source_output_data.flags |= PA_SOURCE_OUTPUT_DONT_MOVE;
-
- pa_source_output_new(&u->source_output, m->core, &source_output_data);
- pa_source_output_new_data_done(&source_output_data);
-
- if (!u->source_output)
- goto fail;
-
- u->source_output->parent.process_msg = source_output_process_msg_cb;
- u->source_output->push = source_output_push_cb;
- u->source_output->process_rewind = source_output_process_rewind_cb;
- u->source_output->kill = source_output_kill_cb;
- u->source_output->attach = source_output_attach_cb;
- u->source_output->detach = source_output_detach_cb;
- u->source_output->may_move_to = source_output_may_move_to_cb;
- u->source_output->moving = source_output_moving_cb;
- u->source_output->suspend = source_output_suspend_cb;
- u->source_output->update_source_latency_range = update_source_latency_range_cb;
- u->source_output->update_source_fixed_latency = update_source_latency_range_cb;
- u->source_output->userdata = u;
-
update_latency_boundaries(u, u->source_output->source, u->sink_input->sink);
set_sink_input_latency(u, u->sink_input->sink);
set_source_output_latency(u, u->source_output->source);
commit 3eb29159f3d9ddd10a156f4c292cf7cbf9841689
Author: Raman Shyshniou <rommer at ibuffed.com>
Date: Tue Feb 20 21:29:16 2018 +0100
loopback: add max_latency_msec argument
Currently loopback module indefinitely increases latency if underruns
occur. This patch allows to set up the upper limit of latency.
diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index aecac0ab..19005e8e 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -45,6 +45,7 @@ PA_MODULE_USAGE(
"sink=<sink to connect to> "
"adjust_time=<how often to readjust rates in s> "
"latency_msec=<latency in ms> "
+ "max_latency_msec=<maximum latency in ms> "
"format=<sample format> "
"rate=<sample rate> "
"channels=<number of channels> "
@@ -89,6 +90,7 @@ struct userdata {
/* Values from command line configuration */
pa_usec_t latency;
+ pa_usec_t max_latency;
pa_usec_t adjust_time;
/* Latency boundaries and current values */
@@ -158,6 +160,7 @@ static const char* const valid_modargs[] = {
"sink",
"adjust_time",
"latency_msec",
+ "max_latency_msec",
"format",
"rate",
"channels",
@@ -325,10 +328,20 @@ static void adjust_rates(struct userdata *u) {
/* If we are seeing underruns then the latency is too small */
if (u->underrun_counter > 2) {
- u->underrun_latency_limit = PA_MAX(u->latency, u->minimum_latency) + 5 * PA_USEC_PER_MSEC;
- u->underrun_latency_limit = PA_CLIP_SUB((int64_t)u->underrun_latency_limit, u->sink_latency_offset + u->source_latency_offset);
+ pa_usec_t target_latency;
+
+ target_latency = PA_MAX(u->latency, u->minimum_latency) + 5 * PA_USEC_PER_MSEC;
+
+ if (u->max_latency == 0 || target_latency < u->max_latency) {
+ u->underrun_latency_limit = PA_CLIP_SUB((int64_t)target_latency, u->sink_latency_offset + u->source_latency_offset);
+ pa_log_warn("Too many underruns, increasing latency to %0.2f ms", (double)target_latency / PA_USEC_PER_MSEC);
+ } else {
+ u->underrun_latency_limit = PA_CLIP_SUB((int64_t)u->max_latency, u->sink_latency_offset + u->source_latency_offset);
+ pa_log_warn("Too many underruns, configured maximum latency of %0.2f ms is reached", (double)u->max_latency / PA_USEC_PER_MSEC);
+ pa_log_warn("Consider increasing the max_latency_msec");
+ }
+
update_minimum_latency(u, u->sink_input->sink, false);
- pa_log_warn("Too many underruns, increasing latency to %0.2f ms", (double)u->minimum_latency / PA_USEC_PER_MSEC);
u->underrun_counter = 0;
}
@@ -347,7 +360,7 @@ static void adjust_rates(struct userdata *u) {
}
u->adjust_time_stamp = now;
- /* Rates and latencies*/
+ /* Rates and latencies */
old_rate = u->sink_input->sample_spec.rate;
base_rate = u->source_output->sample_spec.rate;
@@ -1252,6 +1265,7 @@ int pa__init(pa_module *m) {
pa_source_output_new_data source_output_data;
bool source_dont_move;
uint32_t latency_msec;
+ uint32_t max_latency_msec;
pa_sample_spec ss;
pa_channel_map map;
bool format_set = false;
@@ -1336,10 +1350,22 @@ int pa__init(pa_module *m) {
goto fail;
}
+ max_latency_msec = 0;
+ if (pa_modargs_get_value_u32(ma, "max_latency_msec", &max_latency_msec) < 0) {
+ pa_log("Invalid maximum latency specification");
+ goto fail;
+ }
+
+ if (max_latency_msec > 0 && max_latency_msec < latency_msec) {
+ pa_log_warn("Configured maximum latency is smaller than latency, using latency instead");
+ max_latency_msec = latency_msec;
+ }
+
m->userdata = u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
u->latency = (pa_usec_t) latency_msec * PA_USEC_PER_MSEC;
+ u->max_latency = (pa_usec_t) max_latency_msec * PA_USEC_PER_MSEC;
u->output_thread_info.pop_called = false;
u->output_thread_info.pop_adjust = false;
u->output_thread_info.push_called = false;
More information about the pulseaudio-commits
mailing list