[MPlayer-dev-eng] Re: [patch] A-V sync tuneup, round 2

PALLAI Roland dap at omnis.hu
Wed Nov 7 21:17:06 CET 2001


> your patch has lines with no if(use_dap_sync) before. for example
> resetting relative timer. it will break timing code.
 ah, fixed

> i prefer well commented (english! :)) patches.
 I've renamed some variables, I hope it's easier to understand, now ;}

>> note3: RPC timer should be used for timing based on 8khz clock.
>> note4: RPC is usually disabled for 'average' users. and HZ=100.
> hm, I didn't think on it, cause I had never enabled it. :} it's a Good
> Thing, I'll test it tomorrow.. but softsleep even required by
> non-linux platforms and RPC-less users
 bad news: only the root can use it, users can't, because they can't
enable interrupts..  it's now implemented, but works only for root


--
  DaP

-------------- next part --------------
diff -urN -x configure -x config.h.in -x aclocal.m4 -x *~ -x *.P -x stamp-h -x stamp-h.in -x config.cache -x config.log -x config.status -x config.h -x Makefile -x POTFILES -x .depend -x config.mak -x version.h -x mplayer.txt -x .#* -x CVS -x loader main/cfg-mplayer.h main-dev/cfg-mplayer.h
--- main/cfg-mplayer.h	Tue Oct 23 22:15:00 2001
+++ main-dev/cfg-mplayer.h	Sat Nov  3 15:37:37 2001
@@ -290,5 +290,6 @@
 	{"-help", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
 	{"help", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
 	{"h", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
+	{"nodapsync", &nodapsync, CONF_TYPE_FLAG, 0, 0, 1},
 	{NULL, NULL, 0, 0, 0, 0}
 };
diff -urN -x configure -x config.h.in -x aclocal.m4 -x *~ -x *.P -x stamp-h -x stamp-h.in -x config.cache -x config.log -x config.status -x config.h -x Makefile -x POTFILES -x .depend -x config.mak -x version.h -x mplayer.txt -x .#* -x CVS -x loader main/mplayer.c main-dev/mplayer.c
--- main/mplayer.c	Mon Oct 29 00:38:52 2001
+++ main-dev/mplayer.c	Wed Nov  7 20:31:24 2001
@@ -69,6 +69,10 @@
 #include "Gui/mplayer/play.h"
 #endif
 
+#ifdef TARGET_LINUX
+#include <linux/rtc.h>
+#endif
+
 #define DEBUG if(0)
 int verbose=0;
 int quiet=0;
@@ -79,6 +83,8 @@
 void find_sub(subtitle* subtitles,int key);
 #endif
 
+int nodapsync = 0;
+
 //**************************************************************************//
 //             Config file
 //**************************************************************************//
@@ -1126,12 +1132,16 @@
 char osd_text_buffer[64];
 int drop_frame=0;
 int drop_frame_cnt=0;
+int too_slow_frame_cnt=0;
+int too_fast_frame_cnt=0;
 // for auto-quality:
 float AV_delay=0; // average of A-V timestamp differences
 double cvideo_base_vtime;
 double cvideo_base_vframe;
 double vdecode_time;
-
+unsigned int lastframeout_ts;
+float time_frame_corr_avg=0;
+int rtc_fd=-1;
 
 //================ SETUP AUDIO ==========================
   current_module="setup_audio";
@@ -1192,6 +1202,34 @@
 
 //==================== START PLAYING =======================
 
+if (!nodapsync) {
+#ifdef TARGET_LINUX
+    if ((rtc_fd = open("/dev/rtc", O_RDONLY)) < 0)
+	perror ("Linux RTC init: open");
+    else {
+	unsigned long irqp;
+
+	/* if (ioctl(rtc_fd, RTC_IRQP_SET, _) < 0) { */
+	if (ioctl(rtc_fd, RTC_IRQP_READ, &irqp) < 0) {
+    	    perror ("Linux RTC init: ioctl (rtc_irqp_read)");
+    	    close (rtc_fd);
+    	    rtc_fd = -1;
+	} else if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
+	    /* variable only by the root */
+    	    perror ("Linux RTC init: ioctl (rtc_pie_on)");
+    	    close (rtc_fd);
+	    rtc_fd = -1;
+	}
+	if (rtc_fd > 0)
+	    printf ("Using Linux's hardware RTC timing (%ldHz)\n", irqp);
+	else
+#endif
+	    printf ("Using software timing\n");
+#ifdef TARGET_LINUX
+    }
+#endif
+}
+
 mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_StartPlaying);fflush(stdout);
 
 if(!use_stdin){
@@ -1367,7 +1405,7 @@
     // Increase video timers:
     sh_video->num_frames+=frame_time;
     ++sh_video->num_frames_decoded;
-    frame_time*=sh_video->frametime;
+    frame_time*=sh_video->frametime;	/* CHECKME: if mpeg2 { ft != 1 } */
     if(demuxer->file_format==DEMUXER_TYPE_ASF && !force_fps){
         // .ASF files has no fixed FPS - just frame durations!
         float d=d_video->pts-pts1;
@@ -1418,29 +1456,71 @@
       // It's time to sleep...
       current_module="sleep";
 
-      time_frame-=GetRelativeTime(); // reset timer
+      time_frame-=GetRelativeTime(); // reset timer -- for nosound
 
       if(sh_audio && !d_audio->eof){
           int delay=audio_out->get_delay();
           mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"delay=%d\n",delay);
-          time_frame=sh_video->timer;
-          time_frame-=sh_audio->timer-(float)delay/(float)sh_audio->o_bps;
-          // we are out of time... drop next frame!
-	  if(time_frame<-2*frame_time){
-	      static int drop_message=0;
-	      drop_frame=frame_dropping; // tricky!
-	      ++drop_frame_cnt;
-	      if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
-	          drop_message=1;
-	          mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
-	      }
-	      mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
-	  }
-      } else {
-          if( (time_frame<-3*frame_time || time_frame>3*frame_time) || benchmark)
-	      time_frame=0;
-	  
-      }
+	  if (nodapsync) {
+	      /* Arpi's AV-sync */
+              time_frame=sh_video->timer;
+              time_frame-=sh_audio->timer-(float)delay/(float)sh_audio->o_bps;
+	      if (time_frame < -2 * frame_time) {
+	          static int drop_message=0;
+	          drop_frame=frame_dropping; // tricky!
+	          ++drop_frame_cnt;
+	          if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
+	              drop_message=1;
+	              mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
+	          }
+	          printf ("WARNING (nodapsync): A-V SYNC FAILED: FRAMEDROP!\n");
+	          mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
+	      } else {
+    		  if( (time_frame<-3*frame_time || time_frame>3*frame_time) || benchmark)
+	    	      time_frame=0;
+    	      }
+	  } else {
+	      /* DaP's AV-sync */
+    	      float SH_AV_delay;
+	      /* SH_AV_delay = sh_video->timer - (sh_audio->timer - (float)((float)delay + sh_audio->a_buffer_len) / (float)sh_audio->o_bps); */
+	      SH_AV_delay = sh_video->timer - (sh_audio->timer - (float)((float)delay) / (float)sh_audio->o_bps);
+	      // printf ("audio slp req: %.3f TF: %.3f delta: %.3f (v: %.3f a: %.3f) | ", i, time_frame,
+	      //	    i - time_frame, sh_video->timer, sh_audio->timer - (float)((float)delay / (float)sh_audio->o_bps));
+	      if(SH_AV_delay<-2*frame_time){
+		  static int drop_message=0;
+	          drop_frame=frame_dropping; // tricky!
+	          ++drop_frame_cnt;
+		  if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
+	    	      drop_message=1;
+	    	      mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
+	         }
+		printf ("A-V SYNC: FRAMEDROP (SH_AV_delay=%.3f)!\n", SH_AV_delay);
+	        mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
+	        /* go into unlimited-TF cycle */
+    		time_frame = SH_AV_delay;
+	      } else {
+#define	SL_CORR_AVG_LEN	125
+	        /* don't adjust under framedropping */
+	        time_frame_corr_avg = (time_frame_corr_avg * (SL_CORR_AVG_LEN - 1) +
+	    				(SH_AV_delay - time_frame)) / SL_CORR_AVG_LEN;
+#define	UNEXP_CORR_MAX	0.1	/* limit of unexpected correction between two frames (percentage) */
+#define	UNEXP_CORR_WARN	1.0	/* warn limit of A-V lag (percentage) */
+	        time_frame += time_frame_corr_avg;
+	        // printf ("{%.3f - %.3f}\n", i - time_frame, frame_time + frame_time_corr_avg);
+	        if (SH_AV_delay - time_frame < (frame_time + time_frame_corr_avg) * UNEXP_CORR_MAX &&
+		    SH_AV_delay - time_frame > (frame_time + time_frame_corr_avg) * -UNEXP_CORR_MAX)
+		    time_frame = SH_AV_delay;
+	        else {
+		    if (SH_AV_delay - time_frame > (frame_time + time_frame_corr_avg) * UNEXP_CORR_WARN ||
+		        SH_AV_delay - time_frame < (frame_time + time_frame_corr_avg) * -UNEXP_CORR_WARN)
+		        printf ("WARNING: A-V SYNC LAG TOO LARGE: %.3f {%.3f - %.3f} (too little UNEXP_CORR_MAX?)\n",
+		  	    SH_AV_delay - time_frame, SH_AV_delay, time_frame);
+		        time_frame += (frame_time + time_frame_corr_avg) * ((SH_AV_delay > time_frame) ?
+		    		      UNEXP_CORR_MAX : -UNEXP_CORR_MAX);
+	        }
+	      }	/* /start dropframe */
+      }	/* /sh_audio */
+    }	/* /end dropframe */
 
 //      if(verbose>1)printf("sleep: %5.3f  a:%6.3f  v:%6.3f  \n",time_frame,sh_audio->timer,sh_video->timer);
 
