]> git.sesse.net Git - vlc/blob - modules/demux/ogg.c
* modules/codec/spudec/*: modified the spu decoder to handle text subtitles.
[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.8 2002/11/06 21:48:23 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 #include <codecs.h>                        /* BITMAPINFOHEADER, WAVEFORMATEX */
38
39 #define OGG_BLOCK_SIZE 4096
40 #define PAGES_READ_ONCE 1
41
42 /*****************************************************************************
43  * Definitions of structures and functions used by this plugins 
44  *****************************************************************************/
45 typedef struct logical_stream_s
46 {
47     ogg_stream_state os;                        /* logical stream of packets */
48
49     int              i_serial_no;
50     int              i_cat;                            /* AUDIO_ES, VIDEO_ES */
51     int              i_activated;
52     vlc_fourcc_t     i_fourcc;
53     vlc_fourcc_t     i_codec;
54
55     es_descriptor_t  *p_es;   
56     int              b_selected;                           /* newly selected */
57
58     /* the header of some logical streams (eg vorbis) contain essential
59      * data for the decoder. We back them up here in case we need to re-feed
60      * them to the decoder. */
61     int              b_force_backup;
62     int              i_packets_backup;
63     ogg_packet       *p_packets_backup;
64
65     /* program clock reference (in units of 90kHz) derived from the previous
66      * granulepos */
67     mtime_t i_pcr;
68     long    l_previous_granulepos;
69
70     /* info from logical streams */
71     double i_rate;
72     int i_bitrate;
73     int b_reinit;
74
75     BITMAPINFOHEADER *p_bih;
76     WAVEFORMATEX *p_wf;
77
78 } logical_stream_t;
79
80 struct demux_sys_t
81 {
82     ogg_sync_state oy;        /* sync and verify incoming physical bitstream */
83
84     int i_streams;                           /* number of logical bitstreams */
85     logical_stream_t **pp_stream;  /* pointer to an array of logical streams */
86
87     /* current audio and video es */
88     logical_stream_t *p_stream_video;
89     logical_stream_t *p_stream_audio;
90     logical_stream_t *p_stream_spu;
91
92     /* stream we use as a time reference for demux reading speed */
93     logical_stream_t *p_stream_timeref;
94
95     /* program clock reference (in units of 90kHz) derived from the pcr of
96      * one of the sub-streams (p_stream_timeref) */
97     mtime_t i_pcr;
98
99     mtime_t i_length;
100     int     b_seekable;
101 };
102
103 /* OggDS headers for the new header format (used in ogm files) */
104 typedef struct stream_header_video
105 {
106     ogg_int32_t width;
107     ogg_int32_t height;
108 } stream_header_video;
109         
110 typedef struct stream_header_audio
111 {
112     ogg_int16_t channels;
113     ogg_int16_t blockalign;
114     ogg_int32_t avgbytespersec;
115 } stream_header_audio;
116
117 typedef struct stream_header
118 {
119     char        streamtype[8];
120     char        subtype[4];
121
122     ogg_int32_t size;                               /* size of the structure */
123
124     ogg_int64_t time_unit;                              /* in reference time */
125     ogg_int64_t samples_per_unit;
126     ogg_int32_t default_len;                                /* in media time */
127
128     ogg_int32_t buffersize;
129     ogg_int16_t bits_per_sample;
130
131     union
132     {
133         /* Video specific */
134         stream_header_video video;
135         /* Audio specific */
136         stream_header_audio audio;
137     } sh;
138 } stream_header;
139
140 /* Some defines from OggDS */
141 #define PACKET_TYPE_HEADER   0x01
142 #define PACKET_TYPE_BITS     0x07
143 #define PACKET_LEN_BITS01    0xc0
144 #define PACKET_LEN_BITS2     0x02
145 #define PACKET_IS_SYNCPOINT  0x08
146
147 /* Some functions to manipulate memory */
148 static uint16_t GetWLE( uint8_t *p_buff )
149 {
150     return( (p_buff[0]) + ( p_buff[1] <<8 ) );
151 }
152
153 static uint32_t GetDWLE( uint8_t *p_buff )
154 {
155     return( p_buff[0] + ( p_buff[1] <<8 ) +
156             ( p_buff[2] <<16 ) + ( p_buff[3] <<24 ) );
157 }
158
159 static uint64_t GetQWLE( uint8_t *p_buff )
160 {
161     return( GetDWLE( p_buff ) + ( ((uint64_t)GetDWLE( p_buff + 4 )) << 32 ) );
162 }
163 /*****************************************************************************
164  * Local prototypes
165  *****************************************************************************/
166 static int  Activate  ( vlc_object_t * );
167 static void Deactivate( vlc_object_t * );
168 static int  Demux     ( input_thread_t * );
169
170 /* Stream managment */
171 static int  Ogg_StreamStart  ( input_thread_t *, demux_sys_t *, int );
172 static void Ogg_StreamStop   ( input_thread_t *, demux_sys_t *, int );
173
174 /* Bitstream manipulation */
175 static int  Ogg_Check        ( input_thread_t *p_input );
176 static int  Ogg_ReadPage     ( input_thread_t *, demux_sys_t *, ogg_page * );
177 static void Ogg_DecodePacket ( input_thread_t *p_input,
178                                logical_stream_t *p_stream,
179                                ogg_packet *p_oggpacket );
180 static int  Ogg_FindLogicalStreams( input_thread_t *p_input,
181                                     demux_sys_t *p_ogg );
182
183 /*****************************************************************************
184  * Module descriptor
185  *****************************************************************************/
186 vlc_module_begin();
187     set_description( _("ogg stream demux" ) );
188     set_capability( "demux", 50 );
189     set_callbacks( Activate, Deactivate );
190     add_shortcut( "ogg" );
191 vlc_module_end();
192
193 /*****************************************************************************
194  * Stream managment
195  *****************************************************************************/
196 static int Ogg_StreamStart( input_thread_t *p_input,
197                             demux_sys_t *p_ogg, int i_stream )
198 {
199 #define p_stream p_ogg->pp_stream[i_stream]
200     if( !p_stream->p_es )
201     {
202         msg_Warn( p_input, "stream[%d] unselectable", i_stream );
203         return( 0 );
204     }
205     if( p_stream->i_activated )
206     {
207         msg_Warn( p_input, "stream[%d] already selected", i_stream );
208         return( 1 );
209     }
210
211     if( !p_stream->p_es->p_decoder_fifo )
212     {
213         vlc_mutex_lock( &p_input->stream.stream_lock );
214         input_SelectES( p_input, p_stream->p_es );
215         vlc_mutex_unlock( &p_input->stream.stream_lock );
216     }
217     p_stream->i_activated = p_stream->p_es->p_decoder_fifo ? 1 : 0;
218
219     /* Feed the backup header to the decoder */
220     if( !p_stream->b_force_backup )
221     {
222         int i;
223         for( i = 0; i < p_stream->i_packets_backup; i++ )
224         {
225             Ogg_DecodePacket( p_input, p_stream,
226                               &p_stream->p_packets_backup[i] );
227         }
228     }
229
230     return( p_stream->i_activated );
231 #undef  p_stream
232 }
233
234 static void Ogg_StreamStop( input_thread_t *p_input,
235                             demux_sys_t *p_ogg, int i_stream )
236 {
237 #define p_stream    p_ogg->pp_stream[i_stream]
238
239     if( !p_stream->i_activated )
240     {
241         msg_Warn( p_input, "stream[%d] already unselected", i_stream );
242         return;
243     }
244
245     if( p_stream->p_es->p_decoder_fifo )
246     {
247         vlc_mutex_lock( &p_input->stream.stream_lock );
248         input_UnselectES( p_input, p_stream->p_es );
249         vlc_mutex_unlock( &p_input->stream.stream_lock );
250     }
251
252     p_stream->i_activated = 0;
253
254 #undef  p_stream
255 }
256
257 /****************************************************************************
258  * Ogg_Check: Check we are dealing with an ogg stream.
259  ****************************************************************************/
260 static int Ogg_Check( input_thread_t *p_input )
261 {
262     u8 *p_peek;
263     int i_size = input_Peek( p_input, &p_peek, 4 );
264
265     /* Check for the Ogg capture pattern */
266     if( !(i_size>3) || !(p_peek[0] == 'O') || !(p_peek[1] == 'g') ||
267         !(p_peek[2] == 'g') || !(p_peek[3] == 'S') )
268         return VLC_EGENERIC;
269
270     /* FIXME: Capture pattern might not be enough so we can also check for the
271      * the first complete page */
272
273     return VLC_SUCCESS;
274 }
275
276 /****************************************************************************
277  * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
278  ****************************************************************************
279  * Returns VLC_SUCCESS if a page has been read. An error might happen if we
280  * are at the end of stream.
281  ****************************************************************************/
282 static int Ogg_ReadPage( input_thread_t *p_input, demux_sys_t *p_ogg,
283                          ogg_page *p_oggpage )
284 {
285     int i_read = 0;
286     data_packet_t *p_data;
287     byte_t *p_buffer;
288
289     while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
290     {
291         i_read = input_SplitBuffer( p_input, &p_data, OGG_BLOCK_SIZE );
292         if( i_read <= 0 )
293             return VLC_EGENERIC;
294
295         p_buffer = ogg_sync_buffer( &p_ogg->oy, i_read );
296         p_input->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start, i_read );
297         ogg_sync_wrote( &p_ogg->oy, i_read );
298         input_DeletePacket( p_input->p_method_data, p_data );
299     }
300
301     return VLC_SUCCESS;
302 }
303
304 /****************************************************************************
305  * Ogg_DecodePacket: Decode an Ogg packet.
306  ****************************************************************************/
307 static void Ogg_DecodePacket( input_thread_t *p_input,
308                               logical_stream_t *p_stream,
309                               ogg_packet *p_oggpacket )
310 {
311     pes_packet_t  *p_pes;
312     data_packet_t *p_data;
313     demux_sys_t *p_ogg = p_input->p_demux_data;
314     int i_header_len = 0;
315
316     if( p_stream->b_force_backup )
317     {
318         /* Backup the ogg packet (likely an header) */
319         ogg_packet *p_packet_backup;
320         p_stream->i_packets_backup++;
321         p_stream->p_packets_backup =
322             realloc( p_stream->p_packets_backup, p_stream->i_packets_backup *
323                      sizeof(ogg_packet) );
324
325         p_packet_backup =
326             &p_stream->p_packets_backup[p_stream->i_packets_backup - 1];
327
328         p_packet_backup->bytes = p_oggpacket->bytes;
329         p_packet_backup->granulepos = p_oggpacket->granulepos;
330         p_packet_backup->packet = malloc( p_oggpacket->bytes );
331         if( !p_packet_backup->packet ) return;
332         memcpy( p_packet_backup->packet, p_oggpacket->packet,
333                 p_oggpacket->bytes );
334
335         switch( p_stream->i_fourcc )
336         {
337         case VLC_FOURCC( 'v','o','r','b' ):
338           if( p_stream->i_packets_backup == 3 ) p_stream->b_force_backup = 0;
339           break;
340
341         default:
342           p_stream->b_force_backup = 0;
343           break;
344         }
345     }
346
347     if( !p_stream->p_es->p_decoder_fifo )
348     {
349         /* This stream isn't currently selected so we don't need to decode it,
350          * but we do need to store its pcr as it might be selected later on. */
351
352         /* Convert the next granule into a pcr */
353         p_stream->i_pcr = ( p_oggpacket->granulepos < 0 ) ?
354             p_stream->i_pcr + ( p_oggpacket->bytes * 90000
355                 / p_stream->i_bitrate / 8 ):
356             p_oggpacket->granulepos * 90000 / p_stream->i_rate;
357
358         return;
359     }
360
361     if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
362     {
363         return;
364     }
365     if( !( p_data = input_NewPacket( p_input->p_method_data,
366                                      p_oggpacket->bytes ) ) )
367     {
368         input_DeletePES( p_input->p_method_data, p_pes );
369         return;
370     }
371
372     /* Convert the pcr into a pts */
373     if( p_stream->i_cat != SPU_ES )
374     {
375         p_pes->i_pts = ( p_stream->i_pcr < 0 ) ? 0 :
376             input_ClockGetTS( p_input, p_input->stream.p_selected_program,
377                               p_stream->i_pcr );
378     }
379     else
380     {
381         /* Of course subtitles had to be different! */
382         p_pes->i_pts = ( p_oggpacket->granulepos < 0 ) ? 0 :
383             input_ClockGetTS( p_input, p_input->stream.p_selected_program,
384                               p_oggpacket->granulepos * 90000 /
385                               p_stream->i_rate );
386     }
387
388     /* Convert the next granule into a pcr */
389     if( p_oggpacket->granulepos < 0 )
390     {
391         /* FIXME: ffmpeg doesn't like null pts */
392         if( p_stream->i_cat == VIDEO_ES )
393             p_stream->i_pcr += (90000 / p_stream->i_rate);
394         else
395             p_stream->i_pcr = -1;
396     }
397     else
398     {
399         p_stream->i_pcr = p_oggpacket->granulepos * 90000 / p_stream->i_rate;
400     }
401
402     /* Update the main pcr */
403     if( p_stream == p_ogg->p_stream_timeref )
404     {
405         if( p_ogg->p_stream_timeref->i_pcr >= 0 )
406         {
407             p_ogg->i_pcr = p_ogg->p_stream_timeref->i_pcr;
408         }
409         else
410         {
411             p_ogg->i_pcr += ( p_oggpacket->bytes * 90000
412                               / p_stream->i_bitrate / 8 );
413         }
414     }
415
416     p_pes->i_nb_data = 1;
417     p_pes->i_dts = p_oggpacket->granulepos;
418     p_pes->p_first = p_pes->p_last = p_data;
419     p_pes->i_pes_size = p_oggpacket->bytes;
420
421     if( p_stream->i_fourcc != VLC_FOURCC( 'v','o','r','b' ) )
422     {
423         /* Remove the header from the packet */
424         i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
425         i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
426         i_header_len++;
427
428         p_pes->i_pes_size -= i_header_len;
429     }
430
431     memcpy( p_data->p_payload_start,
432             p_oggpacket->packet + i_header_len,
433             p_oggpacket->bytes - i_header_len );
434
435     p_data->p_payload_end = p_data->p_payload_start + p_pes->i_pes_size;
436     p_data->b_discard_payload = 0;
437
438     input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
439 }
440
441 /****************************************************************************
442  * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
443  *                         stream and fill p_ogg.
444  *****************************************************************************
445  * The initial page of a logical stream is marked as a 'bos' page.
446  * Furthermore, the Ogg specification mandates that grouped bitstreams begin
447  * together and all of the initial pages must appear before any data pages.
448  *
449  * On success this function returns VLC_SUCCESS.
450  ****************************************************************************/
451 static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
452 {
453     ogg_packet oggpacket;
454     ogg_page oggpage;
455     int i_stream;
456
457     while( Ogg_ReadPage( p_input, p_ogg, &oggpage ) == VLC_SUCCESS )
458     {
459         if( ogg_page_bos( &oggpage ) )
460         {
461
462             /* All is wonderful in our fine fine little world.
463              * We found the beginning of our first logical stream. */
464             while( ogg_page_bos( &oggpage ) )
465             {
466                 p_ogg->i_streams++;
467                 p_ogg->pp_stream =
468                     realloc( p_ogg->pp_stream, p_ogg->i_streams *
469                              sizeof(logical_stream_t *) );
470
471 #define p_stream p_ogg->pp_stream[p_ogg->i_streams - 1]
472
473                 p_stream = malloc( sizeof(logical_stream_t) );
474                 memset( p_stream, 0, sizeof(logical_stream_t) );
475
476                 /* Setup the logical stream */
477                 p_stream->i_serial_no = ogg_page_serialno( &oggpage );
478                 ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
479
480                 /* The first stream we find is our timeref (might be changed
481                  * later on) */
482                 p_ogg->p_stream_timeref = p_stream;
483
484                 /* Extract the initial header from the first page and verify
485                  * the codec type of tis Ogg bitstream */
486                 if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 )
487                 {
488                     /* error. stream version mismatch perhaps */
489                     msg_Err( p_input, "Error reading first page of "
490                              "Ogg bitstream data" );
491                     return VLC_EGENERIC;
492                 }
493
494                 /* FIXME: check return value */
495                 ogg_stream_packetpeek( &p_stream->os, &oggpacket );
496
497                 /* Check for Vorbis header */
498                 if( oggpacket.bytes >= 7 &&
499                     ! strncmp( &oggpacket.packet[1], "vorbis", 6 ) )
500                 {
501                     oggpack_buffer opb;
502
503                     msg_Dbg( p_input, "found vorbis header" );
504                     p_stream->i_cat = AUDIO_ES;
505                     p_stream->i_fourcc = VLC_FOURCC( 'v','o','r','b' );
506
507                     /* Signal that we want to keep a backup of the vorbis
508                      * stream headers. They will be used when switching between
509                      * audio streams. */
510                     p_stream->b_force_backup = 1;
511
512                     /* Cheat and get additionnal info ;) */
513                     oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
514                     oggpack_adv( &opb, 96 );
515                     p_stream->i_rate = oggpack_read( &opb, 32 );
516                     oggpack_adv( &opb, 32 );
517                     p_stream->i_bitrate = oggpack_read( &opb, 32 );
518                 }
519                 else if( (*oggpacket.packet & PACKET_TYPE_BITS )
520                          == PACKET_TYPE_HEADER && 
521                          oggpacket.bytes >= (int)sizeof(stream_header)+1 )
522                 {
523                     stream_header *st = (stream_header *)(oggpacket.packet+1);
524
525                     /* Check for video header (new format) */
526                     if( !strncmp( st->streamtype, "video", 5 ) )
527                     {
528                         p_stream->i_cat = VIDEO_ES;
529
530                         /* We need to get rid of the header packet */
531                         ogg_stream_packetout( &p_stream->os, &oggpacket );
532
533                         p_stream->p_bih = (BITMAPINFOHEADER *)
534                             malloc( sizeof(BITMAPINFOHEADER) );
535                         if( !p_stream->p_bih )
536                         {
537                             /* Mem allocation error, just ignore the stream */
538                             free( p_stream );
539                             p_ogg->i_streams--;
540                             continue;
541                         }
542                         p_stream->p_bih->biSize = sizeof(BITMAPINFOHEADER);
543                         p_stream->p_bih->biCompression=
544                             p_stream->i_fourcc = VLC_FOURCC( st->subtype[0],
545                                                              st->subtype[1],
546                                                              st->subtype[2],
547                                                              st->subtype[3] );
548                         msg_Dbg( p_input, "found video header of type: %.4s",
549                                  (char *)&p_stream->i_fourcc );
550
551                         p_stream->i_rate = 10000000.0 /
552                             GetQWLE((uint8_t *)&st->time_unit);
553                         p_stream->p_bih->biBitCount =
554                             GetWLE((uint8_t *)&st->bits_per_sample);
555                         p_stream->p_bih->biWidth =
556                             GetDWLE((uint8_t *)&st->sh.video.width);
557                         p_stream->p_bih->biHeight =
558                             GetDWLE((uint8_t *)&st->sh.video.height);
559                         p_stream->p_bih->biPlanes= 1 ;
560                         p_stream->p_bih->biSizeImage =
561                             (p_stream->p_bih->biBitCount >> 3) *
562                             p_stream->p_bih->biWidth *
563                             p_stream->p_bih->biHeight;
564
565                         msg_Dbg( p_input,
566                              "fps: %f, width:%i; height:%i, bitcount:%i",
567                             p_stream->i_rate, p_stream->p_bih->biWidth,
568                             p_stream->p_bih->biHeight,
569                             p_stream->p_bih->biBitCount);
570
571                         p_stream->i_bitrate = 1; /* FIXME */
572                     }
573                     /* Check for audio header (new format) */
574                     else if( !strncmp( st->streamtype, "audio", 5 ) )
575                     {
576                         char p_buffer[5];
577
578                         p_stream->i_cat = AUDIO_ES;
579
580                         /* We need to get rid of the header packet */
581                         ogg_stream_packetout( &p_stream->os, &oggpacket );
582
583                         p_stream->p_wf = (WAVEFORMATEX *)
584                             malloc( sizeof(WAVEFORMATEX) );
585                         if( !p_stream->p_wf )
586                         {
587                             /* Mem allocation error, just ignore the stream */
588                             free( p_stream );
589                             p_ogg->i_streams--;
590                             continue;
591                         }
592
593                         memcpy( p_buffer, st->subtype, 4 );
594                         p_buffer[4] = '\0';
595                         p_stream->p_wf->wFormatTag = strtol(p_buffer,NULL,16);
596                         p_stream->p_wf->nChannels =
597                             GetWLE((uint8_t *)&st->sh.audio.channels);
598                         p_stream->i_rate = p_stream->p_wf->nSamplesPerSec =
599                             GetQWLE((uint8_t *)&st->samples_per_unit);
600                         p_stream->i_bitrate = p_stream->p_wf->nAvgBytesPerSec =
601                             GetDWLE((uint8_t *)&st->sh.audio.avgbytespersec);
602                         p_stream->i_bitrate *= 8;
603                         p_stream->p_wf->nBlockAlign =
604                             GetWLE((uint8_t *)&st->sh.audio.blockalign);
605                         p_stream->p_wf->wBitsPerSample =
606                             GetWLE((uint8_t *)&st->bits_per_sample);
607                         p_stream->p_wf->cbSize = 0;
608
609                         switch( p_stream->p_wf->wFormatTag )
610                         {
611                         case WAVE_FORMAT_PCM:
612                             p_stream->i_fourcc =
613                                 VLC_FOURCC( 'a', 'r', 'a', 'w' );
614                             break;
615                         case WAVE_FORMAT_MPEG:
616                         case WAVE_FORMAT_MPEGLAYER3:
617                             p_stream->i_fourcc =
618                                 VLC_FOURCC( 'm', 'p', 'g', 'a' );
619                             break;
620                         case WAVE_FORMAT_A52:
621                             p_stream->i_fourcc =
622                                 VLC_FOURCC( 'a', '5', '2', ' ' );
623                             break;
624                         case WAVE_FORMAT_WMA1:
625                             p_stream->i_fourcc =
626                                 VLC_FOURCC( 'w', 'm', 'a', '1' );
627                             break;
628                         case WAVE_FORMAT_WMA2:
629                             p_stream->i_fourcc =
630                                 VLC_FOURCC( 'w', 'm', 'a', '2' );
631                             break;
632                         default:
633                             p_stream->i_fourcc = VLC_FOURCC( 'm', 's',
634                                 ( p_stream->p_wf->wFormatTag >> 8 ) & 0xff,
635                                 p_stream->p_wf->wFormatTag & 0xff );
636                         }
637
638                         msg_Dbg( p_input, "found audio header of type: %.4s",
639                                  (char *)&p_stream->i_fourcc );
640                         msg_Dbg( p_input, "audio:0x%4.4x channels:%d %dHz "
641                                  "%dbits/sample %dkb/s",
642                                  p_stream->p_wf->wFormatTag,
643                                  p_stream->p_wf->nChannels,
644                                  p_stream->p_wf->nSamplesPerSec,
645                                  p_stream->p_wf->wBitsPerSample,
646                                  p_stream->p_wf->nAvgBytesPerSec * 8 / 1024 );
647                     }
648                     /* Check for text (subtitles) header */
649                     else if( !strncmp(st->streamtype, "text", 4) )
650                     {
651                         /* We need to get rid of the header packet */
652                         ogg_stream_packetout( &p_stream->os, &oggpacket );
653
654                         msg_Dbg( p_input, "found text subtitles header" );
655                         p_stream->i_cat = SPU_ES;
656                         p_stream->i_fourcc =
657                             VLC_FOURCC( 's', 'u', 'b', 't' );
658                         p_stream->i_rate = 1000; /* granulepos is in milisec */
659                     }
660                     else
661                     {
662                         msg_Dbg( p_input, "stream %d has a header marker "
663                             "but is of an unknown type", p_ogg->i_streams-1 );
664                         free( p_stream );
665                         p_ogg->i_streams--;
666                     }
667                 }
668                 else
669                 {
670                     msg_Dbg( p_input, "stream %d is of unknown type",
671                              p_ogg->i_streams-1 );
672                     free( p_stream );
673                     p_ogg->i_streams--;
674                 }
675
676 #undef p_stream
677
678                 if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS )
679                     return VLC_EGENERIC;
680             }
681
682             /* This is the first data page, which means we are now finished
683              * with the initial pages. We just need to store it in the relevant
684              * bitstream. */
685             for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
686             {
687                 if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
688                                        &oggpage ) == 0 )
689                 {
690                     break;
691                 }
692             }
693             return VLC_SUCCESS;
694         }
695     }
696     return VLC_EGENERIC;
697 }
698
699 /*****************************************************************************
700  * Activate: initializes ogg demux structures
701  *****************************************************************************/
702 static int Activate( vlc_object_t * p_this )
703 {
704     int i_stream, b_forced;
705     demux_sys_t    *p_ogg;
706     input_thread_t *p_input = (input_thread_t *)p_this;
707
708     p_input->p_demux_data = NULL;
709     b_forced = ( ( *p_input->psz_demux )&&
710                  ( !strncmp( p_input->psz_demux, "ogg", 10 ) ) ) ? 1 : 0;
711
712     /* Check if we are dealing with an ogg stream */
713     if( !b_forced && ( Ogg_Check( p_input ) != VLC_SUCCESS ) )
714         return -1;
715
716     /* Allocate p_ogg */
717     if( !( p_ogg = malloc( sizeof( demux_sys_t ) ) ) )
718     {
719         msg_Err( p_input, "out of memory" );
720         goto error;
721     }
722     memset( p_ogg, 0, sizeof( demux_sys_t ) );
723     p_input->p_demux_data = p_ogg;
724
725     p_ogg->i_pcr  = 0;
726     p_ogg->p_stream_timeref = NULL;
727     p_ogg->b_seekable = ( ( p_input->stream.b_seekable )
728                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
729
730     /* Initialize the Ogg physical bitstream parser */
731     ogg_sync_init( &p_ogg->oy );
732
733     /* Find the logical streams embedded in the physical stream and
734      * initialize our p_ogg structure. */
735     if( Ogg_FindLogicalStreams( p_input, p_ogg ) != VLC_SUCCESS )
736     {
737         msg_Err( p_input, "couldn't find an ogg logical stream" );
738         goto error;
739     }
740
741     /* Set the demux function */
742     p_input->pf_demux = Demux;
743
744     /* Initialize access plug-in structures. */
745     if( p_input->i_mtu == 0 )
746     {
747         /* Improve speed. */
748         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
749     }
750
751     /* Create one program */
752     vlc_mutex_lock( &p_input->stream.stream_lock );
753     if( input_InitStream( p_input, 0 ) == -1)
754     {
755         vlc_mutex_unlock( &p_input->stream.stream_lock );
756         msg_Err( p_input, "cannot init stream" );
757         goto error;
758     }
759     if( input_AddProgram( p_input, 0, 0) == NULL )
760     {
761         vlc_mutex_unlock( &p_input->stream.stream_lock );
762         msg_Err( p_input, "cannot add program" );
763         goto error;
764     }
765     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
766     p_input->stream.i_mux_rate = 0;
767     vlc_mutex_unlock( &p_input->stream.stream_lock );
768
769     for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
770     {
771 #define p_stream p_ogg->pp_stream[i_stream]
772         vlc_mutex_lock( &p_input->stream.stream_lock );
773         p_stream->p_es = input_AddES( p_input,
774                                       p_input->stream.p_selected_program,
775                                       p_ogg->i_streams + 1, 0 );
776         p_input->stream.i_mux_rate += (p_stream->i_bitrate / ( 8 * 50 ));
777         vlc_mutex_unlock( &p_input->stream.stream_lock );
778         p_stream->p_es->i_stream_id = p_stream->p_es->i_id = i_stream;
779         p_stream->p_es->i_fourcc = p_stream->i_fourcc;
780         p_stream->p_es->i_cat = p_stream->i_cat;
781         p_stream->p_es->p_demux_data = p_stream->p_bih ?
782             (void *)p_stream->p_bih : (void *)p_stream->p_wf;
783 #undef p_stream
784     }
785
786     for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
787     {
788 #define p_stream  p_ogg->pp_stream[i_stream]
789         switch( p_stream->p_es->i_cat )
790         {
791             case( VIDEO_ES ):
792                 if( (p_ogg->p_stream_video == NULL) )
793                 {
794                     p_ogg->p_stream_video = p_stream;
795                     /* TODO add test to see if a decoder has been found */
796                     Ogg_StreamStart( p_input, p_ogg, i_stream );
797                 }
798                 break;
799
800             case( AUDIO_ES ):
801                 if( (p_ogg->p_stream_audio == NULL) )
802                 {
803                     int i_audio = config_GetInt( p_input, "audio-channel" );
804                     if( i_audio == i_stream || i_audio <= 0 ||
805                         i_audio >= p_ogg->i_streams ||
806                         p_ogg->pp_stream[i_audio]->p_es->i_cat != AUDIO_ES )
807                     {
808                         p_ogg->p_stream_audio = p_stream;
809                         p_ogg->p_stream_timeref = p_stream;
810                         Ogg_StreamStart( p_input, p_ogg, i_stream );
811                     }
812                 }
813                 break;
814
815             case( SPU_ES ):
816                 if( (p_ogg->p_stream_spu == NULL) )
817                 {
818                     /* for spu, default is none */
819                     int i_spu = config_GetInt( p_input, "spu-channel" );
820                     if( i_spu < 0 || i_spu >= p_ogg->i_streams ||
821                         p_ogg->pp_stream[i_spu]->p_es->i_cat != SPU_ES )
822                     {
823                         break;
824                     }
825                     else if( i_spu == i_stream )
826                     {
827                         p_ogg->p_stream_spu = p_stream;
828                         Ogg_StreamStart( p_input, p_ogg, i_stream );
829                     }
830                 }
831                 break;
832
833             default:
834                 break;
835         }
836 #undef p_stream
837     }
838
839     /* we select the first audio and video ES */
840     vlc_mutex_lock( &p_input->stream.stream_lock );
841     if( !p_ogg->p_stream_video )
842     {
843         msg_Warn( p_input, "no video stream found" );
844     }
845     if( !p_ogg->p_stream_audio )
846     {
847         msg_Warn( p_input, "no audio stream found!" );
848     }
849     p_input->stream.p_selected_program->b_is_ok = 1;
850     vlc_mutex_unlock( &p_input->stream.stream_lock );
851
852     /* Call the pace control */
853     input_ClockManageRef( p_input,
854                           p_input->stream.p_selected_program,
855                           p_ogg->i_pcr );
856
857     return 0;
858
859  error:
860     Deactivate( (vlc_object_t *)p_input );
861     return -1;
862
863 }
864
865 /*****************************************************************************
866  * Deactivate: frees unused data
867  *****************************************************************************/
868 static void Deactivate( vlc_object_t *p_this )
869 {
870     input_thread_t *p_input = (input_thread_t *)p_this;
871     demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ; 
872     int i, j;
873
874     if( p_ogg )
875     {
876         /* Cleanup the bitstream parser */
877         ogg_sync_clear( &p_ogg->oy );
878
879         for( i = 0; i < p_ogg->i_streams; i++ )
880         {
881             ogg_stream_clear( &p_ogg->pp_stream[i]->os );
882             for( j = 0; j < p_ogg->pp_stream[i]->i_packets_backup; j++ )
883             {
884                 free( p_ogg->pp_stream[i]->p_packets_backup[j].packet );
885             }
886             if( p_ogg->pp_stream[i]->p_packets_backup)
887                 free( p_ogg->pp_stream[i]->p_packets_backup );
888 #if 0 /* hmmm, it's already freed in input_DelES() */
889             if( p_ogg->pp_stream[i]->p_bih )
890                 free( p_ogg->pp_stream[i]->p_bih );
891             if( p_ogg->pp_stream[i]->p_wf )
892                 free( p_ogg->pp_stream[i]->p_wf );
893 #endif
894             free( p_ogg->pp_stream[i] );
895         }
896         if( p_ogg->pp_stream ) free( p_ogg->pp_stream );
897
898         free( p_ogg );
899     }
900 }
901
902 /*****************************************************************************
903  * Demux: reads and demuxes data packets
904  *****************************************************************************
905  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
906  *****************************************************************************/
907 static int Demux( input_thread_t * p_input )
908 {
909     int i, i_stream, b_eos = 0;
910     ogg_page    oggpage;
911     ogg_packet  oggpacket;
912     demux_sys_t *p_ogg  = (demux_sys_t *)p_input->p_demux_data;
913
914 #define p_stream p_ogg->pp_stream[i_stream]
915     /* detect new selected/unselected streams */
916     for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
917     {
918         if( p_stream->p_es )
919         {
920             if( p_stream->p_es->p_decoder_fifo &&
921                 !p_stream->i_activated )
922             {
923                 Ogg_StreamStart( p_input, p_ogg, i_stream );
924             }
925             else
926             if( !p_stream->p_es->p_decoder_fifo &&
927                 p_stream->i_activated )
928             {
929                 Ogg_StreamStop( p_input, p_ogg, i_stream );
930             }
931         }
932     }
933
934     /* search for new video and audio stream to select
935      * if current have been unselected */
936     if( ( !p_ogg->p_stream_video )
937             || ( !p_ogg->p_stream_video->p_es->p_decoder_fifo ) )
938     {
939         p_ogg->p_stream_video = NULL;
940         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
941         {
942             if( ( p_stream->i_cat == VIDEO_ES )
943                   &&( p_stream->p_es->p_decoder_fifo ) )
944             {
945                 p_ogg->p_stream_video = p_stream;
946                 break;
947             }
948         }
949     }
950     if( ( !p_ogg->p_stream_audio )
951             ||( !p_ogg->p_stream_audio->p_es->p_decoder_fifo ) )
952     {
953         p_ogg->p_stream_audio = NULL;
954         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
955         {
956             if( ( p_stream->i_cat == AUDIO_ES )
957                   &&( p_stream->p_es->p_decoder_fifo ) )
958             {
959                 p_ogg->p_stream_audio = p_stream;
960                 p_ogg->p_stream_timeref = p_stream;
961                 break;
962             }
963         }
964     }
965
966     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
967     {
968         msg_Warn( p_input, "synchro reinit" );
969
970         /* An ogg packet does only contain the starting date of the next
971          * packet, not its own starting date.
972          * As a quick work around, we just skip an oggpage */
973
974         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
975         {
976             /* we'll trash all the data until we find the next pcr */
977             p_stream->b_reinit = 1;
978             p_ogg->i_pcr = 0;
979         }
980     }
981
982
983     /* Demux ogg pages from the stream */
984     for( i = 0; (i < PAGES_READ_ONCE) || p_ogg->p_stream_timeref->b_reinit;
985          i++ )
986     {
987         if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS )
988         {
989             b_eos = 1;
990             break;
991         }
992
993         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
994         {
995             if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 )
996                 continue;
997
998             while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
999             {
1000                 if( !p_stream->p_es )
1001                 {
1002                     break;
1003                 }
1004
1005                 if( p_stream->b_reinit )
1006                 {
1007                     if( oggpacket.granulepos >= 0 )
1008                     {
1009                         p_stream->b_reinit = 0;
1010                         p_stream->i_pcr = oggpacket.granulepos
1011                             * 90000 / p_stream->i_rate;
1012
1013                         if( !p_ogg->i_pcr ||
1014                             (p_stream == p_ogg->p_stream_timeref) )
1015                         {
1016                             /* Call the pace control to reinitialize
1017                              * the system clock */
1018                             p_ogg->i_pcr = p_stream->i_pcr;
1019                             input_ClockManageRef( p_input,
1020                                p_input->stream.p_selected_program,
1021                                p_ogg->i_pcr );
1022                         }
1023                     }
1024                     continue;
1025                 }
1026
1027                 Ogg_DecodePacket( p_input, p_stream, &oggpacket );
1028
1029             }
1030         }
1031 #undef p_stream
1032     }
1033
1034     /* Call the pace control */
1035     if( !b_eos ) input_ClockManageRef( p_input,
1036                                        p_input->stream.p_selected_program,
1037                                        p_ogg->i_pcr );
1038
1039     /* Did we reach the end of stream ? */
1040     return( b_eos ? 0 : 1 );
1041 }