Skip to content

Commit 77e74be

Browse files
Kwiboomchehab
authored andcommitted
media: rkvdec: h264: Validate and use pic width and height in mbs
The width and height in macroblocks is currently configured based on OUTPUT buffer resolution, this works for frame pictures but can cause issues for field pictures. When frame_mbs_only_flag is 0 the height in mbs should be height of the field instead of height of frame. Validate pic_width_in_mbs_minus1 and pic_height_in_map_units_minus1 against OUTPUT buffer resolution and use these values to configure HW. The validation is happening in both try_ctrt() and start() since it is otherwise possible to trick the driver during initialization by changing the OUTPUT format after having set a valid control. [hverkuil: when -> When (first word in a comment block)] Signed-off-by: Jonas Karlman <[email protected]> Signed-off-by: Nicolas Dufresne <[email protected]> Reviewed-by: Ezequiel Garcia <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent cf76bb4 commit 77e74be

File tree

1 file changed

+62
-19
lines changed

1 file changed

+62
-19
lines changed

drivers/staging/media/rkvdec/rkvdec-h264.c

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -672,8 +672,17 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx,
672672
LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4);
673673
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO),
674674
DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG);
675-
WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.width, 16), PIC_WIDTH_IN_MBS);
676-
WRITE_PPS(DIV_ROUND_UP(ctx->coded_fmt.fmt.pix_mp.height, 16), PIC_HEIGHT_IN_MBS);
675+
676+
/*
677+
* Use the SPS values since they are already in macroblocks
678+
* dimensions, height can be field height (halved) if
679+
* V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY is not set and also it allows
680+
* decoding smaller images into larger allocation which can be used
681+
* to implementing SVC spatial layer support.
682+
*/
683+
WRITE_PPS(sps->pic_width_in_mbs_minus1 + 1, PIC_WIDTH_IN_MBS);
684+
WRITE_PPS(sps->pic_height_in_map_units_minus1 + 1, PIC_HEIGHT_IN_MBS);
685+
677686
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY),
678687
FRAME_MBS_ONLY_FLAG);
679688
WRITE_PPS(!!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD),
@@ -1035,13 +1044,61 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx,
10351044
return 0;
10361045
}
10371046

1047+
static int rkvdec_h264_validate_sps(struct rkvdec_ctx *ctx,
1048+
const struct v4l2_ctrl_h264_sps *sps)
1049+
{
1050+
unsigned int width, height;
1051+
1052+
/*
1053+
* TODO: The hardware supports 10-bit and 4:2:2 profiles,
1054+
* but it's currently broken in the driver.
1055+
* Reject them for now, until it's fixed.
1056+
*/
1057+
if (sps->chroma_format_idc > 1)
1058+
/* Only 4:0:0 and 4:2:0 are supported */
1059+
return -EINVAL;
1060+
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
1061+
/* Luma and chroma bit depth mismatch */
1062+
return -EINVAL;
1063+
if (sps->bit_depth_luma_minus8 != 0)
1064+
/* Only 8-bit is supported */
1065+
return -EINVAL;
1066+
1067+
width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
1068+
height = (sps->pic_height_in_map_units_minus1 + 1) * 16;
1069+
1070+
/*
1071+
* When frame_mbs_only_flag is not set, this is field height,
1072+
* which is half the final height (see (7-18) in the
1073+
* specification)
1074+
*/
1075+
if (!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY))
1076+
height *= 2;
1077+
1078+
if (width > ctx->coded_fmt.fmt.pix_mp.width ||
1079+
height > ctx->coded_fmt.fmt.pix_mp.height)
1080+
return -EINVAL;
1081+
1082+
return 0;
1083+
}
1084+
10381085
static int rkvdec_h264_start(struct rkvdec_ctx *ctx)
10391086
{
10401087
struct rkvdec_dev *rkvdec = ctx->dev;
10411088
struct rkvdec_h264_priv_tbl *priv_tbl;
10421089
struct rkvdec_h264_ctx *h264_ctx;
1090+
struct v4l2_ctrl *ctrl;
10431091
int ret;
10441092

1093+
ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl,
1094+
V4L2_CID_STATELESS_H264_SPS);
1095+
if (!ctrl)
1096+
return -EINVAL;
1097+
1098+
ret = rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps);
1099+
if (ret)
1100+
return ret;
1101+
10451102
h264_ctx = kzalloc(sizeof(*h264_ctx), GFP_KERNEL);
10461103
if (!h264_ctx)
10471104
return -ENOMEM;
@@ -1139,23 +1196,9 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
11391196

11401197
static int rkvdec_h264_try_ctrl(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl)
11411198
{
1142-
if (ctrl->id == V4L2_CID_STATELESS_H264_SPS) {
1143-
const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
1144-
/*
1145-
* TODO: The hardware supports 10-bit and 4:2:2 profiles,
1146-
* but it's currently broken in the driver.
1147-
* Reject them for now, until it's fixed.
1148-
*/
1149-
if (sps->chroma_format_idc > 1)
1150-
/* Only 4:0:0 and 4:2:0 are supported */
1151-
return -EINVAL;
1152-
if (sps->bit_depth_luma_minus8 != sps->bit_depth_chroma_minus8)
1153-
/* Luma and chroma bit depth mismatch */
1154-
return -EINVAL;
1155-
if (sps->bit_depth_luma_minus8 != 0)
1156-
/* Only 8-bit is supported */
1157-
return -EINVAL;
1158-
}
1199+
if (ctrl->id == V4L2_CID_STATELESS_H264_SPS)
1200+
return rkvdec_h264_validate_sps(ctx, ctrl->p_new.p_h264_sps);
1201+
11591202
return 0;
11601203
}
11611204

0 commit comments

Comments
 (0)