From ce1815eb546b864e1cb22e8ac71a7ecae151f9fb Mon Sep 17 00:00:00 2001 From: Gildas Bazin Date: Sun, 3 Nov 2002 13:22:44 +0000 Subject: [PATCH] * modules/demux/ogg.c: we now correctly handle multiple vorbis logical streams in ogm files. * modules/codec/vorbis.c: small bugfix. --- modules/codec/vorbis.c | 9 +++-- modules/demux/ogg.c | 90 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 14 deletions(-) diff --git a/modules/codec/vorbis.c b/modules/codec/vorbis.c index 1830c9eff5..0fa0d8f47c 100644 --- a/modules/codec/vorbis.c +++ b/modules/codec/vorbis.c @@ -2,7 +2,7 @@ * vorbis.c: vorbis decoder module making use of libvorbis. ***************************************************************************** * 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 * @@ -129,6 +129,7 @@ static int RunDecoder( decoder_fifo_t * p_fifo ) } /* Initialize the thread properties */ + memset( p_dec, 0, sizeof(dec_thread_t) ); p_dec->p_fifo = p_fifo; p_dec->p_pes = NULL; @@ -206,14 +207,16 @@ static int RunDecoder( decoder_fifo_t * p_fifo ) return 0; error: + DecoderError( p_fifo ); if( p_dec ) { if( p_dec->p_fifo ) p_dec->p_fifo->b_error = 1; - free( p_dec ); + + /* End of the vorbis decoder thread */ + CloseDecoder( p_dec ); } - DecoderError( p_fifo ); return -1; } diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c index f87426be75..c56d926be1 100644 --- a/modules/demux/ogg.c +++ b/modules/demux/ogg.c @@ -2,7 +2,7 @@ * ogg.c : ogg stream input module for vlc ***************************************************************************** * 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 * @@ -45,7 +45,6 @@ typedef struct logical_stream_s ogg_stream_state os; /* logical stream of packets */ int i_serial_no; - int i_pages_read; int i_cat; /* AUDIO_ES, VIDEO_ES */ int i_activated; vlc_fourcc_t i_fourcc; @@ -54,6 +53,13 @@ typedef struct logical_stream_s es_descriptor_t *p_es; 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 * granulepos */ mtime_t i_pcr; @@ -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; + /* 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 ); return( p_stream->i_activated ); @@ -242,6 +259,51 @@ static void Ogg_DecodePacket( input_thread_t *p_input, data_packet_t *p_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 ) ) ) { return; @@ -265,7 +327,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input, /* Convert the next granule into a pcr */ 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 */ 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) memset( p_stream, 0, sizeof(logical_stream_t) ); /* Setup the logical stream */ - p_stream->i_pages_read++; p_stream->i_serial_no = ogg_page_serialno( &oggpage ); 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) p_stream->i_cat = AUDIO_ES; 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 ;) */ oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes); oggpack_adv( &opb, 96 ); @@ -363,7 +429,8 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) else { msg_Dbg( p_input, "found unknown codec" ); - p_stream->i_cat = UNKNOWN_ES; + free( p_stream ); + p_ogg->i_streams--; } #undef p_stream @@ -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, &oggpage ) == 0 ) { - p_ogg->pp_stream[i_stream]->i_pages_read++; break; } } @@ -538,7 +604,7 @@ static void Deactivate( vlc_object_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 ; - int i; + int i, j; if( p_ogg ) { @@ -548,6 +614,11 @@ static void Deactivate( vlc_object_t *p_this ) for( i = 0; i < p_ogg->i_streams; i++ ) { 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] ); } if( p_ogg->pp_stream ) free( p_ogg->pp_stream ); @@ -649,15 +720,12 @@ static int Demux( input_thread_t * p_input ) 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 ) continue; while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) { - if( !p_stream->p_es || - !p_stream->p_es->p_decoder_fifo ) + if( !p_stream->p_es ) { break; } -- 2.39.2