media: venus: reimplement decoder stop command
authorStanimir Varbanov <stanimir.varbanov@linaro.org>
Fri, 13 Oct 2017 14:13:17 +0000 (16:13 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Nov 2017 08:40:58 +0000 (08:40 +0000)
commit e69b987a97599456b95b5fef4aca8dcdb1505aea upstream.

This addresses the wrong behavior of decoder stop command by
rewriting it. These new implementation enqueue an empty buffer
on the decoder input buffer queue to signal end-of-stream. The
client should stop queuing buffers on the V4L2 Output queue
and continue queuing/dequeuing buffers on Capture queue. This
process will continue until the client receives a buffer with
V4L2_BUF_FLAG_LAST flag raised, which means that this is last
decoded buffer with data.

Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
Tested-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/media/platform/qcom/venus/core.h
drivers/media/platform/qcom/venus/helpers.c
drivers/media/platform/qcom/venus/hfi.c
drivers/media/platform/qcom/venus/vdec.c

index cba092bcb76ddaf5e43f6e499e8365824fbe8e07..a0fe80df0cbd541ee3befb11059dc90343ce21f4 100644 (file)
@@ -194,7 +194,6 @@ struct venus_buffer {
  * @fh:         a holder of v4l file handle structure
  * @streamon_cap: stream on flag for capture queue
  * @streamon_out: stream on flag for output queue
- * @cmd_stop:  a flag to signal encoder/decoder commands
  * @width:     current capture width
  * @height:    current capture height
  * @out_width: current output width
@@ -258,7 +257,6 @@ struct venus_inst {
        } controls;
        struct v4l2_fh fh;
        unsigned int streamon_cap, streamon_out;
-       bool cmd_stop;
        u32 width;
        u32 height;
        u32 out_width;
index 9b2a401a4891c49e1388783cbf4111bf6df26af6..0ce9559a2924fd01249ae406681ad2cc533f6999 100644 (file)
@@ -623,13 +623,6 @@ void venus_helper_vb2_buf_queue(struct vb2_buffer *vb)
 
        mutex_lock(&inst->lock);
 
-       if (inst->cmd_stop) {
-               vbuf->flags |= V4L2_BUF_FLAG_LAST;
-               v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
-               inst->cmd_stop = false;
-               goto unlock;
-       }
-
        v4l2_m2m_buf_queue(m2m_ctx, vbuf);
 
        if (!(inst->streamon_out & inst->streamon_cap))
index c09490876516fbd0ebc793aad7d93cf3c8d38a5f..ba29fd4d49847cc3d1956eefd224823d42cdb14e 100644 (file)
@@ -484,6 +484,7 @@ int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd)
 
        return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(hfi_session_process_buf);
 
 irqreturn_t hfi_isr_thread(int irq, void *dev_id)
 {
index da611a5eb6703793accbd0f8861ca5ebbc18eca2..c9e9576bb08a4e1f568aec1ea55ad003e66dded6 100644 (file)
@@ -469,8 +469,14 @@ static int vdec_subscribe_event(struct v4l2_fh *fh,
 static int
 vdec_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
 {
-       if (cmd->cmd != V4L2_DEC_CMD_STOP)
+       switch (cmd->cmd) {
+       case V4L2_DEC_CMD_STOP:
+               if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK)
+                       return -EINVAL;
+               break;
+       default:
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -479,6 +485,7 @@ static int
 vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
 {
        struct venus_inst *inst = to_inst(file);
+       struct hfi_frame_data fdata = {0};
        int ret;
 
        ret = vdec_try_decoder_cmd(file, fh, cmd);
@@ -486,12 +493,23 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
                return ret;
 
        mutex_lock(&inst->lock);
-       inst->cmd_stop = true;
-       mutex_unlock(&inst->lock);
 
-       hfi_session_flush(inst);
+       /*
+        * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on decoder
+        * input to signal EOS.
+        */
+       if (!(inst->streamon_out & inst->streamon_cap))
+               goto unlock;
+
+       fdata.buffer_type = HFI_BUFFER_INPUT;
+       fdata.flags |= HFI_BUFFERFLAG_EOS;
+       fdata.device_addr = 0xdeadbeef;
 
-       return 0;
+       ret = hfi_session_process_buf(inst, &fdata);
+
+unlock:
+       mutex_unlock(&inst->lock);
+       return ret;
 }
 
 static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
@@ -718,7 +736,6 @@ static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
        inst->reconfig = false;
        inst->sequence_cap = 0;
        inst->sequence_out = 0;
-       inst->cmd_stop = false;
 
        ret = vdec_init_session(inst);
        if (ret)
@@ -807,11 +824,6 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
                vb->timestamp = timestamp_us * NSEC_PER_USEC;
                vbuf->sequence = inst->sequence_cap++;
 
-               if (inst->cmd_stop) {
-                       vbuf->flags |= V4L2_BUF_FLAG_LAST;
-                       inst->cmd_stop = false;
-               }
-
                if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
                        const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };