Commit graph

90 commits

Author SHA1 Message Date
Frédéric Danis
00d51c3d31 bluez5: Rename codec API from *a2dp* to *media*
The BlueZ Media1 interface will not only be used for A2DP but also for
LE Audio and code related can be shared.
2022-09-15 11:17:20 +00:00
Wim Taymans
2fa1b4384b spa: don't warn for NULL io
The io is set to NULL when the port becomes unnegotiated.
2022-09-01 15:31:14 +02:00
Frédéric Danis
6b3390387d bluez5: Test transport pointer before using it
If this->transport is NULL the debug log will crash.
2022-08-18 12:57:04 +02:00
Pauli Virtanen
a8eb146d39 bluez5: tell the codec whether endpoint is sink or source
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.
2022-07-19 13:44:56 +00:00
Pauli Virtanen
8d66b2b2f7 bluez5: a2dp-source: more duplex codec workarounds
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.
2022-07-19 13:44:56 +00:00
Pauli Virtanen
51356ea3d0 bluez5: a2dp-source: separate clock from recv + handle buffering
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.
2022-07-05 14:21:04 +00:00
Pauli Virtanen
f9850ca4f8 bluez5: use bigger decode buffer in a2dp-source
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.
2022-05-01 00:27:05 +03:00
Pauli Virtanen
9ad53d9d19 bluez5: a2dp-source should not stop on codec decode failures
A2DP source should continue trying to decode, even if garbled data is
received.
2022-04-30 23:43:10 +03:00
Wim Taymans
2f5bba112f spa: Improve PropInfo fields
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.
2022-03-30 17:09:08 +02:00
Pauli Virtanen
377bc16eb5 bluez5: handle any quantum in a2dp-sink
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.
2022-03-11 18:09:55 +02:00
Wim Taymans
35cbe4e939 buffers: make alignment optional
Make the alignment parameter optional when negotiating buffers.
Default to a 16 bytes alignment and adjust for the max cpu
alignment.
Remove the useless align buffer parameter in plugins, we always
set it to 16 anyway.
2022-01-03 12:32:26 +01:00
Wim Taymans
b4d33843a6 bluez5: set clock name 2021-12-10 12:31:44 +01:00
Wim Taymans
594f67ec04 a2dp: guard against transport NULL
The transport can become NULL so check that and don't try to
deref it.
2021-10-11 11:22:36 +02:00
Pauli Virtanen
58c7caf1bc bluez5: use log topics
Use log topics instead of prepending NAME: to log messages.
2021-10-02 12:46:02 +03:00
Pauli Virtanen
623b6df8a2 bluez5: work around obscure issue with a2dp-source with duplex
For unknown reason the BT socket when working with A2DP "duplex" stream,
sometimes stops waking up poll when data arrives. Regardless, recv() can
read data packets from it.

To work around this, when A2DP source is in duplex mode, instead of
polling on data, we poll on a timer.
2021-08-21 20:00:52 +03:00
Pauli Virtanen
eca37b58a6 bluez5: make room for a2dp duplex channel
Some non-standard A2DP codecs (FastStream/aptX-LL) have "voice duplex
channel" that can be used to provide an A2DP duplex mode.

Add support for duplex channels, accounting for the fact that the two
directions may be encoded with different actual codecs.
2021-08-21 20:00:52 +03:00
Huang-Huang Bao
8c42e6aecb alsa,bluez5: handle SPA_PARAM_Latency in port_set_param
Simply return 0 instead of -ENOENT.

Fixes #1262
2021-06-05 17:52:40 +00:00
Huang-Huang Bao
38bcec9022
bluez5: add port latency reporting 2021-05-28 20:02:10 +08:00
Huang-Huang Bao
d8435cd5fd
bluez5: use definations to index node and port params 2021-05-28 19:40:19 +08:00
Wim Taymans
46ef88e520 spa: save the old change_mask and restore when emitting full
When we add a new listener to an object, it will emit the full state
of the object. For this it temporarily sets the change_mask to all
changes. Restore the previous state after this or else we might not
emit the right change_mask for the next listener.

Consider the case where one there are two listeners on an object.
The object emits a change and the first listener wants to enumerate the
changed params. For this is adds a new listener and then triggers the
enumeration. If we set the change_mask to 0 after adding the listener,
the second listener would get a 0 change_mask and fail to update
its state.
2021-05-27 15:21:44 +02:00
Peter Hutterer
7697ed0757 treewide: replace strcmp() == 0 with spa_streq()
This change is only done in source files for now, header files will be done
separately.
2021-05-18 22:10:27 +10:00
Andrea Gelmini
47ef2b6b09 Fix typos 2021-04-30 07:40:20 +00:00
Huang-Huang Bao
d44955a199 a2dp: handle source transport destroy
Fix a use-after-free to transport if node is still running.
This revert part of a75fe69c8e.
2021-04-15 06:59:19 +00:00
Wim Taymans
43317f67ba a2dp-source: improve info parsing
Make sure we handle NULL info.
Simplify the property parsing.
2021-03-30 09:24:35 +02:00
Dmitry Sharshakov
e7f2f450ff bluez5: add parameter to use A2DP source as input 2021-03-30 09:21:12 +02:00
Pauli Virtanen
ef74ef3654 bluez5: use the actual latency in a2dp-source 2021-03-28 14:20:42 +03:00
Huang-Huang Bao
1d390addb1 a2dp: allow codec to hold Props params
Initial Props value are parsed from device settings, further changes are triggered by 'set_param' on a2dp node.
Codec can then use props to tweak its transcoder.
2021-03-20 09:16:20 +00:00
George Kiagiadakis
a75fe69c8e bluez5: emit & remove the A2DP source node depending on transport state
Typically a source stops the connection when it has nothing to play
and this causes the transport to become "idle" and our A2DP source
also stops. However, the node is still present and "running" (if linked),
which causes the graph to underrun as it receives no data from this node.

