[xiph-commits] r8340 - in icecast/branches/kh/icecast: . doc src

karl at motherfish-iii.xiph.org karl at motherfish-iii.xiph.org
Tue Dec 7 12:25:03 PST 2004


Author: karl
Date: 2004-12-07 12:25:02 -0800 (Tue, 07 Dec 2004)
New Revision: 8340

Modified:
   icecast/branches/kh/icecast/configure.in
   icecast/branches/kh/icecast/doc/icecast2_config_file.html
   icecast/branches/kh/icecast/src/cfgfile.c
   icecast/branches/kh/icecast/src/cfgfile.h
   icecast/branches/kh/icecast/src/format.h
   icecast/branches/kh/icecast/src/format_mp3.c
   icecast/branches/kh/icecast/src/format_ogg.c
   icecast/branches/kh/icecast/src/format_ogg.h
   icecast/branches/kh/icecast/src/format_theora.c
   icecast/branches/kh/icecast/src/format_vorbis.c
   icecast/branches/kh/icecast/src/source.c
   icecast/branches/kh/icecast/src/stats.c
Log:
update ogg format handler, removed unused code, drop ogg xml option as it is
handled automatically now


Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/configure.in	2004-12-07 20:25:02 UTC (rev 8340)
@@ -83,14 +83,13 @@
     [AC_MSG_ERROR([must have Ogg Vorbis v1.0 or above installed])
     ])
 
-
 XIPH_PATH_THEORA([
     XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$THEORA_CFLAGS])
     XIPH_VAR_APPEND([XIPH_LDFLAGS],[$THEORA_LDFLAGS])
     XIPH_VAR_PREPEND([XIPH_LIBS],[$THEORA_LIBS])
     ICECAST_OPTIONAL="$ICECAST_OPTIONAL format_theora.o"
     ],
-    [ AC_MSG_WARN([Theora not found, disabled!])
+    [ AC_MSG_WARN([Theora disabled!])
     ])
 
 XIPH_PATH_SPEEX(

Modified: icecast/branches/kh/icecast/doc/icecast2_config_file.html
===================================================================
--- icecast/branches/kh/icecast/doc/icecast2_config_file.html	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/doc/icecast2_config_file.html	2004-12-07 20:25:02 UTC (rev 8340)
@@ -353,7 +353,6 @@
         <hidden>1</hidden>
         <burst-size>65536</burst-size>
         <mp3-metadata-interval>8192</mp3-metadata-interval>
-        <ogg-rebuild>1</ogg-rebuild>
         <authentication type="htpasswd">
                 <option name="filename" value="myauth"/>
                 <option name="allow_duplicate_users" value="0"/>
@@ -429,15 +428,6 @@
 is sent every so many bytes, this setting allows for overriding the default for this
 mountpoint. A value of 0 means no metadata is sent to the client even if icecast receives it.
 </div>
-<h4>ogg-rebuild</h4>
-<div class="indentedbox">
-In certain situations some people may prefer to use URL updating of artist/title, this
-requires the stream to be rebuilt.  Even if url updates are not wanted, some may want the
-stream to be rebuilt as the source client/relay may be producing ogg pages that have too
-many samples causing larger, more infrequent writes on low bandwidth streams. The url
-updating mechanism is disabled if multiple codecs are used as not all logical streams
-can be rebuilt.
-</div>
 <h4>authentication</h4>
 <div class="indentedbox">
 This specifies that the named mount point will require listener authentication.  Currently, we only support a file-based authentication scheme (type=htpasswd).  Users and encrypted password are placed in this file (separated by a :) and all requests for this mountpoint will require that a user and password be supplied for authentication purposes.  These values are passed in via normal HTTP Basic Authentication means (i.e. http://user:password@stream:port/mountpoint.ogg).  Users and Passwords are maintained via the web admin interface.  A mountpoint configured with an authenticator will display a red key next to the mount point name on the admin screens.  You can read more about listener authentication <a href="icecast2_listenerauth.html">here</a>.

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2004-12-07 20:25:02 UTC (rev 8340)
@@ -604,11 +604,6 @@
             mount->mp3_meta_interval = atoi(tmp);
             if(tmp) xmlFree(tmp);
         }
-        else if (strcmp(node->name, "ogg-rebuild") == 0) {
-            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
-            mount->ogg_rebuild = atoi(tmp);
-            if(tmp) xmlFree(tmp);
-        }
         else if (strcmp(node->name, "hidden") == 0) {
             tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
             mount->hidden = atoi(tmp);

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2004-12-07 20:25:02 UTC (rev 8340)
@@ -65,7 +65,6 @@
     int hidden; /* Do we list this on the xsl pages */
     unsigned int source_timeout;  /* source timeout in seconds */
     int mp3_meta_interval; /* outgoing per-stream metadata interval */
-    int ogg_rebuild;
 
     char *auth_type; /* Authentication type */
     config_options_t *auth_options; /* Options for this type */

Modified: icecast/branches/kh/icecast/src/format.h
===================================================================
--- icecast/branches/kh/icecast/src/format.h	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/format.h	2004-12-07 20:25:02 UTC (rev 8340)
@@ -47,7 +47,6 @@
     int (*create_client_data)(struct source_tag *source, client_t *client);
     void (*set_tag)(struct _format_plugin_tag *plugin, char *tag, char *value);
     void (*free_plugin)(struct _format_plugin_tag *self);
-    void (*prerelease)(struct source_tag *source, refbuf_t *refbuf);
     void (*apply_settings)(struct source_tag *source, struct _mount_proxy *mount);
 
     /* for internal state management */

Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/format_mp3.c	2004-12-07 20:25:02 UTC (rev 8340)
@@ -89,7 +89,6 @@
     plugin->create_client_data = format_mp3_create_client_data;
     plugin->free_plugin = format_mp3_free_plugin;
     plugin->set_tag = mp3_set_tag;
-    plugin->prerelease = NULL;
     plugin->apply_settings = format_mp3_apply_settings;
 
     plugin->contenttype = httpp_getvar (source->parser, "content-type");
@@ -101,7 +100,7 @@
     plugin->_state = state;
 
     /* initial metadata needs to be blank for sending to clients and for
-        comparing with new metadata */
+       comparing with new metadata */
     meta = refbuf_new (2);
     memcpy (meta->data, "\0\0", 2);
     meta->len = 1;
@@ -181,6 +180,7 @@
             if (p)
             {
                 memcpy (p, metadata+13, len);
+                logging_playlist (source->mount, p, source->listeners);
                 stats_event (source->mount, "title", p);
                 yp_touch (source->mount);
                 free (p);

Modified: icecast/branches/kh/icecast/src/format_ogg.c
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.c	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/format_ogg.c	2004-12-07 20:25:02 UTC (rev 8340)
@@ -11,10 +11,10 @@
  */
 
 /* format_ogg.c
-**
-** format plugin for Ogg
-**
-*/
+ *
+ * format plugin for Ogg
+ *
+ */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -49,7 +49,6 @@
 static void format_ogg_free_plugin (format_plugin_t *plugin);
 static int  create_ogg_client_data(source_t *source, client_t *client);
 static void free_ogg_client_data (client_t *client);
-static void format_ogg_apply_settings (source_t *source, mount_proxy *mount);
 
 static void write_ogg_to_file (struct source_tag *source, refbuf_t *refbuf);
 static refbuf_t *ogg_get_buffer (source_t *source);
@@ -65,24 +64,6 @@
 };
 
 
-void refbuf_page_prerelease (struct source_tag *source, refbuf_t *refbuf)
-{
-    ogg_state_t *ogg_info = source->format->_state;
-
-    /* only theora will be marking refbufs as sync that are behind in the
-     * queue, here we just make sure that it isn't the one we are going to
-     * remove. */
-    if (ogg_info->codec_sync)
-    {
-        if (ogg_info->codec_sync->possible_start == refbuf)
-        {
-            refbuf_release (refbuf);
-            ogg_info->codec_sync->possible_start = NULL;
-        }
-    }
-}
-
-
 refbuf_t *make_refbuf_with_page (ogg_page *page)
 {
     refbuf_t *refbuf = refbuf_new (page->header_len + page->body_len);
@@ -93,10 +74,24 @@
 }
 
 
+/* routine for taking the provided page (should be a header page) and
+ * placing it on the collection of header pages
+ */
 void format_ogg_attach_header (ogg_state_t *ogg_info, ogg_page *page)
 {
     refbuf_t *refbuf = make_refbuf_with_page (page);
 
+    if (ogg_page_bos (page))
+    {
+        DEBUG0 ("attaching BOS page");
+        if (*ogg_info->bos_end == NULL)
+            ogg_info->header_pages_tail = refbuf;
+        refbuf->next = *ogg_info->bos_end;
+        *ogg_info->bos_end = refbuf;
+        ogg_info->bos_end = &refbuf->next;
+        return;
+    }
+    DEBUG0 ("attaching header page");
     if (ogg_info->header_pages_tail)
         ogg_info->header_pages_tail->next = refbuf;
     ogg_info->header_pages_tail = refbuf;
@@ -106,14 +101,10 @@
 }
 
 
-
-static void free_ogg_codecs (ogg_state_t *ogg_info)
+void format_ogg_free_headers (ogg_state_t *ogg_info)
 {
-    ogg_codec_t *codec;
     refbuf_t *header;
 
-    if (ogg_info == NULL)
-        return;
     /* release the header pages first */
     DEBUG0 ("releasing header pages");
     header = ogg_info->header_pages;
@@ -125,7 +116,20 @@
     }
     ogg_info->header_pages = NULL;
     ogg_info->header_pages_tail = NULL;
+    ogg_info->bos_end = &ogg_info->header_pages;
+}
 
+
+/* release the memory used for the codec and header pages from the module */
+static void free_ogg_codecs (ogg_state_t *ogg_info)
+{
+    ogg_codec_t *codec;
+
+    if (ogg_info == NULL)
+        return;
+
+    format_ogg_free_headers (ogg_info);
+
     /* now free the codecs */
     codec = ogg_info->codecs;
     DEBUG0 ("freeing codecs");
@@ -137,7 +141,7 @@
     }
     ogg_info->codecs = NULL;
     ogg_info->current = NULL;
-    ogg_info->headers_completed = 0;
+    ogg_info->bos_completed = 0;
 }
 
 
