Re: [PATCH RFC 0/7] media: qcom: iris: add support for decoding 10bit formats
From: Neil Armstrong
Date: Tue Apr 14 2026 - 11:38:30 EST
On 4/10/26 18:25, Neil Armstrong wrote:
On 4/10/26 14:00, Neil Armstrong wrote:
On 4/9/26 15:19, Nicolas Dufresne wrote:
Le jeudi 09 avril 2026 à 09:36 +0200, Neil Armstrong a écrit :
<snip>
Gst:
$ gst-launch-1.0 -v -m filesrc location=Big_Buck_Bunny_1080_10s_30MB_main10.h265 ! h265parse ! v4l2h265dec ! tee ! fakevideosink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
...
Got message #37 from element "h265parse0" (latency): no message details
ERROR: from element /GstPipeline:pipeline0/GstH265Parse:h265parse0: Internal data stream error.
Redistribute latency...
Additional debug info:
../gstreamer/subprojects/gstreamer/libs/gst/base/gstbaseparse.c(3702): gst_base_parse_loop (): /GstPipeline:pipeline0/GstH265Parse:h265parse0:
streaming stopped, reason not-negotiated (-4)
Got message #39 from pad "h265parse0:src" (property-notify): ERROR: pipeline doesn't want to preroll.
GstMessagePropertyNotify, property-name=(string)caps, property-value=(GstCaps)"video/x-h265\,\ width\=\(int\)1920\,\ height\=\(int\)1080\,\ framerate\=\(fraction\)30/1\,\ chroma-format\=\(string\)4:2:0\,\ bit-depth-luma\=\(uint\)10\,\ bit-depth-chroma\=\(uint\)10\,\ parsed\=\(boolean\)true\,\ stream-format\=\(string\)byte-stream\,\ alignment\=\(string\)au\,\ pixel-aspect-ratio\=\(fraction\)1/1\,\ profile\=\(string\)main-10\,\ tier\=\(string\)main\,\ level\=\(string\)4";
/GstPipeline:pipeline0/GstH265Parse:h265parse0.GstPad:src: caps = video/x-h265, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)10, bit-depth-chroma=(uint)10, parsed=(boolean)true, stream-format=(string)byte-stream, alignment=(string)au, pixel-aspect-ratio=(fraction)1/1, profile=(string)main-10, tier=(string)main, level=(string)4
...
There is not a lot of details here, but I would start looking into
V4L2_CID_MPEG_VIDEO_HEVC_PROFILE and V4L2_CID_MPEG_VIDEO_HEVC_LEVEL
implementation. GStreamer (and Chromium too) will refuse to use a decoder that
does not advertise the supported profile (though I see there is code for that,
maybe its just some bug).
You may get a different hint with more traces, just enabling general warnings:
In this case OUTPUT is not STREAMON and no OUTPUT buffers are queued, so I wonder why this one fails....
My gstreamer and ffmpeg foo is bad and I probably missed something obvious...
export GST_DEBUG=2
Or the full V4L2 traces too:
export GST_DEBUG="v4l2*:7,2"
I'm sure its just a bug (or two). Happy to help to find it.
You were right, this did the trick:
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index a9cdd93e77fd..debdd30a751e 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -56,9 +56,10 @@ static const struct platform_inst_fw_cap inst_fw_cap_sm8550_dec[] = {
{
.cap_id = PROFILE_HEVC,
.min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
- .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
.step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
- BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE),
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10),
.value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
.hfi_id = HFI_PROP_PROFILE,
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
But the gstreamer I'm using is too old and doesn't support P010... updating but it should work now,
and I'll test the QC10 in the same time.
Tested with gstreamer git, it works fine now with P010.
But I applied the QC10 change, but how am I supposed to test it ?
The QC formats seems to be detected and the right modifier is used:
0:00:07.231474967 296677 296852 INFO v4l2 gstv4l2object.c:5544:gst_v4l2_object_probe_caps:<v4l2h265dec0:src> probed caps: video/x-raw(memory:DMABuf), format=(string)DMA_DRM, drm-format=(string){ NV12:0x0500000000000001, NV12 }, width=(int)[ 96, 8192 ], height=(int)[ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1, colorimetry=(string){ bt601, 1:4:16:3, smpte240m, bt709, 1:3:5:1, 2:4:5:2, 2:4:5:3, 1:4:5:3, 1:4:7:1, 2:4:7:1, 2:4:12:8, bt2020, bt2100-pq, 2:0:0:0 }; video/x-raw, format=(string)NV12, width=(int)[ 96, 8192 ], height=(int)[ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1, colorimetry=(string){ bt601, 1:4:16:3, smpte240m, bt709, 1:3:5:1, 2:4:5:2, 2:4:5:3, 1:4:5:3, 1:4:7:1, 2:4:7:1, 2:4:12:8, bt2020, bt2100-pq, 2:0:0:0 }; video/x-raw(memory:DMABuf), format=(string)DMA_DRM, drm-format=(string){ NV12:0x0500000000000001, NV12 }, width=(int)[ 96, 8192 ], height=(int) [ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1; video/x-raw, format=(string)NV12, width=(int)[ 96, 8192 ], height=(int)[ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1
0:00:07.224200523 304189 304365 INFO v4l2 gstv4l2object.c:5544:gst_v4l2_object_probe_caps:<v4l2h265dec0:src> probed caps: video/x-raw(memory:DMABuf), format=(string)DMA_DRM, drm-format=(string){ P010, P010:0x0500000000000001 }, width=(int)[ 96, 8192 ], height=(int)[ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1, colorimetry=(string){ bt601, 1:4:16:3, smpte240m, bt709, 1:3:5:1, 2:4:5:2, 2:4:5:3, 1:4:5:3, 1:4:7:1, 2:4:7:1, 2:4:12:8, bt2020, bt2100-pq, 2:0:0:0 }; video/x-raw, format=(string)P010_10LE, width=(int)[ 96, 8192 ], height=(int)[ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1, colorimetry=(string){ bt601, 1:4:16:3, smpte240m, bt709, 1:3:5:1, 2:4:5:2, 2:4:5:3, 1:4:5:3, 1:4:7:1, 2:4:7:1, 2:4:12:8, bt2020, bt2100-pq, 2:0:0:0 }; video/x-raw(memory:DMABuf), format=(string)DMA_DRM, drm-format=(string){ P010, P010:0x0500000000000001 }, width=(int)[ 96, 8192 ], height=(int)[ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1; video/x-raw, format=(string)P010_10LE, width=(int)[ 96, 8192 ], height=(int)[ 96, 8192 ], framerate=(fraction)[ 0/1, 2147483647/1 ], pixel-aspect-ratio=(fraction)1/1
But what's the proper way to validate ? I've been unable to run kmssink so far.
Ok all works with kmssink, I was trying with a bad kernel config with the screen not modeset...
Anyway, I managed to get all those working:
gst-launch-1.0 -v -m filesrc location=Big_Buck_Bunny_1080_10s_30MB.h265 ! h265parse ! v4l2h265dec ! kmssink
gst-launch-1.0 -v -m filesrc location=Big_Buck_Bunny_1080_10s_30MB_main10.h265 ! h265parse ! v4l2h265dec ! kmssink
gst-launch-1.0 -v -m filesrc location=Big_Buck_Bunny_1080_10s_30MB.h265 ! h265parse ! v4l2h265dec ! "video/x-raw(memory:DMABuf), format=DMA_DRM, drm-format=NV12" ! kmssink
gst-launch-1.0 -v -m filesrc location=Big_Buck_Bunny_1080_10s_30MB.h265 ! h265parse ! v4l2h265dec ! "video/x-raw(memory:DMABuf), format=DMA_DRM, drm-format=NV12:0x0500000000000001" ! kmssink
gst-launch-1.0 -v -m filesrc location=Big_Buck_Bunny_1080_10s_30MB_main10.h265 ! h265parse ! v4l2h265dec ! "video/x-raw(memory:DMABuf), format=DMA_DRM, drm-format=P010" ! kmssink
gst-launch-1.0 -v -m filesrc location=Big_Buck_Bunny_1080_10s_30MB_main10.h265 ! h265parse ! v4l2h265dec ! "video/x-raw(memory:DMABuf), format=DMA_DRM, drm-format=P010:0x0500000000000001" ! kmssink
with those 2 merge requests :
- https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8195
- https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11222
and:
===============================================================================
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index df16adc..f7fbb29 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -4377,6 +4377,9 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
align.padding_right = format.fmt.pix.width - width;
}
+ if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_DMA_DRM)
+ n_v4l_planes = format.fmt.pix_mp.num_planes;
+
if (is_mplane && format.fmt.pix_mp.num_planes != n_v4l_planes)
goto invalid_planes;
===============================================================================
But this causes an error with QC10C:
"plane 1 too small" in msm_framebuffer_init() probably because the plane 1 values are off because of the hack.
Since the NV12 and QC08 buffer size is close it works unlike QC10C where the buffer size is way lower than P010 (4210688 vs 6266880).
With this is works just fine, but it's a hack:
===============================================================================
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 9b681e144c07..4928e2d191dc 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -218,7 +218,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
+ width * info->cpp[i]
+ mode_cmd->offsets[i];
- if (bos[i]->size < min_size) {
+ if (bos[i]->size < min_size && !MSM_FORMAT_IS_UBWC(format)) {
ret = UERR(EINVAL, dev, "plane %d too small", i);
goto fail;
}
===============================================================================
I can get NV12, QC08C, P010 and QC10C all decoding and displaying.
I had to fix some alignement code in iris + remove format filtering on find_format_by_index,
sending a v2 soon with the fixes + fluster reports.
Neil
Neil
Neil
For Q10C on GStreamer, it needs mapping [0] and you need some bugfix [1] and
another that I will be sending tomorrow. We had never tested video compression
with this module before.
[0] https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8195
[1] https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11222
The last issue has to do with:
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/38965e2d9c1119674a65dc437ee7e8ec95339f31/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c#L4378
V4L2 format gives us the number of allocation, but not really the number of
planes, and we forgot to initialize that number for the "opaque" format case. A
tempory fix might be to add this after S_FMT:
if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_DMA_DRM)
n_v4l_planes = format.fmt.pix_mp.num_planes;
Works for AFBC and QC at leat, since both are unambiguously single plane, and so
cannot have mplane variants.
I'll definitely try that ! thanks for the pointers !
Let me know how far you get! Please be aware that Robert and I are making these
patches based on feedback, we don't have access to any boards capable of
decoding to QC compressed formats.
v4l2-ctl --verbose --set-fmt-video-out=pixelformat=HEVC --set-fmt-video=pixelformat=P010 --stream-mmap --stream-out-mmap --stream-from-hdr Big_Buck_Bunny_1080_10s_30MB_main10.h265.hdr --stream-to out.P010
v4l2-ctl --verbose --set-fmt-video-out=pixelformat=HEVC --set-fmt-video=pixelformat=Q10C --stream-mmap --stream-out-mmap --stream-from-hdr Big_Buck_Bunny_1080_10s_30MB_main10.h265.hdr --stream-to out.QC10
The non-10bit decoding still works as before.
With Big_Buck_Bunny_1080_10s_30MB reencoded in 10-bit profile
and tranformed in v4l2 header format with [1]:
ffmpeg -i Big_Buck_Bunny_1080_10s_30MB.h264 -pix_fmt yuv420p10le -c:v libx265 -crf 28 -x265-params profile=main10 Big_Buck_Bunny_1080_10s_30MB_main10.h265
/path/to/mkhdr.sh Big_Buck_Bunny_1080_10s_30MB_main10.h265 raw Big_Buck_Bunny_1080_10s_30MB_main10.h265.hdr
The frames correctness has been verified buy displaying them
via Vulkan DMA_BUF import, including QC10C and QC08C.
In GStreamer, once the video4linux plugin issues are fixed, you should be able
to display the frames using glimagesink. GL only allow for RGB render, which
damages the data, so its not good enough for conformance testing with
compression enabled, but usually just doing visual inspection is acceptable.
The support is probably incomplete for other platforms and
I'm unsure what's required to conform to the V4L2 M2M stateless
stateful
spec, especially since AFAIK the decoder doesn't support
decoding 10bit streams in 8bit pixel format, thus the RFC state.
Review is welcome !
Why would your decoder need to support decoding 10bit into 8bit ? This is quite
rare and its only possible with post-processed capture buffer.
Yeah it's just a note, the Amlogic one supported outputing main10 in NV12 but
only supported 10bit in their compressed format.
Ack. There is a lot of variation with various hardware for sure. The Allwinner
stateless one swallow the extra 2bit plane (since they do some funky NV12 + two
more planes for the missing 2bits, and that's complicate as a format hehe).
cheers,
Nicolas
[1] https://github.com/superna9999/pyv4l2compliance
Signed-off-by: Neil Armstrong <neil.armstrong@xxxxxxxxxx>
---
Neil Armstrong (7):
media: qcom: iris: add QC10C & P010 buffer size calculations
media: qcom: iris: gen2: add support for 10bit decoding
media: qcom: iris: add helpers for 8bit and 10bit formats
media: qcom: iris: vdec: update size and stride calculations for 10bit formats
media: qcom: iris: vdec: forbid g_fmt while waiting for first source change
The is suspicious, it should just send the previous state until you get the
event. Typical use case is for application to set a format based on bitstream
parsing, and use that as a guess to try and pre-allocate the buffers. I don't
usually review iris code, but I'll give that series some more eyes in the coming
days.
Yeah I wasn't sure, venus does that, same as the vendor driver so I thought it would
be good but I'm probably mistaken.
cheers,
Nicolas
Thanks!
Neil
media: qcom: iris: vdec: update find_format to handle 8bit and 10bit formats
media: qcom: iris: vdec: allow decoding into 10bit format
drivers/media/platform/qcom/iris/iris_buffer.c | 81 +++++++++++++++++++++-
.../platform/qcom/iris/iris_hfi_gen2_command.c | 71 ++++++++++++++++++-
.../platform/qcom/iris/iris_hfi_gen2_defines.h | 1 +
.../platform/qcom/iris/iris_hfi_gen2_response.c | 35 ++++++++--
drivers/media/platform/qcom/iris/iris_instance.h | 2 +
.../platform/qcom/iris/iris_platform_common.h | 1 +
.../media/platform/qcom/iris/iris_platform_gen2.c | 3 +-
drivers/media/platform/qcom/iris/iris_state.c | 6 ++
drivers/media/platform/qcom/iris/iris_state.h | 1 +
drivers/media/platform/qcom/iris/iris_utils.c | 16 ++++-
drivers/media/platform/qcom/iris/iris_utils.h | 2 +
drivers/media/platform/qcom/iris/iris_vdec.c | 70 +++++++++++++++++--
drivers/media/platform/qcom/iris/iris_vidc.c | 14 +++-
13 files changed, 285 insertions(+), 18 deletions(-)
---
base-commit: f3e6330d7fe42b204af05a2dbc68b379e0ad179e
change-id: 20260408-topic-sm8x50-iris-10bit-decoding-074c3ac7975c
Best regards,
--
Neil Armstrong <neil.armstrong@xxxxxxxxxx>