Commit graph

15637 commits

Author SHA1 Message Date
Carlos Rafael Giani
95fddd5a48 Merge branch 'rtp-rework-audio-codec-support' into 'master'
module-rtp: Rework audio codec support (specifically Opus audio) + additional RTP module fixes

See merge request pipewire/pipewire!2876
2026-07-01 09:59:05 +00:00
Daniel Scally
551eb0a473 gstpipewiresrc: Add a wait_negotiated() call to create()
Add a wait_negotiated() call to gst_pipewire_src_create(). This works
around a race-condition that we experience where the function is
called after the state is transitioning to paused, and after a
SPA_PARAM_Format with a NULL parameter has been passed. That event
is handled in the pipewire source by setting its negotiated flag to
False, which results in gst_pipewire_src_create() returning
GST_FLOW_NOT_NEGOTIATED, resulting in a failed stream attempt.

With this change, the stream survives the state change.

Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
2026-07-01 09:21:31 +00:00
Julian Bouzas
8d93b779cd pulse-server: don't consider monitor nodes when finding the default source
If a system does not have any Audio/Source node, clients that want to capture
audio from the default source should fail instead of capturing audio from a
monitor Audio/Sink node.
2026-07-01 09:11:03 +00:00
Hugo Osvaldo Barrera
855735d720 Use descriptive description for Pro devices
For Pro Audio devices, the description is the card name with "Pro" or
Pro 1", "Pro 2", etc. appended. The result is user interfaces showing
around half a dozen devices with descriptions that don't help
disambiguate devices in the slightest.

Append the underlying PCM names instead of the "Pro N" string, so that
devices can be recognised at a glance.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/work_items/3982
2026-07-01 09:00:39 +00:00
刘佳和
6eddd1080f avb-pcm: fix typo in error log message 2026-07-01 08:43:31 +00:00
Charles
fc6e12bed0 gst: don't make stream errors fatal in pipewiresink mode=provide
When a consumer (e.g. Firefox via xdg-desktop-portal) connects to a
pipewiresink mode=provide node and format negotiation fails, the error
reaches the stream as a transient proxy error. The comments in
proxy_error suggest the application should decide whether the error is
permanent.

Before this on_state_changed unconditionally made every proxy error
permanent by calling pw_stream_set_error, which posted
GST_ELEMENT_ERROR and killed the entire provider pipeline. A virtual
camera provider should survive consumer negotiation failures.

In mode=provide, log the error as a warning and continue. Other modes
retain the existing behavior.

To reproduce (with the previous pool fix applied):

Producers:

gst-launch-1.0 -v -e pipewiresrc path=<id> ! \
  video/x-raw,width=1280,height=720,framerate=24/1 ! \
  jpegenc ! rtpjpegpay ! rtpstreampay ! \
  udpsink host=127.0.0.1 port=5000
gst-launch-1.0 -e \
  udpsrc address=127.0.0.1 port=5000 ! queue ! \
  application/x-rtp-stream,encoding-name=JPEG ! rtpstreamdepay ! \
  application/x-rtp,encoding-name=JPEG ! rtpjpegdepay ! \
  decodebin ! videorate ! videoconvert ! \
  pipewiresink mode=provide \
  stream-properties="properties,media.class=Video/Source,media.role=Camera" \
  client-name=VirtualCam

Then open Firefox and select VirtualCam as camera source, without this
fix the provider pipeline exits with an error, bringing down any other
clients streaming from it.
2026-07-01 08:42:56 +00:00
Charles
e95cad05ef gst: skip invalid crop metadata in pipewiresrc
META_VideoCrop is present on every buffer negotiated through the
adapter, even when the producer never sets a meaningful crop
region. Before commit c634ef961, gst_buffer_get_video_crop_meta
returned NULL on new GstBuffers so the zero values were never
applied. After that commit, gst_buffer_add_video_crop_meta always
succeeds, and an invalid crop produces black frames.

Without this, the following produces black frames,

Producer:

gst-launch-1.0 videotestsrc is-live=true ! \
  video/x-raw,format=I420,width=1280,height=720,framerate=24/1 ! \
  pipewiresink mode=provide \
  stream-properties="properties,media.class=Video/Source,media.role=Camera" \
  client-name=VirtualCam

Consumer:

