media: venus: vdec: Handle DRC after drain
authorFritz Koenig <frkoenig@chromium.org>
Tue, 1 Dec 2020 04:23:23 +0000 (05:23 +0100)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Wed, 13 Jan 2021 08:04:44 +0000 (09:04 +0100)
If the DRC is near the end of the stream the client
may send a V4L2_DEC_CMD_STOP before the DRC occurs.
V4L2_DEC_CMD_STOP puts the driver into the
VENUS_DEC_STATE_DRAIN state.  DRC must be aware so
that after the DRC event the state can be restored
correctly.

Signed-off-by: Fritz Koenig <frkoenig@chromium.org>
Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/platform/qcom/venus/core.h
drivers/media/platform/qcom/venus/vdec.c

index db0e673..765ab7e 100644 (file)
@@ -413,6 +413,7 @@ struct venus_inst {
        unsigned int core_acquired: 1;
        unsigned int bit_depth;
        bool next_buf_last;
+       bool drain_active;
 };
 
 #define IS_V1(core)    ((core)->res->hfi_version == HFI_VERSION_1XX)
index 8f060db..4af14d8 100644 (file)
@@ -519,8 +519,10 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
 
                ret = hfi_session_process_buf(inst, &fdata);
 
-               if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING)
+               if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING) {
                        inst->codec_state = VENUS_DEC_STATE_DRAIN;
+                       inst->drain_active = true;
+               }
        }
 
 unlock:
@@ -970,9 +972,13 @@ reconfigure:
 
        inst->codec_state = VENUS_DEC_STATE_DECODING;
 
+       if (inst->drain_active)
+               inst->codec_state = VENUS_DEC_STATE_DRAIN;
+
        inst->streamon_cap = 1;
        inst->sequence_cap = 0;
        inst->reconfig = false;
+       inst->drain_active = false;
 
        return 0;
 
@@ -1098,6 +1104,7 @@ static int vdec_stop_capture(struct venus_inst *inst)
                fallthrough;
        case VENUS_DEC_STATE_DRAIN:
                inst->codec_state = VENUS_DEC_STATE_STOPPED;
+               inst->drain_active = false;
                fallthrough;
        case VENUS_DEC_STATE_SEEK:
                vdec_cancel_dst_buffers(inst);
@@ -1297,8 +1304,10 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
 
                        v4l2_event_queue_fh(&inst->fh, &ev);
 
-                       if (inst->codec_state == VENUS_DEC_STATE_DRAIN)
+                       if (inst->codec_state == VENUS_DEC_STATE_DRAIN) {
+                               inst->drain_active = false;
                                inst->codec_state = VENUS_DEC_STATE_STOPPED;
+                       }
                }
 
                if (!bytesused)
@@ -1374,6 +1383,7 @@ static void vdec_event_change(struct venus_inst *inst,
                inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
                break;
        case VENUS_DEC_STATE_DECODING:
+       case VENUS_DEC_STATE_DRAIN:
                inst->codec_state = VENUS_DEC_STATE_DRC;
                break;
        default: