Skip to content

Commit

Permalink
media: cedrus: Add format reset helpers
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
  • Loading branch information
jernejsk authored and Hans Verkuil committed Nov 4, 2022
1 parent d2dd4c6 commit b13ffea
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 36 deletions.
100 changes: 64 additions & 36 deletions drivers/staging/media/sunxi/cedrus/cedrus_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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)
{
Expand All @@ -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);
/*
Expand All @@ -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 = {
Expand Down
2 changes: 2 additions & 0 deletions drivers/staging/media/sunxi/cedrus/cedrus_video.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit b13ffea

Please sign in to comment.