[PATCH] module-loopback.c: latency optimization

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch flushes the buffer when the sink input is detached
and discards data after attaching a sink input until the pop callback
is called for the first time, thus eliminating latency arising from
slow starting sinks and from streaming to the previous sink.

----

  src/modules/module-loopback.c                             | 11 +++++++++--
  1 file changed, 9 insertions(+), 2 deletions(-)

----

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index da83894..22eadfc 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -87,6 +87,7 @@ struct userdata {
      pa_usec_t latency;

      bool in_pop;
+    bool pop_called;
      size_t min_memblockq_length;

      struct {
@@ -464,6 +465,8 @@ static int sink_input_pop_cb(pa_sink_input *i, 
size_t nbytes, pa_memchunk *chunk
      pa_assert_se(u = i->userdata);
      pa_assert(chunk);

+    if (PA_SINK_IS_RUNNING(u->sink_input->sink->thread_info.state) && 
!u->pop_called)
+        u->pop_called = true;
      u->in_pop = true;
      while (pa_asyncmsgq_process_one(u->asyncmsgq) > 0)
          ;
@@ -515,7 +518,7 @@ static int sink_input_process_msg_cb(pa_msgobject 
*obj, int code, void *data, in

              pa_sink_input_assert_io_context(u->sink_input);

-            if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
+            if 
(PA_SINK_IS_RUNNING(u->sink_input->sink->thread_info.state) && 
u->pop_called)
                  pa_memblockq_push_align(u->memblockq, chunk);
              else
                  pa_memblockq_flush_write(u->memblockq, true);
@@ -542,7 +545,7 @@ static int sink_input_process_msg_cb(pa_msgobject 
*obj, int code, void *data, in

              pa_sink_input_assert_io_context(u->sink_input);

-            if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
+            if 
(PA_SINK_IS_RUNNING(u->sink_input->sink->thread_info.state) && 
u->pop_called)
                  pa_memblockq_seek(u->memblockq, -offset, 
PA_SEEK_RELATIVE, true);
              else
                  pa_memblockq_flush_write(u->memblockq, true);
@@ -607,6 +610,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
      pa_memblockq_set_maxrewind(u->memblockq, 
pa_sink_input_get_max_rewind(i));

      u->min_memblockq_length = (size_t) -1;
+    u->pop_called = false;
  }

  /* Called from output thread context */
@@ -621,6 +625,8 @@ static void sink_input_detach_cb(pa_sink_input *i) {
          pa_rtpoll_item_free(u->rtpoll_item_read);
          u->rtpoll_item_read = NULL;
      }
+    pa_memblockq_flush_write(u->memblockq, true);
+    update_min_memblockq_length(u);
  }

  /* Called from output thread context */
@@ -820,6 +826,7 @@ int pa__init(pa_module *m) {
      u->core = m->core;
      u->module = m;
      u->latency = (pa_usec_t) latency_msec * PA_USEC_PER_MSEC;
+    u->pop_called = false;

      adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
      if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) 
< 0) {



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux