media: vicodec: use v4l2-mem2mem draining, stopped and next-buf-is-last states handling
authorNeil Armstrong <narmstrong@baylibre.com>
Tue, 3 Mar 2020 14:33:18 +0000 (15:33 +0100)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Thu, 5 Mar 2020 21:55:57 +0000 (22:55 +0100)
Use the previously introduced v4l2-mem2mem core APIs to handle the drainig,
stopped and next-buf-is-last states.

With these changes, the v4l2-compliance still passes with the following
commands :
>>>><><><><><><><><><><><><><><><><>< 15.53 fps
 15.53 fps
><><><><><><><><><><><><>< 13.99 fps
 13.99 fps
><><><><><><><><><><><>< 13.52 fps
 13.52 fps
><><><><><><><><><><><><>< 13.41 fps
 13.41 fps
><><><><><><><><><><><><>< 13.21 fps
 13.21 fps
><><><><><><><><><><><>< 13.09 fps
 13.09 fps
><><><><><><><
STOP ENCODER
<<<
EOS EVENT

v4l2-compliance SHA: 7ead0e1856b89f2e19369af452bb03fd0cd16793, 64 bits
[...]
Total for vicodec device /dev/video0: 50, Succeeded: 50, Failed: 0, Warnings: 0

The full output is available at [1]

v4l2-compliance SHA: 7ead0e1856b89f2e19369af452bb03fd0cd16793, 64 bits
[...]
Total for vicodec device /dev/video1: 50, Succeeded: 50, Failed: 0, Warnings: 0

The full output is available at [2]

No functional changes should be noticed.

[1] https://termbin.com/25nn
[2] https://termbin.com/dza4

Suggested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Suggested-by: Maxime Jourdan <mjourdan@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/platform/vicodec/vicodec-core.c

index f78579b..30ced1c 100644 (file)
@@ -117,15 +117,10 @@ struct vicodec_ctx {
        struct vicodec_dev      *dev;
        bool                    is_enc;
        bool                    is_stateless;
-       bool                    is_draining;
-       bool                    next_is_last;
-       bool                    has_stopped;
        spinlock_t              *lock;
 
        struct v4l2_ctrl_handler hdl;
 
-       struct vb2_v4l2_buffer *last_src_buf;
-
        /* Source and destination queue data */
        struct vicodec_q_data   q_data[2];
        struct v4l2_fwht_state  state;
@@ -431,11 +426,11 @@ static void device_run(void *priv)
        v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
 
        spin_lock(ctx->lock);
-       if (!ctx->comp_has_next_frame && src_buf == ctx->last_src_buf) {
+       if (!ctx->comp_has_next_frame &&
+           v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
                dst_buf->flags |= V4L2_BUF_FLAG_LAST;
                v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
-               ctx->is_draining = false;
-               ctx->has_stopped = true;
+               v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
        }
        if (ctx->is_enc || ctx->is_stateless) {
                src_buf->sequence = q_src->sequence++;
@@ -586,8 +581,6 @@ static int job_ready(void *priv)
        unsigned int max_to_copy;
        unsigned int comp_frame_size;
 
-       if (ctx->has_stopped)
-               return 0;
        if (ctx->source_changed)
                return 0;
        if (ctx->is_stateless || ctx->is_enc || ctx->comp_has_frame)
@@ -607,7 +600,8 @@ restart:
        if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
                state = get_next_header(ctx, &p, p_src + sz - p);
                if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
-                       if (ctx->is_draining && src_buf == ctx->last_src_buf)
+                       if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx,
+                                                             src_buf))
                                return 1;
                        job_remove_src_buf(ctx, state);
                        goto restart;
@@ -636,7 +630,8 @@ restart:
                p += copy;
                ctx->comp_size += copy;
                if (ctx->comp_size < max_to_copy) {
-                       if (ctx->is_draining && src_buf == ctx->last_src_buf)
+                       if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx,
+                                                             src_buf))
                                return 1;
                        job_remove_src_buf(ctx, state);
                        goto restart;
@@ -1219,41 +1214,6 @@ static int vidioc_s_selection(struct file *file, void *priv,
        return 0;
 }
 
-static int vicodec_mark_last_buf(struct vicodec_ctx *ctx)
-{
-       struct vb2_v4l2_buffer *next_dst_buf;
-       int ret = 0;
-
-       spin_lock(ctx->lock);
-       if (ctx->is_draining) {
-               ret = -EBUSY;
-               goto unlock;
-       }
-       if (ctx->has_stopped)
-               goto unlock;
-
-       ctx->last_src_buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
-       ctx->is_draining = true;
-       if (ctx->last_src_buf)
-               goto unlock;
-
-       next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-       if (!next_dst_buf) {
-               ctx->next_is_last = true;
-               goto unlock;
-       }
-
-       next_dst_buf->flags |= V4L2_BUF_FLAG_LAST;
-       vb2_buffer_done(&next_dst_buf->vb2_buf, VB2_BUF_STATE_DONE);
-       ctx->is_draining = false;
-       ctx->has_stopped = true;
-       v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
-
-unlock:
-       spin_unlock(ctx->lock);
-       return ret;
-}
-
 static int vicodec_encoder_cmd(struct file *file, void *fh,
                            struct v4l2_encoder_cmd *ec)
 {
@@ -1268,18 +1228,19 @@ static int vicodec_encoder_cmd(struct file *file, void *fh,
            !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
                return 0;
 
-       if (ec->cmd == V4L2_ENC_CMD_STOP)
-               return vicodec_mark_last_buf(ctx);
-       ret = 0;
-       spin_lock(ctx->lock);
-       if (ctx->is_draining) {
-               ret = -EBUSY;
-       } else if (ctx->has_stopped) {
-               ctx->has_stopped = false;
+       ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, ec);
+       if (ret < 0)
+               return ret;
+
+       if (ec->cmd == V4L2_ENC_CMD_STOP &&
+           v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
+               v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
+
+       if (ec->cmd == V4L2_ENC_CMD_START &&
+           v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
                vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
-       }
-       spin_unlock(ctx->lock);
-       return ret;
+
+       return 0;
 }
 
 static int vicodec_decoder_cmd(struct file *file, void *fh,
@@ -1296,18 +1257,19 @@ static int vicodec_decoder_cmd(struct file *file, void *fh,
            !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
                return 0;
 
-       if (dc->cmd == V4L2_DEC_CMD_STOP)
-               return vicodec_mark_last_buf(ctx);
-       ret = 0;
-       spin_lock(ctx->lock);
-       if (ctx->is_draining) {
-               ret = -EBUSY;
-       } else if (ctx->has_stopped) {
-               ctx->has_stopped = false;
+       ret = v4l2_m2m_ioctl_decoder_cmd(file, fh, dc);
+       if (ret < 0)
+               return ret;
+
+       if (dc->cmd == V4L2_DEC_CMD_STOP &&
+           v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
+               v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
+
+       if (dc->cmd == V4L2_DEC_CMD_START &&
+           v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
                vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
-       }
-       spin_unlock(ctx->lock);
-       return ret;
+
+       return 0;
 }
 
 static int vicodec_enum_framesizes(struct file *file, void *fh,
@@ -1480,23 +1442,21 @@ static void vicodec_buf_queue(struct vb2_buffer *vb)
                .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
        };
 
-       if (vb2_is_streaming(vq_cap)) {
-               if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) &&
-                   ctx->next_is_last) {
-                       unsigned int i;
+       if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) &&
+           vb2_is_streaming(vb->vb2_queue) &&
+           v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
+               unsigned int i;
 
-                       for (i = 0; i < vb->num_planes; i++)
-                               vb->planes[i].bytesused = 0;
-                       vbuf->flags = V4L2_BUF_FLAG_LAST;
-                       vbuf->field = V4L2_FIELD_NONE;
-                       vbuf->sequence = get_q_data(ctx, vb->vb2_queue->type)->sequence++;
-                       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
-                       ctx->is_draining = false;
-                       ctx->has_stopped = true;
-                       ctx->next_is_last = false;
-                       v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
-                       return;
-               }
+               for (i = 0; i < vb->num_planes; i++)
+                       vb->planes[i].bytesused = 0;
+
+               vbuf->field = V4L2_FIELD_NONE;
+               vbuf->sequence =
+                       get_q_data(ctx, vb->vb2_queue->type)->sequence++;
+
+               v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
+               v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
+               return;
        }
 
        /* buf_queue handles only the first source change event */
@@ -1609,8 +1569,7 @@ static int vicodec_start_streaming(struct vb2_queue *q,
        chroma_div = info->width_div * info->height_div;
        q_data->sequence = 0;
 
-       if (V4L2_TYPE_IS_OUTPUT(q->type))
-               ctx->last_src_buf = NULL;
+       v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
 
        state->gop_cnt = 0;
 
@@ -1689,29 +1648,12 @@ static void vicodec_stop_streaming(struct vb2_queue *q)
 
        vicodec_return_bufs(q, VB2_BUF_STATE_ERROR);
 
-       if (V4L2_TYPE_IS_OUTPUT(q->type)) {
-               if (ctx->is_draining) {
-                       struct vb2_v4l2_buffer *next_dst_buf;
-
-                       spin_lock(ctx->lock);
-                       ctx->last_src_buf = NULL;
-                       next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-                       if (!next_dst_buf) {
-                               ctx->next_is_last = true;
-                       } else {
-                               next_dst_buf->flags |= V4L2_BUF_FLAG_LAST;
-                               vb2_buffer_done(&next_dst_buf->vb2_buf, VB2_BUF_STATE_DONE);
-                               ctx->is_draining = false;
-                               ctx->has_stopped = true;
-                               v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
-                       }
-                       spin_unlock(ctx->lock);
-               }
-       } else {
-               ctx->is_draining = false;
-               ctx->has_stopped = false;
-               ctx->next_is_last = false;
-       }
+       v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
+
+       if (V4L2_TYPE_IS_OUTPUT(q->type) &&
+           v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
+               v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
+
        if (!ctx->is_enc && V4L2_TYPE_IS_OUTPUT(q->type))
                ctx->first_source_change_sent = false;