This is what was actually broken — and it's much smaller than the STUDY
guessed.
The library is in fact multiplanar-aware throughout the v4l2.c helpers
(v4l2_setup_format, v4l2_get_format, v4l2_query_buffer, v4l2_queue_buffer,
v4l2_dequeue_buffer all branch on v4l2_type_is_mplane). The whole
"context.c / picture.c are single-plane" hypothesis from STUDY.md was wrong —
they derive output_type and capture_type from
video_format->v4l2_mplane and pass them through.
The bug is upstream of all that: driver_data->video_format is set in
RequestCreateSurfaces only, and the probe there only tries
V4L2_BUF_TYPE_VIDEO_CAPTURE (single-plane). On hantro the single-plane
ENUM_FMT returns nothing, video_format stays NULL, and every subsequent
operation hits the `if (video_format == NULL) return OPERATION_FAILED`
guard at the top of context.c / buffer.c / image.c. That's exactly what
Brave's vaCreateContext failure was — not a downstream multiplanar fault,
just the format-detection short-circuit firing.
Three small changes:
- src/video.c: add an NV12 multi-plane entry next to the existing
single-plane NV12 / Sunxi entries. Same pixelformat fourcc (S264 vs NV12
has nothing to do with mplane), distinguished by the v4l2_mplane bit.
- src/video.h + src/video.c: video_format_find() takes a `bool mplane`
parameter and matches both fields. Without this the single-plane and
multi-plane NV12 entries collide on pixelformat.
- src/surface.c: the probe block now tries V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
as a fallback after the single-plane probes return nothing. On a
single-plane decoder the mplane probe is a no-op; on hantro it picks
the new mplane NV12 entry, video_format gets set, and the rest of the
library — already mplane-aware — does the right thing for OUTPUT
S_FMT, REQBUFS, EXPBUF, QBUF, DQBUF.
Also: src/context.c: the H264 case still referenced V4L2_PIX_FMT_H264_SLICE_RAW
that we renamed in commit c1f5108. Caught now.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bootlin's original probe assumed single-plane decoders (the sunxi-cedrus
target the library was originally written for). Rockchip's hantro VPU
on RK3566/RK3588 reports V4L2_CAP_VIDEO_M2M_MPLANE only — the single-
plane VIDIOC_ENUM_FMT path returns nothing, so vainfo prints an empty
"Supported profile and entrypoints" list and downstream apps fall back
to software.
Add an OUTPUT_MPLANE fallback to all three format probes (MPEG-2, H.264,
HEVC). On a single-plane decoder the second probe is a no-op; on a
multi-plane decoder it's what makes the profile list non-empty.
This is the *probe* fix only — it gets vainfo to enumerate profiles and
gets Brave's GPU process to attempt vaCreateContext. The rest of the
multiplanar port (S_FMT / REQBUFS / EXPBUF / QBUF in context.c, picture.c,
v4l2.c) is the next phase; vaCreateContext currently fails because
those paths are still single-plane only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three changes that together make the build compile cleanly against a
current linux-api-headers (>= 5.x post-HEVC-UAPI-rename):
- src/meson.build: comment h265.c + h265.h out of sources/headers.
- include/hevc-ctrls.h: replace bundled HEVC structs with a single
#include <linux/v4l2-controls.h>. The bundled definitions were
identical to what later landed in mainline as V4L2_CID_STATELESS_HEVC_*
(renamed) and v4l2_ctrl_hevc_* (kept the field names but moved into
the kernel public header). Keeping a duplicate copy now triggers
redefinition errors. The header is kept as a passthrough rather than
deleted so any downstream patch that says #include <hevc-ctrls.h>
still compiles.
- src/picture.c: drop the four HEVC case blocks. Three of them were in
switches that already had `default: break`, so removing them is
functionally a no-op. The fourth was the only external reference to
h265_set_controls — removing it lets the library link cleanly with
h265.c excluded.
Why this is OK rather than the more ambitious "fix HEVC properly":
RK3566 has no HW HEVC at all (the only decoder block is the Hantro G1
which speaks H.264 / MPEG-2 / VP8). HEVC can come back as a separate
effort once we're on RK3588 silicon AND the library is updated to the
renamed kernel CIDs. For Fourier's first port milestone (H.264 multi-
plane on RK3566 hantro) HEVC is dead weight.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GCC's -Wimplicit-function-declaration is fatal in current toolchains
(GCC 14+) but was a warning when this code was written. h264.c uses
request_log() in two places without including utils.h; the build was
quietly relying on an implicit declaration that recent compilers reject.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Kernel mainline renamed V4L2_PIX_FMT_H264_SLICE_RAW → V4L2_PIX_FMT_H264_SLICE
some time after this library went dormant (the 'S264' fourcc value is
unchanged; only the C identifier moved). The two definitions have the same
value so this is purely cosmetic at runtime, but keeping the name aligned
with linux/videodev2.h matches downstream patches (e.g. bootlin PR #38)
and avoids confusion when reading kernel + library side-by-side.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Distritubions may install libraries under architecture-specific
sub-directories, to support multiple architectures on the same
system. In addition, the user may not wish to install the library
with the default prefix.
Use the libdir variable when setting the install path. This
allows both specifying different sub-directories, and a different
prefix.
The system normally has kernel headers shipped with the distribution.
These typically lag behind actual kernel releases. Thus they would not
have the latest API additions, such as the V4L2 request API this driver
uses.
However, it is also bad practice to just install new kernel headers into
the system wide default location, as there may be some differences
between it and what the C library was built against.
Add an option to specify a path to a set of up-to-date kernel headers.
This would allow the user to build this project in a safe but working
environment.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
We where first copying the image structure and then setting the pitches
and offets, so this information was lost. This fixes vaDerivedImage and
vaGetImage implementation.
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
This enables raw playback within GStreamer. This is useful for testing
even if slower then DMABuf. This is a partial implementation since we
don't implement partial copy of the surface.
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
The vaCreateSurface2 may be called multiple times, setting the format
again would lead to EBUSY being returned as you cannot change the
format if you have buffers allocated.
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Reference frames are now identified using their timestamp:
set the timestamp when queuing the output buffer and use it to identify
the frame later on.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Drop the per-codec options while at it, since we'll soon include a copy
of the associated headers.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Commit 7ff2543e64 ("Add support for the single-planar V4L2 API")
missed the VIDIOC_QBUF bytesused parameter. The kernel will
warn loudly if bytesused is not properly defined for an OUTPUT buffer.
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
Apparently, pixelformats are expected to be settable although
the reason is not exactly clear to me.
However, intel vaapi driver sets all its pixelformats as
settable, and gstreamer-vaapi expects that as well.
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
H.264 and H.265 support is still not supported upstream,
so it makes sense to autodetect each codec and only
enable those that are supported.
Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
Since our use of the v4l2 API has some assumptions on the available
userspace APIs, check the capabilities reported by the driver to make
sure they are supported.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
This adds a helper function to query v4l2 capabilities, returning
either the device caps when available or the general device caps
otherwise.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
This adds support for MPEG2 quantization matrices, which are optional
given that fallback default matrices are used (on the kernel side) when
no such matrix is provided.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Because there might be more than a single call to CreateSurfaces,
we cannot assume that the index relative to the number of surfaces
requested in a single call matches the v4l2 index.
Grab the base index (as returned by the kernel) when allocating
buffers and use it for memory mapping and addressing them in v4l2.
This avoids memory-mapping the first (index 0) buffer multiple times
in that scenario instead of the n-th allocated buffer (in the n-th
call in the sequence).
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
The V4L2 API does not currently provide a way to liberate allocated
buffers one by one (which would fit well with DestroySurfaces in
VAAPI). Moreover, streaming needs to be off before liberating
buffers is allowed.
As a result, output an capture buffers can only be liberated when
destroying the decoding context, all at once, such as implemented
in this patch.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Although this is not needed when using the combination of CREATE_BUFS and
QUERYBUF V4L2 ioctls (as currently done) to allocate and prepare buffers,
the REQBUF ioctl is useful to liberate the buffers after use.
This introduces a helper for this purpose.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Since the V4L2 ioctl is called QUERYBUF, it makes more sense to
call the associated function with the same name.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
This is the latest version of dma-buf export, that does support
specifying DRM modifiers.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
This is the first version of dma-buf export, that does not support
specifying a DRM modifier.
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
The IMAGE macro takes an implicit driver_data argument. In order to make
it obvious that we need it, let's put it as an explicit parameter.
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>