Skip to content

pipewire: read what a video node says it can do - #257

Merged
jcelerier merged 1 commit into
masterfrom
feat/video-node-format-caps
Sep 14, 2026
Merged

jcelerier merged 1 commit into
masterfrom
feat/video-node-format-caps

Conversation

@jcelerier

Copy link
Copy Markdown
Member

The shared PipeWire context binds every node already and installs the node
listener with the param callback left null, so nothing ever asked a camera what
it supports and a consumer had to guess its format, size and framerate.

Video nodes are now asked for SPA_PARAM_EnumFormat, and the answers are kept
on node_info so the snapshot carries them to callers for free. Each candidate
(video_format_caps) holds the format, the extent of the sizes and framerates
it offers, and its DRM modifiers. A property may be fixed or a choice and both
are read, since a choice stores its values past its body rather than at the
start of the pod.

Two things the shape forces:

  • the node id is not on the param event, and the bound-node vector moves its
    elements, so the listener is given a stable per-node record rather than the
    context;
  • the daemon assigns the sequence rather than the caller, so a round is
    identified by what the request returns — a node that re-advertises supersedes
    the replies still in flight, which would otherwise land on top of the new list
    and read as the union of both.

An empty list means "not answered yet", never "supports nothing": a reader has
to fall back rather than refuse.

Why now

ossia score's PipeWire input panel uses this to offer only what the picked node
actually advertises instead of the whole table (ossia/score#2269). That branch
cannot build against a libremidi without it, so this is the first link in the
chain — libossia's vendored pin follows, then score's.

Rebased onto master; builds clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_019QWYTEhFJonuUNTEmBfv7Q

The context binds every node already and installs the node listener with the
param callback left null, so nothing ever asked a camera what it supports and
a consumer had to guess.

Ask video nodes for SPA_PARAM_EnumFormat and keep the answers on node_info,
where the snapshot carries them to callers for free. Each candidate holds the
format, the extent of the sizes and framerates it offers, and its DRM
modifiers; a property may be fixed or a choice and both are read, since a
choice stores its values past its body rather than at the start of the pod.

Two things the shape forces. The node id is not on the param event and the
bound-node vector moves its elements, so the listener is given a stable
per-node record instead of the context. And the daemon assigns the sequence
rather than the caller, so a round is identified by what the request returns:
a node that re-advertises supersedes the replies still in flight, which would
otherwise land on top of the new list and read as the union of both.

An empty list means "not answered yet", never "supports nothing": a reader
has to fall back rather than refuse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QWYTEhFJonuUNTEmBfv7Q
@jcelerier
jcelerier merged commit dd8b586 into master Sep 14, 2026
39 of 90 checks passed
@jcelerier
jcelerier deleted the feat/video-node-format-caps branch September 14, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant