h264: stream mode vpts lookup fail [1/1]
authorPeng Yixin <yixin.peng@amlogic.com>
Thu, 12 Nov 2020 06:20:56 +0000 (14:20 +0800)
committerHui Zhang <hui.zhang@amlogic.com>
Fri, 25 Dec 2020 11:21:04 +0000 (03:21 -0800)
PD#SWPL-35520

Problem:
Because the stream will checkin one vpts every three frames, and some
of the frames size is small, it will cause lookup pts is successful
but it doesn't match, resulting playback unsmooth.

Solution:
When lookup fail is detected many times and the frame size is
small, pts is computed using duration to solve the problem.

Verify:
SC2

Change-Id: Ib9319fc46e28006ccca173c87faf88b88288ba66
Signed-off-by: Peng Yixin <yixin.peng@amlogic.com>
drivers/frame_provider/decoder/h264_multi/h264_dpb.c
drivers/frame_provider/decoder/h264_multi/h264_dpb.h
drivers/frame_provider/decoder/h264_multi/vmh264.c

index 523ce9f5aec1af18e5589f8a584412e6644ca287..2e5bae0dc342c15b45a5ac4d58476f0016e8363e 100644 (file)
@@ -1579,10 +1579,12 @@ static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb,
                        fs->pts64 = 0;
                }
                fs->offset_delimiter = fs->top_field->offset_delimiter;
+               fs->decoded_frame_size = fs->top_field->pic_size + fs->bottom_field->pic_size;
        } else if (fs->bottom_field) {
                fs->pts = fs->bottom_field->pts;
                fs->pts64 = fs->bottom_field->pts64;
                fs->offset_delimiter = fs->bottom_field->offset_delimiter;
+               fs->decoded_frame_size = fs->top_field->pic_size + fs->bottom_field->pic_size;
        }
        /* FIELD_CODING ;*/
 }
@@ -1644,6 +1646,7 @@ static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
                fs->slice_type = p->slice_type;
                fs->frame_size = p->frame_size;
                fs->offset_delimiter = p->offset_delimiter;
+               fs->decoded_frame_size = p->pic_size;
                if (p->used_for_reference) {
                        fs->is_reference = 3;
                        fs->is_orig_reference = 3;
index 1b340982218f33834e9506433fc6c0286f69020e..85ee1583c70059703c832c23b1ed5f818ffe4953 100644 (file)
@@ -740,6 +740,7 @@ struct StorablePicture {
        int max_mv;
        int min_mv;
        int avg_mv;
+       u32 pic_size;
 };
 
 struct FrameStore {
@@ -822,6 +823,7 @@ struct FrameStore {
        u32 frame_size2; // For recording the chunk->size in frame mode
        bool show_frame;
        struct fence *fence;
+       u32 decoded_frame_size;
 };
 
 /* #define DPB_SIZE_MAX     16 */
index 025a8e724ebc024552098b8b2180eb51268b7f6d..7e2fdedd91f46b8875dfc881b7e4431264b05f76 100644 (file)
@@ -345,6 +345,9 @@ static u32 without_display_mode;
 static int loop_playback_poc_threshold = 400;
 static int poc_threshold = 50;
 
+static u32 lookup_check_conut = 30;
+
+
 /*
  *[3:0] 0: default use config from omx.
  *      1: force enable fence.
@@ -923,6 +926,9 @@ struct vdec_h264_hw_s {
        bool discard_dv_data;
        int vdec_pg_enable_flag;
        u32 save_reg_f;
+       u32 start_bit_cnt;
+       u32 right_frame_count;
+       u32 wrong_frame_count;
 };
 
 static u32 again_threshold;
@@ -2763,11 +2769,18 @@ static int post_prepare_process(struct vdec_s *vdec, struct FrameStore *frame)
                        if ((pts_lookup_offset_us64(PTS_TYPE_VIDEO,
                                frame->offset_delimiter, &frame->pts, &frame->frame_size,
                                0, &frame->pts64) == 0)) {
-                               hw->last_pts64 = frame->pts64;
-                               hw->last_pts = frame->pts;
+                               if ((lookup_check_conut && (hw->vf_pre_count > lookup_check_conut) &&
+                                       (hw->wrong_frame_count > hw->right_frame_count)) &&
+                                       ((frame->decoded_frame_size * 2 < frame->frame_size))) {
+                                       /*resolve many frame only one check in pts, cause playback unsmooth issue*/
+                                       frame->pts64 = hw->last_pts64 +DUR2PTS(hw->frame_dur) ;
+                                       frame->pts = hw->last_pts + DUR2PTS(hw->frame_dur);
+                               }
+                               hw->right_frame_count++;
                        } else {
                                frame->pts64 = hw->last_pts64 +DUR2PTS(hw->frame_dur) ;
                                frame->pts = hw->last_pts + DUR2PTS(hw->frame_dur);
+                               hw->wrong_frame_count++;
                        }
                }
                dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
@@ -6045,6 +6058,7 @@ static int vh264_pic_done_proc(struct vdec_s *vdec)
                                struct StorablePicture *pic =
                                        p_H264_Dpb->mVideo.dec_picture;
                                u32 offset = pic->offset_delimiter;
+                               pic->pic_size = (hw->start_bit_cnt - READ_VREG(VIFF_BIT_CNT)) >> 3;
                                if (pts_pickout_offset_us64(PTS_TYPE_VIDEO,
                                        offset, &pic->pts, 0, &pic->pts64)) {
                                        pic->pts = 0;
@@ -9519,6 +9533,7 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                WRITE_VREG(H264_DECODE_INFO, (1<<13));
                WRITE_VREG(H264_DECODE_SIZE, size);
                WRITE_VREG(VIFF_BIT_CNT, size * 8);
+               hw->start_bit_cnt = size * 8;
        }
        config_aux_buf(hw);
        config_decode_mode(hw);