Skip to content

Patched decklink plugin with synchronized capture group support#554

Merged
srperens merged 2 commits intomainfrom
feat/patched-decklink-capture-group
May 8, 2026
Merged

Patched decklink plugin with synchronized capture group support#554
srperens merged 2 commits intomainfrom
feat/patched-decklink-capture-group

Conversation

@srperens
Copy link
Copy Markdown
Collaborator

@srperens srperens commented May 8, 2026

Summary

  • Adds a reproducible Docker-based build setup for patched GStreamer plugins under tools/patched-gstreamer-plugins/. Multi-arch (amd64/arm64) via docker buildx + QEMU, pinned to GStreamer 1.22.12 ABI.
  • Patches gst-plugins-bad decklink to expose BMD's synchronized capture group feature as a capture-group int property on decklinkvideosrc. Lets multiple inputs on the same physical card share a hardware time origin so audio/video are sample-aligned across SDI ports.
  • Built artifacts shipped via GitHub release patched-plugins-v1.0-gst1.22.12. The runtime Dockerfile fetches the right architecture's .so from that release and overlays the distro-shipped libgstdecklink.so.
  • Adds a synchronized_capture: bool block property to decklink_input. Strom hashes the flow ID to a deterministic capture group ID so two synchronized blocks in the same flow always share a group, and different flows can never collide. If the runtime has the stock plugin (no patch), the option is silently ignored.

Why a patched plugin

Stock gst-plugins-bad doesn't expose bmdVideoInputSynchronizeToCaptureGroup / bmdDeckLinkConfigCaptureGroup even though every modern BMD SDK (12.2+) supports them, and the synced-capture lifecycle (one StartStreams/StopStreams call per group, not per element) doesn't match the plugin's element model. Our patch wraps the BMD calls with a refcounted leader-tracking layer so exactly one StartStreams and one StopStreams reach the driver per group, on the same IDeckLinkInput instance.

Known BMD driver quirk

StopStreams() on an input that was enabled with the sync flag blocks for ~12 s before returning. Reproducible in BMD's own SynchronizedCapture SDK example, see forum thread 190441. The patch accepts the wait — bypassing StopStreams violates the documented teardown order and breaks subsequent pipeline starts with caps not-negotiated. The block property's description warns the operator about this so it isn't mistaken for a strom bug.

Test plan

  • Build the patched plugin locally: cd tools/patched-gstreamer-plugins && ./build.sh
  • Verify capture-group property is exposed: GST_PLUGIN_PATH=$PWD/dist/linux_amd64 gst-inspect-1.0 decklinkvideosrc | grep capture-group
  • Build the strom-full Docker image and confirm the runtime Dockerfile pulls the patched .so from the release
  • Create a flow with two decklink_input blocks pointing at the same physical card, both with synchronized_capture enabled. Run a phase-cancellation pipeline (one inverted, summed in audiomixer); the result should be silent across the audible band.
  • Stop the pipeline and confirm restart works without not-negotiated errors (note: stop itself takes ~12 s — this is the documented BMD driver quirk).
  • Run a single-input flow without synchronized_capture; confirm normal behaviour is unchanged.

🤖 Generated with Claude Code

Per Enstedt and others added 2 commits May 8, 2026 12:41
…ture-group support

Adds a reproducible Docker-based build setup for patched GStreamer plugins
under tools/patched-gstreamer-plugins/. The first patch exposes BMD's
synchronized capture group feature as a `capture-group` property on
decklinkvideosrc, letting two SDI inputs on the same physical card share
a hardware time origin so audio/video are sample-aligned across ports.

Build target is GStreamer 1.22.12 (forward-ABI-compatible with 1.24, 1.26+).
Multi-arch (amd64/arm64) via docker buildx + QEMU. Built artifacts are
distributed via GitHub release patched-plugins-v1.0-gst1.22.12.

The runtime Dockerfile fetches the right architecture's .so from the
release and installs it over the distro-shipped libgstdecklink.so.

The strom-side block-property exposure lives in decklink.rs and will be
committed separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a synchronized_capture: bool block property to decklink_input. When
enabled, strom derives a deterministic capture group ID from the flow ID
and sets it on the underlying decklinkvideosrc element via the patched
plugin's capture-group property.

Hashing the flow ID (rather than letting the user pick an integer)
prevents the foot-gun where two flows accidentally pick the same group
ID — BMD synced capture only works within a single pipeline anyway, and
hash-of-flow_id is unique-per-flow by construction.

If the runtime has the stock unpatched decklink plugin, the
capture-group property is absent and we skip silently — no error, the
block just runs without sync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@srperens srperens merged commit 6898195 into main May 8, 2026
7 checks passed
@srperens srperens deleted the feat/patched-decklink-capture-group branch May 8, 2026 12:10
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