Skip to content

Add V4L2 stateful encoder support (-hwaccel v4l2) - #52

Open
nburns wants to merge 1 commit into
omarroth:mainfrom
nburns:v4l2-h264-encoder
Open

nburns wants to merge 1 commit into
omarroth:mainfrom
nburns:v4l2-h264-encoder

Conversation

@nburns

@nburns nburns commented Sep 23, 2026

Copy link
Copy Markdown

Adds a v4l2h264enc candidate (auto mode: after VA-API, before software) and -hwaccel v4l2. This is the standard hardware encode path on ARM SoCs (Raspberry Pi, Qualcomm, i.MX, Rockchip), where NVENC/VA-API don't exist. The element only registers when the kernel exposes a stateful encoder node, so the existing probe gates it correctly.

Tuning uses the kernel-standard controls via extra-controls (bitrate/CBR, GOP, no B-frames, repeated headers); drivers skip controls they don't implement. One quirk found on hardware: bcm2835 fails STREAMON unless negotiation pins the H.264 level, so encoderResult gains an optional afterEncoder caps stage and the v4l2 row pins level=4 (signaling only).

Validated on a Raspberry Pi 4 (bcm2835-codec, kernel 6.12, GStreamer 1.26.2):

  • -test loopback: 1080p30 through the hardware encoder, extra-controls bitrate verifiably applied
  • Live: Pi 4 -> macOS AirPlay receiver (srcvers 935.7.1), PIN pairing + 720p stream confirmed on screen
  • go test ./... / vet / gofmt clean on linux/arm64; new contract-test cases

Not tested on other V4L2 drivers (venus/iris etc.) — happy to iterate on reports.

Add a v4l2h264enc candidate to the H.264 encoder table, between the
existing hardware encoders and the software fallbacks in auto mode, and
accept v4l2 as an explicit -hwaccel method.

V4L2 stateful encoders are the standard hardware encode path on ARM SoCs
(Qualcomm venus/iris, Raspberry Pi, NXP i.MX, Rockchip via hantro), where
neither NVENC nor VA-API is available. The element only registers when
the kernel exposes a matching /dev/video* encoder node, so the existing
gst-inspect probe gates selection correctly on systems without one.

Encoder tuning goes through extra-controls using the standard V4L2
control names (bitrate in bps, CBR mode, I-frame period/GOP matching the
existing keyframe interval, no B-frames, repeated sequence headers).
Controls a driver does not expose are skipped by GStreamer with a
warning rather than failing the pipeline, so the same stage works across
encoder implementations.

encoderResult gains an optional afterEncoder caps stage, placed between
the encoder and the parser. The v4l2 row uses it to pin the H.264 level
(level=4, signaling only): without a fixed level in negotiation the
bcm2835 driver on Raspberry Pi fails STREAMON with "Failed enabling
i/p port, ret -3".

Validated on a Raspberry Pi 4 Model B (bcm2835-codec, kernel 6.12,
GStreamer 1.26.2): -test mode against doubletake-test-receiver selects
V4L2 hardware encoding, streams 1920x1080@30 through the hardware
encoder, and the extra-controls bitrate demonstrably applies. Selection
logic covered by contract tests; go test ./... passes on linux/arm64.
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