Expand description
Hardware H.264 through a generic stateful V4L2 M2M encoder: boards whose encoder sits behind the kernel’s own interface rather than a vendor library or a render node, such as a Raspberry Pi 4, RK356x, or i.MX8M. Built everywhere, since the interface is the kernel’s. Hardware H.264 through a generic stateful V4L2 M2M encoder.
Boards that carry an encoder behind the kernel’s own M2M interface publish no render node the
VA-API backend can probe and no vendor library the NVENC one can load, so the ladder reaches
software on hardware that encodes. A Raspberry Pi 4 is the case at hand (bcm2835-codec), and
RK356x and i.MX8M carry the same interface, so the node is discovered by what it offers rather
than by the board it sits on.
One host frame becomes one access unit: the frame is copied into the output buffer, queued, and
the access unit comes back on the capture queue. The copy is the floor here as it is on Tegra —
X11 capture hands over host memory — and it costs 3.81 ms for a 1080p frame on a Pi 4, which is
the same speed as a copy between two ordinary allocations: the videobuf2-dma-contig buffer
takes a write stream at full memory bandwidth.
Three things about such a device were measured rather than assumed, and each shapes the code:
- The output queue takes packed 32-bit color and the firmware converts it, so nothing converts
on the CPU. The fourcc names are the opposite way round from the memory a caller holds:
AB24takes the BGRA an X11 capture produces, andBGR4takes RGBA. Decoding an encoded chart is what settled that; reading the names would have swapped red and blue. - The conversion is BT.601 at full range, and it cannot be steered: a
S_FMTasking for REC709 at limited range comes back echoed and changes nothing. The stream also carries novideo_signal_type, so what the session declares has to be written into the SPS on the way out, whichcollectis the place for. - Constant bitrate is not available, and asking for it does not merely fail: the driver hands
the firmware a rate control mode it refuses, and the next
STREAMONanswersESRCH. A control this session cannot set is therefore a refusal, never a warning — the node has to be closed and reopened to be usable again.
Structs§
- Buffer 🔒
- Capability 🔒
- Control 🔒
- FmtDesc 🔒
- Format 🔒
- Frame
Size 🔒Enum - Node
Info 🔒 - What an encode node offers, read once for the process.
- PixFormat
Mplane 🔒 - Plane 🔒
- Plane
Format 🔒 - Request
Buffers 🔒 - Stream
Parm 🔒 - The union of
v4l2_streamparmbegins one word in, not two: the frame rate lands in the wrong place if this is laid out likev4l2_format. - V4l2
M2mEncoder
Enums§
- Color 🔒
- What the session has learned about the color its device produces.
Constants§
- BITRATE_
MODE_ 🔒VBR - Variable is the only rate control such a device offers; see the note at the top about what asking for constant does to the session.
- CAPTURE_
BUFFERS 🔒 - CID_
BITRATE 🔒 - CID_
BITRATE_ 🔒MODE - CID_
FORCE_ 🔒KEY_ FRAME - CID_
GOP_ 🔒SIZE - CID_
H264_ 🔒I_ PERIOD - CID_
REPEAT_ 🔒SEQ_ HEADER - FRAME_
TIMEOUT_ 🔒MS - Long enough for a frame the hardware is slow on, short enough that a stalled node rebuilds the session rather than holding the stream. A 1080p frame takes about 35 ms on a Pi 4.
- FRMSIZE_
TYPE_ 🔒DISCRETE - OUTPUT_
BUFFERS 🔒 - V4L2_
BUF_ 🔒TYPE_ VIDEO_ CAPTURE_ MPLANE - V4L2_
BUF_ 🔒TYPE_ VIDEO_ OUTPUT_ MPLANE - V4L2_
CAP_ 🔒VIDEO_ M2M - V4L2_
CAP_ 🔒VIDEO_ M2M_ MPLANE - V4L2_
FIELD_ 🔒NONE - V4L2_
MEMORY_ 🔒MMAP - V4L2_
PIX_ 🔒FMT_ BGRA - Packed 32-bit color. The kernel spells these by channel order in a word and a caller holds
bytes, so
AB24is the BGRA of an X11 capture andBGR4is RGBA. - V4L2_
PIX_ 🔒FMT_ H264 - V4L2_
PIX_ 🔒FMT_ HEVC - V4L2_
PIX_ 🔒FMT_ RGBA - V4L2_
PIX_ 🔒FMT_ VP8 - V4L2_
PIX_ 🔒FMT_ VP9 - VIDIOC_
DQBUF 🔒 - VIDIOC_
ENUM_ 🔒FMT - VIDIOC_
ENUM_ 🔒FRAMESIZES - VIDIOC_
QBUF 🔒 - VIDIOC_
QUERYBUF 🔒 - VIDIOC_
QUERYCAP 🔒 - VIDIOC_
REQBUFS 🔒 - VIDIOC_
STREAMOFF 🔒 - VIDIOC_
STREAMON 🔒 - VIDIOC_
S_ 🔒CTRL - VIDIOC_
S_ 🔒FMT - VIDIOC_
S_ 🔒PARM
Functions§
- abi_
matches 🔒 - The sizes the ioctl numbers above encode, checked once so a layout that drifted is a refusal with a name rather than a scribble through a structure.
- available
- Whether this machine carries an M2M encode node at all.
- coded_
fourcc - The capture-queue format for a codec the kernel’s interface names, or
Nonefor one it does not. The queues, the controls, and the input format are the same whichever of these a node carries, so the codec is a parameter rather than a second backend. - empty_
format 🔒 - encodes
- Whether a session of this codec and size would come up on it, so the ladder can fall through to software before a session exists rather than after one has failed.
- enumerates 🔒
- fallback_
rates 🔒 - The rates to try, in order: what the session asked for, then the ones a device that refuses it is likely to take. A device is asked at its own rate first, so one that can do it is never slowed, and the steps below are the rates video hardware is built around rather than a search.
- frame_
sizes 🔒 - input_
format 🔒 - The fourcc for the bytes a caller holds. The kernel spells these by channel order in a word, so the name of each is the reverse of the memory it takes, and a session that picks by name rather than by byte order swaps red and blue without failing.
- ioctl 🔒 ⚠
- known_
conversion 🔒 - What a device is known to convert RGB with when it declares nothing itself. Only a device
whose behavior is on record earns an entry: a Raspberry Pi with firmware older than August
2024 converts to full range BT.601 and writes no
video_signal_type, which the driver’s author states in the firmware tracker and a decoded chart confirms. Guessing for a device not on this list would put a claim in the stream that nobody has checked, and a wrong declaration colors a picture worse than an absent one. - node 🔒
- The first node that encodes H.264 from packed color, found by asking rather than by name: the number a board gives its encoder is not a contract, and the same interface appears on boards with entirely different numbering.
- served
- The codecs the node encodes, for the report a caller reads before any session exists.