Commit f5a90887 authored by Gildas Bazin's avatar Gildas Bazin

* modules/demux/ogg.c, modules/codec/vorbis.c: seeking in an ogg stream is
   working fine now, + misc other improvements.
parent f7b44627
...@@ -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.2 2002/10/27 16:58:14 gbazin Exp $ * $Id: vorbis.c,v 1.3 2002/11/02 18:13:22 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -188,14 +188,6 @@ static int RunDecoder( decoder_fifo_t * p_fifo ) ...@@ -188,14 +188,6 @@ static int RunDecoder( decoder_fifo_t * p_fifo )
goto error; goto error;
} }
/* Take care of the first pts we receive. We need to be careful as a pts
* in vorbis language does in fact correspond to the presentation time of
* the _next_ packet to receive */
if( i_pts > 0 && i_pts != aout_DateGet( &p_dec->end_date ) )
{
aout_DateSet( &p_dec->end_date, i_pts );
}
/* vorbis decoder thread's main loop */ /* vorbis decoder thread's main loop */
while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) ) while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
{ {
...@@ -243,10 +235,14 @@ static void DecodePacket( dec_thread_t *p_dec ) ...@@ -243,10 +235,14 @@ static void DecodePacket( dec_thread_t *p_dec )
return; return;
} }
/* Date management */
if( i_pts > 0 && i_pts != aout_DateGet( &p_dec->end_date ) )
{
aout_DateSet( &p_dec->end_date, i_pts );
}
if( vorbis_synthesis( &p_dec->vb, &oggpacket ) == 0 ) if( vorbis_synthesis( &p_dec->vb, &oggpacket ) == 0 )
vorbis_synthesis_blockin( &p_dec->vd, &p_dec->vb ); vorbis_synthesis_blockin( &p_dec->vd, &p_dec->vb );
else
msg_Err( p_dec->p_fifo, "vorbis_synthesis error" );
/* **pp_pcm is a multichannel float vector. In stereo, for /* **pp_pcm is a multichannel float vector. In stereo, for
* example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is
...@@ -277,16 +273,6 @@ static void DecodePacket( dec_thread_t *p_dec ) ...@@ -277,16 +273,6 @@ static void DecodePacket( dec_thread_t *p_dec )
p_aout_buffer->end_date = aout_DateIncrement( &p_dec->end_date, p_aout_buffer->end_date = aout_DateIncrement( &p_dec->end_date,
i_samples ); i_samples );
if( i_pts > 0 && i_pts != aout_DateGet( &p_dec->end_date ) )
{
aout_DateSet( &p_dec->end_date, i_pts );
p_aout_buffer->end_date = aout_DateGet( &p_dec->end_date );
}
else
{
aout_DateSet( &p_dec->end_date, p_aout_buffer->end_date );
}
aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer ); aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
} }
......
...@@ -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.2 2002/10/27 16:59:30 gbazin Exp $ * $Id: ogg.c,v 1.3 2002/11/02 18:13:22 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -54,10 +54,14 @@ typedef struct logical_stream_s ...@@ -54,10 +54,14 @@ 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 */
/* info for vorbis logical streams */ /* program clock reference (in units of 90kHz) derived from the previous
* granulepos */
mtime_t i_pcr;
/* info from logical streams */
int i_rate; int i_rate;
int i_channels;
int i_bitrate; int i_bitrate;
int b_reinit;
} logical_stream_t; } logical_stream_t;
...@@ -72,9 +76,14 @@ struct demux_sys_t ...@@ -72,9 +76,14 @@ struct demux_sys_t
logical_stream_t *p_stream_video; logical_stream_t *p_stream_video;
logical_stream_t *p_stream_audio; logical_stream_t *p_stream_audio;
mtime_t i_time; /* stream we use as a time reference for demux reading speed */
logical_stream_t *p_stream_timeref;
/* program clock reference (in units of 90kHz) derived from the pcr of
* one of the sub-streams (p_stream_timeref) */
mtime_t i_pcr;
mtime_t i_length; mtime_t i_length;
mtime_t i_pcr;
int b_seekable; int b_seekable;
}; };
...@@ -231,6 +240,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input, ...@@ -231,6 +240,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
{ {
pes_packet_t *p_pes; pes_packet_t *p_pes;
data_packet_t *p_data; data_packet_t *p_data;
demux_sys_t *p_ogg = p_input->p_demux_data;
if( !( p_pes = input_NewPES( p_input->p_method_data ) ) ) if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
{ {
...@@ -248,12 +258,28 @@ static void Ogg_DecodePacket( input_thread_t *p_input, ...@@ -248,12 +258,28 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
p_pes->i_pes_size = p_oggpacket->bytes; p_pes->i_pes_size = p_oggpacket->bytes;
p_pes->i_dts = p_oggpacket->granulepos; p_pes->i_dts = p_oggpacket->granulepos;
/* Convert the granule into a pts */ /* Convert the pcr into a pts */
p_pes->i_pts = (p_oggpacket->granulepos < 0) ? 0 : p_pes->i_pts = ( p_stream->i_pcr < 0 ) ? 0 :
p_oggpacket->granulepos * 90000 / p_stream->i_rate;
p_pes->i_pts = (p_oggpacket->granulepos < 0) ? 0 :
input_ClockGetTS( p_input, p_input->stream.p_selected_program, input_ClockGetTS( p_input, p_input->stream.p_selected_program,
p_pes->i_pts ); p_stream->i_pcr );
/* Convert the next granule into a pcr */
p_stream->i_pcr = ( p_oggpacket->granulepos < 0 ) ? -1 :
p_oggpacket->granulepos * 90000 / p_stream->i_rate;
/* Update the main pcr */
if( p_stream == p_ogg->p_stream_timeref )
{
if( p_ogg->p_stream_timeref->i_pcr >= 0 )
{
p_ogg->i_pcr = p_ogg->p_stream_timeref->i_pcr;
}
else
{
p_ogg->i_pcr += ( p_oggpacket->bytes * 90000
/ p_stream->i_bitrate / 8 );
}
}
memcpy( p_data->p_payload_start, p_oggpacket->packet, p_oggpacket->bytes ); memcpy( p_data->p_payload_start, p_oggpacket->packet, p_oggpacket->bytes );
...@@ -300,6 +326,10 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) ...@@ -300,6 +326,10 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
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 );
/* The first stream we find is our timeref (might be changed
* later on) */
p_ogg->p_stream_timeref = p_stream;
/* Extract the initial header from the first page and verify /* Extract the initial header from the first page and verify
* the codec type of tis Ogg bitstream */ * the codec type of tis Ogg bitstream */
if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 ) if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 )
...@@ -325,8 +355,7 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg) ...@@ -325,8 +355,7 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
/* 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, 88 ); oggpack_adv( &opb, 96 );
p_stream->i_channels = oggpack_read( &opb, 8 );
p_stream->i_rate = oggpack_read( &opb, 32 ); p_stream->i_rate = oggpack_read( &opb, 32 );
oggpack_adv( &opb, 32 ); oggpack_adv( &opb, 32 );
p_stream->i_bitrate = oggpack_read( &opb, 32 ); p_stream->i_bitrate = oggpack_read( &opb, 32 );
...@@ -389,8 +418,8 @@ static int Activate( vlc_object_t * p_this ) ...@@ -389,8 +418,8 @@ static int Activate( vlc_object_t * p_this )
memset( p_ogg, 0, sizeof( demux_sys_t ) ); memset( p_ogg, 0, sizeof( demux_sys_t ) );
p_input->p_demux_data = p_ogg; p_input->p_demux_data = p_ogg;
p_ogg->i_time = 0;
p_ogg->i_pcr = 0; p_ogg->i_pcr = 0;
p_ogg->p_stream_timeref = NULL;
p_ogg->b_seekable = ( ( p_input->stream.b_seekable ) p_ogg->b_seekable = ( ( p_input->stream.b_seekable )
&&( p_input->stream.i_method == INPUT_METHOD_FILE ) ); &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
...@@ -467,6 +496,7 @@ static int Activate( vlc_object_t * p_this ) ...@@ -467,6 +496,7 @@ static int Activate( vlc_object_t * p_this )
if( (p_ogg->p_stream_audio == NULL) ) if( (p_ogg->p_stream_audio == NULL) )
{ {
p_ogg->p_stream_audio = p_stream; p_ogg->p_stream_audio = p_stream;
p_ogg->p_stream_timeref = p_stream;
Ogg_StreamStart( p_input, p_ogg, i_stream ); Ogg_StreamStart( p_input, p_ogg, i_stream );
} }
break; break;
...@@ -490,6 +520,11 @@ static int Activate( vlc_object_t * p_this ) ...@@ -490,6 +520,11 @@ static int Activate( vlc_object_t * p_this )
p_input->stream.p_selected_program->b_is_ok = 1; p_input->stream.p_selected_program->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
/* Call the pace control */
input_ClockManageRef( p_input,
p_input->stream.p_selected_program,
p_ogg->i_pcr );
return 0; return 0;
error: error:
...@@ -530,7 +565,7 @@ static void Deactivate( vlc_object_t *p_this ) ...@@ -530,7 +565,7 @@ static void Deactivate( vlc_object_t *p_this )
*****************************************************************************/ *****************************************************************************/
static int Demux( input_thread_t * p_input ) static int Demux( input_thread_t * p_input )
{ {
int i, i_stream, b_eos; int i, i_stream, b_eos = 0;
ogg_page oggpage; ogg_page oggpage;
ogg_packet oggpacket; ogg_packet oggpacket;
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;
...@@ -555,7 +590,7 @@ static int Demux( input_thread_t * p_input ) ...@@ -555,7 +590,7 @@ static int Demux( input_thread_t * p_input )
} }
} }
/* search new video and audio stream selected /* search for new video and audio stream to select
* if current have been unselected */ * if current have been unselected */
if( ( !p_ogg->p_stream_video ) if( ( !p_ogg->p_stream_video )
|| ( !p_ogg->p_stream_video->p_es->p_decoder_fifo ) ) || ( !p_ogg->p_stream_video->p_es->p_decoder_fifo ) )
...@@ -581,33 +616,34 @@ static int Demux( input_thread_t * p_input ) ...@@ -581,33 +616,34 @@ static int Demux( input_thread_t * p_input )
&&( p_stream->p_es->p_decoder_fifo ) ) &&( p_stream->p_es->p_decoder_fifo ) )
{ {
p_ogg->p_stream_audio = p_stream; p_ogg->p_stream_audio = p_stream;
p_ogg->p_stream_timeref = p_stream;
break; break;
} }
} }
} }
/* Update program clock reference */ if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
p_ogg->i_pcr = p_ogg->i_time * 9 / 100;
if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
|| (input_ClockManageControl( p_input,
p_input->stream.p_selected_program,
(mtime_t)0 ) == PAUSE_S) )
{ {
msg_Warn( p_input, "synchro reinit" ); msg_Warn( p_input, "synchro reinit" );
p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
/* An ogg packet does only contain the starting date of the next
* packet, not its own starting date.
* As a quick work around, we just skip an oggpage */
for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
{
/* we'll trash all the data until we find the next pcr */
p_stream->b_reinit = 1;
p_ogg->i_pcr = 0;
}
} }
/* Call the pace control. */
input_ClockManageRef( p_input,
p_input->stream.p_selected_program,
p_ogg->i_pcr );
/* Demux ogg pages from the stream */ /* Demux ogg pages from the stream */
b_eos = 0; for( i = 0; (i < PAGES_READ_ONCE) || p_ogg->p_stream_timeref->b_reinit;
for( i = 0; i < PAGES_READ_ONCE; i++ ) i++ )
{ {
if( Ogg_ReadPage(p_input, p_ogg, &oggpage ) != VLC_SUCCESS ) if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS )
{ {
b_eos = 1; b_eos = 1;
break; break;
...@@ -622,27 +658,46 @@ static int Demux( input_thread_t * p_input ) ...@@ -622,27 +658,46 @@ static int Demux( input_thread_t * p_input )
while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
{ {
/* FIXME: handle discontinuity */
if( !p_stream->p_es || if( !p_stream->p_es ||
!p_stream->p_es->p_decoder_fifo ) !p_stream->p_es->p_decoder_fifo )
{ {
break; break;
} }
if( oggpacket.granulepos >= 0 ) if( p_stream->b_reinit )
p_ogg->i_time = oggpacket.granulepos * 1000000 {
/ p_stream->i_rate; if( oggpacket.granulepos >= 0 )
else {
p_ogg->i_time += (oggpacket.bytes * 1000000 p_stream->b_reinit = 0;
/ p_stream->i_bitrate); p_stream->i_pcr = oggpacket.granulepos
* 90000 / p_stream->i_rate;
if( !p_ogg->i_pcr ||
(p_stream == p_ogg->p_stream_timeref) )
{
/* Call the pace control to reinitialize
* the system clock */
p_ogg->i_pcr = p_stream->i_pcr;
input_ClockManageRef( p_input,
p_input->stream.p_selected_program,
p_ogg->i_pcr );
}
}
continue;
}
Ogg_DecodePacket( p_input, p_stream, &oggpacket ); Ogg_DecodePacket( p_input, p_stream, &oggpacket );
} }
} }
#undef p_stream #undef p_stream
} }
/* Call the pace control */
if( !b_eos ) input_ClockManageRef( p_input,
p_input->stream.p_selected_program,
p_ogg->i_pcr );
/* Did we reach the end of stream ? */ /* Did we reach the end of stream ? */
return( b_eos ? 0 : 1 ); return( b_eos ? 0 : 1 );
} }
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