Commit ce1815eb authored by Gildas Bazin's avatar Gildas Bazin

* modules/demux/ogg.c: we now correctly handle multiple vorbis logical streams
   in ogm files.
* modules/codec/vorbis.c: small bugfix.
parent a9ba6193
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vorbis.c: vorbis decoder module making use of libvorbis. * vorbis.c: vorbis decoder module making use of libvorbis.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: vorbis.c,v 1.3 2002/11/02 18:13:22 gbazin Exp $ * $Id: vorbis.c,v 1.4 2002/11/03 13:22:44 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -129,6 +129,7 @@ static int RunDecoder( decoder_fifo_t * p_fifo ) ...@@ -129,6 +129,7 @@ static int RunDecoder( decoder_fifo_t * p_fifo )
} }
/* Initialize the thread properties */ /* Initialize the thread properties */
memset( p_dec, 0, sizeof(dec_thread_t) );
p_dec->p_fifo = p_fifo; p_dec->p_fifo = p_fifo;
p_dec->p_pes = NULL; p_dec->p_pes = NULL;
...@@ -206,14 +207,16 @@ static int RunDecoder( decoder_fifo_t * p_fifo ) ...@@ -206,14 +207,16 @@ static int RunDecoder( decoder_fifo_t * p_fifo )
return 0; return 0;
error: error:
DecoderError( p_fifo );
if( p_dec ) if( p_dec )
{ {
if( p_dec->p_fifo ) if( p_dec->p_fifo )
p_dec->p_fifo->b_error = 1; p_dec->p_fifo->b_error = 1;
free( p_dec );
/* End of the vorbis decoder thread */
CloseDecoder( p_dec );
} }
DecoderError( p_fifo );
return -1; return -1;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ogg.c : ogg stream input module for vlc * ogg.c : ogg stream input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: ogg.c,v 1.4 2002/11/02 22:47:16 gbazin Exp $ * $Id: ogg.c,v 1.5 2002/11/03 13:22:44 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -45,7 +45,6 @@ typedef struct logical_stream_s ...@@ -45,7 +45,6 @@ typedef struct logical_stream_s
ogg_stream_state os; /* logical stream of packets */ ogg_stream_state os; /* logical stream of packets */
int i_serial_no; int i_serial_no;
int i_pages_read;
int i_cat; /* AUDIO_ES, VIDEO_ES */ int i_cat; /* AUDIO_ES, VIDEO_ES */
int i_activated; int i_activated;
vlc_fourcc_t i_fourcc; vlc_fourcc_t i_fourcc;
...@@ -54,6 +53,13 @@ typedef struct logical_stream_s ...@@ -54,6 +53,13 @@ typedef struct logical_stream_s
es_descriptor_t *p_es; es_descriptor_t *p_es;
int b_selected; /* newly selected */ int b_selected; /* newly selected */
/* the header of some logical streams (eg vorbis) contain essential
* data for the decoder. We back them up here in case we need to re-feed
* them to the decoder. */
int b_force_backup;
int i_packets_backup;
ogg_packet *p_packets_backup;
/* program clock reference (in units of 90kHz) derived from the previous /* program clock reference (in units of 90kHz) derived from the previous
* granulepos */ * granulepos */
mtime_t i_pcr; mtime_t i_pcr;
...@@ -144,6 +150,17 @@ static int Ogg_StreamStart( input_thread_t *p_input, ...@@ -144,6 +150,17 @@ static int Ogg_StreamStart( input_thread_t *p_input,
} }
p_stream->i_activated = p_stream->p_es->p_decoder_fifo ? 1 : 0; p_stream->i_activated = p_stream->p_es->p_decoder_fifo ? 1 : 0;
/* Feed the backup header to the decoder */
if( !p_stream->b_force_backup )
{
int i;
for( i = 0; i < p_stream->i_packets_backup; i++ )
{
Ogg_DecodePacket( p_input, p_stream,
&p_stream->p_packets_backup[i] );
}
}
//Ogg_StreamSeek( p_input, p_ogg, i_stream, p_ogg->i_time ); //Ogg_StreamSeek( p_input, p_ogg, i_stream, p_ogg->i_time );
return( p_stream->i_activated ); return( p_stream->i_activated );
...@@ -242,6 +259,51 @@ static void Ogg_DecodePacket( input_thread_t *p_input, ...@@ -242,6 +259,51 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
data_packet_t *p_data; data_packet_t *p_data;
demux_sys_t *p_ogg = p_input->p_demux_data; demux_sys_t *p_ogg = p_input->p_demux_data;
if( p_stream->b_force_backup )
{
/* Backup the ogg packet (likely an header) */
ogg_packet *p_packet_backup;
p_stream->i_packets_backup++;
p_stream->p_packets_backup =
realloc( p_stream->p_packets_backup, p_stream->i_packets_backup *
sizeof(ogg_packet) );
p_packet_backup =
&p_stream->p_packets_backup[p_stream->i_packets_backup - 1];
p_packet_backup->bytes = p_oggpacket->bytes;
p_packet_backup->granulepos = p_oggpacket->granulepos;
p_packet_backup->packet = malloc( p_oggpacket->bytes );
if( !p_packet_backup->packet ) return;
memcpy( p_packet_backup->packet, p_oggpacket->packet,
p_oggpacket->bytes );
switch( p_stream->i_fourcc )
{
case VLC_FOURCC( 'v','o','r','b' ):
if( p_stream->i_packets_backup == 3 ) p_stream->b_force_backup = 0;
break;
default:
p_stream->b_force_backup = 0;
break;
}
}
if( !p_stream->p_es->p_decoder_fifo )
{
/* This stream isn't currently selected so we don't need to decode it,
* but we do need to store its pcr as it might be selected later on. */
/* Convert the next granule into a pcr */
p_stream->i_pcr = ( p_oggpacket->granulepos < 0 ) ?
p_stream->i_pcr + ( p_oggpacket->bytes * 90000
/ p_stream->i_bitrate / 8 ):
p_oggpacket->granulepos * 90000 / p_stream->i_rate;
return;
}
if( !( p_pes = input_NewPES( p_input->p_method_data ) ) ) if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
{ {
return; return;
...@@ -265,7 +327,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input, ...@@ -265,7 +327,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
/* Convert the next granule into a pcr */ /* Convert the next granule into a pcr */
p_stream->i_pcr = ( p_oggpacket->granulepos < 0 ) ? -1 : p_stream->i_pcr = ( p_oggpacket->granulepos < 0 ) ? -1 :
p_oggpacket->granulepos * 90000 / p_stream->i_rate; p_oggpacket->granulepos * 90000 / p_stream->i_rate;
/* Update the main pcr */ /* Update the main pcr */
if( p_stream == p_ogg->p_stream_timeref ) if( p_stream == p_ogg->p_stream_timeref )
...@@ -322,7 +384,6 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) ...@@ -322,7 +384,6 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
memset( p_stream, 0, sizeof(logical_stream_t) ); memset( p_stream, 0, sizeof(logical_stream_t) );
/* Setup the logical stream */ /* Setup the logical stream */
p_stream->i_pages_read++;
p_stream->i_serial_no = ogg_page_serialno( &oggpage ); p_stream->i_serial_no = ogg_page_serialno( &oggpage );
ogg_stream_init( &p_stream->os, p_stream->i_serial_no ); ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
...@@ -353,6 +414,11 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) ...@@ -353,6 +414,11 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
p_stream->i_cat = AUDIO_ES; p_stream->i_cat = AUDIO_ES;
p_stream->i_fourcc = VLC_FOURCC( 'v','o','r','b' ); p_stream->i_fourcc = VLC_FOURCC( 'v','o','r','b' );
/* Signal that we want to keep a backup of the vorbis
* stream headers. They will be used when switching between
* audio streams. */
p_stream->b_force_backup = 1;
/* Cheat and get additionnal info ;) */ /* Cheat and get additionnal info ;) */
oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes); oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
oggpack_adv( &opb, 96 ); oggpack_adv( &opb, 96 );
...@@ -363,7 +429,8 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) ...@@ -363,7 +429,8 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
else else
{ {
msg_Dbg( p_input, "found unknown codec" ); msg_Dbg( p_input, "found unknown codec" );
p_stream->i_cat = UNKNOWN_ES; free( p_stream );
p_ogg->i_streams--;
} }
#undef p_stream #undef p_stream
...@@ -380,7 +447,6 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) ...@@ -380,7 +447,6 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os, if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
&oggpage ) == 0 ) &oggpage ) == 0 )
{ {
p_ogg->pp_stream[i_stream]->i_pages_read++;
break; break;
} }
} }
...@@ -538,7 +604,7 @@ static void Deactivate( vlc_object_t *p_this ) ...@@ -538,7 +604,7 @@ static void Deactivate( vlc_object_t *p_this )
{ {
input_thread_t *p_input = (input_thread_t *)p_this; input_thread_t *p_input = (input_thread_t *)p_this;
demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data ; demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data ;
int i; int i, j;
if( p_ogg ) if( p_ogg )
{ {
...@@ -548,6 +614,11 @@ static void Deactivate( vlc_object_t *p_this ) ...@@ -548,6 +614,11 @@ static void Deactivate( vlc_object_t *p_this )
for( i = 0; i < p_ogg->i_streams; i++ ) for( i = 0; i < p_ogg->i_streams; i++ )
{ {
ogg_stream_clear( &p_ogg->pp_stream[i]->os ); ogg_stream_clear( &p_ogg->pp_stream[i]->os );
for( j = 0; j < p_ogg->pp_stream[i]->i_packets_backup; j++ )
{
free( p_ogg->pp_stream[i]->p_packets_backup[j].packet );
}
free( p_ogg->pp_stream[i]->p_packets_backup );
free( p_ogg->pp_stream[i] ); free( p_ogg->pp_stream[i] );
} }
if( p_ogg->pp_stream ) free( p_ogg->pp_stream ); if( p_ogg->pp_stream ) free( p_ogg->pp_stream );
...@@ -649,15 +720,12 @@ static int Demux( input_thread_t * p_input ) ...@@ -649,15 +720,12 @@ static int Demux( input_thread_t * p_input )
for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ ) for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
{ {
/* FIXME: we already read the header */
if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 ) if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 )
continue; continue;
while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
{ {
if( !p_stream->p_es || if( !p_stream->p_es )
!p_stream->p_es->p_decoder_fifo )
{ {
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment