[Mplayer-cvslog] CVS: main/libmpdemux demux_mpg.c, 1.51, 1.52 demuxer.c, 1.172, 1.173

Aurelien Jacobs CVS syncmail at mplayerhq.hu
Sat Oct 23 02:05:40 CEST 2004


CVS change done by Aurelien Jacobs CVS

Update of /cvsroot/mplayer/main/libmpdemux
In directory mail:/var2/tmp/cvs-serv10661/libmpdemux

Modified Files:
	demux_mpg.c demuxer.c 
Log Message:
seeking based on the largest timestamp in an mpeg stream
It is often more accurate than the current seeking and it has the
additional benefit of giving the (almost) precise total time of the movie.
patch by Michael Behrisch < behrisch at informatik.hu-berlin.de >

Index: demux_mpg.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demux_mpg.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -r1.51 -r1.52
--- demux_mpg.c	15 Oct 2004 16:11:30 -0000	1.51
+++ demux_mpg.c	23 Oct 2004 00:05:37 -0000	1.52
@@ -17,8 +17,58 @@
 //#define MAX_PS_PACKETSIZE 2048
 #define MAX_PS_PACKETSIZE (224*1024)
 
+typedef struct mpg_demuxer {
+  float last_pts;
+  float final_pts;
+  int has_valid_timestamps;
+} mpg_demuxer_t;
+
 static int mpeg_pts_error=0;
 
+/// Open an mpg physical stream
+int demux_mpg_open(demuxer_t* demuxer) {
+  stream_t *s = demuxer->stream;
+  off_t pos = stream_tell(s);
+  off_t end_seq_start = demuxer->movi_end-500000; // 500000 is a wild guess
+  float half_pts = 0.0;
+  mpg_demuxer_t* mpg_d;
+
+  if (!ds_fill_buffer(demuxer->video)) return 0;
+  mpg_d = (mpg_demuxer_t*)calloc(1,sizeof(mpg_demuxer_t));
+  demuxer->priv = mpg_d;
+  mpg_d->final_pts = 0.0;
+  mpg_d->has_valid_timestamps = 1;
+  if (demuxer->seekable && stream_tell(demuxer->stream) < end_seq_start) {
+    stream_seek(s,(pos + end_seq_start / 2));
+    while ((!s->eof) && ds_fill_buffer(demuxer->video) && half_pts == 0.0) {
+      half_pts = mpg_d->last_pts;
+    }
+    stream_seek(s,end_seq_start);
+    while ((!s->eof) && ds_fill_buffer(demuxer->video)) {
+      if (mpg_d->final_pts < mpg_d->last_pts) mpg_d->final_pts = mpg_d->last_pts;
+    }
+    // educated guess about validity of timestamps
+    if (mpg_d->final_pts > 3 * half_pts || mpg_d->final_pts < 1.5 * half_pts) {
+      mpg_d->has_valid_timestamps = 0;
+    }
+    ds_free_packs(demuxer->audio);
+    ds_free_packs(demuxer->video);
+    demuxer->stream->eof=0; // clear eof flag
+    demuxer->video->eof=0;
+    demuxer->audio->eof=0;
+    
+    stream_seek(s,pos);
+    ds_fill_buffer(demuxer->video);
+  }
+  return 1;
+}
+
+void demux_close_mpg(demuxer_t* demuxer) {
+  mpg_demuxer_t* mpg_d = demuxer->priv;
+  if (mpg_d) free(mpg_d);
+}
+
+
 static unsigned int read_mpeg_timestamp(stream_t *s,int c){
   int d,e;
   unsigned int pts;
@@ -222,6 +272,7 @@
     mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id);
 //    printf("packet start = 0x%X  \n",stream_tell(demux->stream)-packet_start_pos);
     ds_read_packet(ds,demux->stream,len,pts/90000.0f,demux->filepos,0);
+    if (demux->priv) ((mpg_demuxer_t*)demux->priv)->last_pts = pts/90000.0f;
 //    if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len);
     return 1;
   }
@@ -357,21 +408,41 @@
     demux_stream_t *d_video=demuxer->video;
     sh_audio_t *sh_audio=d_audio->sh;
     sh_video_t *sh_video=d_video->sh;
+    mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
+    int precision = 1;
+    float oldpts = mpg_d->last_pts;
+    off_t oldpos = demuxer->filepos;
+    float newpts = (flags & 1) ? 0.0 : oldpts;
+    off_t newpos = (flags & 1) ? demuxer->movi_start : oldpos;
 
   //================= seek in MPEG ==========================
-    off_t newpos=(flags&1)?demuxer->movi_start:demuxer->filepos;
+  //calculate the pts to seek to
+    if(flags & 2) {
+      if (mpg_d->final_pts > 0.0)
+        newpts += mpg_d->final_pts * rel_seek_secs;
+      else
+        newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos;
+    } else
+      newpts += rel_seek_secs;
+    if (newpts < 0) newpts = 0;
 	
     if(flags&2){
 	// float seek 0..1
 	newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs;
     } else {
 	// time seek (secs)
-        if(!sh_video || !sh_video->i_bps) // unspecified or VBR
+        if (mpg_d && mpg_d->has_valid_timestamps) {
+          if (mpg_d->final_pts > 0.0)
+            newpos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / mpg_d->final_pts;
+          else if (oldpts > 0.0)
+            newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts;
+        } else if(!sh_video || !sh_video->i_bps) // unspecified or VBR
           newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec
         else
           newpos+=sh_video->i_bps*rel_seek_secs;
     }
 
