media: coda: mark last pending buffer or last meta on decoder stop command
authorPhilipp Zabel <p.zabel@pengutronix.de>
Tue, 18 Jun 2019 16:45:31 +0000 (12:45 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Mon, 24 Jun 2019 18:45:06 +0000 (14:45 -0400)
If there is still a buffer pending, mark it as the last buffer. It will
create a meta that is flagged as last when the buffer is copied into the
bitstream ring buffer. If there are no more buffers pending, find the
last bitstream meta and mark it as last. If there is no bitstream meta
either, wake up the capture queue as there will be no more decoded
frames.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/coda/coda-bit.c
drivers/media/platform/coda/coda-common.c
drivers/media/platform/coda/coda.h

index 44085e3d43d5073815626ef68cba5cc921758b05..1157454e3bc80a6f38326833440e45cc28974d65 100644 (file)
@@ -402,6 +402,9 @@ void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
                                meta->timestamp = src_buf->vb2_buf.timestamp;
                                meta->start = start;
                                meta->end = ctx->bitstream_fifo.kfifo.in;
+                               meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST;
+                               if (meta->last)
+                                       coda_dbg(1, ctx, "marking last meta");
                                spin_lock(&ctx->buffer_meta_lock);
                                list_add_tail(&meta->list,
                                              &ctx->buffer_meta_list);
@@ -2334,6 +2337,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
                        memset(&decoded_frame->meta, 0,
                               sizeof(struct coda_buffer_meta));
                        decoded_frame->meta.sequence = val;
+                       decoded_frame->meta.last = false;
                        ctx->sequence_offset++;
                }
 
index 95c233b2cbf863e8ec312b1c150b0a65a786c40f..11baa5b1eed8de10ef41e2fe0b6a13203c0de96d 100644 (file)
@@ -1077,6 +1077,8 @@ static int coda_decoder_cmd(struct file *file, void *fh,
        struct coda_dev *dev = ctx->dev;
        struct vb2_v4l2_buffer *buf;
        struct vb2_queue *dst_vq;
+       bool stream_end;
+       bool wakeup;
        int ret;
 
        ret = coda_try_decoder_cmd(file, fh, dc);
@@ -1097,23 +1099,51 @@ static int coda_decoder_cmd(struct file *file, void *fh,
                mutex_unlock(&ctx->bitstream_mutex);
                break;
        case V4L2_DEC_CMD_STOP:
+               stream_end = false;
+               wakeup = false;
+
                buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
-               if (buf)
+               if (buf) {
+                       coda_dbg(1, ctx, "marking last pending buffer\n");
+
                        /* Mark last buffer */
                        buf->flags |= V4L2_BUF_FLAG_LAST;
 
-               if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) {
+                       if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) {
+                               coda_dbg(1, ctx, "all remaining buffers queued\n");
+                               stream_end = true;
+                       }
+               } else {
+                       coda_dbg(1, ctx, "marking last meta\n");
+
+                       /* Mark last meta */
+                       spin_lock(&ctx->buffer_meta_lock);
+                       if (!list_empty(&ctx->buffer_meta_list)) {
+                               struct coda_buffer_meta *meta;
+
+                               meta = list_last_entry(&ctx->buffer_meta_list,
+                                                      struct coda_buffer_meta,
+                                                      list);
+                               meta->last = true;
+                               stream_end = true;
+                       } else {
+                               wakeup = true;
+                       }
+                       spin_unlock(&ctx->buffer_meta_lock);
+               }
+
+               if (stream_end) {
+                       coda_dbg(1, ctx, "all remaining buffers queued\n");
+
                        /* Set the stream-end flag on this context */
                        coda_bit_stream_end_flag(ctx);
                        ctx->hold = false;
                        v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
+               }
 
-                       flush_work(&ctx->pic_run_work);
-
+               if (wakeup) {
                        /* If there is no buffer in flight, wake up */
-                       if (!ctx->streamon_out ||
-                           ctx->qsequence == ctx->osequence)
-                               coda_wake_up_capture_queue(ctx);
+                       coda_wake_up_capture_queue(ctx);
                }
 
                break;
index 97845e58fb8b8a8260ccdfae009d98243a82c9fc..5c183c1944fe2c1ea4caaef0441c319907bb4a32 100644 (file)
@@ -146,6 +146,7 @@ struct coda_buffer_meta {
        u64                     timestamp;
        unsigned int            start;
        unsigned int            end;
+       bool                    last;
 };
 
 /* Per-queue, driver-specific private data */