webrtcsink's codec discovery builds its encoding chain with no output caps, so `force_profile` is
true and it inserts a capsfilter demanding `profile=constrained-baseline` — WebRTC's interoperable
floor. h264parse strips `alignment`, `stream-format` and `parsed` from a caps query but not
`profile`, so that demand reaches mpph264enc's src pad, whose template listed only
`{ baseline, main, high }`. Empty intersection, GstVideoEncoder's sink getcaps returns nothing,
and the failure surfaces upstream as videorate reporting it "could not transform NV12 ... in
anything we support". Discovery then drops H.264 with a warning nobody was reading, VP8 wins by
default, and the session dies in rtpvp8pay.
The element could always produce constrained-baseline; only its static template denied it.
Measured on an RK3566: `mpph264enc profile=baseline ! h264parse` negotiates
`profile=(string)constrained-baseline` on the parser's src pad, because baseline mode turns CABAC
and 8x8 transform off and MPP emits no FMO, ASO or redundant slices. So this widens the template
by one word rather than claiming something new.
Patches now live in a directory per upstream, applied by an `apply_patches` helper and recorded in
the MANIFEST as `patch <project>/<file>`. Two reasons: a patch aimed at the wrong tree failed the
same way a stale one does, and the MANIFEST's flat `patch <file>` line landed next to whichever
.so happened to precede it, which read as provenance for the wrong plugin.
Assisted-by: Claude:claude-opus-5[1m]
`make_converter_for_video_caps` builds the chain webrtcsink inserts ahead of an
encoder it selected, special-casing hardware it knows — NVMM, D3D11, CUDA, GL,
VA, and on main also v4l2h264enc — and falling back to software
`videoconvert ! videoscale` for anything else. Rockchip's MPP encoder takes
NV12, I420, YUY2 and more directly and converts on the SoC's 2D accelerator, so
the fallback adds a full CPU pass over every frame to do work the hardware was
going to do anyway, on the four A55s robotd's 50 Hz loop shares.
The reason this matters more than CPU: the robot currently avoids the whole
question by pre-encoding and handing webrtcsink finished H.264. That works, and
it means webrtcsink cannot reach the encoder — so congestion control cannot
adapt the bitrate to the link, and a peer's PLI cannot produce a keyframe, which
leaves a viewer that lost one broken until the next periodic GOP. Letting
webrtcsink own the encoder fixes both. This patch is what makes that affordable.
**This repository is no longer patch-free, and says so.** MPL-2.0 asks that
modifications be identifiable, so the README states it, patches/README.md gives
each patch's reasoning, and build.sh records every applied patch in the release
MANIFEST beside the upstream ref. `git apply --check` runs first, so a patch that
stops applying fails the build naming itself rather than yielding a plugin
quietly missing the change it was carried for.
The trade-off is written down rather than glossed: without videoscale the bin
cannot resize, so the negotiated resolution must be one the source produces.
True on this robot, which pins its caps upstream of the tee — and the reason
upstream may want RGA-backed scaling instead of nothing before taking it. The
v4l2h264enc arm on main is the same shape for another hardware encoder, so the
precedent exists, and if it lands this file is deleted at the next bump.
Verified to apply cleanly against a real 0.15.3 checkout.
Assisted-by: Claude:claude-opus-5[1m] shellcheck