[MPlayer-dev-eng] [PATCH] Timestamps for Ogg Streams correct only for stereo

Wolfram Gloger wmglo at dent.med.uni-muenchen.de
Sun Jun 27 14:39:16 CEST 2004


Hi,

I found that mono Ogg Vorbis streams gave wrong/jumping time stamps in
MPlayer, leading to sync problems.  Please check out:

http://www.xiph.org/ogg/vorbis/doc/vorbis-ogg.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The granule position of pages containing Vorbis audio is in units of
PCM audio samples (per channel; a stereo stream's granule position
does not increment at twice the speed of a mono stream).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Therefore, when computing an artificial "granulepos", given a number
of bytes read from the stream, it is the samplesize in bytes and _not_
the number of channels which is required for the division.  For 16bit
stereo streams, these two numbers coincide, which is probably why
no-one has noticed.

Regards,
Wolfram.

--- libmpdemux/demux_ogg.c.orig	Sat Apr 24 00:30:18 2004
+++ libmpdemux/demux_ogg.c	Sun Jun 27 14:10:15 2004
@@ -313,7 +313,7 @@
 
 }
 
-static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,void *context,float* pts,int* flags) {
+static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,void *context,float* pts,int* flags, int samplesize) {
   unsigned char* data;
 
   *pts = 0;
@@ -328,7 +328,7 @@
        vorbis_info *vi = &((ov_struct_t*)context)->vi;
 
        // When we dump the audio, there is no vi, but we don't care of timestamp in this case
-       int32_t blocksize = vorbis_packet_blocksize(vi,pack) / vi->channels;
+       int32_t 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;
@@ -470,6 +470,7 @@
   float pts = 0;
   int flags = 0;
   void *context = NULL;
+  int samplesize = 1;
 
   // If packet is an comment header then we try to get comments at first
   if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
@@ -501,11 +502,13 @@
 
   // For vorbis packet the packet is the data, for other codec we must jump
   // the header
-  if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == 0xFFFE)
+  if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == 0xFFFE) {
      context = ((sh_audio_t *)ds->sh)->context;
+     samplesize = ((sh_audio_t *)ds->sh)->samplesize;
+  }
   if (ds == d->video && ((sh_audio_t*)ds->sh)->format == 0xFFFC)
      context = ((sh_video_t *)ds->sh)->context;
-  data = demux_ogg_read_packet(os,pack,context,&pts,&flags);
+  data = demux_ogg_read_packet(os,pack,context,&pts,&flags,samplesize);
   if(d->video->id < 0)
       ((sh_audio_t*)ds->sh)->delay = pts;
 
@@ -537,7 +540,7 @@
   ogg_stream_state* oss;
   ogg_stream_t* os;
   ogg_packet op;
-  int np,sid,p;
+  int np,sid,p,samplesize=1;
   void *context = NULL;
   off_t pos, last_pos;
   pos = last_pos = demuxer->movi_start;
@@ -561,8 +564,10 @@
   else {
     sid = demuxer->audio->id;
     /* demux_ogg_read_packet needs decoder context for Vorbis streams */
-    if(((sh_audio_t*)demuxer->audio->sh)->format == 0xFFFE)
+    if(((sh_audio_t*)demuxer->audio->sh)->format == 0xFFFE) {
       context = ((sh_audio_t*)demuxer->audio->sh)->context;
+      samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
+    }
   }
   os = &ogg_d->subs[sid];
   oss = &os->stream;
@@ -597,7 +602,7 @@
     while(ogg_stream_packetout(oss,&op) == 1) {
       float pts;
       int flags;
-      demux_ogg_read_packet(os,&op,context,&pts,&flags);
+      demux_ogg_read_packet(os,&op,context,&pts,&flags,samplesize);
       if(op.granulepos >= 0) ogg_d->final_granulepos = op.granulepos;
       if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
 	ogg_d->syncpoints = (ogg_syncpoint_t*)realloc(ogg_d->syncpoints,(ogg_d->num_syncpoint+1)*sizeof(ogg_syncpoint_t));
@@ -1180,6 +1185,7 @@
   int is_gp_valid;
   float pts;
   int is_keyframe;
+  int samplesize=1;
 
   if(demuxer->video->id >= 0) {
     ds = demuxer->video;
@@ -1194,6 +1200,7 @@
       context = ((sh_audio_t*)demuxer->audio->sh)->context;
     vi = &((ov_struct_t*)((sh_audio_t*)ds->sh)->context)->vi;
     rate = (float)vi->rate;
+    samplesize = ((sh_audio_t*)ds->sh)->samplesize;
   }
 
   os = &ogg_d->subs[ds->id];
@@ -1295,7 +1302,7 @@
         break;
       }
       is_gp_valid = (op.granulepos >= 0);
-      demux_ogg_read_packet(os,&op,context,&pts,&is_keyframe);
+      demux_ogg_read_packet(os,&op,context,&pts,&is_keyframe,samplesize);
       if (precision && is_gp_valid) {
         precision--;
         if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {




More information about the MPlayer-dev-eng mailing list