changeset 7576:c135f7646036

new opt: -autosync, controls ao->get_delay() smoothing (default: disabled) patch by Sidik Isani <lksi@cfht.hawaii.edu>
author arpi
date Tue, 01 Oct 2002 22:29:04 +0000
parents 3a6d7933a6ad
children e5a7d03f794d
files DOCS/mplayer.1 cfg-mplayer.h mplayer.c
diffstat 3 files changed, 61 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/mplayer.1	Tue Oct 01 21:47:32 2002 +0000
+++ b/DOCS/mplayer.1	Tue Oct 01 22:29:04 2002 +0000
@@ -159,14 +159,26 @@
 can use some big number. You may not use it together with \-pp but it is OK
 with \-npp!
 .TP
+.B \-autosync <factor>
+Gradually adjusts the A/V sync based on audio delay measurements.
+Specifying \-autosync 0, the default, will cause frame timing to be based
+entirely on audio delay measurements.  Specifying \-autosync 1 will do the
+same, but will subtly change the A/V correction algorithm used.  An uneven
+video frame rate in a movie which plays fine with -nosound can often be
+helped by setting this to an integer value greater than 1.  The higher
+the value, the closer the timing will be to -nosound.
+
+Try \-autosync 30 to smooth out problems with sound drivers which do
+not implement a perfect audio delay measurement.  With this value, if
+large A/V sync offsets occur, they will only take about 1 or 2 seconds
+to settle out.  This delay in reaction time to sudden A/V offsets should
+be the only side-effect of turning this option on, for all sound drivers.
+.TP
 .B \-benchmark
 Prints some statistics on CPU usage and dropped frames at the end.
 Used in combination with \-nosound and \-vo null for benchmarking only video
 codec.
 .TP
-.B \-dapsync (OBSOLETE)
-Use alternative A/V sync method.
-.TP
 .B \-framedrop (see \-hardframedrop option too!)
 Frame dropping: decode all (except B) frames, video may skip.
 Useful for playback on slow VGA card/bus.
--- a/cfg-mplayer.h	Tue Oct 01 21:47:32 2002 +0000
+++ b/cfg-mplayer.h	Tue Oct 01 22:29:04 2002 +0000
@@ -349,6 +349,8 @@
 	{"playlist", NULL, CONF_TYPE_STRING, 0, 0, 0, NULL},
 
 	// a-v sync stuff:
+	{"noautosync", &autosync, CONF_TYPE_FLAG, 0, 0, -1, NULL},
+	{"autosync", &autosync, CONF_TYPE_INT, CONF_RANGE, 0, 10000, NULL},
 //	{"dapsync", &dapsync, CONF_TYPE_FLAG, 0, 0, 1, NULL},
 //	{"nodapsync", &dapsync, CONF_TYPE_FLAG, 0, 1, 0, NULL},
 
--- a/mplayer.c	Tue Oct 01 21:47:32 2002 +0000
+++ b/mplayer.c	Tue Oct 01 22:29:04 2002 +0000
@@ -164,6 +164,9 @@
 static off_t step_sec=0;
 static int loop_times=-1;
 
+// A/V sync:
+static int autosync=0; // 30 might be a good default value.
+
 // may be changed by GUI:  (FIXME!)
 float rel_seek_secs=0;
 int abs_seek_pos=0;
@@ -1446,7 +1449,16 @@
 }
 #endif
 
-    if(drop_frame && !frame_time_remaining){
+    if(drop_frame && !frame_time_remaining && !autosync){
+      /*
+       * Note: time_frame should not be forced to 0 in autosync mode.
+       * It is used as a cumulative counter to predict and correct the
+       * delay measurements from the audio driver.  time_frame is already
+       * < 0, so the "time to sleep" code does not actually sleep.  Also,
+       * blit_frame is already 0 because drop_frame was true when
+       * decode_video was called (which causes it to set blit_frame to 0.)
+       * When autosync==0, the default behavior is still completely unchanged.
+       */
 
       time_frame=0;	// don't sleep!
       blit_frame=0;	// don't display!
@@ -1462,6 +1474,21 @@
 	  float delay=audio_out->get_delay();
 	  mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"delay=%f\n",delay);
 
+	  if (autosync){
+	    /*
+	     * Adjust this raw delay value by calculating the expected
+	     * delay for this frame and generating a new value which is
+	     * weighted between the two.  The higher autosync is, the
+	     * closer to the delay value gets to that which "-nosound"
+	     * would have used, and the longer it will take for A/V
+	     * sync to settle at the right value (but it eventually will.)
+	     * This settling time is very short for values below 100.
+	     */
+	    float predicted = sh_audio->timer-sh_video->timer+time_frame;
+	    float difference = delay - predicted;
+	    delay = predicted + difference / (float)autosync;
+	  }
+
           time_frame=sh_video->timer;
           time_frame-=sh_audio->timer-delay;
 
@@ -1565,6 +1592,22 @@
     // unplayed bytes in our and soundcard/dma buffer:
     float delay=audio_out->get_delay()+(float)sh_audio->a_buffer_len/(float)sh_audio->o_bps;
 
+    if (autosync){
+      /*
+       * If autosync is enabled, the value for delay must be calculated
+       * a bit differently.  It is set only to the difference between
+       * the audio and video timers.  Any attempt to include the real
+       * or corrected delay causes the pts_correction code below to
+       * try to correct for the changes in delay which autosync is
+       * trying to measure.  This keeps the two from competing, but still
+       * allows the code to correct for PTS drift *only*.  (Using a delay
+       * value here, even a "corrected" one, would be incompatible with
+       * autosync mode.)
+       */
+      delay=sh_audio->timer-sh_video->timer;
+      delay+=(float)sh_audio->a_buffer_len/(float)sh_audio->o_bps;
+    }
+
     if(pts_from_bps){
 	// PTS = sample_no / samplerate
         unsigned int samples=(sh_audio->audio.dwSampleSize)?