@@ -154,9 +158,7 @@
     plugin->write_buf_to_file = write_ogg_to_file;
     plugin->create_client_data = create_ogg_client_data;
     plugin->free_plugin = format_ogg_free_plugin;
-    plugin->apply_settings = format_ogg_apply_settings;
     plugin->set_tag = NULL;
-    plugin->prerelease = refbuf_page_prerelease;
     plugin->contenttype = "application/ogg";
 
     ogg_sync_init (&state->oy);
@@ -164,6 +166,7 @@
     plugin->_state = state;
     source->format = plugin;
     state->mount = source->mount;
+    state->bos_end = &state->header_pages;
 
     return 0;
 }
@@ -178,22 +181,20 @@
     free (state->artist);
     free (state->title);
 
-    /* free state memory */
     ogg_sync_clear (&state->oy);
     free (state);
 
-    /* free the plugin instance */
     free (plugin);
 }
 
 
-
+/* a new BOS page has been seen so check which codec it is */
 static int process_initial_page (format_plugin_t *plugin, ogg_page *page)
 {
     ogg_state_t *ogg_info = plugin->_state;
     ogg_codec_t *codec;
 
-    if (ogg_info->headers_completed)
+    if (ogg_info->bos_completed)
     {
         ogg_info->bitrate = 0;
         ogg_info->codec_sync = NULL;
@@ -231,7 +232,10 @@
 }
 
 
-
+/* This is called when there has been a change in the metadata. Usually
+ * artist and title are provided separately so here we update the stats
+ * and write log entry if required.
+ */
 static void update_comments (source_t *source)
 {
     ogg_state_t *ogg_info = source->format->_state;
@@ -271,11 +275,13 @@
     }
     stats_event (source->mount, "artist", artist);
     stats_event (source->mount, "title", title);
-    DEBUG0 ("running touch");
     yp_touch (source->mount);
 }
 
 
+/* called when preparing a refbuf with audio data to be passed
+ * back for queueing
+ */
 static refbuf_t *complete_buffer (source_t *source, refbuf_t *refbuf)
 {
     ogg_state_t *ogg_info = source->format->_state;
@@ -293,12 +299,17 @@
         update_comments (source);
         ogg_info->log_metadata = 0;
     }
+    /* listeners can start anywhere unless the codecs themselves are
+     * marking starting points */
     if (ogg_info->codec_sync == NULL)
         refbuf->sync_point = 1;
     return refbuf;
 }
 
 
+/* process the incoming page. this requires searching through the
+ * currently known codecs that have been seen in the stream
+ */
 static refbuf_t *process_ogg_page (ogg_state_t *ogg_info, ogg_page *page)
 {
     ogg_codec_t *codec = ogg_info->codecs;
@@ -320,7 +331,10 @@
 }
 
 
-
+/* main plugin handler for getting a buffer for the queue. In here we
+ * just add an incoming page to the codecs and process it until either
+ * more data is needed or we prodice a buffer for the queue.
+ */
 static refbuf_t *ogg_get_buffer (source_t *source)
 {
     ogg_state_t *ogg_info = source->format->_state;
@@ -335,6 +349,7 @@
             refbuf_t *refbuf;
             ogg_codec_t *codec = ogg_info->current;
 
+            /* if a codec has just been given a page then process it */
             if (codec && codec->process)
             {
                 refbuf = codec->process (ogg_info, codec);
@@ -351,7 +366,7 @@
                     process_initial_page (source->format, &page);
                     continue;
                 }
-                ogg_info->headers_completed = 1;
+                ogg_info->bos_completed = 1;
                 refbuf = process_ogg_page (ogg_info, &page);
                 if (ogg_info->error)
                 {
@@ -414,7 +429,9 @@
 }
 
 
-
+/* send out the header pages. These are for all codecs but are
+ * in the order for the stream, ie BOS pages first
+ */
 static int send_ogg_headers (client_t *client, refbuf_t *headers)
 {
     struct ogg_client *client_data = client->format_data;
@@ -453,6 +470,9 @@
 }
 
 
+/* main client write routine for sending ogg data. Each refbuf has a
+ * single page so we only need to determine if there are new headers
+ */
 static int write_buf_to_client (source_t *source, client_t *client)
 {
     refbuf_t *refbuf = client->refbuf;
@@ -531,15 +551,4 @@
     write_ogg_data (source, refbuf);
 }
 
-static void format_ogg_apply_settings (source_t *source, mount_proxy *mount)
-{
-    ogg_state_t *ogg_info = source->format->_state;
 
-    ogg_info->rebuild = 0;
-    if (mount->ogg_rebuild)
-    {
-        ogg_info->rebuild = 1;
-        DEBUG0 ("rebuilding stream enabled");
-    }
-}
-

Modified: icecast/branches/kh/icecast/src/format_ogg.h
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.h	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/format_ogg.h	2004-12-07 20:25:02 UTC (rev 8340)
@@ -35,8 +35,8 @@
     refbuf_t *file_headers;
     refbuf_t *header_pages;
     refbuf_t *header_pages_tail;
-    int headers_completed;
-    int rebuild;
+    refbuf_t **bos_end;
+    int bos_completed;
     long bitrate;
     struct ogg_codec_tag *current;
     struct ogg_codec_tag *codec_sync;
@@ -62,6 +62,7 @@
 
 refbuf_t *make_refbuf_with_page (ogg_page *page);
 void format_ogg_attach_header (ogg_state_t *ogg_info, ogg_page *page);
+void format_ogg_free_headers (ogg_state_t *ogg_info);
 int format_ogg_get_plugin (source_t *source);
 
 #endif  /* __FORMAT_OGG_H__ */

Modified: icecast/branches/kh/icecast/src/format_theora.c
===================================================================
--- icecast/branches/kh/icecast/src/format_theora.c	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/format_theora.c	2004-12-07 20:25:02 UTC (rev 8340)
@@ -59,92 +59,69 @@
 }
 
 
