|
@@ -881,6 +881,47 @@ static int coda_g_selection(struct file *file, void *fh,
|
|
return 0;
|
|
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,
|
|
static int coda_try_decoder_cmd(struct file *file, void *fh,
|
|
struct v4l2_decoder_cmd *dc)
|
|
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_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_try_decoder_cmd = coda_try_decoder_cmd,
|
|
.vidioc_decoder_cmd = coda_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);
|
|
mutex_lock(&ctx->bitstream_mutex);
|
|
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
|
|
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
|
|
if (vb2_is_streaming(vb->vb2_queue))
|
|
if (vb2_is_streaming(vb->vb2_queue))
|
|
|
|
+ /* This set buf->sequence = ctx->qsequence++ */
|
|
coda_fill_bitstream(ctx, true);
|
|
coda_fill_bitstream(ctx, true);
|
|
mutex_unlock(&ctx->bitstream_mutex);
|
|
mutex_unlock(&ctx->bitstream_mutex);
|
|
} else {
|
|
} 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);
|
|
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
|
|
}
|
|
}
|
|
}
|
|
}
|