[xiph-cvs] cvs commit: libshout/src vorbis.c

Michael Smith msmith at xiph.org
Wed Apr 2 04:09:04 PST 2003



msmith      03/04/02 07:09:04

  Modified:    src      vorbis.c
  Log:
  Make vorbis handler in libshout not trust ogg page granulepos values, calculate
  them directly. Neccesary for accurate timing control where there may be
  granulepos gaps (as in a libshout client that optionally takes input from an
  icecast stream).
  
  This needs to be rolled into ices2 at some point, too.

Revision  Changes    Path
1.6       +56 -21    libshout/src/vorbis.c

Index: vorbis.c
===================================================================
RCS file: /usr/local/cvsroot/libshout/src/vorbis.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- vorbis.c	9 Mar 2003 22:56:46 -0000	1.5
+++ vorbis.c	2 Apr 2003 12:09:04 -0000	1.6
@@ -17,12 +17,17 @@
 typedef struct {
         /* total pages broadcasted */
         unsigned int pages;
-	/* the number of samples for the current page */
-	unsigned int samples;
 
-	unsigned int oldsamples;
         unsigned int samplerate;
+
         ogg_sync_state oy;
+    ogg_stream_state os;
+
+    int headers;
+    vorbis_info vi;
+    vorbis_comment vc;
+    int prevW;
+
         long serialno;
 } vorbis_data_t;
 
@@ -46,16 +51,29 @@
         return SHOUTERR_SUCCESS;
 }
 
+static int blocksize(vorbis_data_t *vd, ogg_packet *p)
+{
+    int this = vorbis_packet_blocksize(&vd->vi, p);
+    int ret = (this + vd->prevW)/4;
+
+    if(!vd->prevW)
+    {
+        vd->prevW = this;
+        return 0;
+    }
+
+    vd->prevW = this;
+    return ret;
+}
+
 static int send_vorbis(shout_t *self, const unsigned char *data, size_t len)
 {
         vorbis_data_t *vorbis_data = (vorbis_data_t *)self->format_data;
         int ret;
         char *buffer;
-	ogg_stream_state os;
         ogg_page og;
         ogg_packet op;
-	vorbis_info vi;
-	vorbis_comment vc;
+    int samples;
 
         buffer = ogg_sync_buffer(&vorbis_data->oy, len);
         memcpy(buffer, data, len);
@@ -63,29 +81,46 @@
 
         while (ogg_sync_pageout(&vorbis_data->oy, &og) == 1) {
                 if (vorbis_data->serialno != ogg_page_serialno(&og)) {
-			vorbis_data->serialno = ogg_page_serialno(&og);
 
-			vorbis_data->oldsamples = 0;
+            /* Clear the old one - this is safe even if there was no previous
+             * stream */
+			vorbis_comment_clear(&vorbis_data->vc);
+			vorbis_info_clear(&vorbis_data->vi);
+			ogg_stream_clear(&vorbis_data->os);
 
-			ogg_stream_init(&os, vorbis_data->serialno);
-			ogg_stream_pagein(&os, &og);
-			ogg_stream_packetout(&os, &op);
+			vorbis_data->serialno = ogg_page_serialno(&og);
 
-			vorbis_info_init(&vi);
-			vorbis_comment_init(&vc);
-			vorbis_synthesis_headerin(&vi, &vc, &op);
+			ogg_stream_init(&vorbis_data->os, vorbis_data->serialno);
 
-			vorbis_data->samplerate = vi.rate;
+			vorbis_info_init(&vorbis_data->vi);
+			vorbis_comment_init(&vorbis_data->vc);
 
-			vorbis_comment_clear(&vc);
-			vorbis_info_clear(&vi);
-			ogg_stream_clear(&os);
+            vorbis_data->headers = 1;
                 }
 
-		vorbis_data->samples = ogg_page_granulepos(&og) - vorbis_data->oldsamples;
-		vorbis_data->oldsamples = ogg_page_granulepos(&og);
+        samples = 0;
+
+        ogg_stream_pagein(&vorbis_data->os, &og);
+        while(ogg_stream_packetout(&vorbis_data->os, &op) == 1) {
+            int size;
+
+            if(vorbis_data->headers > 0 && vorbis_data->headers <= 3) {
+			    vorbis_synthesis_headerin(&vorbis_data->vi, &vorbis_data->vc, 
+                        &op);
+                if(vorbis_data->headers == 1)
+        			vorbis_data->samplerate = vorbis_data->vi.rate;
+
+                vorbis_data->headers++;
+                continue;
+            }
+
+            vorbis_data->headers = 0;
+            size = blocksize(vorbis_data, &op);
+            samples += size;
+        }
 
-		self->senttime += ((double)vorbis_data->samples * 1000000 / (double)vorbis_data->samplerate);
+		self->senttime += ((double)samples * 1000000) / 
+                ((double)vorbis_data->samplerate);
 
                 ret = sock_write_bytes(self->socket, og.header, og.header_len);
                 if (ret != og.header_len)

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list