2004-01-28 20:02:12 -05:00
/* Icecast
*
* This program is distributed under the GNU General Public License , version 2.
* A copy of this license is included with this source .
*
2015-01-10 13:53:44 -05:00
* Copyright 2000 - 2004 , Jack Moffitt < jack @ xiph . org ,
2004-01-28 20:02:12 -05:00
* Michael Smith < msmith @ xiph . org > ,
* oddsock < oddsock @ xiph . org > ,
* Karl Heyes < karl @ xiph . org >
* and others ( see AUTHORS for details ) .
*/
2004-12-07 16:06:26 -05:00
/* Ogg codec handler for vorbis streams */
2001-09-09 22:21:46 -04:00
2003-07-20 21:58:54 -04:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2001-09-09 22:21:46 -04:00
# include <stdlib.h>
# include <ogg/ogg.h>
# include <vorbis/codec.h>
2004-12-07 16:06:26 -05:00
# include <memory.h>
2005-08-08 15:21:54 -04:00
# include <string.h>
2001-09-09 22:21:46 -04:00
# include "refbuf.h"
2002-12-30 02:55:56 -05:00
# include "source.h"
# include "client.h"
2001-09-09 22:21:46 -04:00
2004-12-07 16:06:26 -05:00
# include "format_ogg.h"
2002-02-11 04:11:18 -05:00
# include "stats.h"
2001-09-09 22:21:46 -04:00
# include "format.h"
2002-08-10 00:51:11 -04:00
# define CATMODULE "format-vorbis"
# include "logging.h"
2002-04-05 04:28:26 -05:00
2015-01-10 13:53:44 -05:00
typedef struct vorbis_codec_tag
2001-09-09 22:21:46 -04:00
{
2014-11-30 15:32:30 -05:00
vorbis_info vi ;
2003-03-14 21:10:19 -05:00
2004-12-07 16:06:26 -05:00
int rebuild_comment ;
int stream_notify ;
2005-11-14 19:29:24 -05:00
int initial_audio_page ;
2001-09-09 22:21:46 -04:00
2014-11-30 15:32:30 -05:00
ogg_stream_state new_os ;
int page_samples_trigger ;
ogg_int64_t prev_granulepos ;
ogg_packet * prev_packet ;
ogg_int64_t granulepos ;
ogg_int64_t initial_page_granulepos ;
ogg_int64_t samples_in_page ;
int prev_window ;
int initial_audio_packet ;
ogg_page bos_page ;
ogg_packet * header [ 3 ] ;
2004-12-07 16:06:26 -05:00
ogg_int64_t prev_page_samples ;
2014-12-09 11:08:27 -05:00
int ( * process_packet ) ( ogg_state_t * ogg_info , ogg_codec_t * codec , format_plugin_t * plugin ) ;
2004-12-07 16:06:26 -05:00
refbuf_t * ( * get_buffer_page ) ( ogg_state_t * ogg_info , ogg_codec_t * codec ) ;
2004-08-20 11:13:59 -04:00
2004-12-07 16:06:26 -05:00
} vorbis_codec_t ;
2004-08-20 11:13:59 -04:00
2014-12-09 11:08:27 -05:00
static int process_vorbis_headers ( ogg_state_t * ogg_info , ogg_codec_t * codec , format_plugin_t * plugin ) ;
2004-12-07 16:06:26 -05:00
static refbuf_t * process_vorbis_page ( ogg_state_t * ogg_info ,
2014-12-09 11:08:27 -05:00
ogg_codec_t * codec , ogg_page * page , format_plugin_t * plugin ) ;
static refbuf_t * process_vorbis ( ogg_state_t * ogg_info , ogg_codec_t * codec , format_plugin_t * plugin ) ;
2007-08-30 19:36:19 -04:00
static void vorbis_set_tag ( format_plugin_t * plugin , const char * tag , const char * value , const char * charset ) ;
2001-09-09 22:21:46 -04:00
2004-08-20 11:13:59 -04:00
2004-12-07 16:06:26 -05:00
static void free_ogg_packet ( ogg_packet * packet )
2001-09-09 22:21:46 -04:00
{
2004-12-07 16:06:26 -05:00
if ( packet )
{
free ( packet - > packet ) ;
free ( packet ) ;
}
}
2001-09-09 22:21:46 -04:00
2002-01-04 19:29:27 -05:00
2004-12-07 16:06:26 -05:00
static void vorbis_codec_free ( ogg_state_t * ogg_info , ogg_codec_t * codec )
{
vorbis_codec_t * vorbis = codec - > specific ;
2014-10-31 04:46:58 -04:00
ICECAST_LOG_DEBUG ( " freeing vorbis codec " ) ;
2004-12-17 16:05:20 -05:00
stats_event ( ogg_info - > mount , " audio_bitrate " , NULL ) ;
stats_event ( ogg_info - > mount , " audio_channels " , NULL ) ;
stats_event ( ogg_info - > mount , " audio_samplerate " , NULL ) ;
2004-12-07 16:06:26 -05:00
vorbis_info_clear ( & vorbis - > vi ) ;
ogg_stream_clear ( & codec - > os ) ;
ogg_stream_clear ( & vorbis - > new_os ) ;
free_ogg_packet ( vorbis - > header [ 0 ] ) ;
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 ) ;
}
static ogg_packet * copy_ogg_packet ( ogg_packet * packet )
{
ogg_packet * next ;
do
{
next = malloc ( sizeof ( ogg_packet ) ) ;
if ( next = = NULL )
break ;
memcpy ( next , packet , sizeof ( ogg_packet ) ) ;
next - > packet = malloc ( next - > bytes ) ;
if ( next - > packet = = NULL )
break ;
memcpy ( next - > packet , packet - > packet , next - > bytes ) ;
return next ;
} while ( 0 ) ;
2001-09-09 22:21:46 -04:00
2004-12-07 16:06:26 -05:00
if ( next )
free ( next ) ;
return NULL ;
}
2001-09-09 22:21:46 -04:00
2004-12-07 16:06:26 -05:00
static void add_audio_packet ( vorbis_codec_t * source_vorbis , ogg_packet * packet )
{
if ( source_vorbis - > initial_audio_packet )
{
packet - > granulepos = 0 ;
source_vorbis - > initial_audio_packet = 0 ;
}
else
{
source_vorbis - > samples_in_page + =
( packet - > granulepos - source_vorbis - > prev_granulepos ) ;
source_vorbis - > prev_granulepos = packet - > granulepos ;
source_vorbis - > granulepos + = source_vorbis - > prev_window ;
}
ogg_stream_packetin ( & source_vorbis - > new_os , packet ) ;
2001-09-09 22:21:46 -04:00
}
2004-12-07 16:06:26 -05:00
static refbuf_t * get_buffer_audio ( ogg_state_t * ogg_info , ogg_codec_t * codec )
2002-01-04 19:29:27 -05:00
{
2004-12-07 16:06:26 -05:00
refbuf_t * refbuf = NULL ;
ogg_page page ;
vorbis_codec_t * source_vorbis = codec - > specific ;
int ( * get_ogg_page ) ( ogg_stream_state * , ogg_page * ) = ogg_stream_pageout ;
2003-03-14 21:10:19 -05:00
2004-12-07 16:06:26 -05:00
if ( source_vorbis - > samples_in_page > source_vorbis - > page_samples_trigger )
get_ogg_page = ogg_stream_flush ;
2003-03-14 21:10:19 -05:00
2004-12-07 16:06:26 -05:00
if ( get_ogg_page ( & source_vorbis - > new_os , & page ) > 0 )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
/* 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 ) ;
refbuf = make_refbuf_with_page ( & page ) ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
return refbuf ;
}
2003-03-14 21:10:19 -05:00
2004-12-07 16:06:26 -05:00
static refbuf_t * get_buffer_header ( ogg_state_t * ogg_info , ogg_codec_t * codec )
{
int headers_flushed = 0 ;
ogg_page page ;
vorbis_codec_t * source_vorbis = codec - > specific ;
while ( ogg_stream_flush ( & source_vorbis - > new_os , & page ) > 0 )
{
format_ogg_attach_header ( ogg_info , & page ) ;
headers_flushed = 1 ;
}
if ( headers_flushed )
{
source_vorbis - > get_buffer_page = get_buffer_audio ;
}
return NULL ;
2002-01-04 19:29:27 -05:00
}
2004-12-07 16:06:26 -05:00
2014-11-30 15:32:30 -05:00
static refbuf_t * get_buffer_finished ( ogg_state_t * ogg_info , ogg_codec_t * codec )
2001-09-09 22:21:46 -04:00
{
2004-12-07 16:06:26 -05:00
vorbis_codec_t * source_vorbis = codec - > specific ;
ogg_page page ;
refbuf_t * refbuf ;
if ( ogg_stream_flush ( & source_vorbis - > new_os , & page ) > 0 )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
source_vorbis - > samples_in_page - = ( ogg_page_granulepos ( & page ) - source_vorbis - > prev_page_samples ) ;
source_vorbis - > prev_page_samples = ogg_page_granulepos ( & page ) ;
refbuf = make_refbuf_with_page ( & page ) ;
2014-10-31 04:46:58 -04:00
ICECAST_LOG_DEBUG ( " flushing page " ) ;
2004-12-07 16:06:26 -05:00
return refbuf ;
2003-03-14 21:10:19 -05:00
}
2004-12-07 16:06:26 -05:00
ogg_stream_clear ( & source_vorbis - > new_os ) ;
ogg_stream_init ( & source_vorbis - > new_os , rand ( ) ) ;
format_ogg_free_headers ( ogg_info ) ;
source_vorbis - > get_buffer_page = NULL ;
2005-04-18 10:32:26 -04:00
if ( source_vorbis - > prev_packet )
source_vorbis - > process_packet = process_vorbis_headers ;
else
source_vorbis - > process_packet = NULL ;
2004-12-07 16:06:26 -05:00
if ( source_vorbis - > initial_audio_packet = = 0 )
source_vorbis - > prev_window = 0 ;
return NULL ;
}
/* push last packet into stream marked with eos */
static void initiate_flush ( vorbis_codec_t * source_vorbis )
{
if ( source_vorbis - > prev_packet )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
/* insert prev_packet with eos */
2014-10-31 04:46:58 -04:00
ICECAST_LOG_DEBUG ( " adding EOS packet " ) ;
2004-12-07 16:06:26 -05:00
source_vorbis - > prev_packet - > e_o_s = 1 ;
add_audio_packet ( source_vorbis , source_vorbis - > prev_packet ) ;
source_vorbis - > prev_packet - > e_o_s = 0 ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
source_vorbis - > get_buffer_page = get_buffer_finished ;
source_vorbis - > initial_audio_packet = 1 ;
}
2001-09-09 22:21:46 -04:00
2003-03-14 21:10:19 -05:00
2015-01-10 13:53:44 -05:00
/* process the vorbis audio packets. Here we just take each packet out
2004-12-07 16:06:26 -05:00
* 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
*/
2014-12-09 11:08:27 -05:00
static int process_vorbis_audio ( ogg_state_t * ogg_info , ogg_codec_t * codec , format_plugin_t * plugin )
2004-12-07 16:06:26 -05:00
{
vorbis_codec_t * source_vorbis = codec - > specific ;
while ( 1 )
{
int window ;
ogg_packet packet ;
/* now, lets extract what packets we can */
if ( ogg_stream_packetout ( & codec - > os , & packet ) < = 0 )
break ;
/* calculate granulepos for the packet */
window = vorbis_packet_blocksize ( & source_vorbis - > vi , & packet ) / 4 ;
source_vorbis - > granulepos + = window ;
if ( source_vorbis - > prev_packet )
{
ogg_packet * prev_packet = source_vorbis - > prev_packet ;
add_audio_packet ( source_vorbis , prev_packet ) ;
free_ogg_packet ( prev_packet ) ;
2005-11-14 19:29:24 -05:00
/* check for short values on first initial page */
if ( packet . packetno = = 4 )
{
if ( source_vorbis - > initial_page_granulepos < source_vorbis - > granulepos )
{
source_vorbis - > granulepos - = source_vorbis - > initial_page_granulepos ;
source_vorbis - > samples_in_page = source_vorbis - > page_samples_trigger ;
}
}
/* check for long values on first page */
if ( packet . granulepos = = source_vorbis - > initial_page_granulepos )
{
if ( source_vorbis - > initial_page_granulepos > source_vorbis - > granulepos )
source_vorbis - > granulepos = source_vorbis - > initial_page_granulepos ;
}
if ( packet . e_o_s = = 0 )
packet . granulepos = source_vorbis - > granulepos ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
else
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
packet . granulepos = 0 ;
2003-03-14 21:10:19 -05:00
}
2001-09-09 22:21:46 -04:00
2004-12-07 16:06:26 -05:00
/* store the current packet details */
source_vorbis - > prev_window = window ;
source_vorbis - > prev_packet = copy_ogg_packet ( & packet ) ;
if ( packet . e_o_s )
{
initiate_flush ( source_vorbis ) ;
2005-04-18 10:32:26 -04:00
free_ogg_packet ( source_vorbis - > prev_packet ) ;
source_vorbis - > prev_packet = NULL ;
2004-12-07 16:06:26 -05:00
return 1 ;
}
2001-09-09 22:21:46 -04:00
2004-12-07 16:06:26 -05:00
/* 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 ;
2005-04-18 10:32:26 -04:00
return 1 ;
2004-12-07 16:06:26 -05:00
}
return - 1 ;
2001-09-09 22:21:46 -04:00
}
2004-12-07 16:06:26 -05:00
/* This handles the headers at the backend, here we insert the header packets
* we want for the queue .
*/
2014-12-09 11:08:27 -05:00
static int process_vorbis_headers ( ogg_state_t * ogg_info , ogg_codec_t * codec , format_plugin_t * plugin )
2002-12-30 02:55:56 -05:00
{
2004-12-07 16:06:26 -05:00
vorbis_codec_t * source_vorbis = codec - > specific ;
if ( source_vorbis - > header [ 0 ] = = NULL )
return 0 ;
2004-08-20 11:13:59 -04:00
2014-10-31 04:46:58 -04:00
ICECAST_LOG_DEBUG ( " Adding the 3 header packets " ) ;
2004-12-07 16:06:26 -05:00
ogg_stream_packetin ( & source_vorbis - > new_os , source_vorbis - > header [ 0 ] ) ;
/* NOTE: we could build a separate comment packet each time */
if ( source_vorbis - > rebuild_comment )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
ogg_packet header ;
2007-09-02 20:55:27 -04:00
ice_config_t * config ;
2004-12-07 16:06:26 -05:00
2007-09-02 20:55:27 -04:00
config = config_get_config ( ) ;
2014-12-09 11:08:27 -05:00
format_set_vorbiscomment ( plugin , " server " , config - > server_id ) ;
2007-09-02 20:55:27 -04:00
config_release_config ( ) ;
2014-12-09 11:08:27 -05:00
vorbis_commentheader_out ( & plugin - > vc , & header ) ;
2004-12-07 16:06:26 -05:00
ogg_stream_packetin ( & source_vorbis - > new_os , & header ) ;
ogg_packet_clear ( & header ) ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
else
ogg_stream_packetin ( & source_vorbis - > new_os , source_vorbis - > header [ 1 ] ) ;
ogg_stream_packetin ( & source_vorbis - > new_os , source_vorbis - > header [ 2 ] ) ;
source_vorbis - > rebuild_comment = 0 ;
ogg_info - > log_metadata = 1 ;
source_vorbis - > get_buffer_page = get_buffer_header ;
source_vorbis - > process_packet = process_vorbis_audio ;
source_vorbis - > granulepos = source_vorbis - > prev_window ;
source_vorbis - > initial_audio_packet = 1 ;
return 1 ;
2002-12-29 03:10:10 -05:00
}
2001-09-09 22:21:46 -04:00
2004-12-07 16:06:26 -05:00
/* 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 )
2002-12-30 02:55:56 -05:00
{
2004-12-07 16:06:26 -05:00
ogg_codec_t * codec = calloc ( 1 , sizeof ( ogg_codec_t ) ) ;
ogg_packet packet ;
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 ( & vorbis - > vi ) ;
ogg_stream_packetout ( & codec - > os , & packet ) ;
2014-12-09 11:08:27 -05:00
vorbis_comment_clear ( & plugin - > vc ) ;
vorbis_comment_init ( & plugin - > vc ) ;
2014-10-31 04:46:58 -04:00
ICECAST_LOG_DEBUG ( " checking for vorbis codec " ) ;
2014-12-09 11:08:27 -05:00
if ( vorbis_synthesis_headerin ( & vorbis - > vi , & plugin - > vc , & packet ) < 0 )
2004-12-07 16:06:26 -05:00
{
ogg_stream_clear ( & codec - > os ) ;
vorbis_info_clear ( & vorbis - > vi ) ;
2014-12-09 11:08:27 -05:00
vorbis_comment_clear ( & plugin - > vc ) ;
2004-12-07 16:06:26 -05:00
free ( vorbis ) ;
free ( codec ) ;
return NULL ;
}
2014-10-31 04:46:58 -04:00
ICECAST_LOG_INFO ( " seen initial vorbis header " ) ;
2004-12-07 16:06:26 -05:00
codec - > specific = vorbis ;
codec - > codec_free = vorbis_codec_free ;
codec - > headers = 1 ;
2004-12-09 19:11:16 -05:00
codec - > name = " Vorbis " ;
2004-12-07 16:06:26 -05:00
2014-11-30 15:32:30 -05:00
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 ( ) ) ;
2004-12-07 16:06:26 -05:00
codec - > process_page = process_vorbis_page ;
codec - > process = process_vorbis ;
plugin - > set_tag = vorbis_set_tag ;
2014-11-30 15:32:30 -05:00
vorbis - > bos_page . header = malloc ( page - > header_len + page - > body_len ) ;
memcpy ( vorbis - > bos_page . header , page - > header , page - > header_len ) ;
2004-12-07 16:06:26 -05:00
vorbis - > bos_page . header_len = page - > header_len ;
2002-12-30 02:55:56 -05:00
2004-12-07 16:06:26 -05:00
vorbis - > bos_page . body = vorbis - > bos_page . header + page - > header_len ;
2014-11-30 15:32:30 -05:00
memcpy ( vorbis - > bos_page . body , page - > body , page - > body_len ) ;
2004-12-07 16:06:26 -05:00
vorbis - > bos_page . body_len = page - > body_len ;
2002-12-30 02:55:56 -05:00
2004-12-07 16:06:26 -05:00
return codec ;
2002-12-30 02:55:56 -05:00
}
2004-08-20 11:13:59 -04:00
2004-12-07 16:06:26 -05:00
/* called from the admin interface, here we update the artist/title info
* and schedule a new set of header pages
*/
2007-08-30 19:36:19 -04:00
static void vorbis_set_tag ( format_plugin_t * plugin , const char * tag , const char * in_value , const char * charset )
2015-01-10 13:53:44 -05:00
{
2004-12-07 16:06:26 -05:00
ogg_state_t * ogg_info = plugin - > _state ;
ogg_codec_t * codec = ogg_info - > codecs ;
vorbis_codec_t * source_vorbis ;
2007-08-30 19:36:19 -04:00
char * value ;
2004-12-07 16:06:26 -05:00
2018-11-10 04:22:16 -05:00
ICECAST_LOG_WARN ( " Not officially supported metadata update detected, please inform the source client software vendor that they should fix their software! " ) ;
2004-12-07 16:06:26 -05:00
/* avoid updating if multiple codecs in use */
if ( codec & & codec - > next = = NULL )
source_vorbis = codec - > specific ;
else
return ;
2009-01-14 22:38:49 -05:00
if ( tag = = NULL )
{
source_vorbis - > stream_notify = 1 ;
source_vorbis - > rebuild_comment = 1 ;
return ;
}
2007-09-04 23:25:14 -04:00
value = util_conv_string ( in_value , charset , " UTF-8 " ) ;
2007-08-30 19:36:19 -04:00
if ( value = = NULL )
value = strdup ( in_value ) ;
2014-12-09 11:08:27 -05:00
if ( strcmp ( tag , " song " ) = = 0 )
tag = " title " ;
format_set_vorbiscomment ( plugin , tag , value ) ;
free ( value ) ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
/* 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 .
*/
2014-12-09 11:08:27 -05:00
static refbuf_t * process_vorbis ( ogg_state_t * ogg_info , ogg_codec_t * codec , format_plugin_t * plugin )
2004-12-07 16:06:26 -05:00
{
vorbis_codec_t * source_vorbis = codec - > specific ;
refbuf_t * refbuf ;
2004-08-20 11:13:59 -04:00
2004-12-07 16:06:26 -05:00
while ( 1 )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
if ( source_vorbis - > get_buffer_page )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
refbuf = source_vorbis - > get_buffer_page ( ogg_info , codec ) ;
if ( refbuf )
return refbuf ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
if ( source_vorbis - > process_packet & &
2014-12-09 11:08:27 -05:00
source_vorbis - > process_packet ( ogg_info , codec , plugin ) > 0 )
2004-12-07 16:06:26 -05:00
continue ;
return NULL ;
}
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
/* 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 ,
2014-12-09 11:08:27 -05:00
ogg_codec_t * codec , ogg_page * page , format_plugin_t * plugin )
2004-12-07 16:06:26 -05:00
{
return make_refbuf_with_page ( page ) ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
/* 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 ,
2014-12-09 11:08:27 -05:00
ogg_codec_t * codec , ogg_page * page , format_plugin_t * plugin )
2004-12-07 16:06:26 -05:00
{
ogg_packet header ;
vorbis_codec_t * source_vorbis = codec - > specific ;
2004-08-20 11:13:59 -04:00
2004-12-07 16:06:26 -05:00
if ( ogg_stream_pagein ( & codec - > os , page ) < 0 )
{
ogg_info - > error = 1 ;
return NULL ;
}
if ( codec - > headers = = 3 )
2005-11-14 19:29:24 -05:00
{
if ( source_vorbis - > initial_audio_page )
{
source_vorbis - > initial_page_granulepos = ogg_page_granulepos ( page ) ;
source_vorbis - > initial_audio_page = 0 ;
}
2004-12-07 16:06:26 -05:00
return NULL ;
2005-11-14 19:29:24 -05:00
}
2004-08-20 11:13:59 -04:00
2004-12-07 16:06:26 -05:00
while ( codec - > headers < 3 )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
/* now, lets extract the packets */
2014-10-31 04:46:58 -04:00
ICECAST_LOG_DEBUG ( " processing incoming header packet (%d) " , codec - > headers ) ;
2004-12-07 16:06:26 -05:00
if ( ogg_stream_packetout ( & codec - > os , & header ) < = 0 )
{
if ( ogg_info - > codecs - > next )
2014-11-30 15:32:30 -05:00
format_ogg_attach_header ( ogg_info , page ) ;
2004-12-07 16:06:26 -05:00
return NULL ;
}
2014-12-09 11:08:27 -05:00
if ( vorbis_synthesis_headerin ( & source_vorbis - > vi , & plugin - > vc , & header ) < 0 )
2004-08-20 11:13:59 -04:00
{
2004-12-07 16:06:26 -05:00
ogg_info - > error = 1 ;
2014-10-31 04:46:58 -04:00
ICECAST_LOG_WARN ( " Problem parsing ogg vorbis header " ) ;
2004-12-07 16:06:26 -05:00
return NULL ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
header . granulepos = 0 ;
2014-11-30 15:32:30 -05:00
source_vorbis - > header [ codec - > headers ] = copy_ogg_packet ( & header ) ;
2004-12-07 16:06:26 -05:00
codec - > headers + + ;
}
2014-10-31 04:46:58 -04:00
ICECAST_LOG_DEBUG ( " we have the header packets now " ) ;
2004-12-07 16:06:26 -05:00
/* 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 ;
2005-11-14 19:29:24 -05:00
source_vorbis - > initial_audio_page = 1 ;
2004-12-07 16:06:26 -05:00
}
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 ;
2004-08-20 11:13:59 -04:00
}
2004-12-07 16:06:26 -05:00
ogg_info - > log_metadata = 1 ;
2004-12-17 16:05:20 -05:00
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 ) ;
2004-12-07 16:06:26 -05:00
stats_event_args ( ogg_info - > mount , " ice-bitrate " , " %ld " , ( long ) source_vorbis - > vi . bitrate_nominal / 1000 ) ;
return NULL ;
2004-08-20 11:13:59 -04:00
}
2001-09-09 22:21:46 -04:00