Draft: bluetooth: Switch codecs without tearing down sink/source/thread
Implement codec switching without tearing down state. This speeds things up and prevents temporarily switching to another sink output (ie. blasting audio over speakers). Additionally it paves the way to implementing reconfiguration support, where the BT connection follows (if codec/capabilities allow) the native sampling rate of input audio/sink without resampling.
The main source of routing audio to another sink on codec switch is the
PA sink disappearing, together with its IO thread and other primitives.
This is annoying for users but also wasteful; all we need to do for a
codec switch is make the sink temporarily unavailable, release the
transport, perform the usual
SetConfiguration on another
Acquire the resulting stream that is made available, to finally
reconfigure the sink with the new sampling rate and format and make it available again.
When switching codecs that change MTU write-buffer size:
E: [bluetooth] source-output.c: Assertion 'pa_frame_aligned(chunk->length, &o->source->sample_spec)' failed at ../pulseaudio/src/pulsecore/source-output.c:754, function pa_source_output_push(). Aborting.
It seems the source did not get reconfigured properly while the
D: [bluetooth] sink-input.c: Requesting rewind due to corking D: [pulseaudio] sink.c: Suspending sink bluez_sink.XXX.a2dp_sink due to changing format, desired format = float32le rate = 44100 I: [pulseaudio] sink.c: bluez_sink.XXX.a2dp_sink: format: s24le -> float32le I: [pulseaudio] sink.c: Reconfigured successfully D: [pulseaudio] resampler.c: Resampler: D: [pulseaudio] resampler.c: rate 88200 -> 44100 (method speex-float-1) D: [pulseaudio] resampler.c: format s16le -> float32le (intermediate float32le) D: [pulseaudio] resampler.c: channels 2 -> 2 (resampling 2) I: [pulseaudio] speex.c: Choosing speex quality setting 1. D: [pulseaudio] memblockq.c: memblockq requested: maxlength=33554432, tlength=0, base=8, prebuf=0, minreq=1 maxrewind=0 D: [pulseaudio] memblockq.c: memblockq sanitized: maxlength=33554432, tlength=33554432, base=8, prebuf=0, minreq=8 maxrewind=0 D: [pulseaudio] sink-input.c: Updated resampler for sink input 7
And overall handling of implicit and explicit state transitions is beyond confusing :/. Feedback on improving this is welcome, considering that later changes will initiate a codec switch (until we implement
AVDTP_RECONFIGURE_CMD in BlueZ) from
This things will be or are already being looked into following this MR:
- Implement caps renegotation for GStreamer, without destroying and recreating
- Unify codec variants (like LDAC HQ/SQ/MQ) so that only one, reconfigurable codec object exists for it
(fwiw this likely can't be done for aptX and aptX HD, which are different codecs entirely with different
codec_id- even though they share the same reconfigurable GST pipeline);
- Implement better negotation between
pa_sample_spec, what the enc/dec supports, and what the device reports in capabilities;
avoid_resamplingand use aforementioned negotation to find the best intersection between codec capabilities and requested
This has already been implemented, and besides sampling rate (part of caps) includes more lenient formats when supported by the encoder/decoder, rather than forcing PA to perform conversion.
Can we get bluetooth labels on MRs as well?