-static int _ilog (unsigned int v)
-{ 
-  int ret=0;
-  while(v){
-    ret++;
-    v>>=1;
-  }
-  return ret;
-}
-
-
+/* theora pages are not rebuilt, so here we just for headers and then
+ * pass them straight through to the the queue
+ */
 static refbuf_t *process_theora_page (ogg_state_t *ogg_info, ogg_codec_t *codec, ogg_page *page)
 {
-    refbuf_t *refbuf;
     theora_codec_t *theora = codec->specific;
+    ogg_packet packet;
+    int header_page = 0;
+    int has_keyframe = 0;
+    refbuf_t *refbuf = NULL;
     ogg_int64_t granulepos;
 
-    granulepos = ogg_page_granulepos (page);
-    if (codec->headers < 3)
+    if (ogg_stream_pagein (&codec->os, page) < 0)
     {
-        ogg_packet packet;
+        ogg_info->error = 1;
+        return NULL;
+    }
+    granulepos = ogg_page_granulepos (page);
 
-        ogg_stream_pagein (&codec->os, page);
-        while (ogg_stream_packetout (&codec->os, &packet) > 0)
+    while (ogg_stream_packetout (&codec->os, &packet) > 0)
+    {
+        if (theora_packet_isheader (&packet))
         {
-           if (theora_packet_isheader (&packet) == 0 || 
-                   theora_decode_header (&theora->ti, &theora->tc, &packet) < 0)
-           {
-               ogg_info->error = 1;
-               WARN0 ("problem with theora header");
-               return NULL;
-           }
-           codec->headers++;
-           if (codec->headers == 3)
-           {
-               theora->granule_shift = _ilog (theora->ti.keyframe_frequency_force - 1);
-               DEBUG1 ("granule shift is %lu", theora->granule_shift);
-               theora->last_iframe = (ogg_int64_t)-1;
-               codec->possible_start = NULL;
-               ogg_info->bitrate += theora->ti.target_bitrate;
-               stats_event_args (ogg_info->mount, "video_bitrate",
-                       "%ld", (long)theora->ti.target_bitrate);
-               stats_event_args (ogg_info->mount, "frame_size",
-                       "%ld x %ld", (long)theora->ti.frame_width, (long)theora->ti.frame_height);
-               stats_event_args (ogg_info->mount, "framerate",
-                       "%.2f", (float)theora->ti.fps_numerator/theora->ti.fps_denominator);
-           }
+            if (theora_decode_header (&theora->ti, &theora->tc, &packet) < 0)
+            {
+                ogg_info->error = 1;
+                WARN0 ("problem with theora header");
+                return NULL;
+            }
+            header_page = 1;
+            codec->headers++;
+            continue;
         }
-        /* add page to associated list */
+        if (codec->headers < 3)
+        {
+            ogg_info->error = 1;
+            ERROR0 ("Not enough header packets");
+            return NULL;
+        }
+        if (theora_packet_iskeyframe (&packet))
+            has_keyframe = 1;
+    }
+    if (header_page)
+    {
         format_ogg_attach_header (ogg_info, page);
-
         return NULL;
     }
+
     refbuf = make_refbuf_with_page (page);
-    refbuf->sync_point = 1;
+    /* DEBUG3 ("refbuf %p has pageno %ld, %llu", refbuf, ogg_page_pageno (page), (uint64_t)granulepos); */
 
-    if (granulepos == -1 || granulepos == theora->prev_granulepos)
+    if (has_keyframe && codec->possible_start)
     {
-        if (codec->possible_start == NULL)
-        {
-            refbuf_addref (refbuf);
-            codec->possible_start = refbuf;
-        }
+        codec->possible_start->sync_point = 1;
+        refbuf_release (codec->possible_start);
+        codec->possible_start = NULL;
     }
-    else
+    if (granulepos != theora->prev_granulepos || granulepos == 0)
     {
-        if ((granulepos >> theora->granule_shift) != theora->last_iframe)
-        {
-            theora->last_iframe = (granulepos >> theora->granule_shift);
-            if (codec->possible_start == NULL)
-            {
-                refbuf_addref (refbuf);
-                codec->possible_start = refbuf;
-            }
-            codec->possible_start->sync_point = 1;
-        }
-        else
-        {
-            if (theora->prev_granulepos != -1)
-            {
-                if (codec->possible_start)
-                    refbuf_release (codec->possible_start);
-                refbuf_addref (refbuf);
-                codec->possible_start = refbuf;
-            }
-        }
+        if (codec->possible_start)
+            refbuf_release (codec->possible_start);
+        refbuf_addref (refbuf);
+        codec->possible_start = refbuf;
     }
     theora->prev_granulepos = granulepos;
 
@@ -152,6 +129,9 @@
 }
 
 
