]> git.sesse.net Git - vlc/blob - modules/demux/ogg.c
8fde9de4da03a697bc3a5b90fa5bc91af5672d49
[vlc] / modules / demux / ogg.c
1 /*****************************************************************************
2  * ogg.c : ogg stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: ogg.c,v 1.3 2002/11/02 18:13:22 gbazin Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc/input.h>
32
33 #include <sys/types.h>
34
35 #include <ogg/ogg.h>
36
37 #define OGG_BLOCK_SIZE 4096
38 #define PAGES_READ_ONCE 1
39
40 /*****************************************************************************
41  * Definitions of structures and functions used by this plugins 
42  *****************************************************************************/
43 typedef struct logical_stream_s
44 {
45     ogg_stream_state os;                        /* logical stream of packets */
46
47     int              i_serial_no;
48     int              i_pages_read;
49     int              i_cat;                            /* AUDIO_ES, VIDEO_ES */
50     int              i_activated;
51     vlc_fourcc_t     i_fourcc;
52     vlc_fourcc_t     i_codec;
53
54     es_descriptor_t  *p_es;   
55     int              b_selected;                           /* newly selected */
56
57     /* program clock reference (in units of 90kHz) derived from the previous
58      * granulepos */
59     mtime_t i_pcr;
60
61     /* info from logical streams */
62     int i_rate;
63     int i_bitrate;
64     int b_reinit;
65
66 } logical_stream_t;
67
68 struct demux_sys_t
69 {
70     ogg_sync_state oy;        /* sync and verify incoming physical bitstream */
71
72     int i_streams;                           /* number of logical bitstreams */
73     logical_stream_t **pp_stream;  /* pointer to an array of logical streams */
74
75     /* current audio and video es */
76     logical_stream_t *p_stream_video;
77     logical_stream_t *p_stream_audio;
78
79     /* stream we use as a time reference for demux reading speed */
80     logical_stream_t *p_stream_timeref;
81
82     /* program clock reference (in units of 90kHz) derived from the pcr of
83      * one of the sub-streams (p_stream_timeref) */
84     mtime_t i_pcr;
85
86     mtime_t i_length;
87     int     b_seekable;
88 };
89
90 /*****************************************************************************
91  * Local prototypes
92  *****************************************************************************/
93 static int  Activate  ( vlc_object_t * );
94 static void Deactivate( vlc_object_t * );
95 static int  Demux     ( input_thread_t * );
96
97 /* Stream managment */
98 static int  Ogg_StreamStart  ( input_thread_t *, demux_sys_t *, int );
99 static int  Ogg_StreamSeek   ( input_thread_t *, demux_sys_t *, int, mtime_t );
100 static void Ogg_StreamStop   ( input_thread_t *, demux_sys_t *, int );
101
102 /* Bitstream manipulation */
103 static int  Ogg_Check        ( input_thread_t *p_input );
104 static int  Ogg_ReadPage     ( input_thread_t *, demux_sys_t *, ogg_page * );
105 static void Ogg_DecodePacket ( input_thread_t *p_input,
106                                logical_stream_t *p_stream,
107                                ogg_packet *p_oggpacket );
108 static int  Ogg_FindLogicalStreams( input_thread_t *p_input,
109                                     demux_sys_t *p_ogg );
110
111 /*****************************************************************************
112  * Module descriptor
113  *****************************************************************************/
114 vlc_module_begin();
115     set_description( _("ogg stream demux" ) );
116     set_capability( "demux", 50 );
117     set_callbacks( Activate, Deactivate );
118     add_shortcut( "ogg" );
119 vlc_module_end();
120
121 /*****************************************************************************
122  * Stream managment
123  *****************************************************************************/
124 static int Ogg_StreamStart( input_thread_t *p_input,
125                             demux_sys_t *p_ogg, int i_stream )
126 {
127 #define p_stream p_ogg->pp_stream[i_stream]
128     if( !p_stream->p_es )
129     {
130         msg_Warn( p_input, "stream[%d] unselectable", i_stream );
131         return( 0 );
132     }
133     if( p_stream->i_activated )
134     {
135         msg_Warn( p_input, "stream[%d] already selected", i_stream );
136         return( 1 );
137     }
138
139     if( !p_stream->p_es->p_decoder_fifo )
140     {
141         vlc_mutex_lock( &p_input->stream.stream_lock );
142         input_SelectES( p_input, p_stream->p_es );
143         vlc_mutex_unlock( &p_input->stream.stream_lock );
144     }
145     p_stream->i_activated = p_stream->p_es->p_decoder_fifo ? 1 : 0;
146
147     //Ogg_StreamSeek( p_input, p_ogg, i_stream, p_ogg->i_time );
148
149     return( p_stream->i_activated );
150 #undef  p_stream
151 }
152
153 static void Ogg_StreamStop( input_thread_t *p_input,
154                             demux_sys_t *p_ogg, int i_stream )
155 {
156 #define p_stream    p_ogg->pp_stream[i_stream]
157
158     if( !p_stream->i_activated )
159     {
160         msg_Warn( p_input, "stream[%d] already unselected", i_stream );
161         return;
162     }
163
164     if( p_stream->p_es->p_decoder_fifo )
165     {
166         vlc_mutex_lock( &p_input->stream.stream_lock );
167         input_UnselectES( p_input, p_stream->p_es );
168         vlc_mutex_unlock( &p_input->stream.stream_lock );
169     }
170
171     p_stream->i_activated = 0;
172
173 #undef  p_stream
174 }
175
176 static int Ogg_StreamSeek( input_thread_t *p_input, demux_sys_t  *p_ogg,
177                            int i_stream, mtime_t i_date )
178 {
179 #define p_stream    p_ogg->pp_stream[i_stream]
180
181     /* FIXME: todo */
182
183     return 1;
184 #undef p_stream
185 }
186
187 /****************************************************************************
188  * Ogg_Check: Check we are dealing with an ogg stream.
189  ****************************************************************************/
190 static int Ogg_Check( input_thread_t *p_input )
191 {
192     u8 *p_peek;
193     int i_size = input_Peek( p_input, &p_peek, 4 );
194
195     /* Check for the Ogg capture pattern */
196     if( !(i_size>3) || !(p_peek[0] == 'O') || !(p_peek[1] == 'g') ||
197         !(p_peek[2] == 'g') || !(p_peek[3] == 'S') )
198         return VLC_EGENERIC;
199
200     /* FIXME: Capture pattern might not be enough so we can also check for the
201      * the first complete page */
202
203     return VLC_SUCCESS;
204 }
205
206 /****************************************************************************
207  * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
208  ****************************************************************************
209  * Returns VLC_SUCCESS if a page has been read. An error might happen if we
210  * are at the end of stream.
211  ****************************************************************************/
212 static int Ogg_ReadPage( input_thread_t *p_input, demux_sys_t *p_ogg,
213                          ogg_page *p_oggpage )
214 {
215     int i_read = 0;
216     data_packet_t *p_data;
217     byte_t *p_buffer;
218
219     while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
220     {
221         i_read = input_SplitBuffer( p_input, &p_data, OGG_BLOCK_SIZE );
222         if( i_read <= 0 )
223             return VLC_EGENERIC;
224
225         p_buffer = ogg_sync_buffer( &p_ogg->oy, i_read );
226         p_input->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start, i_read );
227         ogg_sync_wrote( &p_ogg->oy, i_read );
228         input_DeletePacket( p_input->p_method_data, p_data );
229     }
230
231     return VLC_SUCCESS;
232 }
233
234 /****************************************************************************
235  * Ogg_DecodePacket: Decode an Ogg packet.
236  ****************************************************************************/
237 static void Ogg_DecodePacket( input_thread_t *p_input,
238                               logical_stream_t *p_stream,
239                               ogg_packet *p_oggpacket )
240 {
241     pes_packet_t  *p_pes;
242     data_packet_t *p_data;
243     demux_sys_t *p_ogg = p_input->p_demux_data;
244
245     if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
246     {
247         return;
248     }
249     if( !( p_data = input_NewPacket( p_input->p_method_data,
250                                      p_oggpacket->bytes ) ) )
251     {
252         input_DeletePES( p_input->p_method_data, p_pes );
253         return;
254     }
255
256     p_pes->p_first = p_pes->p_last = p_data;
257     p_pes->i_nb_data = 1;
258     p_pes->i_pes_size = p_oggpacket->bytes;
259     p_pes->i_dts = p_oggpacket->granulepos;
260
261     /* Convert the pcr into a pts */
262     p_pes->i_pts = ( p_stream->i_pcr < 0 ) ? 0 :
263         input_ClockGetTS( p_input, p_input->stream.p_selected_program,
264                           p_stream->i_pcr );
265
266     /* Convert the next granule into a pcr */
267     p_stream->i_pcr = ( p_oggpacket->granulepos < 0 ) ? -1 :
268                            p_oggpacket->granulepos * 90000 / p_stream->i_rate;
269
270     /* Update the main pcr */
271     if( p_stream == p_ogg->p_stream_timeref )
272     {
273         if( p_ogg->p_stream_timeref->i_pcr >= 0 )
274         {
275             p_ogg->i_pcr = p_ogg->p_stream_timeref->i_pcr;
276         }
277         else
278         {
279             p_ogg->i_pcr += ( p_oggpacket->bytes * 90000
280                               / p_stream->i_bitrate / 8 );
281         }
282     }
283
284     memcpy( p_data->p_payload_start, p_oggpacket->packet, p_oggpacket->bytes );
285
286     input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
287 }
288
289 /****************************************************************************
290  * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
291  *                         stream and fill p_ogg.
292  *****************************************************************************
293  * The initial page of a logical stream is marked as a 'bos' page.
294  * Furthermore, the Ogg specification mandates that grouped bitstreams begin
295  * together and all of the initial pages must appear before any data pages.
296  *
297  * On success this function returns VLC_SUCCESS.
298  ****************************************************************************/
299 static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
300 {
301     ogg_packet oggpacket;
302     ogg_page oggpage;
303     int i_stream;
304
305     while( Ogg_ReadPage( p_input, p_ogg, &oggpage ) == VLC_SUCCESS )
306     {
307         if( ogg_page_bos( &oggpage ) )
308         {
309
310             /* All is wonderful in our fine fine little world.
311              * We found the beginning of our first logical stream. */
312             while( ogg_page_bos( &oggpage ) )
313             {
314                 p_ogg->i_streams++;
315                 p_ogg->pp_stream =
316                     realloc( p_ogg->pp_stream, p_ogg->i_streams *
317                              sizeof(logical_stream_t *) );
318
319 #define p_stream p_ogg->pp_stream[p_ogg->i_streams - 1]
320
321                 p_stream = malloc( sizeof(logical_stream_t) );
322                 memset( p_stream, 0, sizeof(logical_stream_t) );
323
324                 /* Setup the logical stream */
325                 p_stream->i_pages_read++;
326                 p_stream->i_serial_no = ogg_page_serialno( &oggpage );
327                 ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
328
329                 /* The first stream we find is our timeref (might be changed
330                  * later on) */
331                 p_ogg->p_stream_timeref = p_stream;
332
333                 /* Extract the initial header from the first page and verify
334                  * the codec type of tis Ogg bitstream */
335                 if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 )
336                 {
337                     /* error. stream version mismatch perhaps */
338                     msg_Err( p_input, "Error reading first page of "
339                              "Ogg bitstream data" );
340                     return VLC_EGENERIC;
341                 }
342
343                 /* FIXME: check return value */
344                 ogg_stream_packetpeek( &p_stream->os, &oggpacket );
345
346                 /* Check for Vorbis header */
347                 if( oggpacket.bytes >= 7 &&
348                     ! strncmp( &oggpacket.packet[1], "vorbis", 6 ) )
349                 {
350                     oggpack_buffer opb;
351
352                     msg_Dbg( p_input, "found vorbis header" );
353                     p_stream->i_cat = AUDIO_ES;
354                     p_stream->i_fourcc = VLC_FOURCC( 'v','o','r','b' );
355
356                     /* Cheat and get additionnal info ;) */
357                     oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
358                     oggpack_adv( &opb, 96 );
359                     p_stream->i_rate = oggpack_read( &opb, 32 );
360                     oggpack_adv( &opb, 32 );
361                     p_stream->i_bitrate = oggpack_read( &opb, 32 );
362                 }
363                 else
364                 {
365                     msg_Dbg( p_input, "found unknown codec" );
366                     ogg_stream_destroy( &p_stream->os );
367                     free( p_stream );
368                     p_ogg->i_streams--;
369                 }
370
371 #undef p_stream
372
373                 if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS )
374                     return VLC_EGENERIC;
375             }
376
377             /* This is the first data page, which means we are now finished
378              * with the initial pages. We just need to store it in the relevant
379              * bitstream. */
380             for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
381             {
382                 if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
383                                        &oggpage ) == 0 )
384                 {
385                     p_ogg->pp_stream[i_stream]->i_pages_read++;
386                     break;
387                 }
388             }
389             return VLC_SUCCESS;
390         }
391     }
392     return VLC_EGENERIC;
393 }
394
395 /*****************************************************************************
396  * Activate: initializes ogg demux structures
397  *****************************************************************************/
398 static int Activate( vlc_object_t * p_this )
399 {
400     int i_stream, b_forced;
401     demux_sys_t    *p_ogg;
402     input_thread_t *p_input = (input_thread_t *)p_this;
403
404     p_input->p_demux_data = NULL;
405     b_forced = ( ( *p_input->psz_demux )&&
406                  ( !strncmp( p_input->psz_demux, "ogg", 10 ) ) ) ? 1 : 0;
407
408     /* Check if we are dealing with an ogg stream */
409     if( !b_forced && ( Ogg_Check( p_input ) != VLC_SUCCESS ) )
410         return -1;
411
412     /* Allocate p_ogg */
413     if( !( p_ogg = malloc( sizeof( demux_sys_t ) ) ) )
414     {
415         msg_Err( p_input, "out of memory" );
416         goto error;
417     }
418     memset( p_ogg, 0, sizeof( demux_sys_t ) );
419     p_input->p_demux_data = p_ogg;
420
421     p_ogg->i_pcr  = 0;
422     p_ogg->p_stream_timeref = NULL;
423     p_ogg->b_seekable = ( ( p_input->stream.b_seekable )
424                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
425
426     /* Initialize the Ogg physical bitstream parser */
427     ogg_sync_init( &p_ogg->oy );
428
429     /* Find the logical streams embedded in the physical stream and
430      * initialize our p_ogg structure. */
431     if( Ogg_FindLogicalStreams( p_input, p_ogg ) != VLC_SUCCESS )
432     {
433         msg_Err( p_input, "couldn't find an ogg logical stream" );
434         goto error;
435     }
436
437     /* Set the demux function */
438     p_input->pf_demux = Demux;
439
440     /* Initialize access plug-in structures. */
441     if( p_input->i_mtu == 0 )
442     {
443         /* Improve speed. */
444         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
445     }
446
447     /* Create one program */
448     vlc_mutex_lock( &p_input->stream.stream_lock );
449     if( input_InitStream( p_input, 0 ) == -1)
450     {
451         vlc_mutex_unlock( &p_input->stream.stream_lock );
452         msg_Err( p_input, "cannot init stream" );
453         goto error;
454     }
455     if( input_AddProgram( p_input, 0, 0) == NULL )
456     {
457         vlc_mutex_unlock( &p_input->stream.stream_lock );
458         msg_Err( p_input, "cannot add program" );
459         goto error;
460     }
461     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
462     p_input->stream.i_mux_rate = 0;
463     vlc_mutex_unlock( &p_input->stream.stream_lock );
464
465     for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
466     {
467 #define p_stream p_ogg->pp_stream[i_stream]
468         vlc_mutex_lock( &p_input->stream.stream_lock );
469         p_stream->p_es = input_AddES( p_input,
470                                       p_input->stream.p_selected_program,
471                                       p_ogg->i_streams + 1, 0 );
472         p_input->stream.i_mux_rate += (p_stream->i_bitrate / ( 8 * 50 ));
473         vlc_mutex_unlock( &p_input->stream.stream_lock );
474         p_stream->p_es->i_stream_id = i_stream;
475         p_stream->p_es->i_fourcc = p_stream->i_fourcc;
476         p_stream->p_es->i_cat = p_stream->i_cat;
477 #undef p_stream
478     }
479
480     for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
481     {
482 #define p_stream  p_ogg->pp_stream[i_stream]
483         switch( p_stream->p_es->i_cat )
484         {
485             case( VIDEO_ES ):
486
487                 if( (p_ogg->p_stream_video == NULL) )
488                 {
489                     p_ogg->p_stream_video = p_stream;
490                     /* TODO add test to see if a decoder has been found */
491                     Ogg_StreamStart( p_input, p_ogg, i_stream );
492                 }
493                 break;
494
495             case( AUDIO_ES ):
496                 if( (p_ogg->p_stream_audio == NULL) )
497                 {
498                     p_ogg->p_stream_audio = p_stream;
499                     p_ogg->p_stream_timeref = p_stream;
500                     Ogg_StreamStart( p_input, p_ogg, i_stream );
501                 }
502                 break;
503
504             default:
505                 break;
506         }
507 #undef p_stream
508     }
509
510     /* we select the first audio and video ES */
511     vlc_mutex_lock( &p_input->stream.stream_lock );
512     if( !p_ogg->p_stream_video )
513     {
514         msg_Warn( p_input, "no video stream found" );
515     }
516     if( !p_ogg->p_stream_audio )
517     {
518         msg_Warn( p_input, "no audio stream found!" );
519     }
520     p_input->stream.p_selected_program->b_is_ok = 1;
521     vlc_mutex_unlock( &p_input->stream.stream_lock );
522
523     /* Call the pace control */
524     input_ClockManageRef( p_input,
525                           p_input->stream.p_selected_program,
526                           p_ogg->i_pcr );
527
528     return 0;
529
530  error:
531     Deactivate( (vlc_object_t *)p_input );
532     return -1;
533
534 }
535
536 /*****************************************************************************
537  * Deactivate: frees unused data
538  *****************************************************************************/
539 static void Deactivate( vlc_object_t *p_this )
540 {
541     input_thread_t *p_input = (input_thread_t *)p_this;
542     demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ; 
543     int i;
544
545     if( p_ogg )
546     {
547         /* Cleanup the bitstream parser */
548         ogg_sync_clear( &p_ogg->oy );
549
550         for( i = 0; i < p_ogg->i_streams; i++ )
551         {
552             ogg_stream_clear( &p_ogg->pp_stream[i]->os );
553             free( p_ogg->pp_stream[i] );
554         }
555         if( p_ogg->pp_stream ) free( p_ogg->pp_stream );
556
557         free( p_ogg );
558     }
559 }
560
561 /*****************************************************************************
562  * Demux: reads and demuxes data packets
563  *****************************************************************************
564  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
565  *****************************************************************************/
566 static int Demux( input_thread_t * p_input )
567 {
568     int i, i_stream, b_eos = 0;
569     ogg_page    oggpage;
570     ogg_packet  oggpacket;
571     demux_sys_t *p_ogg  = (demux_sys_t *)p_input->p_demux_data;
572
573 #define p_stream p_ogg->pp_stream[i_stream]
574     /* detect new selected/unselected streams */
575     for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
576     {
577         if( p_stream->p_es )
578         {
579             if( p_stream->p_es->p_decoder_fifo &&
580                 !p_stream->i_activated )
581             {
582                 Ogg_StreamStart( p_input, p_ogg, i_stream );
583             }
584             else
585             if( !p_stream->p_es->p_decoder_fifo &&
586                 p_stream->i_activated )
587             {
588                 Ogg_StreamStop( p_input, p_ogg, i_stream );
589             }
590         }
591     }
592
593     /* search for new video and audio stream to select
594      * if current have been unselected */
595     if( ( !p_ogg->p_stream_video )
596             || ( !p_ogg->p_stream_video->p_es->p_decoder_fifo ) )
597     {
598         p_ogg->p_stream_video = NULL;
599         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
600         {
601             if( ( p_stream->i_cat == VIDEO_ES )
602                   &&( p_stream->p_es->p_decoder_fifo ) )
603             {
604                 p_ogg->p_stream_video = p_stream;
605                 break;
606             }
607         }
608     }
609     if( ( !p_ogg->p_stream_audio )
610             ||( !p_ogg->p_stream_audio->p_es->p_decoder_fifo ) )
611     {
612         p_ogg->p_stream_audio = NULL;
613         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
614         {
615             if( ( p_stream->i_cat == AUDIO_ES )
616                   &&( p_stream->p_es->p_decoder_fifo ) )
617             {
618                 p_ogg->p_stream_audio = p_stream;
619                 p_ogg->p_stream_timeref = p_stream;
620                 break;
621             }
622         }
623     }
624
625     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
626     {
627         msg_Warn( p_input, "synchro reinit" );
628
629         /* An ogg packet does only contain the starting date of the next
630          * packet, not its own starting date.
631          * As a quick work around, we just skip an oggpage */
632
633         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
634         {
635             /* we'll trash all the data until we find the next pcr */
636             p_stream->b_reinit = 1;
637             p_ogg->i_pcr = 0;
638         }
639     }
640
641
642     /* Demux ogg pages from the stream */
643     for( i = 0; (i < PAGES_READ_ONCE) || p_ogg->p_stream_timeref->b_reinit;
644          i++ )
645     {
646         if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS )
647         {
648             b_eos = 1;
649             break;
650         }
651
652         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
653         {
654             /* FIXME: we already read the header */
655
656             if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 )
657                 continue;
658
659             while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
660             {
661                 if( !p_stream->p_es ||
662                     !p_stream->p_es->p_decoder_fifo )
663                 {
664                     break;
665                 }
666
667                 if( p_stream->b_reinit )
668                 {
669                     if( oggpacket.granulepos >= 0 )
670                     {
671                         p_stream->b_reinit = 0;
672                         p_stream->i_pcr = oggpacket.granulepos
673                             * 90000 / p_stream->i_rate;
674
675                         if( !p_ogg->i_pcr ||
676                             (p_stream == p_ogg->p_stream_timeref) )
677                         {
678                             /* Call the pace control to reinitialize
679                              * the system clock */
680                             p_ogg->i_pcr = p_stream->i_pcr;
681                             input_ClockManageRef( p_input,
682                                p_input->stream.p_selected_program,
683                                p_ogg->i_pcr );
684                         }
685                     }
686                     continue;
687                 }
688
689                 Ogg_DecodePacket( p_input, p_stream, &oggpacket );
690
691             }
692         }
693 #undef p_stream
694     }
695
696     /* Call the pace control */
697     if( !b_eos ) input_ClockManageRef( p_input,
698                                        p_input->stream.p_selected_program,
699                                        p_ogg->i_pcr );
700
701     /* Did we reach the end of stream ? */
702     return( b_eos ? 0 : 1 );
703 }