[MPlayer-dev-eng] Patch for correct seek in MPEG files with pts offset != 0

Yaro Pollak slava at plris.com
Mon Jul 18 10:48:19 CEST 2005


Hello friends, 

Following my post in MPlayer-users I'm posting the changes I made to demux_mpg.c in order to correct a problem, where seeking was done incorrectly (or not done at all) in MPEG-PS files that started with initial pts > 0. I'm not sure if this is the best solution (as the time stamps remain absolute, and not 0-based, it looks as if the movie started from the middle, but at least the seek works now).

Cheers!
Yaro


--- demux_mpgo.c 2005-07-10 12:36:50.000000000 +0200
+++ demux_mpg.c 2005-07-18 09:57:04.000000000 +0200
@@ -29,6 +29,7 @@
 
 typedef struct mpg_demuxer {
   float last_pts;
+  float start_pts;
   float final_pts;
   int has_valid_timestamps;
   unsigned int es_map[0x40]; //es map of stream types (associated to the pes id) from 0xb0 to 0xef
@@ -109,10 +110,15 @@
   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->start_pts = 0.0;
   mpg_d->final_pts = 0.0;
   mpg_d->has_valid_timestamps = 1;
   mpg_d->num_a_streams = 0;
   if (demuxer->seekable && stream_tell(demuxer->stream) < end_seq_start) {
+    stream_seek(s,pos);
+    while ((!s->eof) && ds_fill_buffer(demuxer->video) && mpg_d->start_pts == 0.0) {
+      mpg_d->start_pts = mpg_d->last_pts;
+    }
     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;
@@ -122,9 +128,12 @@
       if (mpg_d->final_pts < mpg_d->last_pts) mpg_d->final_pts = mpg_d->last_pts;
     }
     // educated guess about validity of timestamps
+    mpg_d->final_pts -= mpg_d->start_pts;
+    half_pts -= mpg_d->start_pts;
     if (mpg_d->final_pts > 3 * half_pts || mpg_d->final_pts < 1.5 * half_pts) {
       mpg_d->has_valid_timestamps = 0;
     }
+    mpg_d->final_pts += mpg_d->start_pts;
     ds_free_packs(demuxer->audio);
     ds_free_packs(demuxer->video);
     demuxer->stream->eof=0; // clear eof flag
@@ -528,7 +537,7 @@
   //calculate the pts to seek to
     if(flags & 2) {
       if (mpg_d && mpg_d->final_pts > 0.0)
-        newpts += mpg_d->final_pts * rel_seek_secs;
+        newpts += (mpg_d->final_pts - mpg_d->start_pts) * rel_seek_secs;
       else
         newpts += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * oldpts / oldpos;
     } else
@@ -542,9 +551,9 @@
  // time seek (secs)
         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;
+            newpos += (rel_seek_secs - mpg_d->start_pts) * (demuxer->movi_end - demuxer->movi_start) / (mpg_d->final_pts - mpg_d->start_pts);
           else if (oldpts > 0.0)
-            newpos += rel_seek_secs * (oldpos - demuxer->movi_start) / oldpts;
+            newpos += (rel_seek_secs - mpg_d->start_pts) * (oldpos - demuxer->movi_start) / (oldpts - mpg_d->start_pts);
         } else if(!sh_video || !sh_video->i_bps) // unspecified or VBR
           newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec
         else
@@ -625,14 +637,14 @@
     switch(cmd) {
  case DEMUXER_CTRL_GET_TIME_LENGTH:
             if (mpg_d && mpg_d->has_valid_timestamps) {
-              *((unsigned long *)arg)=(long)mpg_d->final_pts;
+              *((unsigned long *)arg)=(long)(mpg_d->final_pts - mpg_d->start_pts);
               return DEMUXER_CTRL_GUESS;
             }
       return DEMUXER_CTRL_DONTKNOW;
 
  case DEMUXER_CTRL_GET_PERCENT_POS:
             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);
+              *((int *)arg)=(int)(100 * (mpg_d->last_pts - mpg_d->start_pts) / (mpg_d->final_pts - mpg_d->start_pts));
               return DEMUXER_CTRL_OK;
             }
      return DEMUXER_CTRL_DONTKNOW; 


More information about the MPlayer-dev-eng mailing list