@@ -72,6 +72,15 @@ static bool rkvdec_is_valid_fmt(struct rkvdec_ctx *ctx, u32 fourcc,
return false;
}
+static bool rkvdec_fmt_changed(struct rkvdec_ctx *ctx,
+ enum rkvdec_image_fmt image_fmt)
+{
+ if (image_fmt == RKVDEC_IMG_FMT_ANY)
+ return false;
+
+ return ctx->image_fmt != image_fmt;
+}
+
static void rkvdec_fill_decoded_pixfmt(struct rkvdec_ctx *ctx,
struct v4l2_pix_format_mplane *pix_mp)
{
@@ -111,15 +120,46 @@ static int rkvdec_try_ctrl(struct v4l2_ctrl *ctrl)
{
struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
const struct rkvdec_coded_fmt_desc *desc = ctx->coded_fmt_desc;
+ int ret;
+
+ if (desc->ops->try_ctrl) {
+ ret = desc->ops->try_ctrl(ctx, ctrl);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rkvdec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct rkvdec_ctx *ctx = container_of(ctrl->handler, struct rkvdec_ctx, ctrl_hdl);
+ const struct rkvdec_coded_fmt_desc *desc = ctx->coded_fmt_desc;
+ enum rkvdec_image_fmt image_fmt;
+ struct vb2_queue *vq;
- if (desc->ops->try_ctrl)
- return desc->ops->try_ctrl(ctx, ctrl);
+ /* Check if this change requires a capture format reset */
+ if (!desc->ops->get_image_fmt)
+ return 0;
+
+ image_fmt = desc->ops->get_image_fmt(ctx, ctrl);
+ if (rkvdec_fmt_changed(ctx, image_fmt)) {
+ /* Format changes are not allowed when capture queue is busy */
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (vb2_is_busy(vq))
+ return -EINVAL;
+
+ ctx->image_fmt = image_fmt;
+ rkvdec_reset_decoded_fmt(ctx);
+ }
return 0;
}
static const struct v4l2_ctrl_ops rkvdec_ctrl_ops = {
.try_ctrl = rkvdec_try_ctrl,
+ .s_ctrl = rkvdec_s_ctrl,
};
static const struct rkvdec_ctrl_desc rkvdec_h264_ctrl_descs[] = {
@@ -73,6 +73,8 @@ struct rkvdec_coded_fmt_ops {
struct vb2_v4l2_buffer *dst_buf,
enum vb2_buffer_state result);
int (*try_ctrl)(struct rkvdec_ctx *ctx, struct v4l2_ctrl *ctrl);
+ enum rkvdec_image_fmt (*get_image_fmt)(struct rkvdec_ctx *ctx,
+ struct v4l2_ctrl *ctrl);
};
enum rkvdec_image_fmt {