media: rkvdec: h264: Support High 10 and 4:2:2 profiles

Add support and enable decoding of H264 High 10 and 4:2:2 profiles.

Decoded CAPTURE buffer width is aligned to 64 pixels to accommodate HW
requirement of 10-bit format buffers, fixes decoding of all the 4:2:2
and 10bit 4:2:2 flusters tests except two stream that present some
visual artifacts.

- Hi422FREXT17_SONY_A
- Hi422FREXT19_SONY_A

The get_image_fmt() ops is implemented to select an image format
required for the provided SPS control, and returns RKVDEC_IMG_FMT_ANY
for other controls.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Tested-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Tested-by: Christopher Obbard <chris.obbard@collabora.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
This commit is contained in:
Jonas Karlman 2025-05-01 15:55:50 -04:00 committed by Hans Verkuil
parent d35c64eccf
commit 5e1ff23147
3 changed files with 60 additions and 18 deletions

View File

@ -1027,24 +1027,42 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
return 0;
}
static enum rkvdec_image_fmt rkvdec_h264_get_image_fmt(struct rkvdec_ctx *ctx,
struct v4l2_ctrl *ctrl)
{
const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
if (ctrl->id != V4L2_CID_STATELESS_H264_SPS)
return RKVDEC_IMG_FMT_ANY;
if (sps->bit_depth_luma_minus8 == 0) {
if (sps->chroma_format_idc == 2)
return RKVDEC_IMG_FMT_422_8BIT;
else
return RKVDEC_IMG_FMT_420_8BIT;
} else if (sps->bit_depth_luma_minus8 == 2) {
if (sps->chroma_format_idc == 2)
return RKVDEC_IMG_FMT_422_10BIT;
else
return RKVDEC_IMG_FMT_420_10BIT;
}
return RKVDEC_IMG_FMT_ANY;
}
static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
const struct v4l2_ctrl_h264_sps *sps)
{
unsigned int width, height;
/*
* TODO: The hardware supports 10-bit and 4:2:2 profiles,
* but it's currently broken in the driver.
* Reject them for now, until it's fixed.
*/
if (sps->chroma_format_idc > 1)
/* Only 4:0:0 and 4:2:0 are supported */
if (sps->chroma_format_idc > 2)
/* Only 4:0:0, 4:2:0 and 4:2:2 are supported */
return -EINVAL;
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
/* Luma and chroma bit depth mismatch */
return -EINVAL;
if (sps->bit_depth_luma_minus8 != 0)
/* Only 8-bit is supported */
if (sps->bit_depth_luma_minus8 != 0 && sps->bit_depth_luma_minus8 != 2)
/* Only 8-bit and 10-bit is supported */
return -EINVAL;
width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
@ -1190,4 +1208,5 @@ const struct rkvdec_coded_fmt_ops rkvdec_h264_fmt_ops = {
.stop = rkvdec_h264_stop,
.run = rkvdec_h264_run,
.try_ctrl = rkvdec_h264_try_ctrl,
.get_image_fmt = rkvdec_h264_get_image_fmt,
};

View File

@ -186,9 +186,10 @@ static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
{
.cfg.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
.cfg.min = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE,
.cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
.cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA,
.cfg.menu_skip_mask =
BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED),
BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED) |
BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE),
.cfg.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN,
},
{
@ -203,11 +204,23 @@ static const struct rkvdec_ctrls rkvdec_h264_ctrls = {
.num_ctrls = ARRAY_SIZE(rkvdec_h264_ctrl_descs),
};
static const struct rkvdec_decoded_fmt_desc rkvdec_h264_vp9_decoded_fmts[] = {
static const struct rkvdec_decoded_fmt_desc rkvdec_h264_decoded_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.image_fmt = RKVDEC_IMG_FMT_420_8BIT,
},
{
.fourcc = V4L2_PIX_FMT_NV15,
.image_fmt = RKVDEC_IMG_FMT_420_10BIT,
},
{
.fourcc = V4L2_PIX_FMT_NV16,
.image_fmt = RKVDEC_IMG_FMT_422_8BIT,
},
{
.fourcc = V4L2_PIX_FMT_NV20,
.image_fmt = RKVDEC_IMG_FMT_422_10BIT,
},
};
static const struct rkvdec_ctrl_desc rkvdec_vp9_ctrl_descs[] = {
@ -230,21 +243,28 @@ static const struct rkvdec_ctrls rkvdec_vp9_ctrls = {
.num_ctrls = ARRAY_SIZE(rkvdec_vp9_ctrl_descs),
};
static const struct rkvdec_decoded_fmt_desc rkvdec_vp9_decoded_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.image_fmt = RKVDEC_IMG_FMT_420_8BIT,
},
};
static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_H264_SLICE,
.frmsize = {
.min_width = 48,
.min_width = 64,
.max_width = 4096,
.step_width = 16,
.step_width = 64,
.min_height = 48,
.max_height = 2560,
.step_height = 16,
},
.ctrls = &rkvdec_h264_ctrls,
.ops = &rkvdec_h264_fmt_ops,
.num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_vp9_decoded_fmts),
.decoded_fmts = rkvdec_h264_vp9_decoded_fmts,
.num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_decoded_fmts),
.decoded_fmts = rkvdec_h264_decoded_fmts,
.subsystem_flags = VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF,
},
{
@ -259,8 +279,8 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = {
},
.ctrls = &rkvdec_vp9_ctrls,
.ops = &rkvdec_vp9_fmt_ops,
.num_decoded_fmts = ARRAY_SIZE(rkvdec_h264_vp9_decoded_fmts),
.decoded_fmts = rkvdec_h264_vp9_decoded_fmts,
.num_decoded_fmts = ARRAY_SIZE(rkvdec_vp9_decoded_fmts),
.decoded_fmts = rkvdec_vp9_decoded_fmts,
}
};

View File

@ -80,6 +80,9 @@ struct rkvdec_coded_fmt_ops {
enum rkvdec_image_fmt {
RKVDEC_IMG_FMT_ANY = 0,
RKVDEC_IMG_FMT_420_8BIT,
RKVDEC_IMG_FMT_420_10BIT,
RKVDEC_IMG_FMT_422_8BIT,
RKVDEC_IMG_FMT_422_10BIT,
};
struct rkvdec_decoded_fmt_desc {