media_module: fixed h264 mosaic/freeze about 1mins issue [1/1]
authorPeng Yixin <yixin.peng@amlogic.com>
Mon, 25 May 2020 02:13:58 +0000 (10:13 +0800)
committerYixin Peng <yixin.peng@amlogic.com>
Thu, 18 Jun 2020 08:55:11 +0000 (01:55 -0700)
PD#SWPL-26106

Problem:
1. Due to the particularity of the video file,
it will lead to the diffusion of the error,
resulting playback stuck.
2. Due to the video file error, a reference
frame is not out of the dpb queue, and the
subsequent frames are always referring to this
frame, resulting show mosaic.
3. One frame is decoded into multiple frames
4. Two frames of data are decoded into one frame

Solution:
1.the number of continuous errors reaches
a certain number, this frame is considered to
be correct, so that the error will not continue
to spread.
2.a reference frame exceeds 50 frames and is
not remove dpb queue, the frame is considered
to be problematic and removed from dpb queue
3.two consecutive frames are ref frames and
the frame number is the same, the second one
will not enter the DPB queue.
4.Depending on the information when parsing
slice head, If find two frames decoded into
one frame, saving the previous frame into DPB
before continuing to unwrap the second frame.

Verify:
U215

Change-Id: I64ff9f66cd955689161d45d70867cba7e166937d
Signed-off-by: Peng Yixin <yixin.peng@amlogic.com>
(cherry picked from commit 4a2a8fc447c4a6307233628e1f2fff14c217f609)

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 4b67107a0df36551587cc9cbfe2e000ea720deb7..29910d46a623a0c4a9dc72699b003b7aa9e59224 100644 (file)
@@ -94,7 +94,6 @@ static struct StorablePicture *get_new_pic(
        struct h264_dpb_stru *p_H264_Dpb,
        enum PictureStructure structure, unsigned char is_output);
 
-static void update_ref_list(struct DecodedPictureBuffer *p_Dpb);
 
 static void init_dummy_fs(void)
 {
@@ -930,7 +929,8 @@ void fill_frame_num_gap(struct VideoParameters *p_Vid, struct Slice *currSlice)
                        release_picture(p_H264_Dpb, picture);
                        bufmgr_force_recover(p_H264_Dpb);
                        return;
-               }
+               } else if (ret == -2)
+                       release_picture(p_H264_Dpb, picture);
 
                picture = NULL;
                p_Vid->pre_frame_num = UnusedShortTermFrameNum;
@@ -2459,7 +2459,7 @@ static int is_long_term_reference(struct FrameStore *fs)
        return 0;
 }
 
-static void update_ref_list(struct DecodedPictureBuffer *p_Dpb)
+void update_ref_list(struct DecodedPictureBuffer *p_Dpb)
 {
        unsigned int i, j;
 
@@ -3607,6 +3607,16 @@ int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
                                          PRINT_FLAG_DPB_DETAIL,
                                          "duplicate frame_num in short-term reference picture buffer %d\n",
                                           500);
+                               if (p_Dpb->fs_ref[i]->dpb_frame_count == p_H264_Dpb->dpb_frame_count) {
+                                       dpb_print(p_H264_Dpb->decoder_index,
+                                                         0, "duplicate frame, no insert to dpb\n");
+                                       return -2;
+                               } else {
+                                       dpb_print(p_H264_Dpb->decoder_index,
+                                                 0, "duplicate frame_num release defore ref\n");
+                                       unmark_for_reference(p_Dpb, p_Dpb->fs_ref[i]);
+                                       update_ref_list(p_Dpb);
+                               }
                        }
                }
        }
