Commit graph

14865 commits

Author SHA1 Message Date
Christian F.K. Schaller
3b4a4f541b test: add AVTP audio data path tests
Add 10 Phase 6 tests for the AVTP audio data path:
- IEC61883 and AAF packet structure layout validation
- 802.1Q frame header construction
- PDU size calculations for various audio configurations
- Ringbuffer audio data round-trip integrity
- Ringbuffer wrap-around with multiple PDU-sized writes
- IEC61883 receive simulation (packet → ringbuffer)
- IEC61883 transmit PDU construction and field verification
- Ringbuffer overrun detection
- Sequence number and DBC counter wrapping

These tests validate the AVTP packet formats and audio data path
logic without requiring hardware, AF_PACKET sockets, or CLOCK_TAI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:44 -04:00
Christian F.K. Schaller
6337aa7286 test: add AECP/AEM entity model tests and document new bugs
Add 12 Phase 5 tests for the AECP/AEM entity model:
- READ_DESCRIPTOR for existing and non-existent descriptors
- AECP packet filtering (wrong EtherType, wrong subtype)
- Unsupported AECP message types (ADDRESS_ACCESS, etc.)
- Unimplemented AEM commands (REBOOT, etc.)
- ACQUIRE_ENTITY and LOCK_ENTITY for legacy mode
- Milan ENTITY_AVAILABLE, LOCK_ENTITY (lock/contention/unlock)
- Milan LOCK_ENTITY for non-entity descriptors
- Milan ACQUIRE_ENTITY returns NOT_SUPPORTED
- Milan READ_DESCRIPTOR

Also adds Milan test server helper with properly sized entity
descriptor for lock state, and AECP/AEM packet builder utility.