This patch dynamically creates and destroys the a2dp source node depending
on the transport state. So, when the transport is idle, there is no node
in the graph at all.
2021-03-18 14:34:27 +00:00
Huang-Huang Bao
374180e211 bluez5: pass per-device settings to codec handler, make 'bluez5.sbc-xq-support' a per-device setting 2021-03-16 10:31:08 +00:00
Pauli Virtanen
4389e44903 bluez5: emit props change events only if values actually changed
This may avoid infinite loops if parameters are being set based on events
sent by parameter changes. It's also what alsa-acp devices do, so bluez5
should follow.
2021-03-02 23:46:27 +02:00
Wim Taymans
ecd1d3e1d7 Move node.pause-on-idle setting to config files
So that we can configure it.
Add some more docs to the config file
2021-02-08 17:19:47 +01:00
Wim Taymans
e3d19e5602 a2dp: small cleanups 2021-02-08 10:24:27 +01:00
Wim Taymans
63c5fadcfc a2dp: fix compiler warnings 2021-02-07 19:43:09 +01:00
Pauli Virtanen
f99eefeb4f bluez5: a2dp-source: release transport if it went idle
Release the transport if it went idle, ensuring that the fd is closed,
and add safeguards we won't double-acquire/release it.

This can occur if the device pauses the playback. The transport may also
activate again later on, and in this case we need to reacquire a new fd.
Not closing the old fd causes problems in this case.

However, apparently the BlueZ Release() call fails if the transport is
idle. We just ignore the error and downgrade the error message; it might
not be safe to not call Release() because the idle property update is
async.
2021-02-07 18:32:44 +00:00
Pauli Virtanen
d3d31c4317 bluez5: don't force a2dp-source as driver
Don't force a2dp-source to be driver, because it won't advance clock if
the device is not sending data, and possibly blocks other streams.
2021-02-07 18:32:44 +00:00
Pauli Virtanen
d68bad4673 bluez5: fix a2dp-source clock rate + stuttering
Make a2dp clock advance at the correct rate.

Revert back to accumulating to a single buffer before sending it out.
What it did previously seemed hard to get to work properly with e.g.
aptx which produces block of varying sizes on decoding.
2021-02-07 18:32:44 +00:00
Pauli Virtanen
f1e56b2317 bluez5: provide media.name for a2dp source streams
A2DP source acts as Stream/Output/Audio, so provide media.name for it
indicating the device it comes from (e.g. shown in pulseaudio apps).
2021-02-06 20:24:04 +02:00
Wim Taymans
2a1875fc35 bluez: disable pause on idle by default 2021-01-29 15:37:32 +01:00
Wim Taymans
5bb7a0f573 a2dp-codecs: add settings to codec init function
To make it possible to add extra config options in init.
Also add a method to update settings in a codec.
2021-01-07 17:39:39 +01:00
Pauli Virtanen
da2fa8a599 bluez5: setting this->transport = NULL should block data thread
Since the data thread accesses the spa_bt_transport, its destroy event
needs to sync with data thread to avoid races.

Also check transport is present in places that need it.
2021-01-03 06:59:00 +01:00
Pauli Virtanen
c39ba8570e a2dp-sink/source: don't crash if transport went away 2020-12-30 16:34:23 +02:00
Wim Taymans
7f6339e307 bluez5: Don't deref the transport to get the fd
Use the configured fd in the source for reading and writing because
the transport might be disconnected and cleared from the main thread
at any time.
2020-12-14 13:17:48 +01:00
Wim Taymans
c3c1a1184c a2dp: use unsigned for sizes 2020-12-05 08:30:14 +01:00
Wim Taymans
635a378ca4 bluez5: don't error on 0 decode length
It can happen for the first frame when the codec is filling up.
2020-12-04 12:00:42 +01:00
Wim Taymans
106d597305 bluez5: add aptX and aptX HD codecs
They need the libopenaptx libraries from
https://github.com/pali/libopenaptx
2020-12-04 11:34:38 +01:00
Wim Taymans
73b13e8ad5 a2dp: deinit codec_data in stop 2020-12-03 18:11:06 +01:00
Wim Taymans
8bf0b7b4db a2dp: delay codec init to after acquire
Some codecs need the MTU as a parameter so wait until we acquire
with creating the codec context.

Make some method to enumerate the parameters from the transport
config and use that for the EnumFormat param.
2020-12-03 18:05:57 +01:00
Wim Taymans
3363544d05 bluez5: use start_decode to skip the header 2020-12-02 17:01:22 +01:00
Wim Taymans
77b91823f3 a2dp: mark a2dp-source as stream and autoconnect 2020-10-19 18:53:18 +02:00
Wim Taymans
6cc3224031 a2dp-source: fix source
Use codec methods. Init codec at start.
Remove rate match until we actually implement this
Add some buffering of packets before we hand them out.
Always simply fill a buffer and hand it out.
don't emit signals when we are following another driver.
Acquire transport as soon as it goes to PENDING.
2020-10-19 18:25:52 +02:00