+static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
+ ogg_packet *p_oggpacket )
+{
+ oggpack_buffer opb;
+
+ p_stream->fmt.i_cat = AUDIO_ES;
+ p_stream->fmt.i_codec = VLC_CODEC_SPEEX;
+
+ /* Signal that we want to keep a backup of the speex
+ * stream headers. They will be used when switching between
+ * audio streams. */
+ p_stream->b_force_backup = 1;
+
+ /* Cheat and get additionnal info ;) */
+ oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
+ oggpack_adv( &opb, 224 );
+ oggpack_adv( &opb, 32 ); /* speex_version_id */
+ oggpack_adv( &opb, 32 ); /* header_size */
+ p_stream->f_rate = p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 );
+ oggpack_adv( &opb, 32 ); /* mode */
+ oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
+ p_stream->fmt.audio.i_channels = oggpack_read( &opb, 32 );
+ p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
+}
+
+static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
+ ogg_packet *p_oggpacket )
+{
+ /* Parse the STREAMINFO metadata */
+ bs_t s;
+
+ bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
+
+ bs_read( &s, 1 );
+ if( bs_read( &s, 7 ) == 0 )
+ {
+ if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
+ {
+ bs_skip( &s, 80 );
+ p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
+ p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
+
+ msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
+ p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
+ }
+ else
+ {
+ msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
+ }
+
+ /* Fake this as the last metadata block */
+ *((uint8_t*)p_oggpacket->packet) |= 0x80;
+ }
+ else
+ {
+ /* This ain't a STREAMINFO metadata */
+ msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
+ }
+}
+
+static void Ogg_ReadKateHeader( logical_stream_t *p_stream,
+ ogg_packet *p_oggpacket )
+{
+ oggpack_buffer opb;
+ int32_t gnum;
+ int32_t gden;
+ int n;
+ char *psz_desc;
+
+ p_stream->fmt.i_cat = SPU_ES;
+ p_stream->fmt.i_codec = VLC_CODEC_KATE;
+
+ /* Signal that we want to keep a backup of the kate
+ * stream headers. They will be used when switching between
+ * kate streams. */
+ p_stream->b_force_backup = 1;
+
+ /* Cheat and get additionnal info ;) */
+ oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
+ oggpack_adv( &opb, 11*8 ); /* packet type, kate magic, version */
+ p_stream->i_kate_num_headers = oggpack_read( &opb, 8 );
+ oggpack_adv( &opb, 3*8 );
+ p_stream->i_granule_shift = oggpack_read( &opb, 8 );
+ oggpack_adv( &opb, 8*8 ); /* reserved */
+ gnum = oggpack_read( &opb, 32 );
+ gden = oggpack_read( &opb, 32 );
+ p_stream->f_rate = (double)gnum/gden;
+
+ p_stream->fmt.psz_language = malloc(16);
+ if( p_stream->fmt.psz_language )
+ {
+ for( n = 0; n < 16; n++ )
+ p_stream->fmt.psz_language[n] = oggpack_read(&opb,8);
+ p_stream->fmt.psz_language[15] = 0; /* just in case */
+ }
+ else
+ {
+ for( n = 0; n < 16; n++ )
+ oggpack_read(&opb,8);
+ }
+ p_stream->fmt.psz_description = malloc(16);
+ if( p_stream->fmt.psz_description )
+ {
+ for( n = 0; n < 16; n++ )
+ p_stream->fmt.psz_description[n] = oggpack_read(&opb,8);
+ p_stream->fmt.psz_description[15] = 0; /* just in case */
+
+ /* Now find a localized user readable description for this category */
+ psz_desc = strdup(FindKateCategoryName(p_stream->fmt.psz_description));
+ if( psz_desc )
+ {
+ free( p_stream->fmt.psz_description );
+ p_stream->fmt.psz_description = psz_desc;
+ }
+ }
+ else
+ {
+ for( n = 0; n < 16; n++ )
+ oggpack_read(&opb,8);
+ }
+}
+