@@ -1451,28 +1531,77 @@
 	EventHandling();
       }
 #endif
-      
-      while(time_frame>0.005){
-          if(time_frame<=0.020)
-//             usec_sleep(10000); // sleeps 1 clock tick (10ms)!
-             usec_sleep(0); // sleeps 1 clock tick (10ms)!
-          else
-             usec_sleep(1000000*(time_frame-0.002));
+
+#define	SL_MAX_LAG	0.003	/* maximum sleep latency (ms) */
+      if (nodapsync) {
+#if 0	/* soft-sleep */
+        while(time_frame>0.000){
+            if (!(time_frame < 0.010 - SL_MAX_LAG))
+                usec_sleep(0);	/* man nanosleep (2001) */
+#else
+        while(time_frame>0.005){
+            if(time_frame<=0.010)
+                usec_sleep(0); // sleeps 1 clock tick (10ms)!
+            else
+                usec_sleep(1000000*(time_frame-0.002));
+#endif
 #ifdef HAVE_NEW_GUI
-          if(use_gui){
-            EventHandling();
-          }
+            if(use_gui){
+        	EventHandling();
+            }
 #endif
-          time_frame-=GetRelativeTime();
-      }
+            time_frame-=GetRelativeTime();
+	}
+      } else {
+	int i = 0;
+
+        if (!drop_frame && time_frame < -SL_MAX_LAG) {
+	    printf ("WARNING: frame decoding was too slow - no sleep (%.3f)!\n", time_frame);
+	    i++;
+	}
+        while (time_frame > 0.000) {
+	    unsigned long long rtc_ts;
+//printf ("TF1: %.3f\n", time_frame);
+	    if (rtc_fd > 0) {
+		if (read (rtc_fd, &rtc_ts, sizeof rtc_ts) <= 0)
+		    perror ("read (rtc_fd)");
+	    } else
+#if 1	/* soft-sleep */
+    		if (time_frame > 0.010 - SL_MAX_LAG)
+#endif
+        	    usec_sleep(0);	/* man nanosleep (2001) */
+#ifdef HAVE_NEW_GUI
+    	    if(use_gui){
+        	EventHandling();
+    	    }
+#endif
+    	    time_frame-=GetRelativeTime();
+//printf ("TF2: %.3f\n", time_frame);
+        }
+        if (!drop_frame && time_frame < -SL_MAX_LAG) {
+	    if (!i)
+		printf ("NOTICE: too long sleep: %.3f\n", time_frame);
+	    time_frame = -SL_MAX_LAG;	/* may cause too_slow_cnt++ */
+        }
+      } /* /nodapsync */
 
         current_module="flip_page";
 #ifdef USE_LIBVO2
         if(blit_frame) vo2_flip(video_out,0);
 #else
 	video_out->check_events();
-        if(blit_frame){
+        if(blit_frame){	/* doesn't run under framedrop */
 	   unsigned int t2=GetTimer();
+	   float j;
+#define	FRAME_LAG_WARN	0.2
+	   j = ((float)t2 - lastframeout_ts) / 1000000;
+	   lastframeout_ts = GetTimer();
+	   if (j < frame_time + frame_time * -FRAME_LAG_WARN)
+		too_fast_frame_cnt++;
+		/* printf ("PANIC: too fast frame (%.3f)!\n", j); */
+	   else if (j > frame_time + frame_time * FRAME_LAG_WARN)
+		too_slow_frame_cnt++;
+		/* printf ("PANIC: too slow frame (%.3f)!\n", j); */
 	   video_out->flip_page();
 	   t2=GetTimer()-t2;vout_time_usage+=t2*0.000001f;
 	}
@@ -1541,16 +1670,21 @@
           max_pts_correction=default_max_pts_correction;
         else
           max_pts_correction=sh_video->frametime*0.10; // +-10% of time
-        sh_audio->timer+=x; c_total+=x;
-        if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f  %3d/%3d  %2d%% %2d%% %4.1f%% %d %d %d%%\r",
-	  a_pts-audio_delay-delay,v_pts,AV_delay,c_total,
-          (int)sh_video->num_frames,(int)sh_video->num_frames_decoded,
-          (sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)sh_video->timer):0,
-          (sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)sh_video->timer):0,
-          (sh_video->timer>0.5)?(100.0*audio_time_usage/(double)sh_video->timer):0
+        sh_audio->timer+=x;
+	c_total+=x;
+        if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d %2d%% %2d%% %4.1f%% %d %d%% [%d|%d<>%d]\r",
+ 	  a_pts-audio_delay-delay,v_pts,AV_delay,c_total
+          ,(int)sh_video->num_frames
+//	  ,(int)sh_video->num_frames_decoded
+          ,(sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)sh_video->timer):0
+          ,(sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)sh_video->timer):0
+          ,(sh_video->timer>0.5)?(100.0*audio_time_usage/(double)sh_video->timer):0
+ 	  ,output_quality
+ 	  ,cache_fill_status
+//	  ,time_frame_corr_avg
           ,drop_frame_cnt
-	  ,output_quality
-	  ,cache_fill_status
+	  ,too_slow_frame_cnt
+	  ,too_fast_frame_cnt
         );
         fflush(stdout);
       }
@@ -1648,6 +1782,8 @@
              if(use_stdin) usec_sleep(1000); // do not eat the CPU
          }
          osd_function=OSD_PLAY;
+	 if (!nodapsync)
+            (void)GetRelativeTime();	// keep TF around FT in next cycle
       if (audio_out && sh_audio)
         audio_out->resume();	// resume audio
 #ifdef HAVE_NEW_GUI
@@ -1916,6 +2052,8 @@
       osd_visible=sh_video->fps; // to rewert to PLAY pointer after 1 sec
       audio_time_usage=0; video_time_usage=0; vout_time_usage=0;
       drop_frame_cnt=0;
+      too_slow_frame_cnt=0;
+      too_fast_frame_cnt=0;
   
   }
   rel_seek_secs=0;


More information about the MPlayer-dev-eng mailing list