]> git.sesse.net Git - vlc/blob - modules/demux/ogg.c
* modules/demux/ogg.c: Added Annodex support (www.annodex.net). Patch courtesy of...
[vlc] / modules / demux / ogg.c
1 /*****************************************************************************
2  * ogg.c : ogg stream demux module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *          Andre Pang <Andre.Pang@csiro.au> (Annodex support)
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <vlc/vlc.h>
29 #include <vlc/input.h>
30
31 #include <ogg/ogg.h>
32
33 #include "codecs.h"
34 #include "vlc_bits.h"
35
36 #define OGG_BLOCK_SIZE 4096
37
38 /*****************************************************************************
39  * Definitions of structures and functions used by this plugins
40  *****************************************************************************/
41 typedef struct logical_stream_s
42 {
43     ogg_stream_state os;                        /* logical stream of packets */
44
45     es_format_t      fmt;
46     es_out_id_t      *p_es;
47     double           f_rate;
48
49     int              i_serial_no;
50     int              b_activated;
51
52     /* the header of some logical streams (eg vorbis) contain essential
53      * data for the decoder. We back them up here in case we need to re-feed
54      * them to the decoder. */
55     int              b_force_backup;
56     int              i_packets_backup;
57     ogg_packet       *p_packets_backup;
58
59     /* program clock reference (in units of 90kHz) derived from the previous
60      * granulepos */
61     mtime_t          i_pcr;
62     mtime_t          i_interpolated_pcr;
63     mtime_t          i_previous_pcr;
64
65     /* Misc */
66     int b_reinit;
67     int i_theora_keyframe_granule_shift;
68
69     /* for Annodex logical bitstreams */
70     int secondary_header_packets;
71
72 } logical_stream_t;
73
74 struct demux_sys_t
75 {
76     ogg_sync_state oy;        /* sync and verify incoming physical bitstream */
77
78     int i_streams;                           /* number of logical bitstreams */
79     logical_stream_t **pp_stream;  /* pointer to an array of logical streams */
80
81     /* program clock reference (in units of 90kHz) derived from the pcr of
82      * the sub-streams */
83     mtime_t i_pcr;
84     int     i_old_synchro_state;
85
86     /* stream state */
87     int     i_eos;
88 };
89
90 /* OggDS headers for the new header format (used in ogm files) */
91 typedef struct stream_header_video
92 {
93     ogg_int32_t width;
94     ogg_int32_t height;
95 } stream_header_video;
96
97 typedef struct stream_header_audio
98 {
99     ogg_int16_t channels;
100     ogg_int16_t blockalign;
101     ogg_int32_t avgbytespersec;
102 } stream_header_audio;
103
104 typedef struct stream_header
105 {
106     char        streamtype[8];
107     char        subtype[4];
108
109     ogg_int32_t size;                               /* size of the structure */
110
111     ogg_int64_t time_unit;                              /* in reference time */
112     ogg_int64_t samples_per_unit;
113     ogg_int32_t default_len;                                /* in media time */
114
115     ogg_int32_t buffersize;
116     ogg_int16_t bits_per_sample;
117
118     union
119     {
120         /* Video specific */
121         stream_header_video video;
122         /* Audio specific */
123         stream_header_audio audio;
124     } sh;
125 } stream_header;
126
127 /* Some defines from OggDS */
128 #define PACKET_TYPE_HEADER   0x01
129 #define PACKET_TYPE_BITS     0x07
130 #define PACKET_LEN_BITS01    0xc0
131 #define PACKET_LEN_BITS2     0x02
132 #define PACKET_IS_SYNCPOINT  0x08
133
134 /*****************************************************************************
135  * Local prototypes
136  *****************************************************************************/
137 static int  Activate  ( vlc_object_t * );
138 static void Deactivate( vlc_object_t * );
139 static int  Demux     ( input_thread_t * );
140 static int  Control   ( input_thread_t *, int, va_list );
141
142 /* Bitstream manipulation */
143 static int  Ogg_Check        ( input_thread_t *p_input );
144 static int  Ogg_ReadPage     ( input_thread_t *, demux_sys_t *, ogg_page * );
145 static void Ogg_UpdatePCR    ( logical_stream_t *, ogg_packet * );
146 static void Ogg_DecodePacket ( input_thread_t *p_input,
147                                logical_stream_t *p_stream, ogg_packet * );
148
149 static int Ogg_BeginningOfStream( input_thread_t *p_input, demux_sys_t *p_ogg);
150 static int Ogg_FindLogicalStreams( input_thread_t *p_input,demux_sys_t *p_ogg);
151 static void Ogg_EndOfStream( input_thread_t *p_input, demux_sys_t *p_ogg );
152
153 /* Logical bitstream headers */
154 static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
155                                   ogg_packet *p_oggpacket );
156 static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
157                                   ogg_packet *p_oggpacket );
158 static void Ogg_ReadAnnodexHeader( vlc_object_t *, logical_stream_t *p_stream,
159                                    ogg_packet *p_oggpacket );
160
161 /*****************************************************************************
162  * Module descriptor
163  *****************************************************************************/
164 vlc_module_begin();
165     set_description( _("Ogg stream demuxer" ) );
166     set_capability( "demux", 50 );
167     set_callbacks( Activate, Deactivate );
168     add_shortcut( "ogg" );
169 vlc_module_end();
170
171 /****************************************************************************
172  * Ogg_Check: Check we are dealing with an ogg stream.
173  ****************************************************************************/
174 static int Ogg_Check( input_thread_t *p_input )
175 {
176     uint8_t *p_peek;
177     int i_size = input_Peek( p_input, &p_peek, 4 );
178
179     /* Check for the Ogg capture pattern */
180     if( !(i_size>3) || !(p_peek[0] == 'O') || !(p_peek[1] == 'g') ||
181         !(p_peek[2] == 'g') || !(p_peek[3] == 'S') )
182         return VLC_EGENERIC;
183
184     /* FIXME: Capture pattern might not be enough so we can also check for the
185      * the first complete page */
186
187     return VLC_SUCCESS;
188 }
189
190 /****************************************************************************
191  * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
192  ****************************************************************************
193  * Returns VLC_SUCCESS if a page has been read. An error might happen if we
194  * are at the end of stream.
195  ****************************************************************************/
196 static int Ogg_ReadPage( input_thread_t *p_input, demux_sys_t *p_ogg,
197                          ogg_page *p_oggpage )
198 {
199     int i_read = 0;
200     data_packet_t *p_data;
201     byte_t *p_buffer;
202
203     while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
204     {
205         i_read = input_SplitBuffer( p_input, &p_data, OGG_BLOCK_SIZE );
206         if( i_read <= 0 )
207             return VLC_EGENERIC;
208
209         p_buffer = ogg_sync_buffer( &p_ogg->oy, i_read );
210         p_input->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start, i_read );
211         ogg_sync_wrote( &p_ogg->oy, i_read );
212         input_DeletePacket( p_input->p_method_data, p_data );
213     }
214
215     return VLC_SUCCESS;
216 }
217
218 /****************************************************************************
219  * Ogg_UpdatePCR: update the PCR (90kHz program clock reference) for the
220  *                current stream.
221  ****************************************************************************/
222 static void Ogg_UpdatePCR( logical_stream_t *p_stream,
223                            ogg_packet *p_oggpacket )
224 {
225     /* Convert the granulepos into a pcr */
226     if( p_oggpacket->granulepos >= 0 )
227     {
228         if( p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) )
229         {
230             p_stream->i_pcr = p_oggpacket->granulepos * 90000
231                               / p_stream->f_rate;
232         }
233         else
234         {
235             ogg_int64_t iframe = p_oggpacket->granulepos >>
236               p_stream->i_theora_keyframe_granule_shift;
237             ogg_int64_t pframe = p_oggpacket->granulepos -
238               ( iframe << p_stream->i_theora_keyframe_granule_shift );
239
240             p_stream->i_pcr = ( iframe + pframe ) * 90000
241                               / p_stream->f_rate;
242         }
243
244         p_stream->i_interpolated_pcr = p_stream->i_pcr;
245     }
246     else
247     {
248         p_stream->i_pcr = -1;
249
250         /* no granulepos available, try to interpolate the pcr.
251          * If we can't then don't touch the old value. */
252         if( p_stream->fmt.i_cat == VIDEO_ES )
253             /* 1 frame per packet */
254             p_stream->i_interpolated_pcr += (90000 / p_stream->f_rate);
255         else if( p_stream->fmt.i_bitrate )
256             p_stream->i_interpolated_pcr += ( p_oggpacket->bytes * 90000
257                                               / p_stream->fmt.i_bitrate / 8 );
258     }
259 }
260
261 /****************************************************************************
262  * Ogg_DecodePacket: Decode an Ogg packet.
263  ****************************************************************************/
264 static void Ogg_DecodePacket( input_thread_t *p_input,
265                               logical_stream_t *p_stream,
266                               ogg_packet *p_oggpacket )
267 {
268     block_t *p_block;
269     vlc_bool_t b_selected;
270     int i_header_len = 0;
271     mtime_t i_pts = 0;
272
273     /* Sanity check */
274     if( !p_oggpacket->bytes )
275     {
276         msg_Dbg( p_input, "discarding 0 sized packet" );
277         return;
278     }
279
280     if( p_oggpacket->bytes >= 7 &&
281         ! strncmp ( &p_oggpacket->packet[0], "Annodex", 7 ) )
282     {
283         /* it's an Annodex packet -- skip it (do nothing) */
284         return; 
285     }
286     else if( p_oggpacket->bytes >= 7 &&
287         ! strncmp ( &p_oggpacket->packet[0], "AnxData", 7 ) )
288     {
289         /* it's an AnxData packet -- skip it (do nothing) */
290         return; 
291     }
292
293     if( p_stream->b_force_backup )
294     {
295         ogg_packet *p_packet_backup;
296         p_stream->i_packets_backup++;
297         switch( p_stream->fmt.i_codec )
298         {
299         case VLC_FOURCC( 'v','o','r','b' ):
300         case VLC_FOURCC( 's','p','x',' ' ):
301         case VLC_FOURCC( 't','h','e','o' ):
302           if( p_stream->i_packets_backup == 3 ) p_stream->b_force_backup = 0;
303           break;
304
305         case VLC_FOURCC( 'f','l','a','c' ):
306           if( p_stream->i_packets_backup == 1 ) return;
307           else if( p_stream->i_packets_backup == 2 )
308           {
309               /* Parse the STREAMINFO metadata */
310               bs_t s;
311               bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
312               bs_read( &s, 1 );
313               if( bs_read( &s, 7 ) == 0 )
314               {
315                   if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
316                   {
317                       bs_skip( &s, 80 );
318                       p_stream->f_rate = p_stream->fmt.audio.i_rate =
319                           bs_read( &s, 20 );
320                       p_stream->fmt.audio.i_channels =
321                           bs_read( &s, 3 ) + 1;
322
323                       msg_Dbg( p_input, "FLAC header, channels: %i, rate: %i",
324                                p_stream->fmt.audio.i_channels,
325                                (int)p_stream->f_rate );
326                   }
327                   else
328                   {
329                       msg_Dbg( p_input, "FLAC STREAMINFO metadata too short" );
330                   }
331
332                   /* Store STREAMINFO for the decoder and packetizer */
333                   p_stream->fmt.i_extra = p_oggpacket->bytes + 4;
334                   p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra );
335                   memcpy( p_stream->fmt.p_extra, "fLaC", 4);
336                   memcpy( ((uint8_t *)p_stream->fmt.p_extra) + 4,
337                           p_oggpacket->packet, p_oggpacket->bytes );
338
339                   /* Fake this as the last metadata block */
340                   ((uint8_t*)p_stream->fmt.p_extra)[4] |= 0x80;
341
342                   p_stream->p_es = es_out_Add( p_input->p_es_out,
343                                                &p_stream->fmt );
344               }
345               else
346               {
347                   /* This ain't a STREAMINFO metadata */
348                   msg_Dbg( p_input, "Invalid FLAC STREAMINFO metadata" );
349               }
350               p_stream->b_force_backup = 0;
351               p_stream->i_packets_backup = 0;
352
353               if( p_oggpacket->granulepos >= 0 )
354                   Ogg_UpdatePCR( p_stream, p_oggpacket );
355
356               p_stream->i_previous_pcr = 0;
357               return;
358           }
359           break;
360
361         default:
362           p_stream->b_force_backup = 0;
363           break;
364         }
365
366         /* Backup the ogg packet (likely an header packet) */
367         p_stream->p_packets_backup =
368             realloc( p_stream->p_packets_backup, p_stream->i_packets_backup *
369                      sizeof(ogg_packet) );
370
371         p_packet_backup =
372             &p_stream->p_packets_backup[p_stream->i_packets_backup - 1];
373
374         p_packet_backup->bytes = p_oggpacket->bytes;
375         p_packet_backup->granulepos = p_oggpacket->granulepos;
376
377         if( p_oggpacket->granulepos >= 0 )
378         {
379             /* Because of vorbis granulepos scheme we must set the pcr for the
380              * 1st header packet so it doesn't get discarded in the
381              * packetizer */
382             Ogg_UpdatePCR( p_stream, p_oggpacket );
383         }
384
385         p_packet_backup->packet = malloc( p_oggpacket->bytes );
386         if( !p_packet_backup->packet ) return;
387         memcpy( p_packet_backup->packet, p_oggpacket->packet,
388                 p_oggpacket->bytes );
389     }
390
391     /* Check the ES is selected */
392     es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE,
393                     p_stream->p_es, &b_selected );
394
395     if( b_selected && !p_stream->b_activated )
396     {
397         p_stream->b_activated = VLC_TRUE;
398
399         /* Newly activated stream, feed the backup headers to the decoder */
400         if( !p_stream->b_force_backup )
401         {
402             int i;
403             for( i = 0; i < p_stream->i_packets_backup; i++ )
404             {
405                 /* Set correct starting date in header packets */
406                 p_stream->p_packets_backup[i].granulepos =
407                     p_stream->i_interpolated_pcr * p_stream->f_rate / 90000;
408
409                 Ogg_DecodePacket( p_input, p_stream,
410                                   &p_stream->p_packets_backup[i] );
411             }
412         }
413     }
414
415     /* Convert the pcr into a pts */
416     if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) ||
417         p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) ||
418         p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) )
419     {
420         if( p_stream->i_pcr >= 0 )
421         {
422             /* This is for streams where the granulepos of the header packets
423              * doesn't match these of the data packets (eg. ogg web radios). */
424             if( p_stream->i_previous_pcr == 0 &&
425                 p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY * 9/100 )
426                 p_input->stream.p_selected_program->i_synchro_state =
427                     SYNCHRO_REINIT;
428
429             p_stream->i_previous_pcr = p_stream->i_pcr;
430
431             /* Call the pace control */
432             if( p_input->stream.p_selected_program->i_synchro_state ==
433                 SYNCHRO_REINIT )
434             input_ClockManageRef( p_input,
435                                   p_input->stream.p_selected_program,
436                                   p_stream->i_pcr );
437
438             /* The granulepos is the end date of the sample */
439             i_pts =  input_ClockGetTS( p_input,
440                                        p_input->stream.p_selected_program,
441                                        p_stream->i_pcr );
442         }
443     }
444
445     /* Convert the granulepos into the next pcr */
446     Ogg_UpdatePCR( p_stream, p_oggpacket );
447
448     if( p_stream->i_pcr >= 0 )
449     {
450         /* This is for streams where the granulepos of the header packets
451          * doesn't match these of the data packets (eg. ogg web radios). */
452         if( p_stream->i_previous_pcr == 0 &&
453             p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY * 9/100 )
454             p_input->stream.p_selected_program->i_synchro_state =
455                 SYNCHRO_REINIT;
456
457         /* Call the pace control */
458         if( p_input->stream.p_selected_program->i_synchro_state ==
459             SYNCHRO_REINIT )
460           input_ClockManageRef( p_input, p_input->stream.p_selected_program,
461                                 p_stream->i_pcr );
462     }
463
464     if( p_stream->fmt.i_codec != VLC_FOURCC( 'v','o','r','b' ) &&
465         p_stream->fmt.i_codec != VLC_FOURCC( 's','p','x',' ' ) &&
466         p_stream->fmt.i_codec != VLC_FOURCC( 'f','l','a','c' ) &&
467         p_stream->i_pcr >= 0 )
468     {
469         p_stream->i_previous_pcr = p_stream->i_pcr;
470
471         /* The granulepos is the start date of the sample */
472         i_pts = input_ClockGetTS( p_input, p_input->stream.p_selected_program,
473                                   p_stream->i_pcr );
474     }
475
476     if( !b_selected )
477     {
478         /* This stream isn't currently selected so we don't need to decode it,
479          * but we did need to store its pcr as it might be selected later on */
480         p_stream->b_activated = VLC_FALSE;
481         return;
482     }
483
484     if( !( p_block = block_New( p_input, p_oggpacket->bytes ) ) ) return;
485
486     if( p_stream->fmt.i_cat == AUDIO_ES )
487         p_block->i_dts = p_block->i_pts = i_pts;
488     else if( p_stream->fmt.i_cat == SPU_ES )
489     {
490         p_block->i_pts = i_pts;
491         p_block->i_dts = 0;
492     }
493     else if( p_stream->fmt.i_codec == VLC_FOURCC( 't','h','e','o' ) )
494         p_block->i_dts = p_block->i_pts = i_pts;
495     else
496     {
497         p_block->i_dts = i_pts;
498         p_block->i_pts = 0;
499     }
500
501     if( p_stream->fmt.i_codec != VLC_FOURCC( 'v','o','r','b' ) &&
502         p_stream->fmt.i_codec != VLC_FOURCC( 's','p','x',' ' ) &&
503         p_stream->fmt.i_codec != VLC_FOURCC( 'f','l','a','c' ) &&
504         p_stream->fmt.i_codec != VLC_FOURCC( 't','a','r','k' ) &&
505         p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) &&
506         p_stream->fmt.i_codec != VLC_FOURCC( 'c','m','m','l' ) )
507     {
508         /* We remove the header from the packet */
509         i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
510         i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
511         
512         if( p_stream->fmt.i_codec == VLC_FOURCC( 's','u','b','t' ))
513         {
514             /* But with subtitles we need to retrieve the duration first */
515             int i, lenbytes = 0;
516         
517             if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 )
518             {
519                 for( i = 0, lenbytes = 0; i < i_header_len; i++ )
520                 {
521                     lenbytes = lenbytes << 8;
522                     lenbytes += *(p_oggpacket->packet + i_header_len - i);
523                 }
524             }
525             if( p_oggpacket->bytes - 1 - i_header_len > 2 ||
526                 ( p_oggpacket->packet[i_header_len + 1] != ' ' &&
527                   p_oggpacket->packet[i_header_len + 1] != 0 && 
528                   p_oggpacket->packet[i_header_len + 1] != '\n' &&
529                   p_oggpacket->packet[i_header_len + 1] != '\r' ) )
530             {
531                 p_block->i_dts = p_block->i_pts + (mtime_t)lenbytes * 1000;
532             }
533         }
534
535         i_header_len++;
536         p_block->i_buffer -= i_header_len;
537     }
538
539     if( p_stream->fmt.i_codec == VLC_FOURCC( 't','a','r','k' ) )
540     {
541         /* FIXME: the biggest hack I've ever done */
542         msg_Warn( p_input, "tarkin pts: "I64Fd", granule: "I64Fd,
543                   p_block->i_pts, p_block->i_dts );
544         msleep(10000);
545     }
546
547     memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
548             p_oggpacket->bytes - i_header_len );
549
550     es_out_Send( p_input->p_es_out, p_stream->p_es, p_block );
551 }
552
553 /****************************************************************************
554  * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
555  *                         stream and fill p_ogg.
556  *****************************************************************************
557  * The initial page of a logical stream is marked as a 'bos' page.
558  * Furthermore, the Ogg specification mandates that grouped bitstreams begin
559  * together and all of the initial pages must appear before any data pages.
560  *
561  * On success this function returns VLC_SUCCESS.
562  ****************************************************************************/
563 static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
564 {
565     ogg_packet oggpacket;
566     ogg_page oggpage;
567     int i_stream;
568
569 #define p_stream p_ogg->pp_stream[p_ogg->i_streams - 1]
570
571     while( Ogg_ReadPage( p_input, p_ogg, &oggpage ) == VLC_SUCCESS )
572     {
573         if( ogg_page_bos( &oggpage ) )
574         {
575
576             /* All is wonderful in our fine fine little world.
577              * We found the beginning of our first logical stream. */
578             while( ogg_page_bos( &oggpage ) )
579             {
580                 p_ogg->i_streams++;
581                 p_ogg->pp_stream =
582                     realloc( p_ogg->pp_stream, p_ogg->i_streams *
583                              sizeof(logical_stream_t *) );
584
585                 p_stream = malloc( sizeof(logical_stream_t) );
586                 memset( p_stream, 0, sizeof(logical_stream_t) );
587
588                 es_format_Init( &p_stream->fmt, 0, 0 );
589                 p_stream->b_activated = VLC_TRUE;
590
591                 /* Setup the logical stream */
592                 p_stream->i_serial_no = ogg_page_serialno( &oggpage );
593                 ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
594
595                 /* Extract the initial header from the first page and verify
596                  * the codec type of tis Ogg bitstream */
597                 if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 )
598                 {
599                     /* error. stream version mismatch perhaps */
600                     msg_Err( p_input, "error reading first page of "
601                              "Ogg bitstream data" );
602                     return VLC_EGENERIC;
603                 }
604
605                 /* FIXME: check return value */
606                 ogg_stream_packetpeek( &p_stream->os, &oggpacket );
607
608                 /* Check for Vorbis header */
609                 if( oggpacket.bytes >= 7 &&
610                     ! strncmp( &oggpacket.packet[1], "vorbis", 6 ) )
611                 {
612                     Ogg_ReadVorbisHeader( p_stream, &oggpacket );
613                     msg_Dbg( p_input, "found vorbis header" );
614                 }
615                 /* Check for Speex header */
616                 else if( oggpacket.bytes >= 7 &&
617                     ! strncmp( &oggpacket.packet[0], "Speex", 5 ) )
618                 {
619                     oggpack_buffer opb;
620
621                     p_stream->fmt.i_cat = AUDIO_ES;
622                     p_stream->fmt.i_codec = VLC_FOURCC( 's','p','x',' ' );
623
624                     /* Signal that we want to keep a backup of the vorbis
625                      * stream headers. They will be used when switching between
626                      * audio streams. */
627                     p_stream->b_force_backup = 1;
628
629                     /* Cheat and get additionnal info ;) */
630                     oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
631                     oggpack_adv( &opb, 224 );
632                     oggpack_adv( &opb, 32 ); /* speex_version_id */
633                     oggpack_adv( &opb, 32 ); /* header_size */
634                     p_stream->f_rate = p_stream->fmt.audio.i_rate =
635                         oggpack_read( &opb, 32 );
636                     oggpack_adv( &opb, 32 ); /* mode */
637                     oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
638                     p_stream->fmt.audio.i_channels = oggpack_read( &opb, 32 );
639                     p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
640
641                     msg_Dbg( p_input, "found speex header, channels: %i, "
642                              "rate: %i,  bitrate: %i",
643                              p_stream->fmt.audio.i_channels,
644                              (int)p_stream->f_rate, p_stream->fmt.i_bitrate );
645                 }
646                 /* Check for Flac header */
647                 else if( oggpacket.bytes >= 4 &&
648                     ! strncmp( &oggpacket.packet[0], "fLaC", 4 ) )
649                 {
650                     msg_Dbg( p_input, "found FLAC header" );
651
652                     /* Grrrr!!!! Did they really have to put all the
653                      * important info in the second header packet!!!
654                      * (STREAMINFO metadata is in the following packet) */
655                     p_stream->b_force_backup = 1;
656
657                     p_stream->fmt.i_cat = AUDIO_ES;
658                     p_stream->fmt.i_codec = VLC_FOURCC( 'f','l','a','c' );
659                 }
660                 /* Check for Theora header */
661                 else if( oggpacket.bytes >= 7 &&
662                          ! strncmp( &oggpacket.packet[1], "theora", 6 ) )
663                 {
664                     Ogg_ReadTheoraHeader( p_stream, &oggpacket );
665
666                     msg_Dbg( p_input,
667                              "found theora header, bitrate: %i, rate: %f",
668                              p_stream->fmt.i_bitrate, p_stream->f_rate );
669                 }
670                 /* Check for Tarkin header */
671                 else if( oggpacket.bytes >= 7 &&
672                          ! strncmp( &oggpacket.packet[1], "tarkin", 6 ) )
673                 {
674                     oggpack_buffer opb;
675
676                     msg_Dbg( p_input, "found tarkin header" );
677                     p_stream->fmt.i_cat = VIDEO_ES;
678                     p_stream->fmt.i_codec = VLC_FOURCC( 't','a','r','k' );
679
680                     /* Cheat and get additionnal info ;) */
681                     oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
682                     oggpack_adv( &opb, 88 );
683                     oggpack_adv( &opb, 104 );
684                     p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
685                     p_stream->f_rate = 2; /* FIXME */
686                     msg_Dbg( p_input,
687                              "found tarkin header, bitrate: %i, rate: %f",
688                              p_stream->fmt.i_bitrate, p_stream->f_rate );
689                 }
690                 /* Check for Annodex header */
691                 else if( oggpacket.bytes >= 7 &&
692                          ! strncmp( &oggpacket.packet[0], "Annodex", 7 ) )
693                 {
694                     Ogg_ReadAnnodexHeader( VLC_OBJECT(p_input), p_stream,
695                                            &oggpacket );
696                     /* kill annodex track */
697                     free( p_stream );
698                     p_ogg->i_streams--;
699                 }
700                 /* Check for Annodex header */
701                 else if( oggpacket.bytes >= 7 &&
702                          ! strncmp( &oggpacket.packet[0], "AnxData", 7 ) )
703                 {
704                     Ogg_ReadAnnodexHeader( VLC_OBJECT(p_input), p_stream,
705                                            &oggpacket );
706                 }
707                 else if( oggpacket.bytes >= 142 &&
708                          !strncmp( &oggpacket.packet[1],
709                                    "Direct Show Samples embedded in Ogg", 35 ))
710                 {
711                     /* Old header type */
712
713                     /* Check for video header (old format) */
714                     if( GetDWLE((oggpacket.packet+96)) == 0x05589f80 &&
715                         oggpacket.bytes >= 184 )
716                     {
717                         p_stream->fmt.i_cat = VIDEO_ES;
718                         p_stream->fmt.i_codec =
719                             VLC_FOURCC( oggpacket.packet[68],
720                                         oggpacket.packet[69],
721                                         oggpacket.packet[70],
722                                         oggpacket.packet[71] );
723                         msg_Dbg( p_input, "found video header of type: %.4s",
724                                  (char *)&p_stream->fmt.i_codec );
725
726                         p_stream->f_rate = 10000000.0 /
727                             GetQWLE((oggpacket.packet+164));
728                         p_stream->fmt.video.i_bits_per_pixel =
729                             GetWLE((oggpacket.packet+182));
730                         if( !p_stream->fmt.video.i_bits_per_pixel )
731                             /* hack, FIXME */
732                             p_stream->fmt.video.i_bits_per_pixel = 24;
733                         p_stream->fmt.video.i_width =
734                             GetDWLE((oggpacket.packet+176));
735                         p_stream->fmt.video.i_height =
736                             GetDWLE((oggpacket.packet+180));
737
738                         msg_Dbg( p_input,
739                                  "fps: %f, width:%i; height:%i, bitcount:%i",
740                                  p_stream->f_rate,
741                                  p_stream->fmt.video.i_width,
742                                  p_stream->fmt.video.i_height,
743                                  p_stream->fmt.video.i_bits_per_pixel);
744
745                     }
746                     /* Check for audio header (old format) */
747                     else if( GetDWLE((oggpacket.packet+96)) == 0x05589F81 )
748                     {
749                         unsigned int i_extra_size;
750                         unsigned int i_format_tag;
751
752                         p_stream->fmt.i_cat = AUDIO_ES;
753
754                         i_extra_size = GetWLE((oggpacket.packet+140));
755                         if( i_extra_size )
756                         {
757                             p_stream->fmt.i_extra = i_extra_size;
758                             p_stream->fmt.p_extra = malloc( i_extra_size );
759                             memcpy( p_stream->fmt.p_extra,
760                                     oggpacket.packet + 142, i_extra_size );
761                         }
762
763                         i_format_tag = GetWLE((oggpacket.packet+124));
764                         p_stream->fmt.audio.i_channels =
765                             GetWLE((oggpacket.packet+126));
766                         p_stream->f_rate = p_stream->fmt.audio.i_rate =
767                             GetDWLE((oggpacket.packet+128));
768                         p_stream->fmt.i_bitrate =
769                             GetDWLE((oggpacket.packet+132)) * 8;
770                         p_stream->fmt.audio.i_blockalign =
771                             GetWLE((oggpacket.packet+136));
772                         p_stream->fmt.audio.i_bitspersample =
773                             GetWLE((oggpacket.packet+138));
774
775                         switch( i_format_tag )
776                         {
777                         case WAVE_FORMAT_PCM:
778                             p_stream->fmt.i_codec =
779                                 VLC_FOURCC( 'a', 'r', 'a', 'w' );
780                             break;
781                         case WAVE_FORMAT_MPEG:
782                         case WAVE_FORMAT_MPEGLAYER3:
783                             p_stream->fmt.i_codec =
784                                 VLC_FOURCC( 'm', 'p', 'g', 'a' );
785                             break;
786                         case WAVE_FORMAT_A52:
787                             p_stream->fmt.i_codec =
788                                 VLC_FOURCC( 'a', '5', '2', ' ' );
789                             break;
790                         case WAVE_FORMAT_WMA1:
791                             p_stream->fmt.i_codec =
792                                 VLC_FOURCC( 'w', 'm', 'a', '1' );
793                             break;
794                         case WAVE_FORMAT_WMA2:
795                             p_stream->fmt.i_codec =
796                                 VLC_FOURCC( 'w', 'm', 'a', '2' );
797                             break;
798                         default:
799                             p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
800                                 ( i_format_tag >> 8 ) & 0xff,
801                                 i_format_tag & 0xff );
802                         }
803
804                         msg_Dbg( p_input, "found audio header of type: %.4s",
805                                  (char *)&p_stream->fmt.i_codec );
806                         msg_Dbg( p_input, "audio:0x%4.4x channels:%d %dHz "
807                                  "%dbits/sample %dkb/s",
808                                  i_format_tag,
809                                  p_stream->fmt.audio.i_channels,
810                                  p_stream->fmt.audio.i_rate,
811                                  p_stream->fmt.audio.i_bitspersample,
812                                  p_stream->fmt.i_bitrate / 1024 );
813
814                     }
815                     else
816                     {
817                         msg_Dbg( p_input, "stream %d has an old header "
818                             "but is of an unknown type", p_ogg->i_streams-1 );
819                         free( p_stream );
820                         p_ogg->i_streams--;
821                     }
822                 }
823                 else if( (*oggpacket.packet & PACKET_TYPE_BITS )
824                          == PACKET_TYPE_HEADER &&
825                          oggpacket.bytes >= (int)sizeof(stream_header)+1 )
826                 {
827                     stream_header *st = (stream_header *)(oggpacket.packet+1);
828
829                     /* Check for video header (new format) */
830                     if( !strncmp( st->streamtype, "video", 5 ) )
831                     {
832                         p_stream->fmt.i_cat = VIDEO_ES;
833
834                         /* We need to get rid of the header packet */
835                         ogg_stream_packetout( &p_stream->os, &oggpacket );
836
837                         p_stream->fmt.i_codec =
838                             VLC_FOURCC( st->subtype[0], st->subtype[1],
839                                         st->subtype[2], st->subtype[3] );
840                         msg_Dbg( p_input, "found video header of type: %.4s",
841                                  (char *)&p_stream->fmt.i_codec );
842
843                         p_stream->f_rate = 10000000.0 /
844                             GetQWLE(&st->time_unit);
845                         p_stream->fmt.video.i_bits_per_pixel =
846                             GetWLE(&st->bits_per_sample);
847                         p_stream->fmt.video.i_width =
848                             GetDWLE(&st->sh.video.width);
849                         p_stream->fmt.video.i_height =
850                             GetDWLE(&st->sh.video.height);
851
852                         msg_Dbg( p_input,
853                                  "fps: %f, width:%i; height:%i, bitcount:%i",
854                                  p_stream->f_rate,
855                                  p_stream->fmt.video.i_width,
856                                  p_stream->fmt.video.i_height,
857                                  p_stream->fmt.video.i_bits_per_pixel );
858                     }
859                     /* Check for audio header (new format) */
860                     else if( !strncmp( st->streamtype, "audio", 5 ) )
861                     {
862                         char p_buffer[5];
863                         int i_format_tag;
864
865                         p_stream->fmt.i_cat = AUDIO_ES;
866
867                         /* We need to get rid of the header packet */
868                         ogg_stream_packetout( &p_stream->os, &oggpacket );
869
870                         memcpy( p_buffer, st->subtype, 4 );
871                         p_buffer[4] = '\0';
872                         i_format_tag = strtol(p_buffer,NULL,16);
873                         p_stream->fmt.audio.i_channels =
874                             GetWLE(&st->sh.audio.channels);
875                         p_stream->f_rate = p_stream->fmt.audio.i_rate =
876                             GetQWLE(&st->samples_per_unit);
877                         p_stream->fmt.i_bitrate =
878                             GetDWLE(&st->sh.audio.avgbytespersec) * 8;
879                         p_stream->fmt.audio.i_blockalign =
880                             GetWLE(&st->sh.audio.blockalign);
881                         p_stream->fmt.audio.i_bitspersample =
882                             GetWLE(&st->bits_per_sample);
883
884                         switch( i_format_tag )
885                         {
886                         case WAVE_FORMAT_PCM:
887                             p_stream->fmt.i_codec =
888                                 VLC_FOURCC( 'a', 'r', 'a', 'w' );
889                             break;
890                         case WAVE_FORMAT_MPEG:
891                         case WAVE_FORMAT_MPEGLAYER3:
892                             p_stream->fmt.i_codec =
893                                 VLC_FOURCC( 'm', 'p', 'g', 'a' );
894                             break;
895                         case WAVE_FORMAT_A52:
896                             p_stream->fmt.i_codec =
897                                 VLC_FOURCC( 'a', '5', '2', ' ' );
898                             break;
899                         case WAVE_FORMAT_WMA1:
900                             p_stream->fmt.i_codec =
901                                 VLC_FOURCC( 'w', 'm', 'a', '1' );
902                             break;
903                         case WAVE_FORMAT_WMA2:
904                             p_stream->fmt.i_codec =
905                                 VLC_FOURCC( 'w', 'm', 'a', '2' );
906                             break;
907                         default:
908                             p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
909                                 ( i_format_tag >> 8 ) & 0xff,
910                                 i_format_tag & 0xff );
911                         }
912
913                         msg_Dbg( p_input, "found audio header of type: %.4s",
914                                  (char *)&p_stream->fmt.i_codec );
915                         msg_Dbg( p_input, "audio:0x%4.4x channels:%d %dHz "
916                                  "%dbits/sample %dkb/s",
917                                  i_format_tag,
918                                  p_stream->fmt.audio.i_channels,
919                                  p_stream->fmt.audio.i_rate,
920                                  p_stream->fmt.audio.i_bitspersample,
921                                  p_stream->fmt.i_bitrate / 1024 );
922                     }
923                     /* Check for text (subtitles) header */
924                     else if( !strncmp(st->streamtype, "text", 4) )
925                     {
926                         /* We need to get rid of the header packet */
927                         ogg_stream_packetout( &p_stream->os, &oggpacket );
928
929                         msg_Dbg( p_input, "found text subtitles header" );
930                         p_stream->fmt.i_cat = SPU_ES;
931                         p_stream->fmt.i_codec = VLC_FOURCC('s','u','b','t');
932                         p_stream->f_rate = 1000; /* granulepos is in milisec */
933                     }
934                     else
935                     {
936                         msg_Dbg( p_input, "stream %d has a header marker "
937                             "but is of an unknown type", p_ogg->i_streams-1 );
938                         free( p_stream );
939                         p_ogg->i_streams--;
940                     }
941                 }
942                 else
943                 {
944                     msg_Dbg( p_input, "stream %d is of unknown type",
945                              p_ogg->i_streams-1 );
946                     free( p_stream );
947                     p_ogg->i_streams--;
948                 }
949
950                 if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS )
951                     return VLC_EGENERIC;
952             }
953
954             /* This is the first data page, which means we are now finished
955              * with the initial pages. We just need to store it in the relevant
956              * bitstream. */
957             for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
958             {
959                 if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
960                                        &oggpage ) == 0 )
961                 {
962                     break;
963                 }
964             }
965
966             return VLC_SUCCESS;
967         }
968     }
969 #undef p_stream
970
971     return VLC_EGENERIC;
972 }
973
974 /*****************************************************************************
975  * Activate: initializes ogg demux structures
976  *****************************************************************************/
977 static int Activate( vlc_object_t * p_this )
978 {
979     input_thread_t *p_input = (input_thread_t *)p_this;
980     demux_sys_t    *p_ogg;
981     int            b_forced;
982
983     p_input->p_demux_data = NULL;
984     b_forced = ( ( *p_input->psz_demux )&&
985                  ( !strncmp( p_input->psz_demux, "ogg", 10 ) ) ) ? 1 : 0;
986
987     /* Check if we are dealing with an ogg stream */
988     if( !b_forced && ( Ogg_Check( p_input ) != VLC_SUCCESS ) )
989         return -1;
990
991     /* Allocate p_ogg */
992     if( !( p_ogg = malloc( sizeof( demux_sys_t ) ) ) )
993     {
994         msg_Err( p_input, "out of memory" );
995         goto error;
996     }
997     memset( p_ogg, 0, sizeof( demux_sys_t ) );
998     p_input->p_demux_data = p_ogg;
999     p_ogg->pp_stream = NULL;
1000
1001     /* Initialize the Ogg physical bitstream parser */
1002     ogg_sync_init( &p_ogg->oy );
1003
1004     /* Set exported functions */
1005     p_input->pf_demux = Demux;
1006     p_input->pf_demux_control = Control;
1007
1008     /* Initialize access plug-in structures. */
1009     if( p_input->i_mtu == 0 )
1010     {
1011         /* Improve speed. */
1012         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
1013     }
1014
1015     /* Create one program */
1016     vlc_mutex_lock( &p_input->stream.stream_lock );
1017     if( input_InitStream( p_input, 0 ) == -1)
1018     {
1019         vlc_mutex_unlock( &p_input->stream.stream_lock );
1020         msg_Err( p_input, "cannot init stream" );
1021         goto error;
1022     }
1023     if( input_AddProgram( p_input, 0, 0) == NULL )
1024     {
1025         vlc_mutex_unlock( &p_input->stream.stream_lock );
1026         msg_Err( p_input, "cannot add program" );
1027         goto error;
1028     }
1029     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
1030     vlc_mutex_unlock( &p_input->stream.stream_lock );
1031
1032     /* Begnning of stream, tell the demux to look for elementary streams. */
1033     p_ogg->i_eos = 0;
1034
1035     p_ogg->i_old_synchro_state = !SYNCHRO_REINIT;
1036
1037     return 0;
1038
1039  error:
1040     Deactivate( (vlc_object_t *)p_input );
1041     return -1;
1042
1043 }
1044
1045 /****************************************************************************
1046  * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add
1047  *                        Elementary streams.
1048  ****************************************************************************/
1049 static int Ogg_BeginningOfStream( input_thread_t *p_input, demux_sys_t *p_ogg)
1050 {
1051     int i_stream;
1052
1053     /* Find the logical streams embedded in the physical stream and
1054      * initialize our p_ogg structure. */
1055     if( Ogg_FindLogicalStreams( p_input, p_ogg ) != VLC_SUCCESS )
1056     {
1057         msg_Warn( p_input, "couldn't find any ogg logical stream" );
1058         return VLC_EGENERIC;
1059     }
1060
1061     vlc_mutex_lock( &p_input->stream.stream_lock );
1062     p_input->stream.i_mux_rate = 0;
1063     vlc_mutex_unlock( &p_input->stream.stream_lock );
1064
1065     for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1066     {
1067 #define p_stream p_ogg->pp_stream[i_stream]
1068         if( p_stream->fmt.i_codec != VLC_FOURCC('f','l','a','c') )
1069             p_stream->p_es = es_out_Add( p_input->p_es_out, &p_stream->fmt );
1070
1071         if( p_stream->fmt.i_codec == VLC_FOURCC('c','m','m','l') )
1072         {
1073             /* Set the CMML stream active */
1074             es_out_Control( p_input->p_es_out, ES_OUT_SET_ES,
1075                             p_stream->p_es );
1076         }
1077
1078
1079         vlc_mutex_lock( &p_input->stream.stream_lock );
1080         p_input->stream.i_mux_rate += (p_stream->fmt.i_bitrate / ( 8 * 50 ));
1081         vlc_mutex_unlock( &p_input->stream.stream_lock );
1082
1083         p_stream->i_pcr = p_stream->i_previous_pcr =
1084             p_stream->i_interpolated_pcr = -1;
1085         p_stream->b_reinit = 0;
1086 #undef p_stream
1087     }
1088
1089     return VLC_SUCCESS;
1090 }
1091
1092 /****************************************************************************
1093  * Ogg_EndOfStream: clean up the ES when an End of Stream is detected.
1094  ****************************************************************************/
1095 static void Ogg_EndOfStream( input_thread_t *p_input, demux_sys_t *p_ogg )
1096 {
1097     int i_stream, j;
1098
1099 #define p_stream p_ogg->pp_stream[i_stream]
1100     for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1101     {
1102         if( p_stream->p_es )
1103             es_out_Del( p_input->p_es_out, p_stream->p_es );
1104
1105         vlc_mutex_lock( &p_input->stream.stream_lock );
1106         p_input->stream.i_mux_rate -= (p_stream->fmt.i_bitrate / ( 8 * 50 ));
1107         vlc_mutex_unlock( &p_input->stream.stream_lock );
1108
1109         ogg_stream_clear( &p_ogg->pp_stream[i_stream]->os );
1110         for( j = 0; j < p_ogg->pp_stream[i_stream]->i_packets_backup; j++ )
1111         {
1112             free( p_ogg->pp_stream[i_stream]->p_packets_backup[j].packet );
1113         }
1114         if( p_ogg->pp_stream[i_stream]->p_packets_backup)
1115             free( p_ogg->pp_stream[i_stream]->p_packets_backup );
1116
1117         es_format_Clean( &p_stream->fmt );
1118
1119         free( p_ogg->pp_stream[i_stream] );
1120     }
1121 #undef p_stream
1122
1123     /* Reinit p_ogg */
1124     if( p_ogg->pp_stream ) free( p_ogg->pp_stream );
1125     p_ogg->pp_stream = NULL;
1126     p_ogg->i_streams = 0;
1127 }
1128
1129 /*****************************************************************************
1130  * Deactivate: frees unused data
1131  *****************************************************************************/
1132 static void Deactivate( vlc_object_t *p_this )
1133 {
1134     input_thread_t *p_input = (input_thread_t *)p_this;
1135     demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data  ;
1136
1137     if( p_ogg )
1138     {
1139         /* Cleanup the bitstream parser */
1140         ogg_sync_clear( &p_ogg->oy );
1141
1142         Ogg_EndOfStream( p_input, p_ogg );
1143
1144         free( p_ogg );
1145     }
1146 }
1147
1148 /*****************************************************************************
1149  * Demux: reads and demuxes data packets
1150  *****************************************************************************
1151  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1152  *****************************************************************************/
1153 static int Demux( input_thread_t * p_input )
1154 {
1155     demux_sys_t *p_ogg = (demux_sys_t *)p_input->p_demux_data;
1156     ogg_page    oggpage;
1157     ogg_packet  oggpacket;
1158     int         i_stream;
1159
1160 #define p_stream p_ogg->pp_stream[i_stream]
1161
1162     if( p_ogg->i_eos == p_ogg->i_streams )
1163     {
1164         if( p_ogg->i_eos )
1165         {
1166             msg_Dbg( p_input, "end of a group of logical streams" );
1167             Ogg_EndOfStream( p_input, p_ogg );
1168         }
1169
1170         if( Ogg_BeginningOfStream( p_input, p_ogg ) != VLC_SUCCESS ) return 0;
1171         p_ogg->i_eos = 0;
1172
1173         msg_Dbg( p_input, "beginning of a group of logical streams" );
1174
1175         p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_REINIT;
1176         input_ClockManageRef( p_input, p_input->stream.p_selected_program, 0 );
1177     }
1178
1179     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1180     {
1181         msg_Warn( p_input, "synchro reinit" );
1182
1183         if( p_ogg->i_old_synchro_state != SYNCHRO_REINIT )
1184         for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
1185         {
1186             /* we'll trash all the data until we find the next pcr */
1187             p_stream->b_reinit = 1;
1188             p_stream->i_pcr = -1;
1189             p_stream->i_interpolated_pcr = -1;
1190             ogg_stream_reset( &p_stream->os );
1191         }
1192         if( p_ogg->i_old_synchro_state != SYNCHRO_REINIT )
1193         ogg_sync_reset( &p_ogg->oy );
1194     }
1195
1196     /*
1197      * Demux an ogg page from the stream
1198      */
1199     if( Ogg_ReadPage( p_input, p_ogg, &oggpage ) != VLC_SUCCESS )
1200     {
1201         return 0; /* EOF */
1202     }
1203
1204     /* Test for End of Stream */
1205     if( ogg_page_eos( &oggpage ) ) p_ogg->i_eos++;
1206
1207
1208     for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
1209     {
1210         if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 )
1211             continue;
1212
1213         while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
1214         {
1215             /* Read info from any secondary header packets, if there are any */
1216             if( p_stream->secondary_header_packets > 0 )
1217             {
1218                 if( p_stream->fmt.i_codec == VLC_FOURCC( 't','h','e','o' ) &&
1219                         oggpacket.bytes >= 7 &&
1220                         ! strncmp( &oggpacket.packet[1], "theora", 6 ) )
1221                 {
1222                     Ogg_ReadTheoraHeader( p_stream, &oggpacket );
1223                     p_stream->secondary_header_packets = 0;
1224                 }
1225                 else if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) &&
1226                         oggpacket.bytes >= 7 &&
1227                         ! strncmp( &oggpacket.packet[1], "vorbis", 6 ) )
1228                 {
1229                     Ogg_ReadVorbisHeader( p_stream, &oggpacket );
1230                     p_stream->secondary_header_packets = 0;
1231                 }
1232                 else if ( p_stream->fmt.i_codec == VLC_FOURCC( 'c','m','m','l' ) )
1233                 {
1234                     p_stream->secondary_header_packets = 0;
1235                 }
1236
1237                 p_stream->secondary_header_packets--;
1238             }
1239
1240             if( p_stream->b_reinit )
1241             {
1242                 /* If synchro is re-initialized we need to drop all the packets
1243                  * until we find a new dated one. */
1244                 Ogg_UpdatePCR( p_stream, &oggpacket );
1245
1246                 if( p_stream->i_pcr >= 0 )
1247                 {
1248                     p_stream->b_reinit = 0;
1249                 }
1250                 else
1251                 {
1252                     p_stream->i_interpolated_pcr = -1;
1253                     continue;
1254                 }
1255
1256                 /* An Ogg/vorbis packet contains an end date granulepos */
1257                 if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) ||
1258                     p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) ||
1259                     p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) )
1260                 {
1261                     if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
1262                     {
1263                         Ogg_DecodePacket( p_input, p_stream, &oggpacket );
1264                     }
1265                     else
1266                     {
1267                         input_ClockManageRef( p_input,
1268                                       p_input->stream.p_selected_program,
1269                                       p_stream->i_pcr );
1270                     }
1271                     continue;
1272                 }
1273             }
1274
1275             Ogg_DecodePacket( p_input, p_stream, &oggpacket );
1276         }
1277         break;
1278     }
1279
1280     i_stream = 0; p_ogg->i_pcr = -1;
1281     for( ; i_stream < p_ogg->i_streams; i_stream++ )
1282     {
1283         if( p_stream->fmt.i_cat == SPU_ES )
1284             continue;
1285         if( p_stream->i_interpolated_pcr < 0 )
1286             continue;
1287
1288         if( p_ogg->i_pcr < 0 || p_stream->i_interpolated_pcr < p_ogg->i_pcr )
1289             p_ogg->i_pcr = p_stream->i_interpolated_pcr;
1290     }
1291
1292     if( p_ogg->i_pcr >= 0 )
1293     {
1294         input_ClockManageRef( p_input, p_input->stream.p_selected_program,
1295                               p_ogg->i_pcr );
1296     }
1297
1298 #undef p_stream
1299
1300     p_ogg->i_old_synchro_state =
1301         p_input->stream.p_selected_program->i_synchro_state;
1302
1303     return 1;
1304 }
1305
1306 /*****************************************************************************
1307  * Control:
1308  *****************************************************************************/
1309 static int Control( input_thread_t *p_input, int i_query, va_list args )
1310 {
1311     demux_sys_t *p_ogg  = (demux_sys_t *)p_input->p_demux_data;
1312     int64_t *pi64;
1313
1314     switch( i_query )
1315     {
1316         case DEMUX_GET_TIME:
1317             pi64 = (int64_t*)va_arg( args, int64_t * );
1318             *pi64 = p_ogg->i_pcr * 100 / 9;
1319             return VLC_SUCCESS;
1320
1321         default:
1322             return demux_vaControlDefault( p_input, i_query, args );
1323     }
1324 }
1325
1326 static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
1327                                   ogg_packet *p_oggpacket )
1328 {
1329     bs_t bitstream;
1330     int i_fps_numerator;
1331     int i_fps_denominator;
1332     int i_keyframe_frequency_force;
1333
1334     p_stream->fmt.i_cat = VIDEO_ES;
1335     p_stream->fmt.i_codec = VLC_FOURCC( 't','h','e','o' );
1336
1337     /* Signal that we want to keep a backup of the vorbis
1338      * stream headers. They will be used when switching between
1339      * audio streams. */
1340     p_stream->b_force_backup = 1;
1341
1342     /* Cheat and get additionnal info ;) */
1343     bs_init( &bitstream, p_oggpacket->packet, p_oggpacket->bytes );
1344     bs_skip( &bitstream, 56 );
1345     bs_read( &bitstream, 8 ); /* major version num */
1346     bs_read( &bitstream, 8 ); /* minor version num */
1347     bs_read( &bitstream, 8 ); /* subminor version num */
1348     bs_read( &bitstream, 16 ) /*<< 4*/; /* width */
1349     bs_read( &bitstream, 16 ) /*<< 4*/; /* height */
1350     bs_read( &bitstream, 24 ); /* frame width */
1351     bs_read( &bitstream, 24 ); /* frame height */
1352     bs_read( &bitstream, 8 ); /* x offset */
1353     bs_read( &bitstream, 8 ); /* y offset */
1354
1355     i_fps_numerator = bs_read( &bitstream, 32 );
1356     i_fps_denominator = bs_read( &bitstream, 32 );
1357     bs_read( &bitstream, 24 ); /* aspect_numerator */
1358     bs_read( &bitstream, 24 ); /* aspect_denominator */
1359     i_keyframe_frequency_force = 1 << bs_read( &bitstream, 5 );
1360     bs_read( &bitstream, 8 ); /* colorspace */
1361     p_stream->fmt.i_bitrate = bs_read( &bitstream, 24 );
1362     bs_read( &bitstream, 6 ); /* quality */
1363
1364     /* granule_shift = i_log( frequency_force -1 ) */
1365     p_stream->i_theora_keyframe_granule_shift = 0;
1366     i_keyframe_frequency_force--;
1367     while( i_keyframe_frequency_force )
1368     {
1369         p_stream->i_theora_keyframe_granule_shift++;
1370         i_keyframe_frequency_force >>= 1;
1371     }
1372
1373     p_stream->f_rate = ((float)i_fps_numerator) / i_fps_denominator;
1374
1375     /* Save this data in p_extra for ffmpeg */
1376     p_stream->fmt.i_extra = p_oggpacket->bytes;
1377     p_stream->fmt.p_extra = malloc( p_oggpacket->bytes );
1378     memcpy( p_stream->fmt.p_extra, p_oggpacket->packet, p_oggpacket->bytes );
1379
1380 }
1381
1382 static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
1383                                   ogg_packet *p_oggpacket )
1384 {
1385     oggpack_buffer opb;
1386
1387     p_stream->fmt.i_cat = AUDIO_ES;
1388     p_stream->fmt.i_codec = VLC_FOURCC( 'v','o','r','b' );
1389
1390     /* Signal that we want to keep a backup of the vorbis
1391      * stream headers. They will be used when switching between
1392      * audio streams. */
1393     p_stream->b_force_backup = 1;
1394
1395     /* Cheat and get additionnal info ;) */
1396     oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
1397     oggpack_adv( &opb, 88 );
1398     p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
1399     p_stream->f_rate = p_stream->fmt.audio.i_rate =
1400         oggpack_read( &opb, 32 );
1401     oggpack_adv( &opb, 32 );
1402     p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
1403 }
1404
1405 static void Ogg_ReadAnnodexHeader( vlc_object_t *p_this,
1406                                    logical_stream_t *p_stream,
1407                                    ogg_packet *p_oggpacket )
1408 {
1409     if( ! strncmp( &p_oggpacket->packet[0], "Annodex", 7 ) )
1410     {
1411         Ogg_ReadTheoraHeader( p_stream, p_oggpacket );
1412         oggpack_buffer opb;
1413
1414         uint16_t major_version;
1415         uint16_t minor_version;
1416         uint64_t timebase_numerator;
1417         uint64_t timebase_denominator;
1418
1419         oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
1420         oggpack_adv( &opb, 8*8 ); /* "Annodex\0" header */
1421         major_version = oggpack_read( &opb, 2*8 ); /* major version */
1422         minor_version = oggpack_read( &opb, 2*8 ); /* minor version */
1423         timebase_numerator = GetQWLE( &p_oggpacket->packet[16] );
1424         timebase_denominator = GetQWLE( &p_oggpacket->packet[24] );
1425     }
1426     else if( ! strncmp( &p_oggpacket->packet[0], "AnxData", 7 ) )
1427     {
1428         uint64_t granule_rate_numerator;
1429         uint64_t granule_rate_denominator;
1430         char content_type_string[1024];
1431
1432         /* Read in Annodex header fields */
1433
1434         granule_rate_numerator = GetQWLE( &p_oggpacket->packet[8] );
1435         granule_rate_denominator = GetQWLE( &p_oggpacket->packet[16] );
1436         p_stream->secondary_header_packets =
1437             GetDWLE( &p_oggpacket->packet[24] );
1438
1439         msg_Dbg( p_this, "anxdata packet info: %qd/%qd, %d",
1440                  granule_rate_numerator, granule_rate_denominator,
1441                  p_stream->secondary_header_packets);
1442
1443         /* we are guaranteed that the first header field will be
1444          * the content-type (by the Annodex standard) */
1445         sscanf( &p_oggpacket->packet[28], "Content-Type: %1024s\r\n",
1446                 content_type_string );
1447
1448         p_stream->f_rate = (float) granule_rate_numerator /
1449             (float) granule_rate_denominator;
1450
1451         /* What type of file do we have?
1452          * strcmp is safe to use here because we've extracted
1453          * content_type_string from the stream manually */
1454         if( !strncmp(content_type_string, "audio/x-wav", 11) )
1455         {
1456             /* n.b. WAVs are unsupported right now */
1457             p_stream->fmt.i_cat = UNKNOWN_ES;
1458         }
1459         else if( !strncmp(content_type_string, "audio/x-vorbis", 14) )
1460         {
1461             p_stream->fmt.i_cat = AUDIO_ES;
1462             p_stream->fmt.i_codec = VLC_FOURCC( 'v','o','r','b' );
1463
1464             p_stream->b_force_backup = 1;
1465         }
1466         else if( !strncmp(content_type_string, "video/x-theora", 14) )
1467         {
1468             p_stream->fmt.i_cat = VIDEO_ES;
1469             p_stream->fmt.i_codec = VLC_FOURCC( 't','h','e','o' );
1470
1471             p_stream->b_force_backup = 1;
1472         }
1473         else if( !strncmp(content_type_string, "video/x-xvid", 14) )
1474         {
1475             p_stream->fmt.i_cat = VIDEO_ES;
1476             p_stream->fmt.i_codec = VLC_FOURCC( 'x','v','i','d' );
1477
1478             p_stream->b_force_backup = 1;
1479         }
1480         else if( !strncmp(content_type_string, "video/mpeg", 14) )
1481         {
1482             /* n.b. MPEG streams are unsupported right now */
1483             p_stream->fmt.i_cat = VIDEO_ES;
1484             p_stream->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );
1485         }
1486         else if( !strncmp(content_type_string, "text/x-cmml", 11) )
1487         {
1488             ogg_stream_packetout( &p_stream->os, p_oggpacket );
1489             p_stream->fmt.i_cat = SPU_ES;
1490             p_stream->fmt.i_codec = VLC_FOURCC( 'c','m','m','l' );
1491         }
1492     }
1493 }