Le dimanche 05 novembre 2023 à 16:55 +0000, Jonas Karlman a écrit : > 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: > > - Hi422FR13_SONY_A > - Hi422FR14_SONY_A > - Hi422FR15_SONY_A > - Hi422FR6_SONY_A > - Hi422FR7_SONY_A > - Hi422FR8_SONY_A > - Hi422FR9_SONY_A > - Hi422FREXT18_SONY_A > > The get_image_fmt() ops is implemented to select an image format > required for the provided SPS control. > > Signed-off-by: Jonas Karlman <jonas@xxxxxxxxx> > --- > v4: > - Change to use get_image_fmt() ops > > v3: > - Add get_fmt_opaque ops, the expected pixelformat is used as opaque > - Add new valid_fmt ops that validate pixelformat matches opaque > - Update H264_PROFILE control max value > > drivers/staging/media/rkvdec/rkvdec-h264.c | 37 ++++++++++++++++------ > drivers/staging/media/rkvdec/rkvdec.c | 33 +++++++++++++++---- > drivers/staging/media/rkvdec/rkvdec.h | 3 ++ > 3 files changed, 57 insertions(+), 16 deletions(-) > > diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c > index 815d5359ddd5..baac6d012ddd 100644 > --- a/drivers/staging/media/rkvdec/rkvdec-h264.c > +++ b/drivers/staging/media/rkvdec/rkvdec-h264.c > @@ -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; > @@ -1175,4 +1193,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, > }; > diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c > index 225aa1f0ac48..eb59605ccf28 100644 > --- a/drivers/staging/media/rkvdec/rkvdec.c > +++ b/drivers/staging/media/rkvdec/rkvdec.c > @@ -73,7 +73,7 @@ static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx, > struct v4l2_pix_format_mplane *pix_mp) > { > v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat, > - pix_mp->width, pix_mp->height); > + ALIGN(pix_mp->width, 64), pix_mp->height); If you align regardless if its 8/10bit (which I don't really mind, it does not cost much and helps if you have a Mali GPU), please do in rkvdec_coded_fmts[].frmsize.step_width. Otherwise you'll endup creating a config per bit depth, and probably won't need any of the rk format stuff, since you could just update the config, and enumerate from there. I don't mind your method though, but lets not hardcode alignment where it shouldn't be. > pix_mp->plane_fmt[0].sizeimage += 128 * > DIV_ROUND_UP(pix_mp->width, 16) * > DIV_ROUND_UP(pix_mp->height, 16); > @@ -193,7 +193,7 @@ 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_BASELINE, Do we want to keep this small lie ? Baseline is not supported as we don't support FMO and ASO. That being said, in framework like GStreamer, we try to decode anyway, cause we know we don't have a software fallback anyway. > - .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, > + .cfg.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422, Should include V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA and V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA too .... > .cfg.menu_skip_mask = > BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), Which requires substracting V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE too. > .cfg.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN, > @@ -210,11 +210,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[] = { > @@ -237,6 +249,13 @@ 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, > @@ -250,8 +269,8 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { > }, > .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, > }, > { > @@ -266,8 +285,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, > } > }; > > diff --git a/drivers/staging/media/rkvdec/rkvdec.h b/drivers/staging/media/rkvdec/rkvdec.h > index e466a2753ccf..9a9f4fced7a1 100644 > --- a/drivers/staging/media/rkvdec/rkvdec.h > +++ b/drivers/staging/media/rkvdec/rkvdec.h > @@ -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 {