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.
If we get an EAGAIN, the device has started lagging in processing its
packets. We should not try to stuff the same packet in again, because
the device will just lag more. Instead, just drop current data, and hope
bitpool reduction takes care of it.
Also increase bitpool only if the socket buffer is empty.
Codec probe connections can trigger bad behavior from oFono if done when
device is busy (e.g. at connect), and they might be done at the same
time as A2DP transport is acquired which cannot work.
Also, oFono will not reply to DBus Acquire, if device does not complete
codec negotiation correctly. This is most likely to happen just after
device connect, when it is busy with other stuff (eg A2DP).
Remove codec probe connections altogether: instead, we guess mSBC if
mSBC is enabled and otherwise CVSD. If the guess turns out to be wrong,
which is unlikely (almost all devices have mSBC), we recreate the
transport with correct codec (from main loop, must not be done in
*_acquire because that can destroy nodes + unload the spa libs while
we're being called from there).
To avoid oFono DBus hangs at startup, add delay before marking the
profile connected, enforcing a time difference to A2DP operations.
This allows BT device to connect instantly instead of waiting for profile
timeout when hsp/hfp backend is none, because all available profiles are
connected.
Since meson 0.59.0, a feature object has an `allowed()`
method which returns true when the feature is set to
'enabled' or 'auto'.
Utilize that instead of the previously used
not feature.disabled()
Most feature checks already use #ifdef, and do not care about
the value of the macro. Convert all feature checks to do that,
and simplify the meson build scripts by replacing
if cond
cdata.set('X', 1)
endif
with
cdata.set('X', cond)
When sink is follower, and no data to write is available, it should not
schedule a timeout, but wait for the driver to wake it up again.
Fixes process ending up busylooping in data thread as follower, under
some conditions.
Also, clean up the code to be more clear about timeout logic. Just loop
directly instead of setting timeout 1, if we need to just flush more
immediately.
When acting as SCO AG / A2DP sink, the remote end should decide when to
close the connection. This does not work currently properly, because
stopping sources/sinks releases the transport, which causes it to go
idle, and which then destroys dynamic nodes. The sources/sinks should
not cause the transport to be released.
Implement keepalive flag for spa_bt_transport, such that
spa_bt_transport_release does not actually release the transport when
the refcount reaches zero. Set the flag for dynamic nodes when the
transport becomes pending (remote end connects) and unset the flag when
idle (remote end disconnected, or dynamic node removed).
Using a probe connection to determine adapter msbc capability causes
problems on some adapters (ff8c3d2, 84bc0490a5, 717004334b,
pipewire#2030) and seems to be a bad idea.
Go back to probing for transparent msbc transport capability via HCI
commands. bluetooth/hci.h may be deprecated later, but for now it's
better to go back to using it. (In practice, adapters not supporting
esco appear to be fairly rare; kernel commit in 2013 refers to "older
devices", so if we can't use HCI, assume the adapter supports the
necessary modes.)
Enable SBC-XQ codec for the JBL Endurance RUN BT headset. The codec worked well
with pulseaudio and works equally well with pipewire.
Signed-off-by: Maciek Borzecki <maciek.borzecki@gmail.com>
Devices may appear before or after their adapter does on BlueZ DBus
interface.
When an adapter appears, search the device list, and associated its
devices with it.
All exposed bluez devices should have an adapter specified at all times.
Adapter-less devices appear in some race conditions in BlueZ interface.
Require device has non-null adapter, in all cases before adding any
profiles (which exposes the device), and reject BlueZ profile connection
attempts in that state.
If an adapter gets removed by BlueZ, remove also all its devices, so
that device->adapter pointers stay valid.
Double device profile timeout to 6sec.
In some cases, BlueZ can take more than the previous 3sec to connect all
profiles. It's better to wait for a bit longer, so that devices have all
profiles visible already when they first appear.
This works around issues in Wireplumber profile selection logic.
Don't require all device profiles to be connected before marking the
device as connected before profile timeout. Show device already when all
A2DP/HSP/HFP profiles for sink/source direction have connected.
There are devices that in principle can have both sink/source profiles
present, but cannot operate both directions at the same time. In case
profiles come online later, the only effect is that the device profiles
will get an update after the device is published.
A2DP profile may disappear if several SetConfiguration events occur too
rapidly. Rate limit these calls when switching codecs.
This resolves failures if e.g. the session manager attempts to set the
profile immediately after the device is created, which previously might
cause a failure.
Higher priority for A2DP over HFP/HSP. Prefer mSBC over CVSD for HFP,
and put A2DP codecs in the order we tell BlueZ to use.
Ensures that picking highest-priority profile gives sensible results
(e.g. does not pick HFP unless input route is required, and prefers A2DP
duplex codecs over HFP).