From 833bb93df92e98e49e527bf0b36e80059746bd66 Mon Sep 17 00:00:00 2001 From: "apollo.ling" Date: Tue, 9 Jun 2020 18:07:49 +0800 Subject: [PATCH] vdec: add calculation for duration [1/1] PD#SWPL-26472 Problem: this is a new feature. Solution: Use the first 5 frame's pts to calculate the duration, then compare to driver's duration,select the best one. Verify: ac214 Change-Id: I198fc7d761c08508c56bbe85fcd0ae8c71de37a0 Signed-off-by: apollo.ling --- drivers/frame_provider/decoder/utils/vdec.c | 79 +++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c index 32b7b15..9045951 100644 --- a/drivers/frame_provider/decoder/utils/vdec.c +++ b/drivers/frame_provider/decoder/utils/vdec.c @@ -142,6 +142,8 @@ static int enable_stream_mode_multi_dec; #define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1) +extern void vframe_rate_uevent(int duration); + struct am_reg { char *name; int offset; @@ -2624,6 +2626,8 @@ void vdec_release(struct vdec_s *vdec) pr_info("VDEC_DEBUG: step_mode is clear\n"); } #endif + /* When release, userspace systemctl need this duration 0 event */ + vframe_rate_uevent(0); vdec_disconnect(vdec); if (vdec->vframe_provider.name) { @@ -5515,10 +5519,81 @@ void vdec_set_vframe_comm(struct vdec_s *vdec, char *n) } EXPORT_SYMBOL(vdec_set_vframe_comm); +u32 diff_pts(u32 a, u32 b) +{ + if (!a || !b) + return 0; + else + return abs(a - b); +} + +/* + * We only use the first 5 frames to calc duration. + * The fifo[0]~fifo[4] means the frame 0 to frame 4. + * we start to calculate the duration from frame 1. + * And the caller guarantees that slot > 0. + */ +static void cal_dur_from_pts(struct vdec_s *vdec, u32 slot) +{ +#define DURATION_THRESHOD 10 + static u32 sended = 0; + u32 old = 0, cur, diff; + struct vframe_counter_s *fifo = vdec->mvfrm->fifo_buf; + + if (vdec->mvfrm->wr == 1) + sended = 0; + + if (vdec->format != VFORMAT_H264 && + vdec->format != VFORMAT_HEVC) { + if (fifo[slot].frame_dur != sended) { + sended = fifo[slot].frame_dur; + pr_debug("%s send dur%u \n",__func__, sended); + vframe_rate_uevent(sended); + } + return; + } + + if (!fifo[slot].pts) + return; + + if (slot == 1) { + cur = diff_pts(fifo[1].pts, fifo[0].pts); + } else { + old = diff_pts(fifo[slot - 1].pts, fifo[slot - 2].pts); + cur = diff_pts(fifo[slot].pts, fifo[slot - 1].pts); + } + + diff = abs(cur - old); + if (diff > DURATION_THRESHOD) { + u32 dur, cur2; + + cur2 = (cur << 4) / 15; + diff = abs(cur2 - fifo[slot].frame_dur); + if (fifo[slot].frame_dur == 3600) + dur = cur2; + else if (diff < DURATION_THRESHOD || diff > fifo[slot].frame_dur) + dur = fifo[slot].frame_dur; + else + dur = cur2; + + if (sended == dur) + return; + + sended = dur; + pr_debug("%s vstatus %u dur%u - %u, revised %u\n",__func__,fifo[slot].frame_dur, cur,cur2, dur); + if (diff > 10 && slot >= 2) + pr_debug("wr=%u,slot=%u pts %u, %u, %u\n",vdec->mvfrm->wr,slot, + fifo[slot].pts, fifo[slot-1].pts,fifo[slot-2].pts); + + vframe_rate_uevent(dur); + } +} + void vdec_fill_vdec_frame(struct vdec_s *vdec, struct vframe_qos_s *vframe_qos, struct vdec_info *vinfo,struct vframe_s *vf, u32 hw_dec_time) { +#define MINIMUM_FRAMES 5 u32 i; struct vframe_counter_s *fifo_buf; struct vdec_frames_s *mvfrm = vdec->mvfrm; @@ -5542,6 +5617,10 @@ void vdec_fill_vdec_frame(struct vdec_s *vdec, struct vframe_qos_s *vframe_qos, fifo_buf[i].signal_type = vf->signal_type; fifo_buf[i].pts = vf->pts; fifo_buf[i].pts_us64 = vf->pts_us64; + + /* Calculate the duration from pts */ + if (mvfrm->wr < MINIMUM_FRAMES && mvfrm->wr > 0) + cal_dur_from_pts(vdec, i); } mvfrm->wr++; } -- 2.20.1