Skip to content

Commit

Permalink
Media:Wave5: Fix timestamping issue in the decoder
Browse files Browse the repository at this point in the history
Signed-off-by: Som Qin <[email protected]>
  • Loading branch information
Som Qin authored and MichaIng committed Jan 19, 2024
1 parent a64acb0 commit d03f0d1
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 3 deletions.
61 changes: 58 additions & 3 deletions drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit d03f0d1

Please sign in to comment.