Updates avb-bugs.md with 3 new bugs found (bugs #6-#8).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:44 -04:00
Christian F.K. Schaller
11688debcd test: add ACMP integration tests and bug documentation
Add Phase 4 ACMP integration tests:
- NOT_SUPPORTED response for unimplemented commands
- CONNECT_TX_COMMAND with no streams (error response)
- Entity ID filtering (wrong GUID ignored)
- CONNECT_RX_COMMAND forwarding to talker
- Pending request timeout and retry
- Packet filtering (wrong EtherType/subtype)

Also add avb-bugs.md documenting all bugs found by the test suite.

Total: 24 tests, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:44 -04:00
Christian F.K. Schaller
7ba419e4f1 test: add MRP state machine, MSRP, and packet parsing tests
Extend the AVB test suite with Phase 3 tests:

MRP state machine tests:
- Begin/join/TX cycle with NEW attribute
- Join then leave lifecycle
- RX_NEW registrar notification callback
- Registrar leave timer (LV -> MT after timeout)
- Multiple coexisting attributes

MSRP protocol tests:
- All four attribute types (talker, talker-failed, listener, domain)
- Domain and talker transmit via loopback capture
- Talker-failed notification (validates NULL deref fix)

MRP packet parsing tests:
- Single domain value parse
- Leave-all (LVA) flag detection
- Three-value base-6 event decoding

Total: 18 tests, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:44 -04:00
Christian F.K. Schaller
acbfe5658a test: add AVB protocol test suite with loopback transport
Add a test suite for the AVB (Audio Video Bridging) protocol stack that
runs entirely in software, requiring no hardware, root privileges, or
running PipeWire daemon.

The loopback transport (avb-transport-loopback.h) replaces raw AF_PACKET
sockets with in-memory packet capture, using a synthetic MAC address and
eventfd for protocol handlers that need a valid fd.

Test utilities (test-avb-utils.h) provide helpers for creating test
servers, injecting packets, advancing time, and building ADP packets.

Tests cover:
- ADP entity available/departing/discover/timeout
- MRP attribute lifecycle (create, begin, join)
- Milan v1.2 mode server creation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:44 -04:00
Christian F.K. Schaller
80a372e84d module-avb: add transport abstraction for pluggable network backends
Introduce struct avb_transport_ops vtable with setup/send_packet/
make_socket/destroy callbacks. The existing raw AF_PACKET socket code
becomes the default "raw" transport. avdecc_server_new() defaults to
avb_transport_raw if no transport is set, and avdecc_server_free()
delegates cleanup through the transport ops.

This enables alternative transports (e.g. loopback for testing) without
modifying protocol handler code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:44 -04:00
Christian F.K. Schaller
4d0bf1c5a6 module-avb: fix Milan lock entity error response and re-lock timeout
Fix two bugs in handle_cmd_lock_entity_milan_v12():

1. When server_find_descriptor() returns NULL, reply_status() was called
   with the AEM packet pointer instead of the full ethernet frame,
   corrupting the response ethernet header.

2. When refreshing an existing lock, the expire timeout was extended by
   raw seconds (60) instead of nanoseconds (60 * SPA_NSEC_PER_SEC),
   causing the lock to expire almost immediately after re-lock.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:38 -04:00
Christian F.K. Schaller
d9508ef334 module-avb: fix legacy AECP handlers reading payload at wrong offset
handle_acquire_entity_avb_legacy() and handle_lock_entity_avb_legacy()
incorrectly treated the full ethernet frame pointer as the AEM packet
pointer, causing p->payload to read descriptor_type and descriptor_id
from the wrong offset. Fix by properly skipping the ethernet header,
matching the pattern used by all other AEM command handlers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:38 -04:00
Christian F.K. Schaller
1caa242358 module-avb: fix ACMP error responses sent with wrong message type
In handle_connect_tx_command() and handle_disconnect_tx_command(),
AVB_PACKET_ACMP_SET_MESSAGE_TYPE() is called after the goto done
target. When find_stream() fails and jumps to done, the response
is sent with the original command message type (e.g., CONNECT_TX_COMMAND)
instead of the correct response type (CONNECT_TX_RESPONSE).

Move the SET_MESSAGE_TYPE call before find_stream() so error responses
are always sent with the correct response message type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:32 -04:00
Christian F.K. Schaller
8e7e433412 module-avb: fix MRP NEW messages never being transmitted
AVB_MRP_SEND_NEW was defined as 0, making it indistinguishable from
"no pending send" in the MSRP and MVRP event handlers which check
`if (!pending_send)`. This meant that when an attribute was first
declared (applicant state VN or AN), the NEW message was silently
dropped instead of being transmitted on the network.

Fix by shifting all AVB_MRP_SEND_* values to start at 1, so that 0
unambiguously means "no send pending". Update the MSRP and MVRP
encoders to subtract 1 when encoding to the IEEE 802.1Q wire format
(which uses 0-based event values).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:15 -04:00
Christian F.K. Schaller
c7fa28b7cf module-avb: fix potential NULL pointer dereference in MSRP/MVRP notify
The msrp_notify() and mvrp_notify() functions call dispatch table
notify callbacks without checking for NULL. In MSRP, the
TALKER_FAILED attribute type has a NULL notify callback, which would
crash if a talker-failed attribute received a registrar state change
notification (e.g. RX_NEW triggering NOTIFY_NEW).

Add NULL checks before calling the dispatch notify callbacks, matching
the defensive pattern used in the encode path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:15 -04:00
Christian F.K. Schaller
5bb9ae237d module-avb: fix heap corruption in server_destroy_descriptors
server_add_descriptor() allocates the descriptor and its data in a
single calloc (d->ptr = SPA_PTROFF(d, sizeof(struct descriptor))),
so d->ptr points inside the same allocation as d. Calling free(d->ptr)
frees an interior pointer, corrupting the heap. Only free(d) is needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:10:15 -04:00
Wim Taymans
57299da899 filter-graph: improve debug when loading fails
List the path name and the plugin search path when we can't load an
error.
2026-04-06 15:01:43 +02:00
Wim Taymans
785bf36b9b docs: remove support for absolute paths from docs 2026-04-06 14:47:21 +02:00
Wim Taymans
8fd7982087 only dlopen from the defined search paths
Don't accept absolute library paths and skip the ../ in paths to avoid
opening arbitrary libraries from unexpected places.
2026-04-06 14:20:56 +02:00
Pauli Virtanen
ad0bab69a1 spa: system: make spa_poll_event compatible with epoll_events
spa_poll_event should have exactly same layout as epoll_events to be
compatible across platforms. The structure is packed only on x86-64.

Fix packing and replace the data member with similar union as
epoll_data, to fix compatibility on 32-bit etc.
2026-04-06 10:24:32 +00:00
Wim Taymans
6b0248d68c Revert "impl-node: Don't suspend when links are busy"
This reverts commit bb0efd777f.

It is unclear what the problem was before this commit. If there are any
pending operations, the suspend should simply cancel them.

See #5207
2026-04-06 10:39:15 +02:00
Alexander Sarmanow
54a4515b09 bluez5: bap: add support for manual BIS config 2026-04-05 20:18:22 +00:00
ValdikSS
ee1b429441 bluez5: aac: Use VBR encoding with Mode 5 by default 2026-04-05 20:24:47 +03:00
ValdikSS
a35b6b0c4b bluez5: aac: use higher band limit for CBR mode
FDK-AAC encoder uses band pass filter, which is automatically
applied at all bitrates.
For CBR encoding mode, its values are as follows (for stereo):

* 0-12 kb/s:   5   kHz
* 12-20 kb/s:  6.4 kHz
* 20-28 kb/s:  9.6 kHz
* 40-56 kb/s:  13  kHz
* 56-72 kb/s:  16  kHz
* 72-576 kb/s: 17  kHz

VBR uses the following table (stereo):

* Mode 1: 13   kHz
* Mode 2: 13   kHz
* Mode 3: 15.7 kHz
* Mode 4: 16.5 kHz
* Mode 5: 19.3 kHz

17 kHz for CBR is a limiting value for high bitrate.

Assume >110 kbit/s as a "high bitrate" CBR and increase the
band pass cutout up to 19.3 kHz (as in mode 5 VBR).

Link: d8e6b1a3aa/libAACenc/src/bandwidth.cpp (L114-L160)
2026-04-05 20:24:47 +03:00
ValdikSS
49d5f4f236 bluez5: aac: use maximum possible peak bitrate according to MTU
Android 11 and newer, in both CBR and VBR modes,
* Sets bitrate (AACENC_BITRATE) to the max_bitrate value of A2DP
* Sets peak bitrate (AACENC_PEAK_BITRATE) according to the maximum data
   which could fit into single audio packet based on MTU

AACENC_BITRATE is used only in CBR mode. For VBR mode, the only limiting
factor is AACENC_PEAK_BITRATE.

Do the same in Pipewire.

Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/work_items/1482#note_2949680
Link: https://cs.android.com/android/platform/superproject/+/android16-qpr2-release:packages/modules/Bluetooth/system/stack/a2dp/a2dp_aac_encoder.cc;drc=37d7b4549f7b8740df1a290f04c20c591a2d3391;l=269
2026-04-05 20:24:47 +03:00
Wim Taymans
67dd3549a7 system: use attribute packed for the spa_poll_event
This makes it the same size as epoll_event and we don't need to copy the
results over.

It however technically causes an ABI break, in case someone was using
the system interface directly.
2026-04-01 16:28:47 +02:00
Martin Geier
54c517b2d9 module-rtp: Add more logging for debugging timer related issues 2026-03-30 23:45:34 +02:00
Carlos Rafael Giani
0121bdc475 module-rtp: Lower missing timeout log line from warn to trace
A warning is not warranted in this case, and this log line can spam
the logs, so set it to trace.
2026-03-30 23:45:34 +02:00
Carlos Rafael Giani
5b86e3d418 module-rtp-source: Only enable IGMP recovery when using multicast
IGMP recovery makes no sense with unicast IP addresses.
2026-03-30 23:45:34 +02:00
Carlos Rafael Giani
3080bca85a module-rtp-source: Fix unicast by-address packet filtering
Using connect() on a UDP receiver creates a strict filter based on
the sender's _source_ port, not the sender's destination port. The
source port specifies at what sender port the packet exits the sender.
The destination port specifies at what receiver port the packet enters
the receiver. But, the RTP sink uses an ephemeral (= random) port as the
source port. Consequently, connect() at the receiver will cause a
comparison of that ephemeral port with the fixated one (which is actually
the number of the _destination_ port). This incorrect filtering causes
all packets to be dropped.

Use bind() to filter for the local destination port, and use recvmsg()
with manual IP comparison to filter for the sender's identity.
2026-03-30 23:45:34 +02:00
Carlos Rafael Giani
41b5bc662e network-utils: pw_net_are_addresses_equal() function 2026-03-30 23:45:33 +02:00
Carlos Rafael Giani
9ba92bd728 spa: Do not perform upper range check on 32-bit platforms 2026-03-30 23:31:36 +02:00
Wim Taymans
18c97222c4 channelmix: make up/downmix levels configurable
Add channelmix.center-level, channelmix.surround-level and
channelmix.lfe-level to control how center, surround and LFE is
up/downmixed.

Fixes #5198
2026-03-30 17:50:48 +02:00
Sriman Achanta
03f894bab0 alsa-udev: Add wireless device status monitoring 2026-03-30 07:43:27 +00:00
Barnabás Pőcze
7f4baba41c spa: do not use SPA_PROP_live
Remove support for changing `SPA_PROP_live` in node implementations
that supported it, and hard-code `SPA_PROP_live = true`. If a mode
of operation is desired where the data is processed as fast as possible,
it can be achieved by implementing non-driver operation and using the
freewheel driver in pipewire.
2026-03-27 18:03:24 +01:00
Barnabás Pőcze
00b4717c6e spa: remove async members
Some node implementations have an `async` member, but these members
are not written anywhere. So remove them.
2026-03-27 11:32:29 +01:00
Barnabás Pőcze
84e7b744a6 spa: libcamera: use std::span
libcamera is planning to move to C++20 and drop the custom `libcamera::Span`
type at some point in the future. Since pipewire already uses C++20, remove
all uses of it and instead use `std::span` so that things will compile
after the removal.
2026-03-27 09:57:56 +01:00
Barnabás Pőcze
29b221671f spa: remove timerspec members
These are only used when the timer is set, so convert them to local variables.
No functional changes intended.
2026-03-26 14:43:54 +01:00
Wim Taymans
7599079d61 jack: increase notify buffer and items
Make the notify buffer larger, it was 8K but we can make it 64K. Also
reorder the notify struct fields to make it smaller.

This should avoid "notify queue full" warnings. Ideally we should
dynamically size this queue and not lose any messages.
2026-03-26 11:59:28 +01:00
Wim Taymans
60062432b8 module-rtp: handle the send_packet/feedback as callbacks
They are emited from the streaming thread and therefore can be emitted
concurrently with the events on the main thread. This can cause crashes
when the hook list is iterated.

Instead, make those events into callbacks that are more efficient,
and threadsafe.
2026-03-26 09:34:45 +01:00
Wim Taymans
50fcf64058 tools: add -C | --monitor to pw-cat
It sets the stream.capture.sink property which makes a record stream
capture from a sink monitor instead.
2026-03-25 18:06:17 +01:00
Wim Taymans
9eeb2f1930 mixer: handle control.ump property
Add a control.ump port property. When true, the port wants UMP and the
mixer will convert to it. When false, the port supports both UMP and
Midi1 and no conversions will happen. When unset, the mixer will always
convert UMP to midi1.

Remove the CONTROL_types property from the filter. This causes problems
because this is the format negotiated with peers, which might not
support the types but can still be linked because the mixer will
convert.

The control.ump port property is supposed to be a temporary fix until we
can negotiate the mixer ports properly with the CONTROL_types.

Remove UMP handling from bluetooth midi, just use the raw Midi1 events
now that the mixer will give those and we are supposed to output our
unconverted format.

Fix midi events in-place in netjack because we can.

Update docs and pw-mididump to note that we are back to midi1 as the
default format.

With this, most of the midi<->UMP conversion should be gone again and we
should be able to avoid conversion problems in ALSA and PipeWire.

Fixes #5183
2026-03-25 11:59:43 +01:00
Wim Taymans
7fe191bc10 buffers: handle 0 result from Buffers param enumeration
Since abf37dbdde the param enumeration in
the client-node can return 0 when the parameter is supported but there
are no params uploaded.

When negotiating buffers we need to assume a 0 result as a NULL filter
as well or else we will error.
2026-03-25 11:59:43 +01:00
Wim Taymans
ea28343166 midi: don't convert Midi in nodes
Avoid doing conversions in the nodes between Midi formats, just assume
the imput is what we expect and output what we naturally produce.

For ALSA this means we produce and consume Midi1 or Midi2 depending on the
configurtation.

All of the other modules (ffado, RTP, netjack and VBAN) really only
produce and consume MIDI1.

Set the default MIDI format to MIDI1 in ALSA.

Whith this change, almost everything now produces and consumes MIDI1
again (previously the buffer format was forced to MIDI2).

The problem is that MIDI2 to and from MIDI1 conversion has problems in
some cases in PipeWire and ALSA and breaks compatibility with some
hardware.

The idea is to let elements produce their prefered format and that the
control mixer also negotiates and converts to the node prefered format.
There is then a mix of MIDI2 and MIDI1 on ports but with the control
port adapting, this should not be a problem.

There is one remaining problem to make this work, the port format is
taken from the node port and not the mixer port, which would then expose
the prefered format on the port and force negotiation to it with the
peer instead of in the mixer.

See #5183
2026-03-25 11:59:43 +01:00
Wim Taymans
67070762d0 mixer: only add input ports to mixer 2026-03-25 11:59:43 +01:00
George Kiagiadakis
0d1280a5b2 bluez5: parse the broadcast adapter value from the correct iterator 2026-03-24 16:55:00 +00:00
Barnabás Pőcze
22c1a16dce spa: audioconvert: benchmark-fmt-ops: initialize convert
Since c02cdcb5ce ("audioconvert: add avx2 optimized s32_to f32d")
`conv_s32_to_f32d_avx2()` reads `convert::cpu_flags`, which was
previously unitiailized, fix that by setting it to 0.
2026-03-24 17:50:51 +01:00
Barnabás Pőcze
39f4cbfc98 spa: audioconvert: test-fmt-ops: initialize convert
Since c02cdcb5ce ("audioconvert: add avx2 optimized s32_to f32d")
`conv_s32_to_f32d_avx2()` reads `convert::cpu_flags`, which was
previously unitiailized, fix that by setting it to 0.
2026-03-24 17:38:26 +01:00
lumingzh
bc87bc8588 update Chinese translation 2026-03-24 07:29:02 +00:00
Julian Bouzas
4f56442249 bluez: Discard latency and quality codecs worse than SBC for A2DP auto profiles.
Since SBC is mandatory in all devices that support A2DP, we dont need to inclide
them in the priority tables.

This change also increases the priority of OPUS_G codec as it has better latency
and quality than SBC.
2026-03-24 07:28:14 +00:00
Julian Bouzas
e1f53b7f39 bluez: Set initial profile to quality A2DP 2026-03-24 07:28:14 +00:00
Julian Bouzas
2e7aee3573 bluez: Increase priority of A2DP quality and latency profiles
This improves the UX as the highest A2DP profile will be selected by default.
2026-03-24 07:28:14 +00:00
Vitaliy Fadeev
01b9abc5ef Edit overview.dox
five flags
Node
2026-03-24 07:26:15 +00:00
Wim Taymans
d47b4974ce impl-node: add () around &&
To fix a compiler warning.
2026-03-23 11:55:05 +01:00