KDE bluetooth connection attempt to other computer triggers pulseaudio to increase bluetooth buffer size and results in laggy/out-of-sync sound in bluetooth headset playback
I originally opened a bug report over at bugs.kde.org, but after further investigation and email correspondence with @gchini, Georg suggested to open a bug report here.
I will summarize the issue here; for the full initial investigation, please see KDE Bugtracker Issue 415976.
I am using a setup of:
- Desktop computer with KDE, Pulseaudio, USB bluetooth dongle, Bose bluetooth headset
- Notebook with KDE, Pulseaudio, built in bluetooth.
When I connect my bluetooth headset to the Desktop computer, Pulseaudio will initially set the buffer size to 5120. This is perfectly fine (not laggy and in-sync) when playing a video game like gzdoom:
- I: [bluetooth] module-bluez5-device.c: Changing bluetooth buffer size: Changed from 106496 to 5120
KDE has built-in bluetooth support. An applet in the systray allows to establish a bluetooth connection between two computers. I actually do not use this feature, but somehow my desktop and notebook started trying to connect each other (maybe I once paired them and so they remembered each other) automatically. But a connection attempt can also triggered manually by pressing a "connect" button in the applet.
Whenever a automatic/manual connection attempt is initiated by the desktop to the notebook for the first time while playing audio on the desktop to the bluetooth headset, the audio will begin to stutter shortly and pulseaudio will increase the bluetooth buffer size as follows (interestingly, this will not happen when it is the notebook which initiates the bluetooth connection to the desktop):
- I: [bluetooth] module-bluez5-device.c: Changing bluetooth buffer size: Changed from 5120 to 6144
- I: [bluetooth] module-bluez5-device.c: Changing bluetooth buffer size: Changed from 6144 to 7168
- I: [bluetooth] module-bluez5-device.c: Changing bluetooth buffer size: Changed from 7168 to 8192
Afterwards the playback of audio continues, which is fine for the use case of listening to music, but it will be slightly laggy/out-of-sync in case of a video game. In case of gzdoom, I can notice that the audio (e.g. gunfire sound) will lag slightly behind the animation after the buffer increase event happened. The buffer is never decreased again, and the audio stays laggy/out of sync (even if I stop and restart the video game), until I disconnect and reconnect the headset again or stop playing audio for a while, so that module-suspend-on-idle will suspend the headset, which both resets the buffer again to 5120 on next audio playback:
- I: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.04_52_C7_F0_4A_4C.a2dp_sink idle for too long, suspending ...
- I: [bluetooth] bluez5-util.c: Transport /org/bluez/hci0/dev_04_52_C7_F0_4A_4C/sep1/fd2 released
- I: [pulseaudio] core.c: All sinks and sources are suspended, vacuuming memory
- I: [bluetooth] module-bluez5-device.c: Transport /org/bluez/hci0/dev_04_52_C7_F0_4A_4C/sep1/fd2 acquired: fd 36
- I: [bluetooth] module-bluez5-device.c: Transport /org/bluez/hci0/dev_04_52_C7_F0_4A_4C/sep1/fd2 resuming
- I: [bluetooth] module-bluez5-device.c: Changing bluetooth buffer size: Changed from 8192 to 5120
So, for me it seems that the increased buffer size is causing the audio lag / out-of-sync audio stream, even though @gchini explained to me, that the change of the buffer size is happening because there is some delay in the audio, so it is a reaction to the delay, not the cause.
During the initial discussion with @gchini, he suggested to change the following line:
size_t new_write_block_size = u->a2dp_codec->reduce_encoder_bitrate(u->encoder_info, u->write_link_mtu);
to
size_t new_write_block_size = 0;
in module-bluez5-device.c.
Having changed this, the audio would stutter for a short time on a KDE bluetooth connection attempt like before, but then continuing to play normally - until the next connection attemp, when it stutters again. But this way the audio will continuously stay in sync with the video game, which seems a to be an acceptable solution for me.
Maybe someone (@gchini mentioned that @pali is working on a large change set to include Bluetooth codec selection) will have some other ideas how to fix this behaviour, otherwise I would suggest to offer an user settable parameter for the module-bluez5-device, so users can deactivate the call to reduce_encoder_bitrate function / dynamic buffer increase if desired.
Let me know if you need more information from my side.
Software (Desktop; Notebook similar):
- Pulseaudio: 13.0
- Bluez: 5.52
- Linux: 5.4.10-gentoo-x86_64
- KDE Plasma Version: 5.17.4
- KDE Frameworks Version: 5.64.0
- Qt Version: 5.13.2
Hardware (Desktop):
- Processor: AMD Ryzen 7 3700X 8-Core Processor AuthenticAMD GNU/Linux
- Mainboard: B450 MSI Mortar Max
- USB dongle: LogiLink USB Bluetooth Adapter Micro (V4.0 EDR Class1), lsusb: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
- Headset: Bose Quiet Comfort QC35
Hardware (Notebook):
- Dell Latitude E6400
- lsusb related to bluetooth: ID 413c:8156 Dell Computer Corp. Wireless 370 Bluetooth Mini-card
- another entry: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth)