summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2017-03-02 06:51:44 -0300
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-03-22 10:06:23 -0300
commit59195ceb2d3d1ef82589159be3652d11a902a215 (patch)
treee9318e174f9f2cc6b3e3f52d37d273b6afd7e3c7
parentfbd4676cc2930ba40d507eaadf3ff06d3eba7e6a (diff)
downloadlinux-59195ceb2d3d1ef82589159be3652d11a902a215.tar.bz2
[media] coda: implement encoder stop command
There is no need to call v4l2_m2m_try_schedule to kick off draining the bitstream buffer for the encoder, but we have to wake up the destination queue in case there are no new OUTPUT buffers to be encoded and userspace is already polling for new CAPTURE buffers. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r--drivers/media/platform/coda/coda-common.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index eb6548f46cba..340011f1a08e 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -881,6 +881,47 @@ static int coda_g_selection(struct file *file, void *fh,
return 0;
}
+static int coda_try_encoder_cmd(struct file *file, void *fh,
+ struct v4l2_encoder_cmd *ec)
+{
+ if (ec->cmd != V4L2_ENC_CMD_STOP)
+ return -EINVAL;
+
+ if (ec->flags & V4L2_ENC_CMD_STOP_AT_GOP_END)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int coda_encoder_cmd(struct file *file, void *fh,
+ struct v4l2_encoder_cmd *ec)
+{
+ struct coda_ctx *ctx = fh_to_ctx(fh);
+ struct vb2_queue *dst_vq;
+ int ret;
+
+ ret = coda_try_encoder_cmd(file, fh, ec);
+ if (ret < 0)
+ return ret;
+
+ /* Ignore encoder stop command silently in decoder context */
+ if (ctx->inst_type != CODA_INST_ENCODER)
+ return 0;
+
+ /* Set the stream-end flag on this context */
+ ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+
+ /* If there is no buffer in flight, wake up */
+ if (ctx->qsequence == ctx->osequence) {
+ dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ dst_vq->last_buffer_dequeued = true;
+ wake_up(&dst_vq->done_wq);
+ }
+
+ return 0;
+}
+
static int coda_try_decoder_cmd(struct file *file, void *fh,
struct v4l2_decoder_cmd *dc)
{
@@ -1054,6 +1095,8 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
.vidioc_g_selection = coda_g_selection,
+ .vidioc_try_encoder_cmd = coda_try_encoder_cmd,
+ .vidioc_encoder_cmd = coda_encoder_cmd,
.vidioc_try_decoder_cmd = coda_try_decoder_cmd,
.vidioc_decoder_cmd = coda_decoder_cmd,
@@ -1330,9 +1373,13 @@ static void coda_buf_queue(struct vb2_buffer *vb)
mutex_lock(&ctx->bitstream_mutex);
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
if (vb2_is_streaming(vb->vb2_queue))
+ /* This set buf->sequence = ctx->qsequence++ */
coda_fill_bitstream(ctx, true);
mutex_unlock(&ctx->bitstream_mutex);
} else {
+ if (ctx->inst_type == CODA_INST_ENCODER &&
+ vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ vbuf->sequence = ctx->qsequence++;
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
}
}