diff options
author | andy.hu <andy.hu@starfivetech.com> | 2023-12-14 14:25:34 +0300 |
---|---|---|
committer | andy.hu <andy.hu@starfivetech.com> | 2023-12-14 14:25:34 +0300 |
commit | 1a82e0446fca9d5950bf83a3ad73dfbaf0dd8001 (patch) | |
tree | b42bb7286c299ab747b44670d9cb5581aa41e135 | |
parent | 087fc371bc05df960e63cb53ce307e1ae11c8c70 (diff) | |
parent | 5fb451c271eb68c4c6a5db702449f31c779eb527 (diff) | |
download | linux-1a82e0446fca9d5950bf83a3ad73dfbaf0dd8001.tar.xz |
Merge branch 'CR_8560_wave5_v4l2_Som.Qin' into 'jh7110-5.15.y-devel'
CR 8560 Media:Wave5: Fix timestamping issue in the decoder
See merge request sdk/linux!994
-rw-r--r-- | drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c | 61 | ||||
-rw-r--r-- | drivers/media/platform/chips-media/wave5/wave5-vpuapi.h | 14 |
2 files changed, 72 insertions, 3 deletions
diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c index c9eda6136e95..b5ee9f270343 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -181,6 +181,8 @@ static void wave5_handle_bitstream_buffer(struct vpu_instance *inst) static void wave5_handle_src_buffer(struct vpu_instance *inst) { struct vb2_v4l2_buffer *src_buf; + int i, j, ret; + u64 flag; src_buf = v4l2_m2m_next_src_buf(inst->v4l2_fh.m2m_ctx); if (src_buf) { @@ -189,7 +191,33 @@ static void wave5_handle_src_buffer(struct vpu_instance *inst) if (vpu_buf->consumed) { dev_dbg(inst->dev->dev, "%s: already consumed buffer\n", __func__); src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx); - inst->timestamp = src_buf->vb2_buf.timestamp; + + if (!inst->monotonic_timestamp && !src_buf->vb2_buf.timestamp) { + inst->timestamp_zero_cnt++; + if (inst->timestamp_zero_cnt > 1) { + inst->monotonic_timestamp = TRUE; + } + } + + if(!inst->monotonic_timestamp) { + ret = mutex_lock_interruptible(&inst->time_stamp.lock); + if (ret) { + dev_err(inst->dev->dev, "%s: lock err\n", __func__); + return; + } + inst->time_stamp.buf[inst->time_stamp.cnt] = src_buf->vb2_buf.timestamp; + inst->time_stamp.cnt++; + + for (i = 1; i < inst->time_stamp.cnt; i++) { + flag = inst->time_stamp.buf[i]; + for (j = i - 1; j >= 0 && inst->time_stamp.buf[j] < flag ; j--) { + inst->time_stamp.buf[j + 1] = inst->time_stamp.buf[j]; + } + inst->time_stamp.buf[j + 1] = flag; + } + mutex_unlock(&inst->time_stamp.lock); + } + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); } } @@ -346,7 +374,18 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) ((stride / 2) * (height / 2))); } - dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; + if (!inst->monotonic_timestamp) { + ret = mutex_lock_interruptible(&inst->time_stamp.lock); + if (ret) { + dev_err(inst->dev->dev, "%s: lock err\n", __func__); + return; + } + dst_buf->vb2_buf.timestamp = inst->time_stamp.buf[inst->time_stamp.cnt - 1]; + inst->time_stamp.cnt--; + mutex_unlock(&inst->time_stamp.lock); + } else { + dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; + } dst_buf->field = V4L2_FIELD_NONE; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); @@ -381,7 +420,19 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) vb2_plane_size(&dst_buf->vb2_buf, 2)); } - dst_buf->vb2_buf.timestamp = inst->timestamp; + if (!inst->monotonic_timestamp) { + ret = mutex_lock_interruptible(&inst->time_stamp.lock); + if (ret) { + dev_err(inst->dev->dev, "%s: lock err\n", __func__); + return; + } + dst_buf->vb2_buf.timestamp = inst->time_stamp.buf[inst->time_stamp.cnt - 1]; + inst->time_stamp.cnt--; + mutex_unlock(&inst->time_stamp.lock); + } else { + dst_buf->vb2_buf.timestamp = inst->timestamp_cnt++ * inst->codec_info->dec_info.initial_info.ns_per_frame; + } + dst_buf->flags |= V4L2_BUF_FLAG_LAST; dst_buf->field = V4L2_FIELD_NONE; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); @@ -952,6 +1003,10 @@ static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst) struct dec_initial_info initial_info; int ret = 0; + inst->time_stamp.cnt = 0; + mutex_init(&inst->time_stamp.lock); + memset(&inst->time_stamp.buf, 0, sizeof(MAX_TIMESTAMP_CIR_BUF)); + memset(&initial_info, 0, sizeof(struct dec_initial_info)); ret = wave5_vpu_dec_issue_seq_init(inst); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h index 10f20a283592..d7b5717fd9c1 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h @@ -43,6 +43,8 @@ enum vpu_instance_state { #define MAX_REG_FRAME (WAVE5_MAX_FBS * 2) +#define MAX_TIMESTAMP_CIR_BUF 30 + #define WAVE5_DEC_HEVC_BUF_SIZE(_w, _h) (DIV_ROUND_UP(_w, 64) * DIV_ROUND_UP(_h, 64) * 256 + 64) #define WAVE5_DEC_AVC_BUF_SIZE(_w, _h) ((((ALIGN(_w, 256) / 16) * (ALIGN(_h, 16) / 16)) + 16) * 80) #define WAVE5_DEC_VP9_BUF_SIZE(_w, _h) (((ALIGN(_w, 64) * ALIGN(_h, 64)) >> 2)) @@ -1038,6 +1040,15 @@ struct vpu_instance_ops { void (*finish_process)(struct vpu_instance *inst); }; +/* for support GStreamer ver 1.20 over + * too old frame, eos sent too early + */ +struct timestamp_circ_buf { + u64 buf[MAX_TIMESTAMP_CIR_BUF]; + struct mutex lock; + int cnt; +}; + struct vpu_instance { struct list_head list; struct v4l2_fh v4l2_fh; @@ -1075,7 +1086,10 @@ struct vpu_instance { u32 conf_win_width; u32 conf_win_height; u64 timestamp; + struct timestamp_circ_buf time_stamp; u64 timestamp_cnt; + u32 timestamp_zero_cnt; + bool monotonic_timestamp; bool cbcr_interleave; bool nv21; bool eos; |