Re: [PATCH 7/8] media: cedrus: Add support for holding capture buffer
From: Boris Brezillon
Date: Mon Aug 26 2019 - 14:38:37 EST
On Thu, 22 Aug 2019 21:44:59 +0200
Jernej Skrabec <jernej.skrabec@xxxxxxxx> wrote:
> When frame contains multiple slices and driver works in slice mode, it's
> more efficient to hold capture buffer in queue until all slices of a
> same frame are decoded.
>
> Add support for that to Cedrus driver by exposing and implementing
> V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF capability.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec@xxxxxxxx>
Reviewed-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxxxx>
> ---
> drivers/staging/media/sunxi/cedrus/cedrus_dec.c | 9 +++++++++
> drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 8 +++++---
> drivers/staging/media/sunxi/cedrus/cedrus_video.c | 1 +
> 3 files changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
> index d7b54accfe83..68462b99750e 100644
> --- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
> @@ -31,6 +31,14 @@ void cedrus_device_run(void *priv)
>
> run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +
> + if (v4l2_m2m_release_capture_buf(run.src, run.dst)) {
> + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> + v4l2_m2m_buf_done(run.dst, VB2_BUF_STATE_DONE);
> + run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> + }
> + run.dst->is_held = run.src->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
> +
> run.first_slice =
> run.src->vb2_buf.timestamp != run.dst->vb2_buf.timestamp;
>
> @@ -46,6 +54,7 @@ void cedrus_device_run(void *priv)
> V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS);
> run.mpeg2.quantization = cedrus_find_control_data(ctx,
> V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION);
> + run.dst->is_held = false;
> break;
>
> case V4L2_PIX_FMT_H264_SLICE:
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> index a942cd9bed57..99fedec80224 100644
> --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
> @@ -122,7 +122,7 @@ static irqreturn_t cedrus_irq(int irq, void *data)
> dev->dec_ops[ctx->current_codec]->irq_clear(ctx);
>
> src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
>
> if (!src_buf || !dst_buf) {
> v4l2_err(&dev->v4l2_dev,
> @@ -136,8 +136,10 @@ static irqreturn_t cedrus_irq(int irq, void *data)
> state = VB2_BUF_STATE_DONE;
>
> v4l2_m2m_buf_done(src_buf, state);
> - v4l2_m2m_buf_done(dst_buf, state);
> -
> + if (!dst_buf->is_held) {
> + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> + v4l2_m2m_buf_done(dst_buf, state);
> + }
> v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
>
> return IRQ_HANDLED;
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
> index eeee3efd247b..5153b2bba21e 100644
> --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
> @@ -515,6 +515,7 @@ int cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
> src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
> src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> src_vq->drv_priv = ctx;
> + src_vq->subsystem_flags = VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF;
> src_vq->buf_struct_size = sizeof(struct cedrus_buffer);
> src_vq->min_buffers_needed = 1;
> src_vq->ops = &cedrus_qops;