+/* Check if specified BOS page is the start of a theora stream and
+ * if so, create a codec structure for handling it
+ */
 ogg_codec_t *initial_theora_page (format_plugin_t *plugin, ogg_page *page)
 {
     ogg_state_t *ogg_info = plugin->_state;
@@ -184,6 +164,7 @@
     codec->codec_free = theora_codec_free;
     codec->headers = 1;
     format_ogg_attach_header (ogg_info, page);
+    ogg_info->codec_sync = codec;
     return codec;
 }
 

Modified: icecast/branches/kh/icecast/src/format_vorbis.c
===================================================================
--- icecast/branches/kh/icecast/src/format_vorbis.c	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/format_vorbis.c	2004-12-07 20:25:02 UTC (rev 8340)
@@ -51,6 +51,7 @@
     int prev_window;
     int initial_audio_packet;
 
+    ogg_page bos_page;
     ogg_packet *header [3];
     ogg_int64_t prev_page_samples;
 
@@ -64,8 +65,6 @@
                 ogg_codec_t *codec, ogg_page *page);
 static refbuf_t *process_vorbis (ogg_state_t *ogg_info, ogg_codec_t *codec);
 static void vorbis_set_tag (format_plugin_t *plugin, char *tag, char *value);
-static refbuf_t *vorbis_page (ogg_state_t *ogg_info,
-        ogg_codec_t *codec, ogg_page *page);
 
 
 static void free_ogg_packet (ogg_packet *packet)
@@ -94,6 +93,7 @@
     free_ogg_packet (vorbis->header[1]);
     free_ogg_packet (vorbis->header[2]);
     free_ogg_packet (vorbis->prev_packet);
+    free (vorbis->bos_page.header);
     free (vorbis);
     free (codec);
 }
@@ -147,12 +147,10 @@
     int (*get_ogg_page)(ogg_stream_state*, ogg_page *) = ogg_stream_pageout;
 
     if (source_vorbis->samples_in_page > source_vorbis->page_samples_trigger)
-    {
         get_ogg_page = ogg_stream_flush;
-    }
+
     if (get_ogg_page (&source_vorbis->new_os, &page) > 0)
     {
-        /* printf ("got audio page %lld\n", ogg_page_granulepos (&page)); */
         /* squeeze a page copy into a buffer */
         source_vorbis->samples_in_page -= (ogg_page_granulepos (&page) - source_vorbis->prev_page_samples);
         source_vorbis->prev_page_samples = ogg_page_granulepos (&page);
@@ -176,7 +174,6 @@
     }
     if (headers_flushed)
     {
-        /* printf ("headers have now been handled\n"); */
         source_vorbis->get_buffer_page = get_buffer_audio;
     }
     return NULL;
@@ -191,8 +188,6 @@
 
     if (ogg_stream_flush (&source_vorbis->new_os, &page) > 0)
     {
-        /* printf ("EOS stream flush %lld\n", ogg_page_granulepos (&page)); */
-
         source_vorbis->samples_in_page -= (ogg_page_granulepos (&page) - source_vorbis->prev_page_samples);
         source_vorbis->prev_page_samples = ogg_page_granulepos (&page);
 
@@ -203,17 +198,12 @@
     ogg_stream_clear (&source_vorbis->new_os);
     ogg_stream_init (&source_vorbis->new_os, rand());
 
-    refbuf = ogg_info->header_pages;
-    while (refbuf)
-    {
-        refbuf_t *to_go = refbuf;
-        refbuf = refbuf->next;
-        refbuf_release (to_go);
-    }
-    ogg_info->header_pages = NULL;
-    ogg_info->header_pages_tail = NULL;
+    format_ogg_free_headers (ogg_info);
     source_vorbis->get_buffer_page = NULL;
     source_vorbis->process_packet = process_vorbis_headers;
+    if (source_vorbis->initial_audio_packet == 0)
+        source_vorbis->prev_window = 0;
+
     return NULL;
 }
 
@@ -234,11 +224,13 @@
 }
 
 
