fix(vision mixer): keep per-pixel alpha on keyed pads with an alpha-less output_format - #748
Draft
wagenet wants to merge 2 commits into
Draft
fix(vision mixer): keep per-pixel alpha on keyed pads with an alpha-less output_format#748wagenet wants to merge 2 commits into
wagenet wants to merge 2 commits into
Conversation
…ess output_format The CPU path forced `output_format` on the compositor and on every keyed input feeding it. `compositor` blends in its own output format and converts each sink pad to that format first, so an alpha-less choice (NV12, I420, RGB, ...) flattened the alpha of DSK graphics, the multiview overlay and the border underlays: a transparent DSK region composited as the graphic's own black, and the multiview showed nothing but the overlay. Blend in the alpha-carrying counterpart of the requested format (A420, A422, A422_10LE or RGBA) whenever a compositor has keyed pads, and convert to `output_format` after the mixer. The property still pins what leaves the block. The DSK and overlay capsfilters are gone — they only stripped alpha before the compositor could use it. The video-input capsfilters stay: their tee feeds two independently negotiating compositors and needs the pin. The GPU path never referenced `output_format` and is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The readiness loop waited for the opaque half of the DSK graphic to go dark, which an all-black startup frame also satisfies — so the run could measure a frame composited before anything had arrived. That is what failed on Linux CI while passing locally; an opaque-keyed failure is dark in exactly the same way. Wait for that half to actually be red, and assert on the fraction of red and white pixels rather than mean luma. Readings go to 0.000/1.000 instead of luma thresholds with a 30-point margin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
The vision mixer's
output_formatproperty offers alpha-less formats (I420, NV12, RGB, ...). Setting one on the CPU path destroyed the per-pixel alpha of every keyed pad:There is a standing incentive to set the property: unpinned RGBA into
vtenc_h264_hwnegotiates AYUV64 rather than NV12.Cause
Two places, one mechanism.
The builder inserted
output_formatcapsfilters on the DSK chains and on the overlay appsrc chain, flattening alpha before the compositor saw it. Removing those alone does not fix it — measured, not assumed.compositorblends in its own output format and converts every sink pad to that format first, so pinning an alpha-less format on the compositor's src caps makes its sink pads alpha-less too. Directly:The hazard was already known in this file — the border underlays pin RGBA with a comment saying an alpha-less
output_format"would silently drop the alpha of #RRGGBBAA border colors" — but the conclusion was never applied to the compositor's own output.Fix
When a compositor has keyed pads and
output_formatcannot carry alpha, blend in the alpha-carrying counterpart of the requested format (A420, A422, A422_10LE, or RGBA — matching the requested chroma subsampling) and convert tooutput_formatafter the mixer.output_formatstill pins what leaves the block; it no longer dictates the blend space.The dist compositor gets this when DSK inputs or PiP border underlays exist; the multiview always does, since its overlay is a full-canvas RGBA pad.
The DSK and overlay capsfilters are dropped. The video-input capsfilters stay — their tee feeds two independently negotiating compositors, which is what they are for.
builder/pipeline_gpu.rsnever referencedoutput_formatand is unchanged.Tests
New
backend/tests/vision_mixer_keyed_alpha_test.rsbuilds a real flow throughPipelineManager(followingvision_mixer_fx_test.rs): a white program input, a DSK graphic that is opaque red on the left half and fully transparent on the right,output_format=NV12, CPU backend. It asserts the transparent half still reads the white background, that the multiview shows picture once the overlay renderer has actually pushed frames, and that PGM still negotiates NV12. A second test runs the same flow withoutput_format=Autoas the never-broken baseline.Two things the measurement has to get right, both of which produced a green test that guarded nothing until fixed. The multiview reading is gated on a buffer probe counting overlay appsrc pushes, so it cannot pass by measuring a multiview the overlay has not reached yet. And readiness is detected by colour, not brightness: an all-black startup frame is dark in exactly the way an opaque-keyed failure is dark, so the run waits for the graphic's opaque half to actually be red before measuring.
Verified by reverting the fix and re-running — the guard goes red on both halves:
Run locally on macOS (Apple silicon, GStreamer 1.28.6): the full
cargo testsuite, all green, including the new test andvision_mixer_fx_test. Nothing was skipped in the new test — it needscompositor(gst-plugins-base) andvideobox(gst-plugins-good), both already in the CI package list on every platform, and it has no skip path. Not run: anything requiring hardware absent from this machine (NVIDIA/CUDA paths).🤖 Generated with Claude Code