[MPlayer-dev-eng] [PATCH] correctly calculate ogg duration if streams do not start a 0

Reimar Döffinger Reimar.Doeffinger at gmx.de
Tue Oct 13 19:41:29 CEST 2009


Hello,
attached patch takes care of fixing the displayed duration/percent
position etc. for the file mentioned here:
http://code.google.com/p/gnome-mplayer/issues/detail?id=300
It's a bit ugly but since it's ogg I don't care much...
-------------- next part --------------
Index: libmpdemux/demux_ogg.c
===================================================================
--- libmpdemux/demux_ogg.c	(revision 29770)
+++ libmpdemux/demux_ogg.c	(working copy)
@@ -145,7 +145,9 @@
   ogg_syncpoint_t* syncpoints;
   int num_syncpoint;
   off_t pos, last_size;
+  int64_t initial_granulepos;
   int64_t final_granulepos;
+  int64_t duration;
 
   /* Used for subtitle switching. */
   int n_text;
@@ -263,20 +265,23 @@
   if(os->vorbis) {
     if(*pack->packet & PACKET_TYPE_HEADER)
       os->hdr_packets++;
-    else if (os->vi_initialized)
+    else
     {
        vorbis_info *vi;
-       int32_t blocksize;
+       int32_t blocksize = 0;
 
        // When we dump the audio, there is no vi, but we don't care of timestamp in this case
-       vi = &(os->vi);
+       vi = os->vi_initialized ? &os->vi : NULL;
+       if (vi)
        blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
        // Calculate the timestamp if the packet don't have any
        if(pack->granulepos == -1) {
 	  pack->granulepos = os->lastpos;
 	  if(os->lastsize > 0)
 	     pack->granulepos += os->lastsize;
-       }
+       } else
+         *flags = 1;
+       if (vi)
        *pts = pack->granulepos / (float)vi->rate;
        os->lastsize = blocksize;
        os->lastpos = pack->granulepos;
@@ -521,12 +526,7 @@
   pos = last_pos = demuxer->movi_start;
 
   // Reset the stream
-  if(index_mode == 2) {
   stream_seek(s,demuxer->movi_start);
-  } else {
-    //the 270000 are just a wild guess
-    stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
-  }
   ogg_sync_reset(sync);
 
   // Get the serial number of the stream we use
@@ -574,7 +574,18 @@
       float pts;
       int flags;
       demux_ogg_read_packet(os,&op,&pts,&flags,samplesize);
-      if(op.granulepos >= 0) ogg_d->final_granulepos = op.granulepos;
+      if(op.granulepos >= 0) {
+	ogg_d->final_granulepos = op.granulepos;
+	if(ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
+	  ogg_d->initial_granulepos = op.granulepos;
+	  if (index_mode != 2 && ogg_d->pos < demuxer->movi_end-2*270000) {
+	    //the 270000 are just a wild guess
+	    stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
+	    ogg_sync_reset(sync);
+	    continue;
+	  }
+	}
+      }
       if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
 	if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break;
 	ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t));
@@ -1122,6 +1133,7 @@
   }
 
   ogg_d->final_granulepos=0;
+  ogg_d->initial_granulepos = MP_NOPTS_VALUE;
   if(!s->end_pos)
     demuxer->seekable = 0;
   else {
@@ -1130,6 +1142,9 @@
     demuxer->seekable = 1;
     demux_ogg_scan_stream(demuxer);
   }
+  if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
+    ogg_d->initial_granulepos = 0;
+  ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
 
   mp_msg(MSGT_DEMUX,MSGL_V,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio,n_audio>1?"s":"",n_video,n_video>1?"s":"",ogg_d->n_text,ogg_d->n_text>1?"s":"");
 
@@ -1361,10 +1376,10 @@
   old_pos = ogg_d->pos;
 
   //calculate the granulepos to seek to
-    gp = flags & SEEK_ABSOLUTE ? 0 : os->lastpos;
+    gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
   if(flags & SEEK_FACTOR) {
-    if (ogg_d->final_granulepos > 0)
-      gp += ogg_d->final_granulepos * rel_seek_secs;
+    if (ogg_d->duration > 0)
+      gp += ogg_d->duration * rel_seek_secs;
       else
       gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
   } else
@@ -1391,8 +1406,8 @@
     if(flags & SEEK_FACTOR)
       pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
     else {
-      if (ogg_d->final_granulepos > 0) {
-        pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->final_granulepos / rate);
+      if (ogg_d->duration > 0) {
+        pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
       } else if (os->lastpos > 0) {
       pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
     }
@@ -1547,13 +1562,13 @@
 
     switch(cmd) {
 	case DEMUXER_CTRL_GET_TIME_LENGTH:
-	    if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
-	    *(double *)arg=(double)ogg_d->final_granulepos / rate;
+	    if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
+	    *(double *)arg=(double)(ogg_d->duration) / rate;
 	    return DEMUXER_CTRL_GUESS;
 
 	case DEMUXER_CTRL_GET_PERCENT_POS:
-	    if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
-	    *(int *)arg=(os->lastpos*100) / ogg_d->final_granulepos;
+	    if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
+	    *(int *)arg=((os->lastpos - ogg_d->initial_granulepos)*100) / ogg_d->duration;
 	    return DEMUXER_CTRL_OK;
 
 	default:


More information about the MPlayer-dev-eng mailing list