media_module: h265 the first frame is different when play many times [1/1]
authorPeng Yixin <yixin.peng@amlogic.com>
Tue, 5 Jan 2021 08:48:21 +0000 (16:48 +0800)
committerYixin Peng <yixin.peng@amlogic.com>
Wed, 6 Jan 2021 13:02:37 +0000 (05:02 -0800)
PD#SWPL-39208

Problem:
CSD information is discarded mistakenly due to the dirty data found at
the start of playing, cause this problem.

Solution:
When it is found that when the dirty data is more than 1M at start
play, it will not discarded completely, and only half of the data is
discarded to solve this problem.

Verify:
SC2

Signed-off-by: Peng Yixin <yixin.peng@amlogic.com>
Change-Id: Ia498f5b97496a7f392fcd5547d088a5224ff6eb0

drivers/frame_provider/decoder/h265/vh265.c

index 87f390e0168cdc0a459fd785a9f0cda3b4744407..d59fae4369b5a4a8754bb9bdb040d703fd36951c 100644 (file)
@@ -468,8 +468,8 @@ static u32 max_decoding_time;
  *
  *bit 8: 0, use interlace policy
  *       1, NOT use interlace policy
- *bit 9: 0, use manual parser NAL
- *       1, NOT use manual parser NAL
+ *bit 9: 0, discard dirty data on playback start
+ *       1, do not discard dirty data on playback start
  *
  */
 
@@ -1506,6 +1506,7 @@ struct tile_s {
 #define DEC_RESULT_FREE_CANVAS      11
 #define DEC_RESULT_DISCARD_DATA      12
 
+
 static void vh265_work(struct work_struct *work);
 static void vh265_timeout_work(struct work_struct *work);
 static void vh265_notify_work(struct work_struct *work);
@@ -1829,6 +1830,7 @@ struct hevc_state_s {
        bool enable_fence;
        int fence_usage;
        int low_latency_flag;
+       u32 dirty_shift_flag;
 } /*hevc_stru_t */;
 
 #ifdef AGAIN_HAS_THRESHOLD
@@ -12004,9 +12006,9 @@ static void vh265_prot_init(struct hevc_state_s *hevc)
                        ctl_val = 0x4;  /* check vps/sps/pps only in ucode */
                else if (hevc->PB_skip_mode == 3)
                        ctl_val = 0x0;  /* check vps/sps/pps/idr in ucode */
-               if (((error_handle_policy & 0x200) == 0) &&
+               /*if (((error_handle_policy & 0x200) == 0) &&
                                input_stream_based(vdec))
-                       ctl_val = 0x1;
+                       ctl_val = 0x1;*/
                WRITE_VREG(NAL_SEARCH_CTL, ctl_val);
        }
        if ((get_dbg_flag(hevc) & H265_DEBUG_NO_EOS_SEARCH_DONE)
@@ -12395,6 +12397,45 @@ static s32 vh265_init(struct hevc_state_s *hevc)
        return 0;
 }
 
+static int check_dirty_data(struct vdec_s *vdec)
+{
+       struct hevc_state_s *hevc =
+               (struct hevc_state_s *)(vdec->private);
+       struct vdec_input_s *input = &vdec->input;
+       u32 wp, rp, level;
+       u32 rp_set;
+
+       rp = STBUF_READ(&vdec->vbuf, get_rp);
+       wp = hevc->pre_parser_wr_ptr;
+
+       if (wp > rp)
+               level = wp - rp;
+       else
+               level = wp + vdec->input.size - rp;
+
+       if (level > 0x100000) {
+               u32 skip_size = ((level >> 1) >> 19) << 19;
+               if (!vdec->input.swap_valid) {
+                       hevc_print(hevc , 0, "h265 start data discard level 0x%x, buffer level 0x%x, RP 0x%x, WP 0x%x\n",
+                               ((level >> 1) >> 19) << 19, level, rp, wp);
+                       if (wp >= rp) {
+                               rp_set = rp + skip_size;
+                       }
+                       else if ((rp + skip_size) < (input->start + input->size)) {
+                               rp_set = rp + skip_size;
+                       } else {
+                               rp_set = rp + skip_size - input->size;
+                       }
+                       STBUF_WRITE(&vdec->vbuf, set_rp, rp_set);
+                       vdec->input.stream_cookie += skip_size;
+                       hevc->dirty_shift_flag = 1;
+               }
+               return 1;
+       }
+       return 0;
+}
+
+
 static int vh265_stop(struct hevc_state_s *hevc)
 {
        if (get_dbg_flag(hevc) &
@@ -13196,10 +13237,7 @@ static void vh265_work_implement(struct hevc_state_s *hevc,
                        hevc->pre_parser_video_wp = STBUF_READ(&vdec->vbuf, get_wp);
 
                        if (((hevc->again_count > dirty_count_threshold) &&
-                                       time_after64(get_jiffies_64(), hevc->again_timeout_jiffies)) ||
-                                       (((error_handle_policy & 0x200) == 0) &&
-                                               (hevc->pic_list_init_flag == 0) &&
-                                               !(hevc->have_vps || hevc->have_sps || hevc->have_pps))) {
+                                       time_after64(get_jiffies_64(), hevc->again_timeout_jiffies))) {
                                mutex_lock(&hevc->chunks_mutex);
                                hevc->again_count = 0;
                                vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk);
@@ -13207,6 +13245,9 @@ static void vh265_work_implement(struct hevc_state_s *hevc,
                                hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL,
                                        "Discard dirty data\n");
                                mutex_unlock(&hevc->chunks_mutex);
+                       } else if ((((error_handle_policy & 0x200) == 0) &&
+                                               (hevc->pic_list_init_flag == 0))) {
+                               check_dirty_data(vdec);
                        }
                }
        } else if (hevc->dec_result == DEC_RESULT_EOS) {
@@ -13552,7 +13593,11 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                        check_sum,
                        READ_VREG(HEVC_SHIFT_BYTE_COUNT)
                        );
+       if ((hevc->dirty_shift_flag == 1) && !(vdec->input.swap_valid)) {
+               WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, vdec->input.stream_cookie);
+       }
        hevc->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
+
        hevc_print(hevc, PRINT_FLAG_VDEC_STATUS,
                "%s: size 0x%x sum 0x%x (%x %x %x %x %x) byte count %x\n",
                __func__, r,