Similar to the situation/comment in `endpoint_release` BlueZ does not
request any reply to `ClearConfiguration()` either; sending one results
in the same "0 matched rules" warning from dbus-daemon:
dbus-daemon[1309]: [system] Rejected send message, 0 matched rules; type="method_return", sender=":1.71" (uid=1000 pid=87548 comm="../build/src/daemon/pulseaudio -vvvv -n -F ../buil") interface="(unset)" member="(unset)" error name="(unset)" requested_reply="0" destination=":1.3" (uid=0 pid=1308 comm="/usr/lib/bluetooth/bluetoothd -d ")
Solve this by only creating a return message when an (othwise empty)
reply is solicited for, just like in `endpoint_release`.
Unfortunately we also have to make sure to not send any error back if no
reply is requested, but fortunately an argument parsing error here is
extremely unlikely.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/472>
We move the codec specific bits to their own respective files and now
make the codec specific initialisation use a GstBin, which the generic
GStreamer module now uses in the pipeline.
It is job of the codec specific function to add elements in the GstBin
and link the added elements in the bin. It should also set up the ghost
pads as a GstBin has no pads of it's own and without which the bin
cannot be linked to the appsrc/appsink.
Also, we now only initialise either the encoding or the decoding
pipeline and not both. The codec init API already gets passed the
for_encoding flag. We pass and use the same to codec specific init
functions.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
As we now support codecs other than SBC, we might have codec which does
not have an encode or a decode capability. Specifically, in the case of
LDAC there isn't a known decoder implementation available. For such a
case, we should not register the corresponding endpoint.
In case of LDAC, as decoding cannot be supported, we should not register
a sink endpoint or vice versa in the other scenario.
To do this, we check if encode_buffer or decode_buffer entry for a codec
has been set in pa_a2dp_codec and accordingly prevent or allow it's
registration.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
When it comes to codecs provided via GStreamer, we register all codecs
if GStreamer option is enabled for bluez5 via meson. However, the
GStreamer plugin required for the codec might not be present on the
system. This results in the codec being available for registration with
the bluez stack or selection by the user, but, trying to use the said
codec then fails.
To prevent the above, we now use the can_be_supported codec API to check
if the codec is usable and if not, we do not register the said codec and
also prevent users from switching to it.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
This API internally checks if a requested codec can be supported on the
system. This is especially required for codecs supported via GStreamer
where the availability of a plugin decides if the said codec can be
supported.
This will be used to prevent registration of a codec which the remote
endpoint device might be able to support, but, PulseAudio can't as the
codec is not available on the system due to the absence of a plugin.
We can also prevent listing or switching to an unavailable codec.
Note that the codec negotiation happens with the bluez stack even before
a device is connected. Because of this, we need to make sure that gst_init
is called before checking for the availability of a plugin. Since
module-bluez5-device gets loaded only after a connection to the device
has been established, doing the gst_init in that or one of the bluetooth
modules is not feasible.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
For example, using the following on the command line will return the
current codec for a bluetooth device
pacmd send-message /card/bluez_card.4C_BC_98_80_01_9B/bluez get-codec
where 4C_BC_98_80_01_9B is the bluetooth device.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
This exposes the currently active codec on the source or sink via the
proplist and can be seen in output of pacmd list-sinks/list-sources.
Also set it on the card. In case of a bi-directional codec, the codec
for the sink and source could be different. For example, for aptX-LL,
the codec name on card, sink and source would be aptx-ll, aptx and sbc
respectively.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
For example, using the following on the command line will return the
list of possible codecs for a bluetooth device
pacmd send-message /card/bluez_card.4C_BC_98_80_01_9B/bluez list-codecs
where 4C_BC_98_80_01_9B is the bluetooth device.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
This adds a generic gstreamer codec module based on which other
bluetooth codecs viz. aptX, aptX-HD, LDAC and AAC can be supported.
The GStreamer codec plugins used here themselves depend on the native
codec implementation.
aptX/aptX-HD -> libopenaptx
LDAC -> libldac
AAC -> Fraunhofer FDK AAC
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
This uses the messaging API to initiate a codec switch.
While a particular codec might be applicable only for a particular
profile, for eg. aptX can only be applicable for A2DP sink or source
and not for let's say HSP, the codec switching logic has not been
tied to the logic for switching profiles.
Codec can be switched by running the following on the command line.
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec{"ldac_hq"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"ldac_mq"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"ldac_sq"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"aptx_hd"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"aptx"}
pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"sbc"}
Codec name passed above is matched against pa_a2dp_codec->name. Note that
the match is case sensitive. XX_XX_XX_XX_XX_XX needs to be substituted with
the actual bluetooth device id.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
Instead of letting a codec with higher index have higher priority,
just use a lower index for high priority. This allows the for loop
iterating over the codecs to be written in a straightforward manner
and not have to iterate from the end. FWIW Pipewire does the same.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>
Since commit ad447d1468 (in 2009) pa_read and pa_write take care of
handling EINTR error.
So, pa_read, pa_write, pa_iochannel_read and pa_iochannel_write can not
exit with errno set to EINTR, and testing it is useless.
Hashmap loaded_device_paths contain objects holding keys to entries, and
these objects must be alive while map is emptied.
Reorder freeing this hashmap before destroying device objects to fix
crash on exit.
Support for multiple codecs needs to use a new Bluez API which pulseaudio
does not implement yet.
So register explicitly only SBC codec which is provided by pulseaudio A2DP
codec API.
This was being done automatically by autotools, now we need to manually
specify this for each executable/library with a dependency in a
non-standard directory.
Rename struct rtp_payload to rtp_sbc_payload as it is specific for SBC
codec payload.
Add proper checks for endianity in rtp.h header and use uint8_t type
where appropriated.
Field frame_count is only 4 bit number, so add checks to prevent overflow.
And because is_fragmented field is not parsed by decoder there is no
support for decoding fragmented SBC frames. So throw an error in this case.
Add explanation why minimal bitpool value is used in SBC codec as initial
bitpool value for A2DP source.
Set buffer size for reading/writing from/to A2DP socket to exact link MTU
value. This would ensure that A2DP codec does not produce larger packet as
maximal possible size which can be sent.
Because A2DP socket is of SOCK_SEQPACKET type, it is guaranteed that
we do not read two packets via one read/recvmsg call.
Properly check for all return values of encode/encode methods of A2DP codec
functions. They may fail at different levels. Also encode or decode API
method may return zero length buffer (e.g. because of algorithmic delay of
codec), so do not fail in this case.
This crash occurs when PA is connected to a phone through the oFono
backend.
When disabling the Bluetooth adapter, pa_bluetooth_device is removed before
hf_audio_card. Both keep refs on pa_bluetooth_transport. Those removal will
call pa_bluetooth_transport_free() from device_free() (bluez5-util.c) and
hf_audio_card_free() (backend-ofono.c).
In the end, the call to pa_bluetooth_transport_free() calls
pa_hasmap_remove() through pa_bluetooth_transport_unlink(), but since
memory has already been freed, the second try results in a segfault.
Triggering hf_audio_card removal during pa_bluetooth_device removal allows
hf_audio_card to be freed at the right time.
setup_stream() crashes when calling set_nonblock() with an invalid
stream_fd.
On a new call, the ofono backend gets notified of a new connection.
The ofono backend sets the transport state to playing, and that triggers
a profile change, which sets up the stream for the first time.
Then module-bluetooth-policy sets up the loopbacks. The loopbacks get
fully initialized before the crash.
After module-bluetooth-policy has done its things, the execution
continues in the transport state change hook. The next hook user is
module-bluez5-device, whose handle_transport_state_change() function
gets called. It will then set up the stream again even though it's
already set up. I'm not sure if that's a some kind of a bug.
setup_stream() can handle the case where it's unnecessarily called,
though, so this second setup is not a big problem.
The crash happens, because the connection died due to POLLHUP in the IO
thread before the second setup_stream() call.
The warnings:
modules/bluetooth/a2dp-codec-sbc.c: In function ‘default_bitpool’:
modules/bluetooth/a2dp-codec-sbc.c:161:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
switch (mode) {
^~~~~~
modules/bluetooth/a2dp-codec-sbc.c:169:9: note: here
case SBC_SAMPLING_FREQ_44100:
^~~~
modules/bluetooth/a2dp-codec-sbc.c:170:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
switch (mode) {
^~~~~~
modules/bluetooth/a2dp-codec-sbc.c:180:9: note: here
case SBC_SAMPLING_FREQ_48000:
^~~~
These were valid warnings in that an invalid channel mode would result
in unintended fallthroughs, but the end result would anyway been a crash
in the pa_assert_not_reached() at the end of the function, so
functionally there's no change.
Brings things in line with the autotools build, and adds ALSA mixer
paths and profile-sets into the meson build system as well.
The module installation path is also now customisable.
Pulseaudio SBC codec defines that audio samples are in PA_SAMPLE_S16LE
format which is little endian. But libsbc library expects audio samples by
default in host endianity which is big endian on big endian system. So SBC
support on big endian system is broken. To fix this problem tell libsbc
library that audio samples are in little endian to match PA_SIMPLE_S16LE
sample format.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=91359
Remove dead code and replace numeric bitpool values by macro definitions.
Maximal bitpool value in fill_capabilities() was reduced from 64 to 53
(SBC_BITPOOL_HQ_JOINT_STEREO_44100) because default_bitpool() already set
maximal value to 53.
This patch does not change SBC behavior as maximal bitpool was already
limited to 53. So it is just clean up.
This patch introduce new modular API for bluetooth A2DP codecs. Its
benefits are:
* bluez5-util and module-bluez5-device does not contain any codec specific
code, they are codec independent.
* For adding new A2DP codec it is needed just to adjust one table in
a2dp-codec-util.c file. All codec specific functions are in separate
codec file.
* Support for backchannel (microphone voice). Some A2DP codecs (like
FastStream or aptX Low Latency) are bi-directional and can be used for
both music playback and audio call.
* Support for more configurations per codec. This allows to implement low
quality mode of some codec together with high quality.
Current SBC codec implementation was moved from bluez5-util and
module-bluez5-device to its own file and converted to this new A2DP API.
If one device tries to use PulseAudio to send audio over A2DP to another
device with bluez-alsa, that doesn't work because PulseAudio uses an
incorrect RTP payload type and bluez-alsa checks that the RTP payload
type is correct. According to the A2DP spec, the payload type should be
set to a number between 96 and 127.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/591
I can't promise that the logic is *exactly* the same as the logic
currently in use with the autotools, but it seems correct to me.
Signed-off-by: Arnaud Rebillout <arnaud.rebillout@collabora.com>
Please notice that the bluez5 version seems wrong in the dependency
declaration: `>= 4.x`, while we're talking about version 5.
The ofono part will need to be made optional when we start to work on
the meson_options file.
I follow the current configure.ac to define 'HAVE_BLUEZ', but it looks
like this part would benefit from a bit of rework. Setting HAVE_BLUEZ
when we have dbus+sbc sounds weird, there's probably a better name for
this variable.
Signed-off-by: Arnaud Rebillout <arnaud.rebillout@collabora.com>
Now that both backend-native and backend-ofono can coexist and
backend-ofono is always loaded, even on systems without oFono, failing
to register with org.ofono is not necessarily an error.
This lowers the failure message log level from error to info.