[MPlayer-dev-eng] [PATCH] float comparisons and A/V desynchronization fix (mainly with real videos)

Pierre Lombard p_l at gmx.fr
Fri May 5 10:33:50 CEST 2006


Hi,

The culprit file is libmpdemux/video.c: because of how floats are
encoded in computers, you may almost never compare directly floating
points values (floats are not a totally ordered set unlike integers for
instance).

This is why most math libs have an epsilon and also why a (myfloat ==
0.0f) will almost always fail...

FWIW, I chose epsilon to be 1.0f/1000.0f as it seems to match a 1000fps
precision - though it should indeed be related to both compared numbers.

This improves dramatically the A/V sync for some real videos I have (
the A/V sync goes wild because of incorrect frame durations because of
this incorrect comparison).

Patch attached - please test and apply (or some flavor of it as you see
fit).
-- 
Pierre Lombard
-------------- next part --------------
Index: libmpdemux/video.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/video.c,v
retrieving revision 1.62
diff -u -r1.62 video.c
--- libmpdemux/video.c	23 Apr 2006 12:29:10 -0000	1.62
+++ libmpdemux/video.c	5 May 2006 08:29:35 -0000
@@ -609,18 +609,22 @@
       case DEMUXER_TYPE_VIVO:
       case DEMUXER_TYPE_REAL:
       case DEMUXER_TYPE_ASF: {
+	const float epsilon = 0.001f;
         float next_pts = ds_get_next_pts(d_video);
-        float d= next_pts > 0 ? next_pts - d_video->pts : d_video->pts-pts1;
-        if(d>=0){
-          if(d>0){
-            if((int)sh_video->fps==1000)
+        float d = next_pts > -epsilon ? next_pts - d_video->pts : d_video->pts-pts1;
+        if(d > -epsilon){
+          if(fabs(d)>epsilon){
+            if((int)sh_video->fps==1000) {
               mp_msg(MSGT_CPLAYER,MSGL_V,"\navg. framerate: %d fps             \n",(int)(1.0f/d));
+	    }
 	    sh_video->frametime=d; // 1ms
             sh_video->fps=1.0f/d;
+            frame_time = d;
+	  } else {
+            frame_time = 0.0f;
 	  }
-          frame_time = d;
         } else {
-          mp_msg(MSGT_CPLAYER,MSGL_WARN,"\nInvalid frame duration value (%5.3f/%5.3f => %5.3f). Defaulting to %5.3f sec.\n",d_video->pts,next_pts,d,frame_time);
+          mp_msg(MSGT_CPLAYER,MSGL_WARN,"\nInvalid frame duration value (%5.8f/%5.8f => %5.8f). Defaulting to %5.8f sec.\n",d_video->pts,next_pts,d,frame_time);
           // frame_time = 1/25.0;
         }
       }


More information about the MPlayer-dev-eng mailing list