index 619ba416b70932e2423b00b256602c2ed5c48dec..493501735c36f3ae7972345bb8924b0a484836c2 100644 (file)
@@ -971,4 +971,7 @@ int dpb_check_ref_list_error(
 void unmark_for_reference(struct DecodedPictureBuffer *p_Dpb,
        struct FrameStore *fs);
 
+void update_ref_list(struct DecodedPictureBuffer *p_Dpb);
+
+
 #endif
index dbd07c09aad6d46be36444881a8357597f770064..5c19e9ea2e46389eff41f14daef274fee528e682 100644 (file)
@@ -277,8 +277,9 @@ static unsigned int i_only_flag;
        bit[17] 1: If the decoded Mb count is insufficient but greater than the threshold, it is considered the correct frame.
        bit[18] 1: time out status, store pic to dpb buffer.
        bit[19] 1: If a lot b frames are wrong consecutively, the DPB queue reset.
+       bit[20] 1: fixed some error stream will lead to the diffusion of the error, resulting playback stuck.
 */
-static unsigned int error_proc_policy = 0xfCfb6; /*0x1f14*/
+static unsigned int error_proc_policy = 0x1fCfb6; /*0x1f14*/
 
 
 /*
@@ -891,6 +892,7 @@ struct vdec_h264_hw_s {
        int sidebind_type;
        int sidebind_channel_id;
        u32 low_latency_mode;
+       int ip_field_error_count;
 };
 
 static u32 again_threshold;
@@ -5655,6 +5657,38 @@ static void check_decoded_pic_error(struct vdec_h264_hw_s *hw)
                }
        }
 
+       if ((error_proc_policy & 0x100000) &&
+                       hw->last_dec_picture &&
+                               (hw->last_dec_picture->slice_type == I_SLICE) &&
+                               (hw->dpb.mSlice.slice_type == P_SLICE)) {
+               if ((p->data_flag & ERROR_FLAG) &&
+                               (decode_mb_count >= mb_total)) {
+                               hw->ip_field_error_count++;
+                               if (hw->ip_field_error_count == 4) {
+                                       unsigned int i;
+                                       struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+                                       for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+                                               if (p_Dpb->fs_ref[i]->top_field)
+                                                       p_Dpb->fs_ref[i]->top_field->data_flag &= ~ERROR_FLAG;
+                                               if (p_Dpb->fs_ref[i]->bottom_field)
+                                                       p_Dpb->fs_ref[i]->bottom_field->data_flag &= ~ERROR_FLAG;
+                                               if (p_Dpb->fs_ref[i]->frame)
+                                                       p_Dpb->fs_ref[i]->frame->data_flag &= ~ERROR_FLAG;
+                                       }
+                                       hw->ip_field_error_count = 0;
+                                       p->data_flag &= ~ERROR_FLAG;
+                                       hw->data_flag &= ~ERROR_FLAG;
+                                       dpb_print(DECODE_ID(hw), 0,
+                                               "clear all ref frame error flag\n");
+                               }
+               } else {
+                       if (hw->ip_field_error_count > 0)
+                               dpb_print(DECODE_ID(hw), 0,
+                                       "clear error count %d\n", hw->ip_field_error_count);
+                       hw->ip_field_error_count = 0;
+               }
+       }
+
        if (p->data_flag & ERROR_FLAG) {
                dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG,
                        "%s: decode error, seq_info2 0x%x, mby_mbx 0x%x, mb_total %d decoded mb_count %d ERROR_STATUS_REG 0x%x\n",
@@ -5780,6 +5814,8 @@ static int vh264_pic_done_proc(struct vdec_s *vdec)
                        if (ret == -1) {
                                release_cur_decoding_buf(hw);
                                bufmgr_force_recover(p_H264_Dpb);
+                       } else if (ret == -2) {
+                               release_cur_decoding_buf(hw);
                        } else {
                        if (hw->data_flag & ERROR_FLAG) {
                                hw->no_error_count = 0;
@@ -5900,6 +5936,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
                int slice_header_process_status = 0;
                int I_flag;
                int frame_num_gap = 0;
+               union param dpb_param_bak;
                /*unsigned char is_idr;*/
                unsigned short *p = (unsigned short *)hw->lmem_addr;
                reset_process_time(hw);
@@ -5987,6 +6024,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
                        /* printk("%x:%x\n", i,data32); */
                }
 #else
+               dpb_param_bak = p_H264_Dpb->dpb_param;
                for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) {
                        int ii;
 
@@ -6009,6 +6047,19 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
                                }
                        }
                }
+#endif
+#ifdef DETECT_WRONG_MULTI_SLICE
+
+               if (p_H264_Dpb->mVideo.dec_picture &&
+                               hw->multi_slice_pic_flag == 2 &&
+                               (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] != dpb_param_bak.l.data[SLICE_TYPE] ||
+                               dpb_param_bak.l.data[FIRST_MB_IN_SLICE] > p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE])) {
+                       dpb_print(DECODE_ID(hw), 0,
+                               "decode next pic, save before, SLICE_TYPE BAK %d, SLICE_TYPE %d, FIRST_MB_IN_SLICE BAK %d, FIRST_MB_IN_SLICE %d\n",
+                                       dpb_param_bak.l.data[SLICE_TYPE], p_H264_Dpb->dpb_param.l.data[SLICE_TYPE],
+                                       dpb_param_bak.l.data[FIRST_MB_IN_SLICE], p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]);
+                       vh264_pic_done_proc(vdec);
+               }
 #endif
                data_low = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_LOW];
                data_hight = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_HIGHT];
