[MPlayer-dev-eng] [PATCH] correct seeking with long audio buffer

Mikulas Patocka mikulas at artax.karlin.mff.cuni.cz
Mon Aug 2 17:28:48 CEST 2004


Hi

When I configures my OSS sound driver so that it has 2M (12 seconds) large
buffer, mplayer hit a bug that it coudn't seek reliably in streams. When I
pressed back arrow (it should seek 10 seconds backward), it seeked 2
seconds forward.

The problem is caused by the fact, that some demuxers seek according to
current audio position in stream (which is 12 seconds forward from the
position that user sees & hears) and some demuxers seek according to video
position (they behave correctly even with large audio buffer).

The demuxers seeking according to audio position:
mpeg, asf, ogg audio, all the audio-only formats

The demuxers seeking according to video position:
avi, mov

For audio-only demuxers, there not possible to fix the demuxer, the
demuxer has no knowledge of what the user hears now, so it can't seek
according to that information. Seeking according to the position that was
last read from file is very inaccurate.

I fixed the problem by adding another parameter audio_delay to demux_seek
function. If the demuxer is the one seeking by audio offset, demux_seek
subtracts this parameter from the number of seconds to seek.

With this patch, I can reliably seek in all files I have (avi, asf, mov,
mpg, mp3, ogg, wav) with 2M audio buffer size.

Mikulas
-------------- next part --------------
diff -u -r ../MPLAYER-1.0PRE4-BAK2/LIBMPDEMUX/DEMUXER.C ./LIBMPDEMUX/DEMUXER.C
--- ../MPLAYER-1.0PRE4-BAK2/LIBMPDEMUX/DEMUXER.C	2004-04-17 17:46:40.000000000 +0100
+++ ./libmpdemux/demuxer.c	2004-08-02 04:57:27.000000000 +0100
@@ -1462,7 +1462,7 @@
 extern void demux_xmms_seek(demuxer_t *demuxer,float rel_seek_secs,int flags);
 extern void demux_mkv_seek(demuxer_t *demuxer,float rel_seek_secs,int flags);
 
-int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags){
+int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags,float audio_delay){
     demux_stream_t *d_audio=demuxer->audio;
     demux_stream_t *d_video=demuxer->video;
     sh_audio_t *sh_audio=d_audio->sh;
@@ -1496,6 +1496,21 @@
 #endif
 
 switch(demuxer->file_format){
+  case DEMUXER_TYPE_H264_ES:
+  case DEMUXER_TYPE_MPEG4_ES:
+  case DEMUXER_TYPE_MPEG_ES:
+  case DEMUXER_TYPE_MPEG_PS:
+  case DEMUXER_TYPE_MPEG_TY:
+  case DEMUXER_TYPE_ASF:
+  case DEMUXER_TYPE_AUDIO:
+  case DEMUXER_TYPE_RAWAUDIO:
+#ifdef HAVE_OGGVORBIS
+  case DEMUXER_TYPE_OGG:
+#endif
+    if (!flags) rel_seek_secs -= audio_delay;
+}
+
+switch(demuxer->file_format){
 
 #ifdef HAVE_LIBDV095
   case DEMUXER_TYPE_RAWDV:
diff -u -r ../MPLAYER-1.0PRE4-BAK2/LIBMPDEMUX/DEMUXER.H ./LIBMPDEMUX/DEMUXER.H
--- ../MPLAYER-1.0PRE4-BAK2/LIBMPDEMUX/DEMUXER.H	2004-04-12 15:19:12.000000000 +0100
+++ ./libmpdemux/demuxer.h	2004-08-02 04:38:04.000000000 +0100
@@ -262,7 +262,7 @@
 }
 
 demuxer_t* demux_open(stream_t *stream,int file_format,int aid,int vid,int sid,char* filename);
-int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags);
+int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags,float audio_delay);
 demuxer_t*  new_demuxers_demuxer(demuxer_t* vd, demuxer_t* ad, demuxer_t* sd);
 
 // AVI demuxer params:
diff -u -r ../MPLAYER-1.0PRE4-BAK2/LIBMPDEMUX/DEMUX_DEMUXERS.C ./LIBMPDEMUX/DEMUX_DEMUXERS.C
--- ../MPLAYER-1.0PRE4-BAK2/LIBMPDEMUX/DEMUX_DEMUXERS.C	2003-03-27 21:40:50.000000000 +0100
+++ ./libmpdemux/demux_demuxers.c	2004-08-02 04:45:31.000000000 +0100
@@ -63,13 +63,13 @@
   priv->sd->stream->eof = 0;
 
   // Seek video
-  demux_seek(priv->vd,rel_seek_secs,flags);
+  demux_seek(priv->vd,rel_seek_secs,flags,0);
   // Get the new pos
   pos = demuxer->video->pts;
 
   if(priv->ad != priv->vd) {
     sh_audio_t* sh = (sh_audio_t*)demuxer->audio->sh;
-    demux_seek(priv->ad,pos,1);
+    demux_seek(priv->ad,pos,1,0);
     // In case the demuxer don't set pts
     if(!demuxer->audio->pts)
       demuxer->audio->pts = pos-((ds_tell_pts(demuxer->audio)-sh->a_in_buffer_len)/(float)sh->i_bps);
@@ -77,7 +77,7 @@
   }
 
   if(priv->sd != priv->vd)
-      demux_seek(priv->sd,pos,1);
+      demux_seek(priv->sd,pos,1,0);
 
 }
 
diff -u -r ../MPLAYER-1.0PRE4-BAK2/MENCODER.C ./MENCODER.C
--- ../MPLAYER-1.0PRE4-BAK2/MENCODER.C	2004-04-17 17:46:40.000000000 +0100
+++ ./mencoder.c	2004-08-02 04:35:32.000000000 +0100
@@ -1047,12 +1047,12 @@
     else 
         sscanf(seek_to_sec, "%f", &d);
 
-    demux_seek(demuxer, d, 1);
+    demux_seek(demuxer, d, 1, 0);
 //  there is 2 way to handle the -ss option in 3-pass mode:
 // > 1. do the first pass for the whole file, and use -ss for 2nd/3rd pases only
 // > 2. do all the 3 passes with the same -ss value
 //  this line enables behaviour 1. (and kills 2. at the same time):
-//    if(demuxer2) demux_seek(demuxer2, d, 1);
+//    if(demuxer2) demux_seek(demuxer2, d, 1, 0);
 }
 
 if (out_file_format == MUXER_TYPE_MPEG)
diff -u -r ../MPLAYER-1.0PRE4-BAK2/MPLAYER.C ./MPLAYER.C
--- ../MPLAYER-1.0PRE4-BAK2/MPLAYER.C	2004-08-02 04:20:46.000000000 +0100
+++ ./mplayer.c	2004-08-02 04:36:24.000000000 +0100
@@ -3385,7 +3385,7 @@
 
 if(rel_seek_secs || abs_seek_pos){
   current_module="seek";
-  if(demux_seek(demuxer,rel_seek_secs,abs_seek_pos)){
+  if(demux_seek(demuxer,rel_seek_secs,abs_seek_pos,sh_audio?audio_out->get_delay()*playback_speed:0)){
       // success:
       /* FIXME there should be real seeking for vobsub */
       if(sh_video) sh_video->pts=d_video->pts;


More information about the MPlayer-dev-eng mailing list