Support Opus as A2DP vendor codec.
The specification for vendor A2DP codec is our Pipewire-specific one, so
it is compatible only with devices running Pipewire.
The device is not know at SelectConfiguration time, so the settings
argument in select_config is currently unused. Pass on a global settings
dict instead, so that codec parameters can be configured.
Also add settings argument to caps_preference_cmp.
Bump codec API version.
Add a flag A2DP_CODEC_FLAG_SINK to incidate a sink endpoint.
Also enum_config and caps_preference_cmp may need to know whether the
codec is being configured for SRC or SNK. Also add the flags argument to
init_props.
Bump codec API version.
a2dp-sink writing duplex data to the BT socket breaks a2dp-source source
polling, also in A2DP source role. Hence, use the timer-based polling
workaround always in duplex mode.
User changing volume via headset buttons should be treated on the same
level as changing from desktop UI. Also initial headset volume should
be considered saved (even though session managers currently ignore the
initial route values on route restore).
Mark route as saved on volume events.
When emitting node, get initial volumes from transport hardware volume,
if available.
The session manager usually overrides these immediately with saved
values, but it's better to show the HW volume when the node first
appears.
The A2DP and HFP profiles may have different volume curves, so trying to
convert volumes between the two can produce undesirable volume spikes.
For example, when one of them is using hardware volume and the other
software.
Fix by separating HFP and A2DP routes.
a2dp-source as driver does not produce regularly spaced graph cycles,
because A2DP is not isochronous. This causes e.g. crackling for alsa
etc. that expect regular timings. It also does not rate match.
Change a2dp-source to trigger graph on regular intervals. Change recv to
only accumulate data to a buffer, and put data to buffers in process().
Rate match with DLL, keeping average buffer level constant. Keep track
of jitter to determine a safe target value.
It causes some headsets behave strangely. See pipewire#2391,
pipewire#1853.
The BlueZ issue of AVRCP volume sometimes missing that this worked
around was fixed in recent versions. The issue of some headsets not
sending volume without AVRCP player remains, but it appears this breaks
more headsets than fixes.
Don't try to reconnect or wait for profiles, which cannot be connected
because the adapter doesn't have the counterpart sink/source profile.
E.g. we should not reconnect/wait for HFP HF on remote device, if
we don't have the corresponding HFP AG.
If A2DP remote does not acquire its pending transport within a timeout,
we won't get a write error in a2dp-sink, but instead the transport
becomes idle. Currently, we continue writing to the socket as if
everything was fine, even though the data won't be processed at the
remote end.
Handle this by stopping the node and emitting a node error event.
Pipewire may then restart the node to retry.
Endpoints without decode/encode capability are skipped in the object
manager, but we should also skip them in the registration calls (even
though in practice this doesn't appear to matter).
AVDTP (v1.3 Sec 5.3) has a limitation that a local SEP (on the same
adapter) can be connected to at most one remote SEP. Trying to do have
it connected to multiple remotes either fails or causes misbehavior
later on.
Skip SetConfigure the same local endpoint for multiple remote ones in
codec switch. BlueZ observes this restriction in SelectConfiguration,
so also it won't try to do invalid configurations.
In BlueZ 5.64, the SetConfiguration calls succeed, but subsequent
transport acquires will fail. (Likely already the SetConfiguration DBus
call should fail.)
This all has the consequence, with the current approach to the
codec=endpoint correspondence, that if multiple devices are connected to
the same adapter, they currently have to use different codecs.
The file name "lc3.h" in the ETSI LC3plus package may conflict with the
actual LC3 codec, so try to find a file "lc3plus.h" instead. Also try
to find a pkg-config dependency for it first (in which case use lc3.h,
assuming it's in different directory). This can be fine tuned, if
something starts to package that library.
LC3plus expands 509 bytes input -> 7680 bytes output, which is bigger
than current decode buffer.
Make the decode buffer bigger, and put it on heap, not stack.
Codecs may need to fragment a single encoder frame across multiple
packets that are sent consecutively.
Allow codec->encode() to set need_flush=NEED_FLUSH_FRAGMENT, so that
sink should immediately call start_encode + encode with NULL input data,
to produce the next packet.
Previously, other return values than need_flush=1 were unused, so no
need to bump codec ABI for this.
Codec switch flag should be cleared on device connection status change,
to deal with codec_switched() callback not being called if device is
suddenly disconnected.
When device is disconnected, running codec switches are not meaningful,
and should be stopped.
The codec switch callback may also trigger A2DP profile switch, which
may reconnect the device. Fix it so this does not happen.
See #2334
The PropInfo either has a registered id (and then also a name from the
type-info) or a custom name as a string.
In all cases, the description contains a free form text that clarifies
the property.
Use the description in the stream controls name.
Remove quantum limitation from a2dp-sink, and adjust how flushing is
done.
The "low-latency" A2DP codecs are not able to flush all data at once, so
for them flush based on a timeout, such that "excess samples" for each
quantum is bounded. We also limit excess samples for the other A2DP
codecs, based on some testing on flaky headset/adapter combinations (for
most cases, this does not appear to matter).
Leave decision of packet sizes to the codecs. Currently, we send packets
based on min_latency, but sendinf full packets might help with stutter
on some headset/adapter combinations. The slightly increased latency
hardly matters against the 100ms delays in BT headsets.
Bump codec API version.