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.
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.
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.
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.
This pushes the latency to 256 samples, which still seems to work
Latency of 128 seems to be too small. (NB. the number of input samples
is also the size of packets sent in bytes)
Since pipewire clients usually use powers of two, this may be the
smallest value that makes sense.
Disable flush polling when we don't have data ready to write to the
socket (or socket send failed). This avoids entering into a poll busy
loop, which may result to rtkit killing the process.
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.
SPA_MEMBER is misleading, all we're doing here is pointer+offset and a
type-casting the result. Rename to SPA_PTROFF which is more expressive (and
has the same number of characters so we don't need to re-indent).
Let codec decides when rtp packet need to be sent (terminated by MTU size in most case).
LDAC encoding loop can now be terminated by reading if frame_num is written, no 'frame_count' updating is needed.
RTP payload fragmentation can now be implemented more easily based on this.
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.
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.
Not all devices report their A2DP delay. In those cases, use a fallback
value of 150ms by default.
Make the delay adjustable with a SPA_Prop, and expose it as a part of
the route. Implement the corresponding parts in media-session.
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.