Currently, module-tunnel uses the default fixed latency of 250ms as fixed latency. There is no reason for such a large latency. This patch adds a parameter latency_msec to the module to set the fixed latency at load time of the module. The parameter can range from 5 to 500 milliseconds. With this patch, I was able to run a tunnel sink at 7ms latency without problems. --- src/modules/module-tunnel.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index c21c7847..2068deca 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -79,6 +79,7 @@ PA_MODULE_USAGE( "format=<sample format> " "channels=<number of channels> " "rate=<sample rate> " + "latency_msec=<fixed latency in ms> " "channel_map=<channel map>"); #else PA_MODULE_DESCRIPTION("Tunnel module for sources"); @@ -92,6 +93,7 @@ PA_MODULE_USAGE( "format=<sample format> " "channels=<number of channels> " "rate=<sample rate> " + "latency_msec=<fixed latency in ms> " "channel_map=<channel map>"); #endif @@ -106,6 +108,7 @@ static const char* const valid_modargs[] = { "format", "channels", "rate", + "latency_msec", #ifdef TUNNEL_SINK "sink_name", "sink_properties", @@ -135,8 +138,7 @@ enum { SINK_MESSAGE_POST }; -#define DEFAULT_TLENGTH_MSEC 150 -#define DEFAULT_MINREQ_MSEC 25 +#define DEFAULT_LATENCY_MSEC 100 #else @@ -147,7 +149,7 @@ enum { SOURCE_MESSAGE_GET_LATENCY_SNAPSHOT }; -#define DEFAULT_FRAGSIZE_MSEC 25 +#define DEFAULT_LATENCY_MSEC 25 #endif @@ -213,6 +215,7 @@ struct userdata { uint32_t ctag; uint32_t device_index; uint32_t channel; + uint32_t latency; int64_t counter; uint64_t receive_counter; @@ -1672,11 +1675,11 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t u->maxlength = 4*1024*1024; #ifdef TUNNEL_SINK - u->tlength = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &u->sink->sample_spec); - u->minreq = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &u->sink->sample_spec); + u->tlength = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * u->latency, &u->sink->sample_spec); + u->minreq = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * u->latency / 4, &u->sink->sample_spec); u->prebuf = u->tlength; #else - u->fragsize = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &u->source->sample_spec); + u->fragsize = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * u->latency, &u->source->sample_spec); #endif #ifdef TUNNEL_SINK @@ -1946,6 +1949,7 @@ int pa__init(pa_module*m) { pa_sample_spec ss; pa_channel_map map; char *dn = NULL; + uint32_t latency_msec; #ifdef TUNNEL_SINK pa_sink_new_data data; #else @@ -2009,6 +2013,15 @@ int pa__init(pa_module*m) { goto fail; } + /* Allow latencies between 5ms and 500ms */ + latency_msec = DEFAULT_LATENCY_MSEC; + if (pa_modargs_get_value_u32(ma, "latency_msec", &latency_msec) < 0 || latency_msec < 5 || latency_msec > 500) { + pa_log("Invalid latency specification"); + goto fail; + } + + u->latency = latency_msec; + cookie_path = pa_modargs_get_value(ma, "cookie", NULL); server = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)); @@ -2190,6 +2203,7 @@ int pa__init(pa_module*m) { pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); + pa_sink_set_fixed_latency(u->sink, latency_msec * PA_USEC_PER_MSEC); #else @@ -2230,6 +2244,7 @@ int pa__init(pa_module*m) { pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); pa_source_set_rtpoll(u->source, u->rtpoll); + pa_source_set_fixed_latency(u->source, latency_msec * PA_USEC_PER_MSEC); u->mcalign = pa_mcalign_new(pa_frame_size(&u->source->sample_spec)); #endif -- 2.14.1