@@ -6055,7 +6106,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
                                        vdec_schedule_work(&hw->work);
                                        dpb_print(DECODE_ID(hw),
                                                PRINT_FLAG_UCODE_EVT,
-                                               "has_i_frame is 0, discard none I(DR) frame\n");
+                                               "has_i_frame is 0, discard none I(DR) frame silce_type %d is_idr %d\n", p_H264_Dpb->dpb_param.l.data[SLICE_TYPE], is_idr);
                                        return IRQ_HANDLED;
                                }
                        } else {
@@ -6109,6 +6160,9 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
                if (p_H264_Dpb->mVideo.dec_picture) {
                        int cfg_ret = 0;
                        bool field_pic_flag = false;
+                       unsigned mby_mbx = READ_VREG(MBY_MBX);
+                       struct StorablePicture *p =
+                               p_H264_Dpb->mVideo.dec_picture;
 
                        if (slice_header_process_status == 1) {
                                if (!p_H264_Dpb->mSPS.frame_mbs_only_flag) {
@@ -6133,21 +6187,28 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
                                        dpb_param.dpb.NAL_info_mmco & 0x1f)
                                        == 5)
                                        hw->data_flag |= IDR_FLAG;
+                               if ((p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]) && !mby_mbx) {
+                                       p->data_flag |= ERROR_FLAG;
+                                       dpb_print(DECODE_ID(hw),
+                                               PRINT_FLAG_VDEC_STATUS,
+                                               "one slice error in muulti-slice  first_mb 0x%x mby_mbx 0x%x  slice_type %d\n",
+                                               p_H264_Dpb->dpb_param.l.
+                                               data[FIRST_MB_IN_SLICE],
+                                               READ_VREG(MBY_MBX),
+                                                p->slice_type);
+                               }
                                dpb_print(DECODE_ID(hw),
                                PRINT_FLAG_VDEC_STATUS,
                                "==================> frame count %d to skip %d\n",
                                hw->decode_pic_count+1,
                                hw->skip_frame_count);
                                } else if (error_proc_policy & 0x100){
-                                       struct StorablePicture *p =
-                                               p_H264_Dpb->mVideo.dec_picture;
-                                       unsigned mby_mbx = READ_VREG(MBY_MBX);
                                        unsigned decode_mb_count =
                                                ((mby_mbx & 0xff) * hw->mb_width +
                                                (((mby_mbx >> 8) & 0xff) + 1));
                                        if (decode_mb_count <
                                                ((p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]) *
-                                               (1 + p->mb_aff_frame_flag))) {
+                                               (1 + p->mb_aff_frame_flag)) && decode_mb_count) {
                                                dpb_print(DECODE_ID(hw),
                                                PRINT_FLAG_VDEC_STATUS,
                                                "Error detect! first_mb 0x%x mby_mbx 0x%x decode_mb 0x%x\n",
@@ -8513,11 +8574,18 @@ result_done:
                                struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
 
                                for (i = 0; i < p_Dpb->used_size; i++) {
-                                       if (p_Dpb->fs[i]->dpb_frame_count + 500 < p_H264_Dpb->dpb_frame_count) {
+                                       int i_flag = p_Dpb->fs[i]->bottom_field || p_Dpb->fs[i]->top_field;
+                                       int threshold = i_flag ? ((50 + p_Dpb->used_size) * 2)  : 50 + p_Dpb->used_size;
+                                       if ((p_Dpb->fs[i]->dpb_frame_count + threshold
+                                                       < p_H264_Dpb->dpb_frame_count) &&
+                                               p_Dpb->fs[i]->is_reference &&
+                                               !p_Dpb->fs[i]->is_long_term &&
+                                               p_Dpb->fs[i]->is_output) {
                                                dpb_print(DECODE_ID(hw),
                                                        0,
                                                        "unmark reference dpb_frame_count diffrence large in dpb\n");
                                                unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
+                                               update_ref_list(p_Dpb);
                                        }
                                }
                        }