media: cedrus: Add format reset helpers

By re-arranging try format handlers and set out format handler, we can
easily implement reset out/cap format helpers.

There is only one subtle, but important functional change. Capture
pixel format will be reset each time output format is set. This is
actually expected behaviour per stateless decoder API.

Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
This commit is contained in:
Jernej Skrabec 2022-11-02 19:08:01 +01:00 committed by Hans Verkuil
parent d2dd4c6799
commit b13ffeafc3
2 changed files with 66 additions and 36 deletions

View file

@ -241,12 +241,10 @@ static int cedrus_g_fmt_vid_out(struct file *file, void *priv,
return 0;
}
static int cedrus_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
static int cedrus_try_fmt_vid_cap_p(struct cedrus_ctx *ctx,
struct v4l2_pix_format *pix_fmt)
{
struct cedrus_ctx *ctx = cedrus_file2ctx(file);
struct cedrus_dev *dev = ctx->dev;
struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
struct cedrus_format *fmt =
cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST,
dev->capabilities);
@ -262,12 +260,16 @@ static int cedrus_try_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
static int cedrus_try_fmt_vid_out(struct file *file, void *priv,
static int cedrus_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cedrus_ctx *ctx = cedrus_file2ctx(file);
return cedrus_try_fmt_vid_cap_p(cedrus_file2ctx(file), &f->fmt.pix);
}
static int cedrus_try_fmt_vid_out_p(struct cedrus_ctx *ctx,
struct v4l2_pix_format *pix_fmt)
{
struct cedrus_dev *dev = ctx->dev;
struct v4l2_pix_format *pix_fmt = &f->fmt.pix;
struct cedrus_format *fmt =
cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC,
dev->capabilities);
@ -281,6 +283,12 @@ static int cedrus_try_fmt_vid_out(struct file *file, void *priv,
return 0;
}
static int cedrus_try_fmt_vid_out(struct file *file, void *priv,
struct v4l2_format *f)
{
return cedrus_try_fmt_vid_out_p(cedrus_file2ctx(file), &f->fmt.pix);
}
static int cedrus_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
@ -301,13 +309,60 @@ static int cedrus_s_fmt_vid_cap(struct file *file, void *priv,
return 0;
}
void cedrus_reset_cap_format(struct cedrus_ctx *ctx)
{
ctx->dst_fmt.pixelformat = 0;
cedrus_try_fmt_vid_cap_p(ctx, &ctx->dst_fmt);
}
static int cedrus_s_fmt_vid_out_p(struct cedrus_ctx *ctx,
struct v4l2_pix_format *pix_fmt)
{
struct vb2_queue *vq;
int ret;
ret = cedrus_try_fmt_vid_out_p(ctx, pix_fmt);
if (ret)
return ret;
ctx->src_fmt = *pix_fmt;
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
switch (ctx->src_fmt.pixelformat) {
case V4L2_PIX_FMT_H264_SLICE:
case V4L2_PIX_FMT_HEVC_SLICE:
vq->subsystem_flags |=
VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
break;
default:
vq->subsystem_flags &=
~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
break;
}
/* Propagate format information to capture. */
ctx->dst_fmt.colorspace = pix_fmt->colorspace;
ctx->dst_fmt.xfer_func = pix_fmt->xfer_func;
ctx->dst_fmt.ycbcr_enc = pix_fmt->ycbcr_enc;
ctx->dst_fmt.quantization = pix_fmt->quantization;
cedrus_reset_cap_format(ctx);
return 0;
}
void cedrus_reset_out_format(struct cedrus_ctx *ctx)
{
ctx->src_fmt.pixelformat = 0;
cedrus_s_fmt_vid_out_p(ctx, &ctx->src_fmt);
}
static int cedrus_s_fmt_vid_out(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cedrus_ctx *ctx = cedrus_file2ctx(file);
struct vb2_queue *vq;
struct vb2_queue *peer_vq;
int ret;
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
/*
@ -328,34 +383,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv,
if (vb2_is_busy(peer_vq))
return -EBUSY;
ret = cedrus_try_fmt_vid_out(file, priv, f);
if (ret)
return ret;
ctx->src_fmt = f->fmt.pix;
switch (ctx->src_fmt.pixelformat) {
case V4L2_PIX_FMT_H264_SLICE:
case V4L2_PIX_FMT_HEVC_SLICE:
vq->subsystem_flags |=
VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
break;
default:
vq->subsystem_flags &=
~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
break;
}
/* Propagate format information to capture. */
ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
ctx->dst_fmt.quantization = f->fmt.pix.quantization;
ctx->dst_fmt.width = ctx->src_fmt.width;
ctx->dst_fmt.height = ctx->src_fmt.height;
cedrus_prepare_format(&ctx->dst_fmt);
return 0;
return cedrus_s_fmt_vid_out_p(cedrus_file2ctx(file), &f->fmt.pix);
}
const struct v4l2_ioctl_ops cedrus_ioctl_ops = {

View file

@ -27,5 +27,7 @@ extern const struct v4l2_ioctl_ops cedrus_ioctl_ops;
int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
struct vb2_queue *dst_vq);
void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt);
void cedrus_reset_cap_format(struct cedrus_ctx *ctx);
void cedrus_reset_out_format(struct cedrus_ctx *ctx);
#endif