+    while (1) {
         if(newpos<demuxer->movi_start){
 	    if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD
 	    if(newpos<demuxer->movi_start) newpos=demuxer->movi_start;
@@ -407,6 +478,20 @@
           if(i==0x1B3 || i==0x1B8) break; // found it!
           if(!i || !skip_video_packet(d_video)) break; // EOF?
         }
+        if (!precision || abs(newpts - mpg_d->last_pts) < 0.5 || (mpg_d->last_pts == oldpts)) break;
+        if ((newpos - oldpos) * (mpg_d->last_pts - oldpts) < 0) { // invalid timestamps
+          mpg_d->has_valid_timestamps = 0;
+          break;
+        }
+        precision--;
+        //prepare another seek because we are off by more than 0.5s
+        newpos += (newpts - mpg_d->last_pts) * (newpos - oldpos) / (mpg_d->last_pts - oldpts);
+        ds_free_packs(d_audio);
+        ds_free_packs(d_video);
+        demuxer->stream->eof=0; // clear eof flag
+        d_video->eof=0;
+        d_audio->eof=0;
+    }
 }
 
 int demux_mpg_control(demuxer_t *demuxer,int cmd, void *arg){
@@ -414,9 +499,14 @@
     demux_stream_t *d_video=demuxer->video;
 /*    sh_audio_t *sh_audio=d_audio->sh;*/
     sh_video_t *sh_video=d_video->sh;
+    mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv;
 
     switch(cmd) {
 	case DEMUXER_CTRL_GET_TIME_LENGTH:
+            if (mpg_d && mpg_d->has_valid_timestamps) {
+              *((unsigned long *)arg)=(long)mpg_d->final_pts;
+              return DEMUXER_CTRL_GUESS;
+            }
 	    if(!sh_video || !sh_video->i_bps)  // unspecified or VBR 
     		return DEMUXER_CTRL_DONTKNOW;
 	    *((unsigned long *)arg)=(demuxer->movi_end-demuxer->movi_start)/sh_video->i_bps;
@@ -425,6 +515,10 @@
 	case DEMUXER_CTRL_GET_PERCENT_POS:
 	    if (demuxer->movi_end==demuxer->movi_start) 
     		return DEMUXER_CTRL_DONTKNOW;
+            if (mpg_d && mpg_d->has_valid_timestamps && mpg_d->final_pts > 0.0) {
+              *((int *)arg)=(int)(100 * mpg_d->last_pts / mpg_d->final_pts);
+              return DEMUXER_CTRL_OK;
+            }
     	    *((int *)arg)=(int)((demuxer->filepos-demuxer->movi_start)/((demuxer->movi_end-demuxer->movi_start)/100));
 	    return DEMUXER_CTRL_OK;
 

Index: demuxer.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demuxer.c,v
retrieving revision 1.172
retrieving revision 1.173
diff -u -r1.172 -r1.173
--- demuxer.c	19 Oct 2004 01:21:54 -0000	1.172
+++ demuxer.c	23 Oct 2004 00:05:38 -0000	1.173
@@ -134,6 +134,7 @@
 extern void demux_close_nuv(demuxer_t* demuxer);
 extern void demux_close_audio(demuxer_t* demuxer);
 extern void demux_close_ogg(demuxer_t* demuxer);
+extern void demux_close_mpg(demuxer_t* demuxer);
 extern void demux_close_rtp(demuxer_t* demuxer);
 extern void demux_close_demuxers(demuxer_t* demuxer);
 extern void demux_close_avi(demuxer_t *demuxer);
@@ -232,6 +233,8 @@
     case DEMUXER_TYPE_MPEG_TS:
     case DEMUXER_TYPE_MPEG4_IN_TS:
       demux_close_ts(demuxer); break;
+    case DEMUXER_TYPE_MPEG_PS:
+      demux_close_mpg(demuxer); break;
     case DEMUXER_TYPE_REALAUDIO:
       demux_close_ra(demuxer); break;
 #ifdef USE_LIBAVFORMAT
@@ -616,6 +619,7 @@
 extern void demux_open_nuv(demuxer_t *demuxer);
 extern int demux_audio_open(demuxer_t* demuxer);
 extern int demux_ogg_open(demuxer_t* demuxer);
+extern int demux_mpg_open(demuxer_t* demuxer);
 extern int demux_rawaudio_open(demuxer_t* demuxer);
 extern int demux_rawvideo_open(demuxer_t* demuxer);
 extern int smjpeg_check_file(demuxer_t *demuxer);
@@ -990,7 +994,7 @@
   num_h264_pps=0;
   num_mp3audio_packets=0;
 
-  if(ds_fill_buffer(demuxer->video)){
+  if(demux_mpg_open(demuxer)){
     if(!pes)
       mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_Detected_XXX_FileFormat,"MPEG-PES");
     else




More information about the MPlayer-cvslog mailing list