[PATCH 18/25] raop: Set precise wake up timer for rtpoll

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

 



Due to timer precision limitation, poll(2) may sleep longer or
shorter than originally specified. Therefore it is not safe to
always specify the fixed sleep interval for poll(2)
(pa_rtpoll_set_timer_relative()) when executing some periodic
tasks that are sensitive to precise timing.

This patch calculates when the thread should wake up to transmit
the next audio packet, and try to amortize the jitter caused by
the actual poll sleep duration.

This patch eliminates the audio glitch issue in Pioneer VSX-43
(and possibly in other devices as well).
---
 src/modules/raop/module-raop-sink.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/modules/raop/module-raop-sink.c b/src/modules/raop/module-raop-sink.c
index c6008e9..0038bad 100644
--- a/src/modules/raop/module-raop-sink.c
+++ b/src/modules/raop/module-raop-sink.c
@@ -669,6 +669,11 @@ finish:
 }
 
 static void udp_thread_func(struct userdata *u) {
+    /* Sleep interval per audio packet */
+    pa_usec_t sleep_interval = pa_bytes_to_usec(u->block_size,
+                                              &u->sink->sample_spec);
+    pa_usec_t wakeup_target = 0; /* Next wakeup target clock (in us) */
+
     pa_assert(u);
 
     pa_log_debug("UDP thread starting up");
@@ -753,7 +758,17 @@ static void udp_thread_func(struct userdata *u) {
         pa_assert(u->encoded_memchunk.length > 0);
 
         pa_raop_client_udp_send_audio_packet(u->raop, &u->encoded_memchunk, &written);
-        pa_rtpoll_set_timer_relative(u->rtpoll, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
+
+        /* Determine when to wake up next:
+           next_target = prev_target + interval, unless we passed
+           prev_target + interval.
+           In such a case just sleep for one interval */
+        if (wakeup_target + sleep_interval < pa_rtclock_now())
+            wakeup_target = pa_rtclock_now() + sleep_interval;
+        else
+            wakeup_target += sleep_interval;
+        /* Sleep until next packet transmission */
+        pa_rtpoll_set_timer_absolute(u->rtpoll, wakeup_target);
 
         pa_assert(written != 0);
 
-- 
1.8.1.2



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

  Powered by Linux