[PATCH] bluetooth-device: Add safe guard against BT streaming irregularities.

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

 



Some bad quality BT-headsets block bluez socket sometimes for hundreds
of milliseconds, especially when changing mode. When the module tries
catch up the lost time it may SBC encode up to half a second of audio
without yielding. On slow machine this may cause maximum RT time slice
to be exceeded.
---
 src/modules/bluetooth/module-bluetooth-device.c |   27 ++++++++++++++++++----
 1 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index ecb5e83..2a70496 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -174,6 +174,8 @@ struct userdata {
 #define FIXED_LATENCY_PLAYBACK_HSP (125*PA_USEC_PER_MSEC)
 #define FIXED_LATENCY_RECORD_HSP (25*PA_USEC_PER_MSEC)
 
+#define MAX_PLAYBACK_CATCH_UP_USEC (100*PA_USEC_PER_MSEC)
+
 #ifdef NOKIA
 #define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
 #endif
@@ -1296,15 +1298,27 @@ static void thread_func(void *userdata) {
 
                 if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && do_write <= 0 && writable) {
                     pa_usec_t time_passed;
-                    uint64_t should_have_written;
+                    pa_usec_t audio_sent;
 
                     /* Hmm, there is no input stream we could synchronize
                      * to. So let's do things by time */
 
                     time_passed = pa_rtclock_usec() - u->started_at;
-                    should_have_written = pa_usec_to_bytes(time_passed, &u->sample_spec);
-
-                    do_write = u->write_index <= should_have_written;
+                    audio_sent = pa_bytes_to_usec(u->write_index, &u->sample_spec);
+
+                    if (audio_sent <= time_passed) {
+                        pa_usec_t audio_to_send = time_passed - audio_sent;
+                        if (u->write_index > 0 && audio_to_send > MAX_PLAYBACK_CATCH_UP_USEC) {
+                            pa_usec_t skip_usec = audio_to_send - MAX_PLAYBACK_CATCH_UP_USEC;
+                            uint64_t skip_bytes = pa_usec_to_bytes(skip_usec, &u->sample_spec);
+                            pa_memchunk tmp;
+                            pa_log_warn("Skipping %lld us (= %lld bytes) in audio stream", skip_usec, skip_bytes);
+                            pa_sink_render_full(u->sink, skip_bytes, &tmp);
+                            pa_memblock_unref(tmp.memblock);
+                            u->write_index += skip_bytes;
+                        }
+                        do_write = 1;
+                    }
                 }
 
                 if (writable && do_write > 0) {
@@ -1822,8 +1836,11 @@ static int start_thread(struct userdata *u) {
 
 #ifdef NOKIA
     if (USE_SCO_OVER_PCM(u)) {
-        if (start_stream_fd(u) < 0)
+        if (start_stream_fd(u) < 0) {
+            u->sink = NULL;
+            u->source = NULL;
             return -1;
+        }
 
         pa_sink_ref(u->sink);
         pa_source_ref(u->source);
-- 
1.5.6.3




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

  Powered by Linux