VENUS_DEC_STATE_SEEK = 4,
VENUS_DEC_STATE_DRAIN = 5,
VENUS_DEC_STATE_DECODING = 6,
- VENUS_DEC_STATE_DRC = 7
+ VENUS_DEC_STATE_DRC = 7,
+ VENUS_DEC_STATE_DRC_FLUSH_DONE = 8,
};
struct venus_ts_metadata {
* @priv: a private for HFI operations callbacks
* @session_type: the type of the session (decoder or encoder)
* @hprop: a union used as a holder by get property
+ * @last_buf: last capture buffer for dynamic-resoluton-change
*/
struct venus_inst {
struct list_head list;
union hfi_get_property hprop;
unsigned int core_acquired: 1;
unsigned int bit_depth;
+ struct vb2_buffer *last_buf;
};
#define IS_V1(core) ((core)->res->hfi_version == HFI_VERSION_1XX)
u32 hfi_flags, u64 timestamp_us);
void (*event_notify)(struct venus_inst *inst, u32 event,
struct hfi_event_data *data);
+ void (*flush_done)(struct venus_inst *inst);
};
struct hfi_ops {
int hfi_session_abort(struct venus_inst *inst);
int hfi_session_load_res(struct venus_inst *inst);
int hfi_session_unload_res(struct venus_inst *inst);
-int hfi_session_flush(struct venus_inst *inst, u32 type);
+int hfi_session_flush(struct venus_inst *inst, u32 type, bool block);
int hfi_session_set_buffers(struct venus_inst *inst,
struct hfi_buffer_desc *bd);
int hfi_session_unset_buffers(struct venus_inst *inst,
return 0;
reconfigure:
- ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT);
+ ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, true);
if (ret)
return ret;
switch (inst->codec_state) {
case VENUS_DEC_STATE_DECODING:
- ret = hfi_session_flush(inst, HFI_FLUSH_ALL);
+ ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
/* fallthrough */
case VENUS_DEC_STATE_DRAIN:
vdec_cancel_dst_buffers(inst);
inst->codec_state = VENUS_DEC_STATE_STOPPED;
break;
case VENUS_DEC_STATE_DRC:
- ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT);
+ WARN_ON(1);
+ fallthrough;
+ case VENUS_DEC_STATE_DRC_FLUSH_DONE:
inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
venus_helper_free_dpb_bufs(inst);
break;
case VENUS_DEC_STATE_DECODING:
case VENUS_DEC_STATE_DRAIN:
case VENUS_DEC_STATE_STOPPED:
- ret = hfi_session_flush(inst, HFI_FLUSH_ALL);
+ ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
inst->codec_state = VENUS_DEC_STATE_SEEK;
break;
case VENUS_DEC_STATE_INIT:
case VENUS_DEC_STATE_CAPTURE_SETUP:
- ret = hfi_session_flush(inst, HFI_FLUSH_INPUT);
+ ret = hfi_session_flush(inst, HFI_FLUSH_INPUT, true);
break;
default:
break;
vb->timestamp = timestamp_us * NSEC_PER_USEC;
vbuf->sequence = inst->sequence_cap++;
+ if (inst->last_buf == vb) {
+ inst->last_buf = NULL;
+ vbuf->flags |= V4L2_BUF_FLAG_LAST;
+ vb2_set_plane_payload(vb, 0, 0);
+ vb->timestamp = 0;
+ }
+
if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
}
}
+ /*
+ * The assumption is that the firmware have to return the last buffer
+ * before this event is received in the v4l2 driver. Also the firmware
+ * itself doesn't mark the last decoder output buffer with HFI EOS flag.
+ */
+
+ if (!sufficient && inst->codec_state == VENUS_DEC_STATE_DRC) {
+ struct vb2_v4l2_buffer *last;
+ int ret;
+
+ last = v4l2_m2m_last_dst_buf(inst->m2m_ctx);
+ if (last)
+ inst->last_buf = &last->vb2_buf;
+
+ ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, false);
+ if (ret)
+ dev_dbg(dev, "flush output error %d\n", ret);
+ }
+
inst->reconfig = true;
v4l2_event_queue_fh(&inst->fh, &ev);
wake_up(&inst->reconf_wait);
}
}
+static void vdec_flush_done(struct venus_inst *inst)
+{
+ if (inst->codec_state == VENUS_DEC_STATE_DRC)
+ inst->codec_state = VENUS_DEC_STATE_DRC_FLUSH_DONE;
+}
+
static const struct hfi_inst_ops vdec_hfi_ops = {
.buf_done = vdec_buf_done,
.event_notify = vdec_event_notify,
+ .flush_done = vdec_flush_done,
};
static void vdec_inst_init(struct venus_inst *inst)