gst-launch-1.0 pipewiresrc path=<id> ! videoconvert ! autovideosink
2026-07-01 08:42:56 +00:00
Torkel Niklasson
0a413c866c gst: deviceprovider: tear down node proxies before releasing core
Destroy the bound node proxies in probe() and stop() while the loop is
locked, before releasing the core. This removes the node listeners so no
node_event_info can fire after the core is gone, fixing the root cause of
the resync() NULL-deref crash and a node-proxy leak.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-30 14:21:08 +00:00
Elliot Chen
7ee2416bdd pipewiresrc: fix caps negotiation failure in some cases when changing state from playing to paused
basesrc will do caps negotiation if pad is reconfigured. Should check and
wait if caps negotiation is currently in progress before corking the stream.

Return true when flushing to avoid caps negotiation failure.
2026-06-30 14:20:10 +00:00
Wim Taymans
3c14693bed client-node: clear mix when clearing the node
Even if we don't have a transport we should clear the mix info if there
is any available.

Fixes #5348
2026-06-30 16:17:12 +02:00
Wim Taymans
187b9154a6 filter-chain: pass context to filter-graph
Pass the IO_Position and IO_Latency to the filter graph in the
context.
2026-06-30 12:52:32 +02:00
Wim Taymans
e42657f030 io: flesh out the node IO_Latency
Make this more useful by adding the capture and playback latency.

This structure can be used to say how much latency there is between the
capture and playback hardware.
2026-06-30 12:35:00 +02:00
Wim Taymans
5e521d3532 filter-graph: pass context to plugins
Make it possible to pass context to plugins and nodes in the
filter-chain.

We can use this to make filters aware of the graph clock or
latency, for example.
2026-06-30 12:24:54 +02:00
Wim Taymans
aa075c2a12 filter-graph: add support for multiple handles
Make instantiate create all the related handles in one go.

When a processing node has 1 in/out, multiple handles are created to
support multichannel. By instantiating the handles in one go, the
implementation could do some special multichannel support or do some
optimizations, like parse the config string only once.
2026-06-30 11:58:33 +02:00
Wim Taymans
b3eb2eabb8 filter-graph: return result from instatiate
Instead of returning a handle (and errno on NULL), return a result code
and store the handle in a return variable.

This makes it easier to handle the errors but also makes it possible to
return multiple handles later.
2026-06-30 11:20:15 +02:00
Wim Taymans
978e8c1a4b audioconvert: small cleanups
Move the sync code to before it is used.

We don't need to clear the graph setup state anymore in force mode, we
did that before we did the sync.
2026-06-29 10:36:26 +02:00
Torkel Niklasson
f174b4e688 audioconvert: sync filter-graphs out of data loop before forced rebuild
A forced setup_filter_graphs() deactivates and re-instantiates every graph,
which frees and recreates the underlying plugin handles (node_cleanup sets
node->hndl[i] = NULL before re-instantiating). This was done on a graph that
was still referenced by the RT data-loop snapshot (filter_graph[]), so the
RT thread could run a graph whose handles were NULL mid-rebuild, leading to a
NULL handle dereference in the filter-graph process path.

Mirror the safe ordering already used by load_filter_graph()/clean_filter_handles():
before reconfiguring, mark the graphs not-setup and sync_filter_graph() so the
data loop drops them from filter_graph[] under the loop lock. They are
republished by the sync that follows setup. The cheap snapshot swap is done
under the lock; the heavy re-instantiation stays off the RT path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 08:17:07 +00:00
Wim Taymans
10b339bbf8 docs: fix SVG text rendering to always use black
The drawio-exported SVGs used light-dark() CSS to switch text between
black and white based on color scheme. This caused white-on-light text
when viewing in dark mode. Replace all light-dark() values with their
light-mode equivalents so text and strokes are always black.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 12:52:47 +02:00
Wim Taymans
a988df47a2 docs: escape angle brackets in conf.c and fix page_core_api references
- conf.c: escape <key>, <value>, <action> placeholders in doc comment
- context.h, permission.h: fix \ref page_core_api to \ref api_pw_core

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 12:46:00 +02:00
Wim Taymans
9710f02837 docs: escape angle brackets and fix @filename and \ref in doc comments
Escape <portname>, <tensorname>, <paramname>, <port>, <rules> and
similar angle-bracket placeholders that doxygen interprets as HTML
tags. Also escape @filename (unknown doxygen command) and fix the
pw_stream::process() reference in thread-loop.h.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 12:43:56 +02:00
Wim Taymans
f055949cb5 docs: fix broken doxygen references and escape HTML tags
- modules.dox: remove references to non-existent sendspin modules
- access.dox: remove reference to deprecated pipewire-media-session
- dma-buf.dox: fix \ref EnumFormat to \ref SPA_PARAM_EnumFormat,
  fix \ref struct to struct \ref for spa_meta_sync_timeline
- pipewire.conf.5.md: add explicit {#synopsis} anchor for internal links
- pipewire-client.conf.5.md: fix audio_converter to audio_adapter ref
- pipewire-jack.conf.5.md: escape <id> HTML tags
- pipewire-props.7.md: fix monitor-prop__ to props__ for card profiles ref
- pipewire-pulse.1.md: fix pipewire-env ref to full anchor name
- pipewire.1.md: fix \ref CPU to \ref spa_cpu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 12:42:01 +02:00
Wim Taymans
c4b767cba1 docs: rename pulse module files to fix doxygen \file name collisions
Prefix all pulse module source files with pulse- to give them unique
basenames, avoiding ambiguous \file suffix matching in doxygen when
identically-named files exist under src/modules/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 12:37:39 +02:00
Simon A. Eugster
2a88fb6ae8 docs: Remove specific user overview page again 2026-06-26 10:00:15 +00:00
Simon A. Eugster
1201b2ed32 docs: Extend description of object types 2026-06-26 10:00:15 +00:00
Simon A. Eugster
24770baaa0 docs: Add Tools and Configuration sections 2026-06-26 10:00:15 +00:00
Simon A. Eugster
8e5617c439 docs: Add routing examples 2026-06-26 10:00:15 +00:00
Simon A. Eugster
8a659f1aaa docs: Explain PipeWire role, add graphics 2026-06-26 10:00:15 +00:00
Simon A. Eugster
6a6feb45fe docs: Add user overview docs for PipeWire 2026-06-26 10:00:15 +00:00
Elliot Chen
9b2ff82aea pipewiresrc: unlock loop when failing to wait negotiated 2026-06-26 09:57:23 +00:00
Val Lorentz
acbcf5cece doc: Fix paths to config files 2026-06-26 09:52:08 +00:00
Wim Taymans
07955ff312 Doc: fix some formatting and syntax issues
In pipewire-props.7.md changed ALSA-specific audio.* entries from @PAR@ node-prop
to plain \par to eliminate duplicate section label anchors.
2026-06-26 11:15:38 +02:00
Wim Taymans
f1658434be docs: fix some signedness compilation warnings 2026-06-26 10:27:34 +02:00
Pauli Virtanen
393da55797 bluez5: backend-native: fix multiple profile registration
Handling pending RegisterProfile callbacks was wrong as it forgot that
there can be multiple profiles to be registered.

Fix the handling by allowing several concurrent register callbacks.
2026-06-25 18:21:46 +03:00
Pauli Virtanen
422765c91d test: bluezenv: check multiple backend-native profiles can be registered 2026-06-25 18:21:46 +03:00
Wim Taymans
7dc35030dc filter-graph: add normalize option for sofa
Add an option to enable the use of the sofa loudness function to
normalize the IR.

See #5322
2026-06-25 16:24:38 +02:00
Barnabás Pőcze
a5ade5f96e spa: {libcamera,v4l2}: device: remove params
No params are implemented, so remove them from the emitted `spa_device_info`.
For v4l2, `n_params` was already set to 0 in 938e2b1451
("v4l2: profiles params are not implement yet"), effectively removing them.

No implementation has materialized in the last 5 years, so remove them
altogether, and do the same in the libcamera plugin as well.
2026-06-25 12:05:04 +02:00
Wim Taymans
2a4222a538 jack: fix race in get_buffer_output()
When a single output port is linked to multiple input ports of the same
client and the client uses multiple threads to process the input ports,
get_buffer_output() is called from multiple threads concurrently and
causes a race.

Multiple threads will try to dequeue a buffer concurrently and set the
HAVE_DATA io status, which causes the port to run out of buffers quickly
and the io are to become corrupted.

Use CAS to make sure only one thread dequeues and sets the io status.
The other concurrent threads will spin until there is a buffer. The fast
path will be that the buffer is already dequeued and then it is simply
reused.

Fixes #5324
2026-06-25 11:21:01 +02:00
Wim Taymans
d97a9bf44b pulse-server: actually print properties of module
When inspecting the loaded modules, actually list the properties that
were used when loading the module instead of the informational generic
ones from the info.

Pulsaudio also does not list the Usage properties when listing modules.
2026-06-25 09:21:27 +02:00
Carlos Rafael Giani
6b524fd596 module-rtp: Add audio codec support to audio.c and replace opus.c with it
Opus was integrated as a completely separate code path to the PCM audio
processing found in audio.c. This is actually not ideal, since the only
part that actually is Opus specific is the part that en- and decodes from
and to PCM. The rest is 1:1 the same PCM handling.

For this reason, it is much better to instead add audio codec support to
audio.c, meaning that the code in there can now encode PCM audio right
before sending it out as RTP, and decode incoming packets to PCM right
before actually processing the decoded audio data.

This significantly modifies how stream.c initializes the PCM audio path,
since the audio codec feature is new. It now treats the Opus subtype
as an audio codec selector instead of a selector for an entirely
alternate code path (like how MIDI integration remains entirely separate).

Since audio codecs usually require their frames to be decoded in order,
this also integrates the RTP jitter buffer in the RTP module.

Opus is now integrated as such a codec in audio.c. When it is selected,
incoming packets in rtp_audio_receive() are first inserted into the
jitter buffer. That buffer then outputs packets in order, and then, these
packets are decoded to PCM. The rest of the processing chain goes as usual.
A similar route is used for when the jitter buffer signals packet loss
to be able to apply PLC.

For encoding, it is similar (except that no jitter buffer is involved);
in rtp_audio_flush_packets(), when Opus is active, the PCM data is
rerouted to be fed to Opus for encoding, and the Opus output is then
placed into the iovec array instead of the original PCM.

This also improves overall Opus support; it supports S16 PCM data in
addition to F32 data, correctly checks the ptime, sample rate etc. for
Opus compatibility, computes an ideal bitrate, allows for manual bitrate
selection and encoding complexity adjustment (via the new stream properties
"opus.encoder.bitrate" and "opus.encoder.complexity"), sets several other
Opus CTLs to fixed values, supports the Opus restricted-lowdelay mode
(sacrifices Speech code paths for lower latency, enabled by setting the
"opus.encoder.restricted-lowdelay" stream property to true), and also uses
Opus' PLC in case of packet loss.

The audio codec interface is designed such that adding other codecs in
the future is easily doable. New integrations need to implement the
function pointers found in the rtp_audio_codec structure, and expose
an instance of such a custom rtp_audio_codec structure instance (see
the get_rtp_opus_codec() implementation for an example).
2026-06-24 19:01:13 +02:00
Carlos Rafael Giani
31bb82e116 module-rtp: Add RTP jitter buffer
This new data structure is useful for reordering incoming packets if they
arrive out-of-order. Many audio codecs require frames and/or packets to be
processed in sequence order due to inter-frame dependencies, so reordering
is critical for such encoded data. It also detects lost packets and reports
those in sequence with received packets (crucial for proper PLC), and
detects and drops late and duplicate packets.
2026-06-24 19:01:13 +02:00
Carlos Rafael Giani
f17b9b3ce6 module-rtp-source: Detect and drop packets that are larger than the MTU 2026-06-24 19:01:13 +02:00
Carlos Rafael Giani
470a758e2a module-rtp: Correctly scale device_delay in constant latency mode 2026-06-24 19:01:13 +02:00
Carlos Rafael Giani
11775850e5 module-rtp: Cleanup default raw / raop formats
This places the default formats into a single place, which makes
it easier to keep track of them.
2026-06-24 19:01:13 +02:00
Wim Taymans
9bcbd7b586 pulse: generate Usage from module_args definition
Add some more fields like the type, default value and possible enum
values for the module_args.

Use this to generate the Usage in describe-module and the docs.

This should give more consistent and correct Usage output in all
modules.
2026-06-24 18:59:19 +02:00
AMG
9f7eb63486 refactor: pr 2026-06-24 16:32:43 +00:00
AMG
b4b4e03816 pw-container: Add socket path parameter 2026-06-24 16:32:43 +00:00
Julian Bouzas
62e98466fa conf: fix matching of property values with colons
Use spa_json_begin_array() instead of the relaxed variant when parsing
property values in pw_conf_find_match().

This prevents plain string values containing ':' (such as object.path)
from being incorrectly tokenized while preserving support for actual
JSON array properties.
2026-06-24 10:52:49 -04:00
Wim Taymans
7dac6a71d5 conf: avoid using close_range when undefined
Only call close_range when CLOSE_RANGE_UNSHARE is defined.

Fixes compilation on alpine.
2026-06-23 18:36:52 +02:00
Barnabás Pőcze
559a30b0b4 spa: libcamera: source: reject buffers with incorrect number of planes
`SPA_PARAM_BUFFERS_blocks` is a specific value, the plugin host should
not use any other number of data planes, so reject other values.

For example, the `buffers[i]->n_datas > planes.size()` situation was
not handled correctly, and this removes the need for handling that.
2026-06-23 15:00:15 +00:00
Barnabás Pőcze
44176d4118 spa: libcamera: expose libcamera version
Expose the libcamera header and library versions in the device properties
similarly to `api.v4l2.cap.version` used by the v4l2 plugin.

The keys are not yet promoted into the public `keys.h` header file.
2026-06-23 15:00:15 +00:00