avsync: tsync: fix avsync issue when streams replayed [2/2]
authorXiaoming Sui <xiaoming.sui@amlogic.com>
Thu, 30 May 2019 11:25:35 +0000 (19:25 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Tue, 4 Jun 2019 14:54:40 +0000 (07:54 -0700)
PD#TV-6448

Problem:
when streams replayed, the video is blocked about 6s sometimes.

Solution:
when streams replayed,  if pcr clock enable, then recalculate the
pcr clock for system clock from the stream to sync the video and audio.

Verify:
X301

Change-Id: Ic414fdc102753e1e1dcedfef2a5cb76ddddf6383
Signed-off-by: Xiaoming Sui <xiaoming.sui@amlogic.com>
drivers/amlogic/media/frame_sync/tsync_pcr.c

index 7555715..695a0bb 100644 (file)
@@ -192,7 +192,10 @@ static u32 tsync_last_play_mode;
 
 static u32 tsync_use_demux_pcr = 1;
 
-static u32 tsync_pcr_debug = 0x01;
+static u32 tsync_pcr_debug;
+static u32 tsync_demux_last_pcr;
+static u32 tsync_demux_pcr_discontinue_count;
+static u32 tsync_demux_pcr_continue_count;
 
 static DEFINE_SPINLOCK(tsync_pcr_lock);
 
@@ -350,8 +353,9 @@ void tsync_pcr_pcrscr_set(void)
 
        if (tsdemux_pcrvideo_valid_cb &&
                tsdemux_pcraudio_valid_cb && tsdemux_pcraudio_valid_cb()) {
-               if (cur_checkin_apts == 0xffffffff)
-                       return;
+               if (cur_checkin_apts == 0xffffffff) {
+                       pr_info("tsync_pcr_pcrscr_set not checkin_apts\n ");
+               }
        } else {
                if (tsync_pcr_debug&0x01)
                        pr_info("now and the cur_checkin_apts is %x\n ",
@@ -381,6 +385,7 @@ void tsync_pcr_pcrscr_set(void)
                        min_checkinpts != 0xffffffff) {
                        ref_pcr = min_checkinpts;
                        tsync_use_demux_pcr = 0;
+                       tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO;
                        if (tsync_pcr_debug&0x01) {
                                pr_info("check init.first_pcr=0x%x, first_apts=0x%x, ",
                                first_pcr, first_apts);
@@ -400,12 +405,20 @@ void tsync_pcr_pcrscr_set(void)
                                timestamp_pcrscr_set(ref_pcr);
                                timestamp_pcrscr_enable(1);
                                tsync_use_demux_pcr = 0;
-                       } else
+                               if (cur_checkin_vpts == 0xffffffff)
+                                       tsync_pcr_inited_mode =
+                                               INIT_PRIORITY_AUDIO;
+                               else
+                                       tsync_pcr_inited_mode =
+                                               INIT_PRIORITY_VIDEO;
+                       } else {
                                tsync_use_demux_pcr = 1;
+                               tsync_pcr_inited_mode = INIT_PRIORITY_PCR;
+                       }
                }
-               timestamp_pcrscr_set(ref_pcr);
-               timestamp_pcrscr_enable(1);
-               init_check_first_systemtime = ref_pcr;
+               pr_info("tsync set:pcrsrc %x,vpts %x,mode %d\n",
+                       timestamp_pcrscr_get(), timestamp_firstvpts_get(),
+                       tsync_use_demux_pcr);
                if (tsdemux_pcrscr_get_cb)
                        init_check_first_demuxpcr = tsdemux_pcrscr_get_cb();
        }
