[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