2022-04-20 20:30:13

by Ming Qian

[permalink] [raw]
Subject: [PATCH v3 0/2] media: amphion: copy timestamp from output to

v3
- add helper function vpu_skip_frame() and vpu_next_src_buf()

v2
- reduce the min buffers count

There is a timestamp manager in firmware,
so in previous, driver will pass the timestamp to firmware,
and when a frame is decoded or encoded,
firmware will pass the timestamp to driver,
then driver set the timestamp to the capture vb2_buffer.

But there is problem that the timestamp manager will ensure that the
timestamps are monotonically increasing.
So if there are reorder frames, the capture buffer's timestamp is
inconsistent with the timestamp of the corresponding output buffer.

It goes against the description of V4L2_BUF_FLAG_TIMESTAMP_COPY in the
specification

In order to comply with the specification, driver should copy timestamp
from output buffer to capture buffer, and there is an helper function
v4l2_m2m_buf_copy_metadata to handle it.

Ming Qian (2):
media: amphion: decoder copy timestamp from output to capture
media: amphion: encoder copy timestamp from output to capture

drivers/media/platform/amphion/vdec.c | 76 ++++++++-------------
drivers/media/platform/amphion/venc.c | 47 +++++--------
drivers/media/platform/amphion/vpu_malone.c | 2 +-
drivers/media/platform/amphion/vpu_v4l2.c | 56 +++++++++++++++
drivers/media/platform/amphion/vpu_v4l2.h | 3 +
5 files changed, 103 insertions(+), 81 deletions(-)

--
2.35.1


2022-04-22 10:13:38

by Ming Qian

[permalink] [raw]
Subject: [PATCH v3 2/2] media: amphion: encoder copy timestamp from output to capture

copy the timestamp using the helper function
V4L2_BUF_FLAG_TIMESTAMP_COPY

To implement this, driver will keep the output buffer until it's
encoded, in previous, driver will return the output buffer immediately
after firmware return it

Signed-off-by: Ming Qian <[email protected]>
---
drivers/media/platform/amphion/venc.c | 47 +++++++++------------------
1 file changed, 16 insertions(+), 31 deletions(-)

diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c
index d33c2748e4b7..06c873fd0031 100644
--- a/drivers/media/platform/amphion/venc.c
+++ b/drivers/media/platform/amphion/venc.c
@@ -33,6 +33,8 @@
#define VENC_CAPTURE_ENABLE BIT(1)
#define VENC_ENABLE_MASK (VENC_OUTPUT_ENABLE | VENC_CAPTURE_ENABLE)
#define VENC_MAX_BUF_CNT 8
+#define VENC_MIN_BUFFER_OUT 6
+#define VENC_MIN_BUFFER_CAP 6

struct venc_t {
struct vpu_encode_params params;
@@ -423,7 +425,7 @@ static int venc_drain(struct vpu_inst *inst)
if (inst->state != VPU_CODEC_STATE_DRAIN)
return 0;

- if (v4l2_m2m_num_src_bufs_ready(inst->fh.m2m_ctx))
+ if (!vpu_is_source_empty(inst))
return 0;

if (!venc->input_ready)
@@ -775,10 +777,20 @@ static int venc_get_one_encoded_frame(struct vpu_inst *inst,
struct vb2_v4l2_buffer *vbuf)
{
struct venc_t *venc = inst->priv;
+ struct vb2_v4l2_buffer *src_buf;

if (!vbuf)
return -EAGAIN;

+ src_buf = vpu_find_buf_by_sequence(inst, inst->out_format.type, frame->info.frame_id);
+ if (src_buf) {
+ v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);
+ vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
+ v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, src_buf);
+ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+ } else {
+ vbuf->vb2_buf.timestamp = frame->info.timestamp;
+ }
if (!venc_get_enable(inst->priv, vbuf->vb2_buf.type)) {
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
return 0;
@@ -800,11 +812,10 @@ static int venc_get_one_encoded_frame(struct vpu_inst *inst,
}
vb2_set_plane_payload(&vbuf->vb2_buf, 0, frame->bytesused);
vbuf->sequence = frame->info.frame_id;
- vbuf->vb2_buf.timestamp = frame->info.timestamp;
vbuf->field = inst->cap_format.field;
vbuf->flags |= frame->info.pic_type;
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
- dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, frame->info.timestamp);
+ dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
venc->ready_count++;

@@ -860,33 +871,6 @@ static int venc_frame_encoded(struct vpu_inst *inst, void *arg)
return ret;
}

-static void venc_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame)
-{
- struct vb2_v4l2_buffer *vbuf;
-
- if (!inst->fh.m2m_ctx)
- return;
-
- vpu_inst_lock(inst);
- if (!venc_get_enable(inst->priv, frame->type))
- goto exit;
- vbuf = vpu_find_buf_by_sequence(inst, frame->type, frame->sequence);
- if (!vbuf) {
- dev_err(inst->dev, "[%d] can't find buf: type %d, sequence %d\n",
- inst->id, frame->type, frame->sequence);
- goto exit;
- }
-
- vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
- if (V4L2_TYPE_IS_OUTPUT(frame->type))
- v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);
- else
- v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);
- v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
-exit:
- vpu_inst_unlock(inst);
-}
-
static void venc_set_last_buffer_dequeued(struct vpu_inst *inst)
{
struct venc_t *venc = inst->priv;
@@ -1252,7 +1236,6 @@ static struct vpu_inst_ops venc_inst_ops = {
.check_ready = venc_check_ready,
.input_done = venc_input_done,
.get_one_frame = venc_frame_encoded,
- .buf_done = venc_buf_done,
.stop_done = venc_stop_done,
.event_notify = venc_event_notify,
.release = venc_release,
@@ -1333,6 +1316,8 @@ static int venc_open(struct file *file)
if (ret)
return ret;

+ inst->min_buffer_out = VENC_MIN_BUFFER_OUT;
+ inst->min_buffer_cap = VENC_MIN_BUFFER_CAP;
venc_init(file);

return 0;
--
2.35.1