-
+/* process the vorbis audio packets. Here we just take each packet out 
+ * and add them into the new stream, flushing after so many samples. We
+ * also check if an new headers are requested after each processed page
+ */
 static int process_vorbis_audio (ogg_state_t *ogg_info, ogg_codec_t *codec)
 {
     vorbis_codec_t *source_vorbis = codec->specific;
-    int result = 0;
 
     while (1)
     {
@@ -247,7 +239,7 @@
 
         /* now, lets extract what packets we can */
         if (ogg_stream_packetout (&codec->os, &packet) <= 0)
-            return result;
+            break;
 
         /* calculate granulepos for the packet */
         window = vorbis_packet_blocksize (&source_vorbis->vi, &packet) / 4;
@@ -256,8 +248,7 @@
         if (source_vorbis->prev_packet)
         {
             ogg_packet *prev_packet = source_vorbis->prev_packet;
-            if (packet.b_o_s)
-                prev_packet->e_o_s = 1;
+
             add_audio_packet (source_vorbis, prev_packet);
             free_ogg_packet (prev_packet);
             packet . granulepos = source_vorbis->granulepos;
@@ -266,25 +257,32 @@
         {
             packet . granulepos = 0;
         }
-        source_vorbis->prev_window = window;
 
-        /* copy the next packet */
+        /* store the current packet details */
+        source_vorbis->prev_window = window;
         source_vorbis->prev_packet = copy_ogg_packet (&packet);
-
-        if (source_vorbis->stream_notify)
+        if (packet.e_o_s)
         {
             initiate_flush (source_vorbis);
-            source_vorbis->stream_notify = 0;
+            return 1;
         }
 
         /* allow for pages to be flushed if there's over a certain number of samples */
         if (source_vorbis->samples_in_page > source_vorbis->page_samples_trigger)
             return 1;
     }
+    if (source_vorbis->stream_notify)
+    {
+        initiate_flush (source_vorbis);
+        source_vorbis->stream_notify = 0;
+    }
+    return -1;
 }
 
 
-/* handle the headers we want going to the clients */
+/* This handles the headers at the backend, here we insert the header packets
+ * we want for the queue.
+ */
 static int process_vorbis_headers (ogg_state_t *ogg_info, ogg_codec_t *codec)
 {
     vorbis_codec_t *source_vorbis = codec->specific;
@@ -320,128 +318,73 @@
     ogg_info->log_metadata = 1;
     source_vorbis->get_buffer_page = get_buffer_header;
     source_vorbis->process_packet = process_vorbis_audio;
-    source_vorbis->granulepos = 0;
+    source_vorbis->granulepos = source_vorbis->prev_window;
     source_vorbis->initial_audio_packet = 1;
     return 1;
 }
 
 
-/* this is called with the first page after the initial header */
-/* it processes any headers that have come in on the stream */
-static int process_vorbis_incoming_hdrs (ogg_state_t *ogg_info, ogg_codec_t *codec)
-{
-    ogg_packet header;
-    vorbis_codec_t *source_vorbis = codec->specific;
-    char *comment;
-
-    DEBUG1 ("processing incoming header packet (%d)", codec->headers);
-    while (codec->headers < 3)
-    {
-        /* now, lets extract the packets */
-        int result = ogg_stream_packetout (&codec->os, &header);
-
-        if (result <= 0)
-            return -1;   /* need more pages */
-
-        /* change comments here if need be */
-        if (vorbis_synthesis_headerin (&source_vorbis->vi, &source_vorbis->vc, &header) < 0)
-        {
-            ogg_info->error = 1;
-            WARN0 ("Problem parsing ogg vorbis header");
-            return -1;
-        }
-        header.granulepos = 0;
-        source_vorbis->header [codec->headers] = copy_ogg_packet (&header);
-        codec->headers++;
-    }
-    DEBUG0 ("we have the header packets now");
-
-    /* we have all headers */
-    free (ogg_info->title);
-    comment = vorbis_comment_query (&source_vorbis->vc, "TITLE", 0);
-    if (comment)
-        ogg_info->title = strdup (comment);
-    else
-        ogg_info->title = NULL;
-
-    free (ogg_info->artist);
-    comment = vorbis_comment_query (&source_vorbis->vc, "ARTIST", 0);
-    if (comment)
-        ogg_info->artist = strdup (comment);
-    else
-        ogg_info->artist = NULL;
-    ogg_info->log_metadata = 1;
-
-    stats_event_args (ogg_info->mount, "audio-samplerate", "%ld", (long)source_vorbis->vi.rate);
-    stats_event_args (ogg_info->mount, "audio-channels", "%ld", (long)source_vorbis->vi.channels);
-    stats_event_args (ogg_info->mount, "audio-bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal);
-    stats_event_args (ogg_info->mount, "ice-bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal/1000);
-
-    /* set queued pages to contain a 1/4 of a second worth of samples */
-    source_vorbis->page_samples_trigger = source_vorbis->vi.rate / 4;
-
-    source_vorbis->process_packet = process_vorbis_headers;
-
-    return 1;
-}
-
-
+/* check if the provided BOS page is the start of a vorbis stream. If so
+ * then setup a structure so it can be used
+ */
 ogg_codec_t *initial_vorbis_page (format_plugin_t *plugin, ogg_page *page)
 {
-    ogg_state_t *ogg_info = plugin->_state;
+    // ogg_state_t *ogg_info = plugin->_state;
     ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t));
     ogg_packet packet;
 
-    vorbis_codec_t *source_vorbis = calloc (1, sizeof (vorbis_codec_t));
+    vorbis_codec_t *vorbis = calloc (1, sizeof (vorbis_codec_t));
 
     ogg_stream_init (&codec->os, ogg_page_serialno (page));
     ogg_stream_pagein (&codec->os, page);
 
-    vorbis_info_init (&source_vorbis->vi);
-    vorbis_comment_init (&source_vorbis->vc);
+    vorbis_info_init (&vorbis->vi);
+    vorbis_comment_init (&vorbis->vc);
 
     ogg_stream_packetout (&codec->os, &packet);
 
     DEBUG0("checking for vorbis codec");
-    if (vorbis_synthesis_headerin (&source_vorbis->vi, &source_vorbis->vc, &packet) < 0)
+    if (vorbis_synthesis_headerin (&vorbis->vi, &vorbis->vc, &packet) < 0)
     {
         ogg_stream_clear (&codec->os);
-        vorbis_info_clear (&source_vorbis->vi);
-        vorbis_comment_clear (&source_vorbis->vc);
-        free (source_vorbis);
+        vorbis_info_clear (&vorbis->vi);
+        vorbis_comment_clear (&vorbis->vc);
+        free (vorbis);
         free (codec);
         return NULL;
     }
     INFO0 ("seen initial vorbis header");
-    codec->specific = source_vorbis;
+    codec->specific = vorbis;
     codec->codec_free = vorbis_codec_free;
     codec->headers = 1;
 
-    /* */
-    if (ogg_info->rebuild)
-    {
-        free_ogg_packet (source_vorbis->header[0]);
-        free_ogg_packet (source_vorbis->header[1]);
-        free_ogg_packet (source_vorbis->header[2]);
-        memset (source_vorbis->header, 0, sizeof (source_vorbis->header));
-        source_vorbis->header [0] = copy_ogg_packet (&packet);
-        ogg_stream_init (&source_vorbis->new_os, rand());
+    free_ogg_packet (vorbis->header[0]);
+    free_ogg_packet (vorbis->header[1]);
+    free_ogg_packet (vorbis->header[2]);
+    memset (vorbis->header, 0, sizeof (vorbis->header));
+    vorbis->header [0] = copy_ogg_packet (&packet);
+    ogg_stream_init (&vorbis->new_os, rand());
 
-        codec->process_page = process_vorbis_page;
-        codec->process = process_vorbis;
-        plugin->set_tag = vorbis_set_tag;
-        source_vorbis->process_packet = process_vorbis_incoming_hdrs;
-    }
-    else
-    {
-        codec->process_page = vorbis_page;
-        format_ogg_attach_header (ogg_info, page);
-    }
+    codec->process_page = process_vorbis_page;
+    codec->process = process_vorbis;
+    plugin->set_tag = vorbis_set_tag;
+
+    vorbis->bos_page.header = malloc (page->header_len + page->body_len);
     
+    memcpy (vorbis->bos_page.header, page->header, page->header_len);
+    vorbis->bos_page.header_len = page->header_len;
+
+    vorbis->bos_page.body = vorbis->bos_page.header + page->header_len;
+    memcpy (vorbis->bos_page.body, page->body, page->body_len);
+    vorbis->bos_page.body_len = page->body_len;
+
     return codec;
 }
 
 
+/* called from the admin interface, here we update the artist/title info
+ * and schedule a new set of header pages
+ */
 static void vorbis_set_tag (format_plugin_t *plugin, char *tag, char *value)
 {   
     ogg_state_t *ogg_info = plugin->_state;
@@ -495,6 +438,9 @@
 }
 
 
+/* main backend routine when rebuilding streams. Here we loop until we either
+ * have a refbuf to add onto the queue, or we want more data to process.
+ */
 static refbuf_t *process_vorbis (ogg_state_t *ogg_info, ogg_codec_t *codec)
 {
     vorbis_codec_t *source_vorbis = codec->specific;
@@ -517,65 +463,93 @@
 }
 
 
-static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info,
+/* no processing of pages, just wrap them up in a refbuf and pass
+ * back for adding to the queue
+ */
+static refbuf_t *process_vorbis_passthru_page (ogg_state_t *ogg_info,
         ogg_codec_t *codec, ogg_page *page)
 {
-    if (ogg_stream_pagein (&codec->os, page) < 0)
-        ogg_info->error = 1;
-    return NULL;
+    return make_refbuf_with_page (page);
 }
 
 
-static refbuf_t *vorbis_page (ogg_state_t *ogg_info,
+/* handle incoming page. as the stream is being rebuilt, we need to
+ * add all pages from the stream before processing packets
+ */
+static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info,
         ogg_codec_t *codec, ogg_page *page)
 {
-    if (codec->headers < 3)
+    ogg_packet header;
+    vorbis_codec_t *source_vorbis = codec->specific;
+    char *comment;
+
+    if (ogg_stream_pagein (&codec->os, page) < 0)
     {
-        vorbis_codec_t *vorbis = codec->specific;
-        ogg_packet packet;
+        ogg_info->error = 1;
+        return NULL;
+    }
+    if (codec->headers == 3)
+        return NULL;
 
-        ogg_stream_pagein (&codec->os, page);
-        while (ogg_stream_packetout (&codec->os, &packet) > 0)
+    while (codec->headers < 3)
+    {
+        /* now, lets extract the packets */
+        DEBUG1 ("processing incoming header packet (%d)", codec->headers);
+
+        if (ogg_stream_packetout (&codec->os, &header) <= 0)
         {
-            if (vorbis_synthesis_headerin (&vorbis->vi, &vorbis->vc, &packet) < 0)
-            {
-                ogg_info->error = 1;
-                WARN0 ("error processing vorbis header packet");
-                return NULL;
-            }
-            codec->headers++;
+            if (ogg_info->codecs->next)
+                format_ogg_attach_header (ogg_info, page);
+            return NULL;
         }
-        /* add header page to associated list */
-        format_ogg_attach_header (ogg_info, page);
-        DEBUG1 ("header page processed, headers at %d", codec->headers);
-        if (codec->headers == 3)
-        {
-            char *comment;
-            free (ogg_info->title);
-            comment = vorbis_comment_query (&vorbis->vc, "TITLE", 0);
-            if (comment)
-                ogg_info->title = strdup (comment);
-            else
-                ogg_info->title = NULL;
 
-            free (ogg_info->artist);
-            comment = vorbis_comment_query (&vorbis->vc, "ARTIST", 0);
-            if (comment)
-                ogg_info->artist = strdup (comment);
-            else
-                ogg_info->artist = NULL;
-
-            ogg_info->bitrate += vorbis->vi.bitrate_nominal;
-            stats_event_args (ogg_info->mount, "audio-samplerate", "%ld", (long)vorbis->vi.rate);
-            stats_event_args (ogg_info->mount, "audio-channels", "%ld", (long)vorbis->vi.channels);
-            stats_event_args (ogg_info->mount, "audio-bitrate", "%ld", (long)vorbis->vi.bitrate_nominal);
-            stats_event_args (ogg_info->mount, "ice-bitrate", "%ld", (long)vorbis->vi.bitrate_nominal/1000);
-            ogg_info->log_metadata = 1;
+        /* change comments here if need be */
+        if (vorbis_synthesis_headerin (&source_vorbis->vi, &source_vorbis->vc, &header) < 0)
+        {
+            ogg_info->error = 1;
+            WARN0 ("Problem parsing ogg vorbis header");
+            return NULL;
         }
-        return NULL;
+        header.granulepos = 0;
+        source_vorbis->header [codec->headers] = copy_ogg_packet (&header);
+        codec->headers++;
     }
-    return make_refbuf_with_page (page);
-}
+    DEBUG0 ("we have the header packets now");
 
+    /* if vorbis is the only codec then allow rebuilding of the streams */
+    if (ogg_info->codecs->next == NULL)
+    {
+        /* set queued vorbis pages to contain about 1/2 of a second worth of samples */
+        source_vorbis->page_samples_trigger = source_vorbis->vi.rate / 2;
+        source_vorbis->process_packet = process_vorbis_headers;
+    }
+    else
+    {
+        format_ogg_attach_header (ogg_info, &source_vorbis->bos_page);
+        format_ogg_attach_header (ogg_info, page);
+        codec->process_page = process_vorbis_passthru_page;
+    }
 
+    free (ogg_info->title);
+    comment = vorbis_comment_query (&source_vorbis->vc, "TITLE", 0);
+    if (comment)
+        ogg_info->title = strdup (comment);
+    else
+        ogg_info->title = NULL;
 
+    free (ogg_info->artist);
+    comment = vorbis_comment_query (&source_vorbis->vc, "ARTIST", 0);
+    if (comment)
+        ogg_info->artist = strdup (comment);
+    else
+        ogg_info->artist = NULL;
+    ogg_info->log_metadata = 1;
+
+    stats_event_args (ogg_info->mount, "audio-samplerate", "%ld", (long)source_vorbis->vi.rate);
+    stats_event_args (ogg_info->mount, "audio-channels", "%ld", (long)source_vorbis->vi.channels);
+    stats_event_args (ogg_info->mount, "audio-bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal);
+    stats_event_args (ogg_info->mount, "ice-bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal/1000);
+
+    return NULL;
+}
+

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/source.c	2004-12-07 20:25:02 UTC (rev 8340)
@@ -877,8 +877,6 @@
                 }
                 source->stream_data = to_go->next;
                 source->queue_size -= to_go->len;
-                if (source->format->prerelease)
-                    source->format->prerelease (source, to_go);
                 refbuf_release (to_go);
             }
         }

Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c	2004-12-06 19:32:54 UTC (rev 8339)
+++ icecast/branches/kh/icecast/src/stats.c	2004-12-07 20:25:02 UTC (rev 8340)
@@ -562,7 +562,6 @@
             thread_mutex_unlock(&_global_event_mutex);
 
             event->next = NULL;
-            thread_mutex_unlock(&_global_event_mutex);
 
             thread_mutex_lock(&_stats_mutex);
 



More information about the commits mailing list