@@ -431,6 +444,7 @@ void tsync_pcr_pcrscr_set(void)
                        }
                } else {
                        tsync_use_demux_pcr = 1;
+                       tsync_pcr_inited_mode = INIT_PRIORITY_PCR;
                        ref_pcr = timestamp_pcrscr_get();
                        if ((tsync_pcr_debug & 0x01) && tsdemux_pcrscr_get_cb) {
                                pr_info("use the pcr from stream , the cur demux pcr is %x\n",
@@ -587,47 +601,117 @@ static u8 tsync_process_checkspeed(void)
        return tsync_last_play_mode;
 }
 
-static void tsync_process_discontinue(void)
+static void tsync_set_pcr_mode(int mode, u32 param)
 {
+       if (tsync_pcr_debug & 0x03) {
+               pr_info("tsync_use_demux_pcr: %d to %d\n",
+                       tsync_use_demux_pcr, mode);
+       }
+       if (mode == 0) {
+               tsync_use_demux_pcr = 0;
+               timestamp_pcrscr_set(param);
+               timestamp_pcrscr_enable(1);
+               timestamp_vpts_set(param);
+       } else if (mode == 1) {
+               tsync_use_demux_pcr = 1;
+               timestamp_pcrscr_enable(0);
+       }
+}
 
-       u32 cur_apts = timestamp_apts_get();
+static void tsync_process_discontinue(void)
+{
        u32 cur_vpts = timestamp_vpts_get();
+       u32 cur_tsdemuxpcr = 0;
+       u32 ref_pcr  = 0, tsdemux_pcr_diff;
+       u32 cur_checkin_vpts = get_last_checkin_pts(PTS_TYPE_VIDEO);
 
-       u32 last_checkout_minpts = cur_apts > cur_vpts ? cur_apts : cur_vpts;
-
-       if (tsdemux_pcraudio_valid_cb && tsdemux_pcraudio_valid_cb() &&
-               tsdemux_pcrvideo_valid_cb && tsdemux_pcrvideo_valid_cb()) {
-               /*set pcr after discontinue according to apts and vpts */
-               if ((tsync_pcr_tsdemuxpcr_discontinue &
-                       (AUDIO_DISCONTINUE | VIDEO_DISCONTINUE)) ==
-                   (AUDIO_DISCONTINUE | VIDEO_DISCONTINUE)) {
-                       last_checkout_minpts = last_checkout_minpts;
+       if (tsdemux_pcrscr_get_cb && (tsync_demux_last_pcr == 0
+               || tsync_demux_last_pcr == 0xffffffff))
+               tsync_demux_last_pcr = tsdemux_pcrscr_get_cb();
+       if (tsdemux_pcrscr_get_cb)
+               cur_tsdemuxpcr = tsdemux_pcrscr_get_cb();
+       else
+               return;
+       if (cur_tsdemuxpcr == 0xffffffff || cur_tsdemuxpcr == 0)
+               return;
+       if (tsync_pcr_inited_mode != INIT_PRIORITY_PCR) {
+               if ((tsync_pcr_tsdemuxpcr_discontinue & VIDEO_DISCONTINUE)
+                       == VIDEO_DISCONTINUE) {
+                       cur_checkin_vpts -= tsync_pcr_ref_latency;
+                       tsync_set_pcr_mode(0, cur_checkin_vpts);
                        tsync_pcr_tsdemuxpcr_discontinue = 0;
-                       tsync_pcr_reset_flag = 1;
-                       if (tsync_pcr_debug&0x02) {
-                               pr_info(" now audio &video discontinue,need replay now\n");
-                       }
                }
-       } else if (tsdemux_pcraudio_valid_cb && tsdemux_pcraudio_valid_cb()) {
-               if ((tsync_pcr_tsdemuxpcr_discontinue &
-                       AUDIO_DISCONTINUE) ==
-                       AUDIO_DISCONTINUE) {
-                       if (tsync_pcr_debug&0x02) {
-                               pr_info(" now audio discontinue\n");
-                               tsync_pcr_tsdemuxpcr_discontinue = 0;
-                               pr_info("after discontinue, pcr = 0x%x,apts=0x%x\n",
-                               timestamp_pcrscr_get(), cur_apts);
+               return;
+       }
+       tsdemux_pcr_diff = abs(cur_tsdemuxpcr - tsync_demux_last_pcr);
+       if (tsync_demux_last_pcr != 0 && cur_tsdemuxpcr != 0
+               && tsdemux_pcr_diff > tsync_pcr_discontinue_threshold) {
+               tsync_demux_pcr_discontinue_count++;
+               tsync_demux_pcr_continue_count = 0;
+               tsync_demux_last_pcr = cur_tsdemuxpcr;
+       } else {
+               tsync_demux_pcr_discontinue_count = 0;
+               tsync_demux_last_pcr = cur_tsdemuxpcr;
+               tsync_demux_pcr_continue_count++;
+               if (tsync_pcr_demux_pcr_used() == 0 &&
+                       abs(cur_tsdemuxpcr - cur_vpts) <
+                       tsync_vpts_discontinuity_margin() &&
+                       tsync_demux_pcr_continue_count > 10 &&
+                       abs(cur_checkin_vpts - cur_vpts) <
+                       tsync_vpts_discontinuity_margin()) {
+                       tsync_set_pcr_mode(1, cur_vpts);
+                       tsync_pcr_tsdemuxpcr_discontinue = 0;
+                       if (tsync_pcr_debug & 0x03) {
+                               pr_info("discontinue,resume checkvpts %x,curvpts %x\n",
+                                       cur_checkin_vpts, cur_vpts);
                        }
-                       timestamp_pcrscr_set(cur_apts);
+                       return;
                }
-       } else {
-               if ((tsync_pcr_tsdemuxpcr_discontinue & VIDEO_DISCONTINUE) ==
-                       VIDEO_DISCONTINUE) {
+       }
+       if (tsync_demux_pcr_discontinue_count > 100) {
+               if (tsync_pcr_debug & 0x03) {
+                       pr_info("PCR_DISCONTINUE, reset!,checkvpts %x,curvpts %x\n",
+                               cur_checkin_vpts, cur_vpts);
+               }
+               tsync_pcr_inited_mode = INIT_PRIORITY_VIDEO;
+               cur_checkin_vpts -= tsync_pcr_ref_latency;
+               tsync_set_pcr_mode(0, cur_checkin_vpts);
+               return;
+       }
+       if ((tsync_pcr_tsdemuxpcr_discontinue &
+               (VIDEO_DISCONTINUE | PCR_DISCONTINUE)) ==
+               VIDEO_DISCONTINUE) {
+               if (abs(cur_checkin_vpts - cur_vpts) >
+                       tsync_vpts_discontinuity_margin()) {
+                       tsync_set_pcr_mode(0, cur_checkin_vpts -
+                               tsync_pcr_ref_latency);
+                       tsync_pcr_tsdemuxpcr_discontinue = 0;
+               } else if (!tsync_check_vpts_discontinuity(cur_vpts) &&
+                       tsync_pcr_demux_pcr_used() == 0) {
+                       tsync_set_pcr_mode(1, cur_vpts);
                        tsync_pcr_tsdemuxpcr_discontinue = 0;
-                       tsync_pcr_reset_flag = 1;
-                       if (tsync_pcr_debug&0x02)
-                               pr_info(" now video discontinue,need replay now\n");
+               } else {
+                       tsync_pcr_tsdemuxpcr_discontinue = 0;
+                       return;
                }
+               if (tsync_pcr_debug & 0x03) {
+                       pr_info("VIDEO_DISCONTINUE checkvpts %x,curvpts %x\n",
+                               cur_checkin_vpts, cur_vpts);
+               }
+       } else if ((tsync_pcr_tsdemuxpcr_discontinue &
+               (VIDEO_DISCONTINUE|PCR_DISCONTINUE)) ==
+               PCR_DISCONTINUE) {
+               if (tsync_use_demux_pcr == 1) {
+                       ref_pcr -= tsync_pcr_ref_latency;
+                       timestamp_pcrscr_set(ref_pcr);
+                       timestamp_pcrscr_enable(1);
+                       tsync_use_demux_pcr = 0;
+               }
+       } else if ((tsync_pcr_tsdemuxpcr_discontinue &
+               (VIDEO_DISCONTINUE|PCR_DISCONTINUE)) ==
+               (VIDEO_DISCONTINUE|PCR_DISCONTINUE)) {
+               tsync_use_demux_pcr = 1;
+               tsync_pcr_tsdemuxpcr_discontinue = 0;
        }
 }
 
@@ -735,36 +819,33 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param)
        case VIDEO_TSTAMP_DISCONTINUITY:{
                unsigned int systime;
 
-               /* unsigned oldpts=timestamp_vpts_get(); */
-               if (!get_vsync_pts_inc_mode()) {
-                       tsync_pcr_tsdemuxpcr_discontinue |=
-                               VIDEO_DISCONTINUE;
-                               tsync_process_discontinue();
-               }
-               if (tsdemux_pcrscr_valid_cb &&
+               if (tsync_pcr_inited_mode != INIT_PRIORITY_PCR) {
+                       timestamp_pcrscr_set(param);
+                       if (tsync_pcr_debug & 0x03) {
+                               pr_info("vdiscontinue param %x,pcrsrc %x\n",
+                                       param, timestamp_pcrscr_get());
+                       }
+               } else if (tsdemux_pcrscr_valid_cb &&
                        tsdemux_pcrscr_valid_cb() == 1 &&
                        tsync_check_vpts_discontinuity(param)) {
+                       if (tsync_pcr_debug & 0x03) {
+                               pr_info("vdiscontinue %d,param %x,pcrsrc %x\n",
+                                       tsync_use_demux_pcr, param,
+                                       timestamp_pcrscr_get());
+                       }
                        if (tsync_pcr_demux_pcr_used() == 1) {
                                systime = timestamp_pcrscr_get() +
                                        timestamp_get_pcrlatency();
-                               if (systime < param) {
-                                       tsync_use_demux_pcr = 0;
-                                       tsync_pcr_freerun_mode = 1;
-                                       timestamp_pcrscr_set(param);
-                                       timestamp_pcrscr_enable(1);
-                               } else {
+                               if (systime + 900000 < param)
+                                       tsync_set_pcr_mode(0, param);
+                               else
                                        timestamp_pcrscr_set(param);
-                               }
                        } else {
                                systime = timestamp_pcrscr_get();
-                               if (systime > param && tsync_pcr_freerun_mode) {
-                                       tsync_use_demux_pcr = 1;
-                                       tsync_pcr_freerun_mode = 0;
+                               if (systime > param)
+                                       tsync_set_pcr_mode(1, param);
+                               else
                                        timestamp_pcrscr_set(param);
-                                       timestamp_pcrscr_enable(0);
-                               } else {
-                                       timestamp_pcrscr_set(param);
-                               }
                        }
                }
                timestamp_vpts_set(param);
@@ -773,7 +854,8 @@ void tsync_pcr_avevent_locked(enum avevent_e event, u32 param)
        case AUDIO_TSTAMP_DISCONTINUITY:{
                tsync_pcr_tsdemuxpcr_discontinue |= AUDIO_DISCONTINUE;
                        timestamp_apts_set(param);
-                       tsync_process_discontinue();
+                       param = timestamp_pcrscr_get();
+                       timestamp_apts_set(param);
        }
        break;
 
@@ -1104,6 +1186,9 @@ int tsync_pcr_start(void)
        }
        abuf_fatal_error = 0;
        vbuf_fatal_error = 0;
+       tsync_demux_last_pcr = 0;
+       tsync_demux_pcr_discontinue_count = 0;
+       tsync_demux_pcr_continue_count = 0;
        return 0;
 }
 EXPORT_SYMBOL(tsync_pcr_start);