Pass zero-length packets to the codec. BAP/ISO may use these to indicate
missing data.
Fix A2DP codecs to not parse input with spa_return_val_if_fail, that's
meant for assertions. Just return -EINVAL directly, it's normal that
input data may contain garbage.
LC3 and Opus have built-in support for packet loss concealment.
Add codec interface for that, and implement for LC3.
Extend media_codec interface so that packets not aligned with socket
reads can be handled, as in HFP. This is required for correct sequence
number counting, and for being able to run codec PLC *before* decoding
the next correctly received packet.
I'm not aware of any devices that support 48 kHz output in duplex
configuration, so disable that for now.
Doing this properly requires catching errors when on transport Acquire,
and switching to another configuration if the error was due to bad
configuration.
Due to how BAP specification works, it's not necessarily possible to
know whether a configuration was really accepted at earlier stage, and
anyway there's no proper error -> reconfiguration handling currently on
BlueZ side either.
Add configuration options for the BAP/PACS sink and source endpoint
location (= channel positions) and context settings.
Although BlueZ associates these with individual endpoints, in the PACS
spec they are actually device-global, so configure directly in monitor
settings.
Parse BAP settings in a single place, and simplify QoS customization a
bit.
Ensure the selected preset gets selected.
For all the BAP codec settings, use device settings instead of global
monitor ones.
The current BAP QoS configuration allows to register a sampling
frequency based on the configuration done using wireplumber configuration.
However, for a scenario were the user need to use a specific SDU framelength
it cannot be done as the select_bap_qos function selects the QOS based on
priority and hence it will use the best possible config rather than the user
configured.
This PR adds option to select the QoS set based on user configured value. If
the remote device doesn't have the user configured capabilities it will always
use the best priority config.
Further, this change also allows the user to set RTN, Latency, Delay QoS config
for certain use case to have controller use optimum bandwidth usage.
Below are the example configuration on setting LC3 capabilities in config file:
bluez5.bap.set_name = "48_2_1"
bluez5.bap.rtn = 5
bluez5.bap.latency = 20
bluez5.bap.delay = 40000
bluez5.framing = false
The current BAP unicast QoS configuration allows to register a sampling
frequency based on the configuration done using wireplumber configuration.
However, for a scenario were the user need to use a specific SDU framelength
it cannot be done as the select_bap_qos function selects the QoS based on
priority and hence it will use the best possible config rather than the user
configured.
This PR adds option to select the QoS set based on user configured value. If
the remote device doesn't have the user configured capabilities it will always
use the best priority config.
Further, this change also allows the user to set RTN, Latency, Delay QoS config
for certain use case to have controller use optimum bandwidth usage.
Below is the example for the options that can be configured & selected
in config file:
bluez5.bap.set_name = "48_2_1"
bluez5.bap.rtn = 5
bluez5.bap.latency = 20
bluez5.bap.delay = 40000
bluez5.framing = false
Currently, the PipeWire daemon registers BlueZ LE Media Endpoints
with audio capabilities covering all settings defined in the BAP spec.
However, some scenarios might require the capabilities to be restricted
to specific configurations.
This adds a method to read LC3 codec specific capabilities from the
Wireplumber config file, and provide those settings when registering
Media Endpoint objects with BlueZ. If the values are not present in
the config file, all settings will be used by default.
Below is an example of how to set the LC3 capabilities in the config
file, to support the 16_2 setting from the BAP spec:
bluez5.bap-server-capabilities.rates = [16000]
bluez5.bap-server-capabilities.durations = [10]
bluez5.bap-server-capabilities.channels = [1, 2]
bluez5.bap-server-capabilities.framelen_min = 40
bluez5.bap-server-capabilities.framelen_max = 40
bluez5.bap-server-capabilities.max_frames = 2
BlueZ API as BAP Server gives us the ISO interval, instead of the SDU
interval, in the MediaTransport.QoS.Interval property. They are not
necessarily the same. What we need is the SDU interval.
The SDU interval is the interval between packets the encoder outputs, so
it is determined by the codec configuration, and for LC3 is equal to the
frame duration.
Add codec method get_interval() that returns the correct interval, and
use it in iso-io.
Fix some sanity checks and add mtu check. Don't use
spa_return_val_if_fail here as it can spam stderr.
The buffer size check in codec_encode can't be hit.
Devices may advertise other values, but not certain they will work well
in duplex configuration.
E.g. my Samsung Galaxy Buds2 Pro emits buzzing sound with 48kHz duplex
input.
Don't believe QoS values recommended by the device, which may be
suboptimal. Instead, pick the values from the BAP v1.0.1 Table 5.2.
Link: https://github.com/bluez/bluez/issues/713
For multi-ASE configurations, BlueZ does the channel allocation itself,
and passes us the result in the ChannelAllocation parameter.
If it is present, don't do the allocation ourselves but use that value
instead.
If Supported_Max_Codec_Frames_Per_SDU is less than what is required by
Supported_Audio_Channel_Counts, override its value assuming the device
actually supports at least that. Needed for Creative Zen Hybrid Pro.
Fix default value for channel count bitmask.
Some devices appear to set Supported_Max_Codec_Frames_Per_SDU == 1 while
claiming they support two channels per stream, which is then not
possible.
In this case, limit the number of channels by the number of frames per
SDU when selecting.
Also adjust PAC sorting.
BlueZ now requires endpoints to set Locations/Context, so set them to
some sensible default values. These could in principle be made
configurable later.
Do BAP audio location selection properly in SelectProperties, now that
BlueZ provides the supported locations there. Remove a previous
workaround.
The audio location in SelectProperties determines the audio channel
allocation, which determines the channel positions.
Use the "high-reliability" values for QoS parameters instead of the
low-latency ones. Under some condition BlueZ does not pass on the
endpoint QoS values to us, in which case we may end up selecting bad
latency.
If BAP codec configuration is mono channel with unspecified location,
set the channel position from transport location.
This in principle should be set in SelectProperties, but currently BlueZ
doesn't tell us that yet there, so we hack it up later on.
The number of channels is determined by Audio_Channel_Allocation.
One frame block contains all channels. (BAP v1.0.1 Sec. 4.2)
Fix the handling of frame blocks and counting of numbers of channels. We
support and configure only one frame block per packet.
Consider omitted Audio_Channel_Allocation to indicate MONO stream (see
BAP v1.0.1 Sec 4.3.2).
BlueZ may send multiple PACs in the capabilities delimited by zero LTV.
Handle this case by selecting the "best" one.
The configuration size may also for BAP generally be different from PAC
size.
The codec may need to take into account endpoint preferred QoS values,
so parse this information and pass it to the codec's get_qos.
All the QoS struct values need to be set, as otherwise BlueZ may pass
uninitialized zero values over the air, which devices can reject. This
does not apply to CIG/CIS ids, which are automatically allocated by
default.
Fixes connecting to nrf5340 devkit, which requires a valid TargetLatency
value.