Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

ogg.c

00001 /*****************************************************************************
00002  * ogg.c : ogg stream demux module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2001-2003 the VideoLAN team
00005  * $Id: ogg.c 12801 2005-10-09 17:56:25Z fenrir $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *          Andre Pang <[email protected]> (Annodex support)
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <vlc/vlc.h>
00029 #include <vlc/input.h>
00030 
00031 #include <ogg/ogg.h>
00032 
00033 #include "codecs.h"
00034 #include "vlc_bits.h"
00035 
00036 /*****************************************************************************
00037  * Module descriptor
00038  *****************************************************************************/
00039 static int  Open ( vlc_object_t * );
00040 static void Close( vlc_object_t * );
00041 
00042 vlc_module_begin();
00043     set_description( _("Ogg stream demuxer" ) );
00044     set_category( CAT_INPUT );
00045     set_subcategory( SUBCAT_INPUT_DEMUX );
00046     set_capability( "demux2", 50 );
00047     set_callbacks( Open, Close );
00048     add_shortcut( "ogg" );
00049 vlc_module_end();
00050 
00051 
00052 /*****************************************************************************
00053  * Definitions of structures and functions used by this plugins
00054  *****************************************************************************/
00055 typedef struct logical_stream_s
00056 {
00057     ogg_stream_state os;                        /* logical stream of packets */
00058 
00059     es_format_t      fmt;
00060     es_out_id_t      *p_es;
00061     double           f_rate;
00062 
00063     int              i_serial_no;
00064 
00065     /* the header of some logical streams (eg vorbis) contain essential
00066      * data for the decoder. We back them up here in case we need to re-feed
00067      * them to the decoder. */
00068     int              b_force_backup;
00069     int              i_packets_backup;
00070     uint8_t          *p_headers;
00071     int              i_headers;
00072 
00073     /* program clock reference (in units of 90kHz) derived from the previous
00074      * granulepos */
00075     mtime_t          i_pcr;
00076     mtime_t          i_interpolated_pcr;
00077     mtime_t          i_previous_pcr;
00078 
00079     /* Misc */
00080     int b_reinit;
00081     int i_theora_keyframe_granule_shift;
00082 
00083     /* for Annodex logical bitstreams */
00084     int secondary_header_packets;
00085 
00086 } logical_stream_t;
00087 
00088 struct demux_sys_t
00089 {
00090     ogg_sync_state oy;        /* sync and verify incoming physical bitstream */
00091 
00092     int i_streams;                           /* number of logical bitstreams */
00093     logical_stream_t **pp_stream;  /* pointer to an array of logical streams */
00094 
00095     /* program clock reference (in units of 90kHz) derived from the pcr of
00096      * the sub-streams */
00097     mtime_t i_pcr;
00098 
00099     /* stream state */
00100     int     i_eos;
00101 
00102     /* bitrate */
00103     int     i_bitrate;
00104 };
00105 
00106 /* OggDS headers for the new header format (used in ogm files) */
00107 typedef struct stream_header_video
00108 {
00109     ogg_int32_t width;
00110     ogg_int32_t height;
00111 } stream_header_video;
00112 
00113 typedef struct stream_header_audio
00114 {
00115     ogg_int16_t channels;
00116     ogg_int16_t blockalign;
00117     ogg_int32_t avgbytespersec;
00118 } stream_header_audio;
00119 
00120 typedef struct stream_header
00121 {
00122     char        streamtype[8];
00123     char        subtype[4];
00124 
00125     ogg_int32_t size;                               /* size of the structure */
00126 
00127     ogg_int64_t time_unit;                              /* in reference time */
00128     ogg_int64_t samples_per_unit;
00129     ogg_int32_t default_len;                                /* in media time */
00130 
00131     ogg_int32_t buffersize;
00132     ogg_int16_t bits_per_sample;
00133 
00134     union
00135     {
00136         /* Video specific */
00137         stream_header_video video;
00138         /* Audio specific */
00139         stream_header_audio audio;
00140     } sh;
00141 } stream_header;
00142 
00143 #define OGG_BLOCK_SIZE 4096
00144 
00145 /* Some defines from OggDS */
00146 #define PACKET_TYPE_HEADER   0x01
00147 #define PACKET_TYPE_BITS     0x07
00148 #define PACKET_LEN_BITS01    0xc0
00149 #define PACKET_LEN_BITS2     0x02
00150 #define PACKET_IS_SYNCPOINT  0x08
00151 
00152 /*****************************************************************************
00153  * Local prototypes
00154  *****************************************************************************/
00155 static int  Demux  ( demux_t * );
00156 static int  Control( demux_t *, int, va_list );
00157 
00158 /* Bitstream manipulation */
00159 static int  Ogg_ReadPage     ( demux_t *, ogg_page * );
00160 static void Ogg_UpdatePCR    ( logical_stream_t *, ogg_packet * );
00161 static void Ogg_DecodePacket ( demux_t *, logical_stream_t *, ogg_packet * );
00162 
00163 static int Ogg_BeginningOfStream( demux_t *p_demux );
00164 static int Ogg_FindLogicalStreams( demux_t *p_demux );
00165 static void Ogg_EndOfStream( demux_t *p_demux );
00166 
00167 /* Logical bitstream headers */
00168 static void Ogg_ReadTheoraHeader( logical_stream_t *, ogg_packet * );
00169 static void Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
00170 static void Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
00171 static void Ogg_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );
00172 static void Ogg_ReadAnnodexHeader( vlc_object_t *, logical_stream_t *, ogg_packet * );
00173 
00174 /*****************************************************************************
00175  * Open: initializes ogg demux structures
00176  *****************************************************************************/
00177 static int Open( vlc_object_t * p_this )
00178 {
00179     demux_t *p_demux = (demux_t *)p_this;
00180     demux_sys_t    *p_sys;
00181     uint8_t        *p_peek;
00182 
00183 
00184     /* Check if we are dealing with an ogg stream */
00185     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
00186     if( strcmp( p_demux->psz_demux, "ogg" ) && memcmp( p_peek, "OggS", 4 ) )
00187     {
00188         return VLC_EGENERIC;
00189     }
00190 
00191     /* Set exported functions */
00192     p_demux->pf_demux = Demux;
00193     p_demux->pf_control = Control;
00194     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00195 
00196     memset( p_sys, 0, sizeof( demux_sys_t ) );
00197     p_sys->i_bitrate = 0;
00198     p_sys->pp_stream = NULL;
00199 
00200     /* Begnning of stream, tell the demux to look for elementary streams. */
00201     p_sys->i_eos = 0;
00202 
00203     /* Initialize the Ogg physical bitstream parser */
00204     ogg_sync_init( &p_sys->oy );
00205 
00206     return VLC_SUCCESS;
00207 }
00208 
00209 /*****************************************************************************
00210  * Close: frees unused data
00211  *****************************************************************************/
00212 static void Close( vlc_object_t *p_this )
00213 {
00214     demux_t *p_demux = (demux_t *)p_this;
00215     demux_sys_t *p_sys = p_demux->p_sys  ;
00216 
00217     /* Cleanup the bitstream parser */
00218     ogg_sync_clear( &p_sys->oy );
00219 
00220     Ogg_EndOfStream( p_demux );
00221 
00222     free( p_sys );
00223 }
00224 
00225 /*****************************************************************************
00226  * Demux: reads and demuxes data packets
00227  *****************************************************************************
00228  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
00229  *****************************************************************************/
00230 static int Demux( demux_t * p_demux )
00231 {
00232     demux_sys_t *p_sys = p_demux->p_sys;
00233     ogg_page    oggpage;
00234     ogg_packet  oggpacket;
00235     int         i_stream;
00236 
00237 
00238     if( p_sys->i_eos == p_sys->i_streams )
00239     {
00240         if( p_sys->i_eos )
00241         {
00242             msg_Dbg( p_demux, "end of a group of logical streams" );
00243             Ogg_EndOfStream( p_demux );
00244         }
00245 
00246         p_sys->i_eos = 0;
00247         if( Ogg_BeginningOfStream( p_demux ) != VLC_SUCCESS ) return 0;
00248 
00249         msg_Dbg( p_demux, "beginning of a group of logical streams" );
00250         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00251     }
00252 
00253     /*
00254      * Demux an ogg page from the stream
00255      */
00256     if( Ogg_ReadPage( p_demux, &oggpage ) != VLC_SUCCESS )
00257     {
00258         return 0; /* EOF */
00259     }
00260 
00261     /* Test for End of Stream */
00262     if( ogg_page_eos( &oggpage ) ) p_sys->i_eos++;
00263 
00264 
00265     for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
00266     {
00267         logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
00268 
00269         if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 )
00270             continue;
00271 
00272         while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
00273         {
00274             /* Read info from any secondary header packets, if there are any */
00275             if( p_stream->secondary_header_packets > 0 )
00276             {
00277                 if( p_stream->fmt.i_codec == VLC_FOURCC('t','h','e','o') &&
00278                         oggpacket.bytes >= 7 &&
00279                         ! memcmp( &oggpacket.packet[1], "theora", 6 ) )
00280                 {
00281                     Ogg_ReadTheoraHeader( p_stream, &oggpacket );
00282                     p_stream->secondary_header_packets = 0;
00283                 }
00284                 else if( p_stream->fmt.i_codec == VLC_FOURCC('v','o','r','b') &&
00285                         oggpacket.bytes >= 7 &&
00286                         ! memcmp( &oggpacket.packet[1], "vorbis", 6 ) )
00287                 {
00288                     Ogg_ReadVorbisHeader( p_stream, &oggpacket );
00289                     p_stream->secondary_header_packets = 0;
00290                 }
00291                 else if ( p_stream->fmt.i_codec == VLC_FOURCC('c','m','m','l') )
00292                 {
00293                     p_stream->secondary_header_packets = 0;
00294                 }
00295             }
00296 
00297             if( p_stream->b_reinit )
00298             {
00299                 /* If synchro is re-initialized we need to drop all the packets
00300                  * until we find a new dated one. */
00301                 Ogg_UpdatePCR( p_stream, &oggpacket );
00302 
00303                 if( p_stream->i_pcr >= 0 )
00304                 {
00305                     p_stream->b_reinit = 0;
00306                 }
00307                 else
00308                 {
00309                     p_stream->i_interpolated_pcr = -1;
00310                     continue;
00311                 }
00312 
00313                 /* An Ogg/vorbis packet contains an end date granulepos */
00314                 if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) ||
00315                     p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) ||
00316                     p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) )
00317                 {
00318                     if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
00319                     {
00320                         Ogg_DecodePacket( p_demux, p_stream, &oggpacket );
00321                     }
00322                     else
00323                     {
00324                         es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00325                                         p_stream->i_pcr );
00326                     }
00327                     continue;
00328                 }
00329             }
00330 
00331             Ogg_DecodePacket( p_demux, p_stream, &oggpacket );
00332         }
00333         break;
00334     }
00335 
00336     i_stream = 0; p_sys->i_pcr = -1;
00337     for( ; i_stream < p_sys->i_streams; i_stream++ )
00338     {
00339         logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
00340 
00341         if( p_stream->fmt.i_cat == SPU_ES )
00342             continue;
00343         if( p_stream->i_interpolated_pcr < 0 )
00344             continue;
00345 
00346         if( p_sys->i_pcr < 0 || p_stream->i_interpolated_pcr < p_sys->i_pcr )
00347             p_sys->i_pcr = p_stream->i_interpolated_pcr;
00348     }
00349 
00350     if( p_sys->i_pcr >= 0 )
00351     {
00352         es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr );
00353     }
00354 
00355 
00356     return 1;
00357 }
00358 
00359 /*****************************************************************************
00360  * Control:
00361  *****************************************************************************/
00362 static int Control( demux_t *p_demux, int i_query, va_list args )
00363 {
00364     demux_sys_t *p_sys  = p_demux->p_sys;
00365     int64_t *pi64;
00366     int i;
00367 
00368     switch( i_query )
00369     {
00370         case DEMUX_GET_TIME:
00371             pi64 = (int64_t*)va_arg( args, int64_t * );
00372             *pi64 = p_sys->i_pcr;
00373             return VLC_SUCCESS;
00374 
00375         case DEMUX_SET_TIME:
00376             return VLC_EGENERIC;
00377 
00378         case DEMUX_SET_POSITION:
00379             for( i = 0; i < p_sys->i_streams; i++ )
00380             {
00381                 logical_stream_t *p_stream = p_sys->pp_stream[i];
00382 
00383                 /* we'll trash all the data until we find the next pcr */
00384                 p_stream->b_reinit = 1;
00385                 p_stream->i_pcr = -1;
00386                 p_stream->i_interpolated_pcr = -1;
00387                 ogg_stream_reset( &p_stream->os );
00388             }
00389             ogg_sync_reset( &p_sys->oy );
00390 
00391         default:
00392             return demux2_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
00393                                            1, i_query, args );
00394     }
00395 }
00396 
00397 /****************************************************************************
00398  * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
00399  ****************************************************************************
00400  * Returns VLC_SUCCESS if a page has been read. An error might happen if we
00401  * are at the end of stream.
00402  ****************************************************************************/
00403 static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage )
00404 {
00405     demux_sys_t *p_ogg = p_demux->p_sys  ;
00406     int i_read = 0;
00407     char *p_buffer;
00408 
00409     while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
00410     {
00411         p_buffer = ogg_sync_buffer( &p_ogg->oy, OGG_BLOCK_SIZE );
00412 
00413         i_read = stream_Read( p_demux->s, p_buffer, OGG_BLOCK_SIZE );
00414         if( i_read <= 0 )
00415             return VLC_EGENERIC;
00416 
00417         ogg_sync_wrote( &p_ogg->oy, i_read );
00418     }
00419 
00420     return VLC_SUCCESS;
00421 }
00422 
00423 /****************************************************************************
00424  * Ogg_UpdatePCR: update the PCR (90kHz program clock reference) for the
00425  *                current stream.
00426  ****************************************************************************/
00427 static void Ogg_UpdatePCR( logical_stream_t *p_stream,
00428                            ogg_packet *p_oggpacket )
00429 {
00430     /* Convert the granulepos into a pcr */
00431     if( p_oggpacket->granulepos >= 0 )
00432     {
00433         if( p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) )
00434         {
00435             p_stream->i_pcr = p_oggpacket->granulepos * I64C(1000000)
00436                               / p_stream->f_rate;
00437         }
00438         else
00439         {
00440             ogg_int64_t iframe = p_oggpacket->granulepos >>
00441               p_stream->i_theora_keyframe_granule_shift;
00442             ogg_int64_t pframe = p_oggpacket->granulepos -
00443               ( iframe << p_stream->i_theora_keyframe_granule_shift );
00444 
00445             p_stream->i_pcr = ( iframe + pframe ) * I64C(1000000)
00446                               / p_stream->f_rate;
00447         }
00448 
00449         p_stream->i_interpolated_pcr = p_stream->i_pcr;
00450     }
00451     else
00452     {
00453         p_stream->i_pcr = -1;
00454 
00455         /* no granulepos available, try to interpolate the pcr.
00456          * If we can't then don't touch the old value. */
00457         if( p_stream->fmt.i_cat == VIDEO_ES )
00458             /* 1 frame per packet */
00459             p_stream->i_interpolated_pcr += (I64C(1000000) / p_stream->f_rate);
00460         else if( p_stream->fmt.i_bitrate )
00461             p_stream->i_interpolated_pcr +=
00462                 ( p_oggpacket->bytes * I64C(1000000) /
00463                   p_stream->fmt.i_bitrate / 8 );
00464     }
00465 }
00466 
00467 /****************************************************************************
00468  * Ogg_DecodePacket: Decode an Ogg packet.
00469  ****************************************************************************/
00470 static void Ogg_DecodePacket( demux_t *p_demux,
00471                               logical_stream_t *p_stream,
00472                               ogg_packet *p_oggpacket )
00473 {
00474     block_t *p_block;
00475     vlc_bool_t b_selected;
00476     int i_header_len = 0;
00477     mtime_t i_pts = -1, i_interpolated_pts;
00478 
00479     /* Sanity check */
00480     if( !p_oggpacket->bytes )
00481     {
00482         msg_Dbg( p_demux, "discarding 0 sized packet" );
00483         return;
00484     }
00485 
00486     if( p_oggpacket->bytes >= 7 &&
00487         ! memcmp ( &p_oggpacket->packet[0], "Annodex", 7 ) )
00488     {
00489         /* it's an Annodex packet -- skip it (do nothing) */
00490         return; 
00491     }
00492     else if( p_oggpacket->bytes >= 7 &&
00493         ! memcmp ( &p_oggpacket->packet[0], "AnxData", 7 ) )
00494     {
00495         /* it's an AnxData packet -- skip it (do nothing) */
00496         return; 
00497     }
00498 
00499     if( p_stream->fmt.i_codec == VLC_FOURCC( 's','u','b','t' ) &&
00500         p_oggpacket->packet[0] & PACKET_TYPE_BITS ) return;
00501 
00502     /* Check the ES is selected */
00503     es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
00504                     p_stream->p_es, &b_selected );
00505 
00506     if( p_stream->b_force_backup )
00507     {
00508         uint8_t *p_extra;
00509         vlc_bool_t b_store_size = VLC_TRUE;
00510 
00511         p_stream->i_packets_backup++;
00512         switch( p_stream->fmt.i_codec )
00513         {
00514         case VLC_FOURCC( 'v','o','r','b' ):
00515         case VLC_FOURCC( 's','p','x',' ' ):
00516         case VLC_FOURCC( 't','h','e','o' ):
00517             if( p_stream->i_packets_backup == 3 ) p_stream->b_force_backup = 0;
00518             break;
00519 
00520         case VLC_FOURCC( 'f','l','a','c' ):
00521             if( !p_stream->fmt.audio.i_rate && p_stream->i_packets_backup == 2 )
00522             {
00523                 Ogg_ReadFlacHeader( p_demux, p_stream, p_oggpacket );
00524                 p_stream->b_force_backup = 0;
00525             }
00526             else if( p_stream->fmt.audio.i_rate )
00527             {
00528                 p_stream->b_force_backup = 0;
00529                 if( p_oggpacket->bytes >= 9 )
00530                 {
00531                     p_oggpacket->packet += 9;
00532                     p_oggpacket->bytes -= 9;
00533                 }
00534             }
00535             b_store_size = VLC_FALSE;
00536             break;
00537 
00538         default:
00539             p_stream->b_force_backup = 0;
00540             break;
00541         }
00542 
00543         /* Backup the ogg packet (likely an header packet) */
00544         p_stream->p_headers =
00545             realloc( p_stream->p_headers, p_stream->i_headers +
00546                      p_oggpacket->bytes + (b_store_size ? 2 : 0) );
00547         p_extra = p_stream->p_headers + p_stream->i_headers;
00548         if( b_store_size )
00549         {
00550             *(p_extra++) = p_oggpacket->bytes >> 8;
00551             *(p_extra++) = p_oggpacket->bytes & 0xFF;
00552         }
00553         memcpy( p_extra, p_oggpacket->packet, p_oggpacket->bytes );
00554         p_stream->i_headers += p_oggpacket->bytes + (b_store_size ? 2 : 0);
00555 
00556         if( !p_stream->b_force_backup )
00557         {
00558             /* Last header received, commit changes */
00559             p_stream->fmt.i_extra = p_stream->i_headers;
00560             p_stream->fmt.p_extra =
00561                 realloc( p_stream->fmt.p_extra, p_stream->i_headers );
00562             memcpy( p_stream->fmt.p_extra, p_stream->p_headers,
00563                     p_stream->i_headers );
00564             es_out_Control( p_demux->out, ES_OUT_SET_FMT,
00565                             p_stream->p_es, &p_stream->fmt );
00566         }
00567 
00568         b_selected = VLC_FALSE; /* Discard the header packet */
00569     }
00570 
00571     /* Convert the pcr into a pts */
00572     if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) ||
00573         p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) ||
00574         p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) )
00575     {
00576         if( p_stream->i_pcr >= 0 )
00577         {
00578             /* This is for streams where the granulepos of the header packets
00579              * doesn't match these of the data packets (eg. ogg web radios). */
00580             if( p_stream->i_previous_pcr == 0 &&
00581                 p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY )
00582             {
00583                 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00584 
00585                 /* Call the pace control */
00586                 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
00587                                 p_stream->i_pcr );
00588             }
00589 
00590             p_stream->i_previous_pcr = p_stream->i_pcr;
00591 
00592             /* The granulepos is the end date of the sample */
00593             i_pts =  p_stream->i_pcr;
00594         }
00595     }
00596 
00597     /* Convert the granulepos into the next pcr */
00598     i_interpolated_pts = p_stream->i_interpolated_pcr;
00599     Ogg_UpdatePCR( p_stream, p_oggpacket );
00600 
00601     if( p_stream->i_pcr >= 0 )
00602     {
00603         /* This is for streams where the granulepos of the header packets
00604          * doesn't match these of the data packets (eg. ogg web radios). */
00605         if( p_stream->i_previous_pcr == 0 &&
00606             p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY )
00607         {
00608             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00609 
00610             /* Call the pace control */
00611             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_stream->i_pcr );
00612         }
00613     }
00614 
00615     if( p_stream->fmt.i_codec != VLC_FOURCC( 'v','o','r','b' ) &&
00616         p_stream->fmt.i_codec != VLC_FOURCC( 's','p','x',' ' ) &&
00617         p_stream->fmt.i_codec != VLC_FOURCC( 'f','l','a','c' ) &&
00618         p_stream->i_pcr >= 0 )
00619     {
00620         p_stream->i_previous_pcr = p_stream->i_pcr;
00621 
00622         /* The granulepos is the start date of the sample */
00623         i_pts = p_stream->i_pcr;
00624     }
00625 
00626     if( !b_selected )
00627     {
00628         /* This stream isn't currently selected so we don't need to decode it,
00629          * but we did need to store its pcr as it might be selected later on */
00630         return;
00631     }
00632 
00633     if( p_oggpacket->bytes <= 0 )
00634         return;
00635 
00636     if( !( p_block = block_New( p_demux, p_oggpacket->bytes ) ) ) return;
00637 
00638     /* Normalize PTS */
00639     if( i_pts == 0 ) i_pts = 1;
00640     else if( i_pts == -1 && i_interpolated_pts == 0 ) i_pts = 1;
00641     else if( i_pts == -1 ) i_pts = 0;
00642 
00643     if( p_stream->fmt.i_cat == AUDIO_ES )
00644         p_block->i_dts = p_block->i_pts = i_pts;
00645     else if( p_stream->fmt.i_cat == SPU_ES )
00646     {
00647         p_block->i_dts = p_block->i_pts = i_pts;
00648         p_block->i_length = 0;
00649     }
00650     else if( p_stream->fmt.i_codec == VLC_FOURCC( 't','h','e','o' ) )
00651         p_block->i_dts = p_block->i_pts = i_pts;
00652     else
00653     {
00654         p_block->i_dts = i_pts;
00655         p_block->i_pts = 0;
00656     }
00657 
00658     if( p_stream->fmt.i_codec != VLC_FOURCC( 'v','o','r','b' ) &&
00659         p_stream->fmt.i_codec != VLC_FOURCC( 's','p','x',' ' ) &&
00660         p_stream->fmt.i_codec != VLC_FOURCC( 'f','l','a','c' ) &&
00661         p_stream->fmt.i_codec != VLC_FOURCC( 't','a','r','k' ) &&
00662         p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) &&
00663         p_stream->fmt.i_codec != VLC_FOURCC( 'c','m','m','l' ) )
00664     {
00665         /* We remove the header from the packet */
00666         i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
00667         i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
00668 
00669         if( p_stream->fmt.i_codec == VLC_FOURCC( 's','u','b','t' ))
00670         {
00671             /* But with subtitles we need to retrieve the duration first */
00672             int i, lenbytes = 0;
00673 
00674             if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 )
00675             {
00676                 for( i = 0, lenbytes = 0; i < i_header_len; i++ )
00677                 {
00678                     lenbytes = lenbytes << 8;
00679                     lenbytes += *(p_oggpacket->packet + i_header_len - i);
00680                 }
00681             }
00682             if( p_oggpacket->bytes - 1 - i_header_len > 2 ||
00683                 ( p_oggpacket->packet[i_header_len + 1] != ' ' &&
00684                   p_oggpacket->packet[i_header_len + 1] != 0 && 
00685                   p_oggpacket->packet[i_header_len + 1] != '\n' &&
00686                   p_oggpacket->packet[i_header_len + 1] != '\r' ) )
00687             {
00688                 p_block->i_length = (mtime_t)lenbytes * 1000;
00689             }
00690         }
00691 
00692         i_header_len++;
00693         if( p_block->i_buffer >= i_header_len )
00694             p_block->i_buffer -= i_header_len;
00695         else
00696             p_block->i_buffer = 0;
00697     }
00698 
00699     if( p_stream->fmt.i_codec == VLC_FOURCC( 't','a','r','k' ) )
00700     {
00701         /* FIXME: the biggest hack I've ever done */
00702         msg_Warn( p_demux, "tarkin pts: "I64Fd", granule: "I64Fd,
00703                   p_block->i_pts, p_block->i_dts );
00704         msleep(10000);
00705     }
00706 
00707     memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
00708             p_oggpacket->bytes - i_header_len );
00709 
00710     es_out_Send( p_demux->out, p_stream->p_es, p_block );
00711 }
00712 
00713 /****************************************************************************
00714  * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
00715  *                         stream and fill p_ogg.
00716  *****************************************************************************
00717  * The initial page of a logical stream is marked as a 'bos' page.
00718  * Furthermore, the Ogg specification mandates that grouped bitstreams begin
00719  * together and all of the initial pages must appear before any data pages.
00720  *
00721  * On success this function returns VLC_SUCCESS.
00722  ****************************************************************************/
00723 static int Ogg_FindLogicalStreams( demux_t *p_demux )
00724 {
00725     demux_sys_t *p_ogg = p_demux->p_sys  ;
00726     ogg_packet oggpacket;
00727     ogg_page oggpage;
00728     int i_stream;
00729 
00730 #define p_stream p_ogg->pp_stream[p_ogg->i_streams - 1]
00731 
00732     while( Ogg_ReadPage( p_demux, &oggpage ) == VLC_SUCCESS )
00733     {
00734         if( ogg_page_bos( &oggpage ) )
00735         {
00736 
00737             /* All is wonderful in our fine fine little world.
00738              * We found the beginning of our first logical stream. */
00739             while( ogg_page_bos( &oggpage ) )
00740             {
00741                 p_ogg->i_streams++;
00742                 p_ogg->pp_stream =
00743                     realloc( p_ogg->pp_stream, p_ogg->i_streams *
00744                              sizeof(logical_stream_t *) );
00745 
00746                 p_stream = malloc( sizeof(logical_stream_t) );
00747                 memset( p_stream, 0, sizeof(logical_stream_t) );
00748                 p_stream->p_headers = 0;
00749                 p_stream->secondary_header_packets = 0;
00750 
00751                 es_format_Init( &p_stream->fmt, 0, 0 );
00752 
00753                 /* Setup the logical stream */
00754                 p_stream->i_serial_no = ogg_page_serialno( &oggpage );
00755                 ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
00756 
00757                 /* Extract the initial header from the first page and verify
00758                  * the codec type of tis Ogg bitstream */
00759                 if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 )
00760                 {
00761                     /* error. stream version mismatch perhaps */
00762                     msg_Err( p_demux, "error reading first page of "
00763                              "Ogg bitstream data" );
00764                     return VLC_EGENERIC;
00765                 }
00766 
00767                 /* FIXME: check return value */
00768                 ogg_stream_packetpeek( &p_stream->os, &oggpacket );
00769 
00770                 /* Check for Vorbis header */
00771                 if( oggpacket.bytes >= 7 &&
00772                     ! memcmp( &oggpacket.packet[1], "vorbis", 6 ) )
00773                 {
00774                     Ogg_ReadVorbisHeader( p_stream, &oggpacket );
00775                     msg_Dbg( p_demux, "found vorbis header" );
00776                 }
00777                 /* Check for Speex header */
00778                 else if( oggpacket.bytes >= 7 &&
00779                     ! memcmp( &oggpacket.packet[0], "Speex", 5 ) )
00780                 {
00781                     Ogg_ReadSpeexHeader( p_stream, &oggpacket );
00782                     msg_Dbg( p_demux, "found speex header, channels: %i, "
00783                              "rate: %i,  bitrate: %i",
00784                              p_stream->fmt.audio.i_channels,
00785                              (int)p_stream->f_rate, p_stream->fmt.i_bitrate );
00786                 }
00787                 /* Check for Flac header (< version 1.1.1) */
00788                 else if( oggpacket.bytes >= 4 &&
00789                     ! memcmp( &oggpacket.packet[0], "fLaC", 4 ) )
00790                 {
00791                     msg_Dbg( p_demux, "found FLAC header" );
00792 
00793                     /* Grrrr!!!! Did they really have to put all the
00794                      * important info in the second header packet!!!
00795                      * (STREAMINFO metadata is in the following packet) */
00796                     p_stream->b_force_backup = 1;
00797 
00798                     p_stream->fmt.i_cat = AUDIO_ES;
00799                     p_stream->fmt.i_codec = VLC_FOURCC( 'f','l','a','c' );
00800                 }
00801                 /* Check for Flac header (>= version 1.1.1) */
00802                 else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F &&
00803                     ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) &&
00804                     ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) )
00805                 {
00806                     int i_packets = ((int)oggpacket.packet[7]) << 8 |
00807                         oggpacket.packet[8];
00808                     msg_Dbg( p_demux, "found FLAC header version %i.%i "
00809                              "(%i header packets)",
00810                              oggpacket.packet[5], oggpacket.packet[6],
00811                              i_packets );
00812 
00813                     p_stream->b_force_backup = 1;
00814 
00815                     p_stream->fmt.i_cat = AUDIO_ES;
00816                     p_stream->fmt.i_codec = VLC_FOURCC( 'f','l','a','c' );
00817                     oggpacket.packet += 13; oggpacket.bytes -= 13;
00818                     Ogg_ReadFlacHeader( p_demux, p_stream, &oggpacket );
00819                 }
00820                 /* Check for Theora header */
00821                 else if( oggpacket.bytes >= 7 &&
00822                          ! memcmp( &oggpacket.packet[1], "theora", 6 ) )
00823                 {
00824                     Ogg_ReadTheoraHeader( p_stream, &oggpacket );
00825 
00826                     msg_Dbg( p_demux,
00827                              "found theora header, bitrate: %i, rate: %f",
00828                              p_stream->fmt.i_bitrate, p_stream->f_rate );
00829                 }
00830                 /* Check for Tarkin header */
00831                 else if( oggpacket.bytes >= 7 &&
00832                          ! memcmp( &oggpacket.packet[1], "tarkin", 6 ) )
00833                 {
00834                     oggpack_buffer opb;
00835 
00836                     msg_Dbg( p_demux, "found tarkin header" );
00837                     p_stream->fmt.i_cat = VIDEO_ES;
00838                     p_stream->fmt.i_codec = VLC_FOURCC( 't','a','r','k' );
00839 
00840                     /* Cheat and get additionnal info ;) */
00841                     oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
00842                     oggpack_adv( &opb, 88 );
00843                     oggpack_adv( &opb, 104 );
00844                     p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
00845                     p_stream->f_rate = 2; /* FIXME */
00846                     msg_Dbg( p_demux,
00847                              "found tarkin header, bitrate: %i, rate: %f",
00848                              p_stream->fmt.i_bitrate, p_stream->f_rate );
00849                 }
00850                 /* Check for Annodex header */
00851                 else if( oggpacket.bytes >= 7 &&
00852                          ! memcmp( &oggpacket.packet[0], "Annodex", 7 ) )
00853                 {
00854                     Ogg_ReadAnnodexHeader( VLC_OBJECT(p_demux), p_stream,
00855                                            &oggpacket );
00856                     /* kill annodex track */
00857                     free( p_stream );
00858                     p_ogg->i_streams--;
00859                 }
00860                 /* Check for Annodex header */
00861                 else if( oggpacket.bytes >= 7 &&
00862                          ! memcmp( &oggpacket.packet[0], "AnxData", 7 ) )
00863                 {
00864                     Ogg_ReadAnnodexHeader( VLC_OBJECT(p_demux), p_stream,
00865                                            &oggpacket );
00866                 }
00867                 else if( oggpacket.bytes >= 142 &&
00868                          !memcmp( &oggpacket.packet[1],
00869                                    "Direct Show Samples embedded in Ogg", 35 ))
00870                 {
00871                     /* Old header type */
00872 
00873                     /* Check for video header (old format) */
00874                     if( GetDWLE((oggpacket.packet+96)) == 0x05589f80 &&
00875                         oggpacket.bytes >= 184 )
00876                     {
00877                         p_stream->fmt.i_cat = VIDEO_ES;
00878                         p_stream->fmt.i_codec =
00879                             VLC_FOURCC( oggpacket.packet[68],
00880                                         oggpacket.packet[69],
00881                                         oggpacket.packet[70],
00882                                         oggpacket.packet[71] );
00883                         msg_Dbg( p_demux, "found video header of type: %.4s",
00884                                  (char *)&p_stream->fmt.i_codec );
00885 
00886                         p_stream->fmt.video.i_frame_rate = 10000000;
00887                         p_stream->fmt.video.i_frame_rate_base =
00888                             GetQWLE((oggpacket.packet+164));
00889                         p_stream->f_rate = 10000000.0 /
00890                             GetQWLE((oggpacket.packet+164));
00891                         p_stream->fmt.video.i_bits_per_pixel =
00892                             GetWLE((oggpacket.packet+182));
00893                         if( !p_stream->fmt.video.i_bits_per_pixel )
00894                             /* hack, FIXME */
00895                             p_stream->fmt.video.i_bits_per_pixel = 24;
00896                         p_stream->fmt.video.i_width =
00897                             GetDWLE((oggpacket.packet+176));
00898                         p_stream->fmt.video.i_height =
00899                             GetDWLE((oggpacket.packet+180));
00900 
00901                         msg_Dbg( p_demux,
00902                                  "fps: %f, width:%i; height:%i, bitcount:%i",
00903                                  p_stream->f_rate,
00904                                  p_stream->fmt.video.i_width,
00905                                  p_stream->fmt.video.i_height,
00906                                  p_stream->fmt.video.i_bits_per_pixel);
00907 
00908                     }
00909                     /* Check for audio header (old format) */
00910                     else if( GetDWLE((oggpacket.packet+96)) == 0x05589F81 )
00911                     {
00912                         unsigned int i_extra_size;
00913                         unsigned int i_format_tag;
00914 
00915                         p_stream->fmt.i_cat = AUDIO_ES;
00916 
00917                         i_extra_size = GetWLE((oggpacket.packet+140));
00918                         if( i_extra_size )
00919                         {
00920                             p_stream->fmt.i_extra = i_extra_size;
00921                             p_stream->fmt.p_extra = malloc( i_extra_size );
00922                             memcpy( p_stream->fmt.p_extra,
00923                                     oggpacket.packet + 142, i_extra_size );
00924                         }
00925 
00926                         i_format_tag = GetWLE((oggpacket.packet+124));
00927                         p_stream->fmt.audio.i_channels =
00928                             GetWLE((oggpacket.packet+126));
00929                         p_stream->f_rate = p_stream->fmt.audio.i_rate =
00930                             GetDWLE((oggpacket.packet+128));
00931                         p_stream->fmt.i_bitrate =
00932                             GetDWLE((oggpacket.packet+132)) * 8;
00933                         p_stream->fmt.audio.i_blockalign =
00934                             GetWLE((oggpacket.packet+136));
00935                         p_stream->fmt.audio.i_bitspersample =
00936                             GetWLE((oggpacket.packet+138));
00937 
00938                         wf_tag_to_fourcc( i_format_tag,
00939                                           &p_stream->fmt.i_codec, 0 );
00940 
00941                         if( p_stream->fmt.i_codec ==
00942                             VLC_FOURCC('u','n','d','f') )
00943                         {
00944                             p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
00945                                 ( i_format_tag >> 8 ) & 0xff,
00946                                 i_format_tag & 0xff );
00947                         }
00948 
00949                         msg_Dbg( p_demux, "found audio header of type: %.4s",
00950                                  (char *)&p_stream->fmt.i_codec );
00951                         msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
00952                                  "%dbits/sample %dkb/s",
00953                                  i_format_tag,
00954                                  p_stream->fmt.audio.i_channels,
00955                                  p_stream->fmt.audio.i_rate,
00956                                  p_stream->fmt.audio.i_bitspersample,
00957                                  p_stream->fmt.i_bitrate / 1024 );
00958 
00959                     }
00960                     else
00961                     {
00962                         msg_Dbg( p_demux, "stream %d has an old header "
00963                             "but is of an unknown type", p_ogg->i_streams-1 );
00964                         free( p_stream );
00965                         p_ogg->i_streams--;
00966                     }
00967                 }
00968                 else if( (*oggpacket.packet & PACKET_TYPE_BITS )
00969                          == PACKET_TYPE_HEADER &&
00970                          oggpacket.bytes >= (int)sizeof(stream_header)+1 )
00971                 {
00972                     stream_header *st = (stream_header *)(oggpacket.packet+1);
00973 
00974                     /* Check for video header (new format) */
00975                     if( !strncmp( st->streamtype, "video", 5 ) )
00976                     {
00977                         p_stream->fmt.i_cat = VIDEO_ES;
00978 
00979                         /* We need to get rid of the header packet */
00980                         ogg_stream_packetout( &p_stream->os, &oggpacket );
00981 
00982                         p_stream->fmt.i_codec =
00983                             VLC_FOURCC( st->subtype[0], st->subtype[1],
00984                                         st->subtype[2], st->subtype[3] );
00985                         msg_Dbg( p_demux, "found video header of type: %.4s",
00986                                  (char *)&p_stream->fmt.i_codec );
00987 
00988                         p_stream->fmt.video.i_frame_rate = 10000000;
00989                         p_stream->fmt.video.i_frame_rate_base =
00990                             GetQWLE(&st->time_unit);
00991                         p_stream->f_rate = 10000000.0 /
00992                             GetQWLE(&st->time_unit);
00993                         p_stream->fmt.video.i_bits_per_pixel =
00994                             GetWLE(&st->bits_per_sample);
00995                         p_stream->fmt.video.i_width =
00996                             GetDWLE(&st->sh.video.width);
00997                         p_stream->fmt.video.i_height =
00998                             GetDWLE(&st->sh.video.height);
00999 
01000                         msg_Dbg( p_demux,
01001                                  "fps: %f, width:%i; height:%i, bitcount:%i",
01002                                  p_stream->f_rate,
01003                                  p_stream->fmt.video.i_width,
01004                                  p_stream->fmt.video.i_height,
01005                                  p_stream->fmt.video.i_bits_per_pixel );
01006                     }
01007                     /* Check for audio header (new format) */
01008                     else if( !strncmp( st->streamtype, "audio", 5 ) )
01009                     {
01010                         char p_buffer[5];
01011                         int i_format_tag;
01012 
01013                         p_stream->fmt.i_cat = AUDIO_ES;
01014 
01015                         /* We need to get rid of the header packet */
01016                         ogg_stream_packetout( &p_stream->os, &oggpacket );
01017 
01018                         p_stream->fmt.i_extra = GetQWLE(&st->size) -
01019                             sizeof(stream_header);
01020                         if( p_stream->fmt.i_extra )
01021                         {
01022                             p_stream->fmt.p_extra =
01023                                 malloc( p_stream->fmt.i_extra );
01024                             memcpy( p_stream->fmt.p_extra, st + 1,
01025                                     p_stream->fmt.i_extra );
01026                         }
01027 
01028                         memcpy( p_buffer, st->subtype, 4 );
01029                         p_buffer[4] = '\0';
01030                         i_format_tag = strtol(p_buffer,NULL,16);
01031                         p_stream->fmt.audio.i_channels =
01032                             GetWLE(&st->sh.audio.channels);
01033                         p_stream->f_rate = p_stream->fmt.audio.i_rate =
01034                             GetQWLE(&st->samples_per_unit);
01035                         p_stream->fmt.i_bitrate =
01036                             GetDWLE(&st->sh.audio.avgbytespersec) * 8;
01037                         p_stream->fmt.audio.i_blockalign =
01038                             GetWLE(&st->sh.audio.blockalign);
01039                         p_stream->fmt.audio.i_bitspersample =
01040                             GetWLE(&st->bits_per_sample);
01041 
01042                         wf_tag_to_fourcc( i_format_tag,
01043                                           &p_stream->fmt.i_codec, 0 );
01044 
01045                         if( p_stream->fmt.i_codec ==
01046                             VLC_FOURCC('u','n','d','f') )
01047                         {
01048                             p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
01049                                 ( i_format_tag >> 8 ) & 0xff,
01050                                 i_format_tag & 0xff );
01051                         }
01052 
01053                         msg_Dbg( p_demux, "found audio header of type: %.4s",
01054                                  (char *)&p_stream->fmt.i_codec );
01055                         msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
01056                                  "%dbits/sample %dkb/s",
01057                                  i_format_tag,
01058                                  p_stream->fmt.audio.i_channels,
01059                                  p_stream->fmt.audio.i_rate,
01060                                  p_stream->fmt.audio.i_bitspersample,
01061                                  p_stream->fmt.i_bitrate / 1024 );
01062                     }
01063                     /* Check for text (subtitles) header */
01064                     else if( !strncmp(st->streamtype, "text", 4) )
01065                     {
01066                         /* We need to get rid of the header packet */
01067                         ogg_stream_packetout( &p_stream->os, &oggpacket );
01068 
01069                         msg_Dbg( p_demux, "found text subtitles header" );
01070                         p_stream->fmt.i_cat = SPU_ES;
01071                         p_stream->fmt.i_codec = VLC_FOURCC('s','u','b','t');
01072                         p_stream->f_rate = 1000; /* granulepos is in milisec */
01073                     }
01074                     else
01075                     {
01076                         msg_Dbg( p_demux, "stream %d has a header marker "
01077                             "but is of an unknown type", p_ogg->i_streams-1 );
01078                         free( p_stream );
01079                         p_ogg->i_streams--;
01080                     }
01081                 }
01082                 else
01083                 {
01084                     msg_Dbg( p_demux, "stream %d is of unknown type",
01085                              p_ogg->i_streams-1 );
01086                     free( p_stream );
01087                     p_ogg->i_streams--;
01088                 }
01089 
01090                 if( Ogg_ReadPage( p_demux, &oggpage ) != VLC_SUCCESS )
01091                     return VLC_EGENERIC;
01092             }
01093 
01094             /* This is the first data page, which means we are now finished
01095              * with the initial pages. We just need to store it in the relevant
01096              * bitstream. */
01097             for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
01098             {
01099                 if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
01100                                        &oggpage ) == 0 )
01101                 {
01102                     break;
01103                 }
01104             }
01105 
01106             return VLC_SUCCESS;
01107         }
01108     }
01109 #undef p_stream
01110 
01111     return VLC_EGENERIC;
01112 }
01113 
01114 /****************************************************************************
01115  * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add
01116  *                        Elementary streams.
01117  ****************************************************************************/
01118 static int Ogg_BeginningOfStream( demux_t *p_demux )
01119 {
01120     demux_sys_t *p_ogg = p_demux->p_sys  ;
01121     int i_stream;
01122 
01123     /* Find the logical streams embedded in the physical stream and
01124      * initialize our p_ogg structure. */
01125     if( Ogg_FindLogicalStreams( p_demux ) != VLC_SUCCESS )
01126     {
01127         msg_Warn( p_demux, "couldn't find any ogg logical stream" );
01128         return VLC_EGENERIC;
01129     }
01130 
01131     p_ogg->i_bitrate = 0;
01132 
01133     for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
01134     {
01135 #define p_stream p_ogg->pp_stream[i_stream]
01136         p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt );
01137 
01138         if( p_stream->fmt.i_codec == VLC_FOURCC('c','m','m','l') )
01139         {
01140             /* Set the CMML stream active */
01141             es_out_Control( p_demux->out, ES_OUT_SET_ES, p_stream->p_es );
01142         }
01143 
01144         p_ogg->i_bitrate += p_stream->fmt.i_bitrate;
01145 
01146         p_stream->i_pcr = p_stream->i_previous_pcr =
01147             p_stream->i_interpolated_pcr = -1;
01148         p_stream->b_reinit = 0;
01149 #undef p_stream
01150     }
01151 
01152     return VLC_SUCCESS;
01153 }
01154 
01155 /****************************************************************************
01156  * Ogg_EndOfStream: clean up the ES when an End of Stream is detected.
01157  ****************************************************************************/
01158 static void Ogg_EndOfStream( demux_t *p_demux )
01159 {
01160     demux_sys_t *p_ogg = p_demux->p_sys  ;
01161     int i_stream;
01162 
01163 #define p_stream p_ogg->pp_stream[i_stream]
01164     for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
01165     {
01166         if( p_stream->p_es )
01167             es_out_Del( p_demux->out, p_stream->p_es );
01168 
01169         p_ogg->i_bitrate -= p_stream->fmt.i_bitrate;
01170 
01171         ogg_stream_clear( &p_ogg->pp_stream[i_stream]->os );
01172         if( p_ogg->pp_stream[i_stream]->p_headers)
01173             free( p_ogg->pp_stream[i_stream]->p_headers );
01174 
01175         es_format_Clean( &p_stream->fmt );
01176 
01177         free( p_ogg->pp_stream[i_stream] );
01178     }
01179 #undef p_stream
01180 
01181     /* Reinit p_ogg */
01182     if( p_ogg->pp_stream ) free( p_ogg->pp_stream );
01183     p_ogg->pp_stream = NULL;
01184     p_ogg->i_streams = 0;
01185 }
01186 
01187 static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
01188                                   ogg_packet *p_oggpacket )
01189 {
01190     bs_t bitstream;
01191     int i_fps_numerator;
01192     int i_fps_denominator;
01193     int i_keyframe_frequency_force;
01194 
01195     p_stream->fmt.i_cat = VIDEO_ES;
01196     p_stream->fmt.i_codec = VLC_FOURCC( 't','h','e','o' );
01197 
01198     /* Signal that we want to keep a backup of the theora
01199      * stream headers. They will be used when switching between
01200      * audio streams. */
01201     p_stream->b_force_backup = 1;
01202 
01203     /* Cheat and get additionnal info ;) */
01204     bs_init( &bitstream, p_oggpacket->packet, p_oggpacket->bytes );
01205     bs_skip( &bitstream, 56 );
01206     bs_read( &bitstream, 8 ); /* major version num */
01207     bs_read( &bitstream, 8 ); /* minor version num */
01208     bs_read( &bitstream, 8 ); /* subminor version num */
01209     bs_read( &bitstream, 16 ) /*<< 4*/; /* width */
01210     bs_read( &bitstream, 16 ) /*<< 4*/; /* height */
01211     bs_read( &bitstream, 24 ); /* frame width */
01212     bs_read( &bitstream, 24 ); /* frame height */
01213     bs_read( &bitstream, 8 ); /* x offset */
01214     bs_read( &bitstream, 8 ); /* y offset */
01215 
01216     i_fps_numerator = bs_read( &bitstream, 32 );
01217     i_fps_denominator = bs_read( &bitstream, 32 );
01218     bs_read( &bitstream, 24 ); /* aspect_numerator */
01219     bs_read( &bitstream, 24 ); /* aspect_denominator */
01220 
01221     p_stream->fmt.video.i_frame_rate = i_fps_numerator;
01222     p_stream->fmt.video.i_frame_rate_base = i_fps_denominator;
01223 
01224     bs_read( &bitstream, 8 ); /* colorspace */
01225     p_stream->fmt.i_bitrate = bs_read( &bitstream, 24 );
01226     bs_read( &bitstream, 6 ); /* quality */
01227 
01228     i_keyframe_frequency_force = 1 << bs_read( &bitstream, 5 );
01229 
01230     /* granule_shift = i_log( frequency_force -1 ) */
01231     p_stream->i_theora_keyframe_granule_shift = 0;
01232     i_keyframe_frequency_force--;
01233     while( i_keyframe_frequency_force )
01234     {
01235         p_stream->i_theora_keyframe_granule_shift++;
01236         i_keyframe_frequency_force >>= 1;
01237     }
01238 
01239     p_stream->f_rate = ((float)i_fps_numerator) / i_fps_denominator;
01240 }
01241 
01242 static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
01243                                   ogg_packet *p_oggpacket )
01244 {
01245     oggpack_buffer opb;
01246 
01247     p_stream->fmt.i_cat = AUDIO_ES;
01248     p_stream->fmt.i_codec = VLC_FOURCC( 'v','o','r','b' );
01249 
01250     /* Signal that we want to keep a backup of the vorbis
01251      * stream headers. They will be used when switching between
01252      * audio streams. */
01253     p_stream->b_force_backup = 1;
01254 
01255     /* Cheat and get additionnal info ;) */
01256     oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
01257     oggpack_adv( &opb, 88 );
01258     p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
01259     p_stream->f_rate = p_stream->fmt.audio.i_rate =
01260         oggpack_read( &opb, 32 );
01261     oggpack_adv( &opb, 32 );
01262     p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
01263 }
01264 
01265 static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
01266                                  ogg_packet *p_oggpacket )
01267 {
01268     oggpack_buffer opb;
01269 
01270     p_stream->fmt.i_cat = AUDIO_ES;
01271     p_stream->fmt.i_codec = VLC_FOURCC( 's','p','x',' ' );
01272 
01273     /* Signal that we want to keep a backup of the speex
01274      * stream headers. They will be used when switching between
01275      * audio streams. */
01276     p_stream->b_force_backup = 1;
01277 
01278     /* Cheat and get additionnal info ;) */
01279     oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
01280     oggpack_adv( &opb, 224 );
01281     oggpack_adv( &opb, 32 ); /* speex_version_id */
01282     oggpack_adv( &opb, 32 ); /* header_size */
01283     p_stream->f_rate = p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 );
01284     oggpack_adv( &opb, 32 ); /* mode */
01285     oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
01286     p_stream->fmt.audio.i_channels = oggpack_read( &opb, 32 );
01287     p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
01288 }
01289 
01290 static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
01291                                 ogg_packet *p_oggpacket )
01292 {
01293     /* Parse the STREAMINFO metadata */
01294     bs_t s;
01295 
01296     bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
01297 
01298     bs_read( &s, 1 );
01299     if( bs_read( &s, 7 ) == 0 )
01300     {
01301         if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
01302         {
01303             bs_skip( &s, 80 );
01304             p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
01305             p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
01306 
01307             msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
01308                      p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
01309         }
01310         else msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
01311 
01312         /* Fake this as the last metadata block */
01313         *((uint8_t*)p_oggpacket->packet) |= 0x80;
01314     }
01315     else
01316     {
01317         /* This ain't a STREAMINFO metadata */
01318         msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
01319     }
01320 }
01321 
01322 static void Ogg_ReadAnnodexHeader( vlc_object_t *p_this,
01323                                    logical_stream_t *p_stream,
01324                                    ogg_packet *p_oggpacket )
01325 {
01326     if( p_oggpacket->bytes >= 28 &&
01327         !memcmp( &p_oggpacket->packet[0], "Annodex", 7 ) )
01328     {
01329         oggpack_buffer opb;
01330 
01331         uint16_t major_version;
01332         uint16_t minor_version;
01333         uint64_t timebase_numerator;
01334         uint64_t timebase_denominator;
01335 
01336         Ogg_ReadTheoraHeader( p_stream, p_oggpacket );
01337 
01338         oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
01339         oggpack_adv( &opb, 8*8 ); /* "Annodex\0" header */
01340         major_version = oggpack_read( &opb, 2*8 ); /* major version */
01341         minor_version = oggpack_read( &opb, 2*8 ); /* minor version */
01342         timebase_numerator = GetQWLE( &p_oggpacket->packet[16] );
01343         timebase_denominator = GetQWLE( &p_oggpacket->packet[24] );
01344     }
01345     else if( p_oggpacket->bytes >= 42 &&
01346              !memcmp( &p_oggpacket->packet[0], "AnxData", 7 ) )
01347     {
01348         uint64_t granule_rate_numerator;
01349         uint64_t granule_rate_denominator;
01350         char content_type_string[1024];
01351 
01352         /* Read in Annodex header fields */
01353 
01354         granule_rate_numerator = GetQWLE( &p_oggpacket->packet[8] );
01355         granule_rate_denominator = GetQWLE( &p_oggpacket->packet[16] );
01356         p_stream->secondary_header_packets =
01357             GetDWLE( &p_oggpacket->packet[24] );
01358 
01359         /* we are guaranteed that the first header field will be
01360          * the content-type (by the Annodex standard) */
01361         content_type_string[0] = '\0';
01362         if( !strncasecmp( &p_oggpacket->packet[28], "Content-Type: ", 14 ) )
01363         {
01364             uint8_t *p = memchr( &p_oggpacket->packet[42], '\r',
01365                                  p_oggpacket->bytes - 1 );
01366             if( p && p[0] == '\r' && p[1] == '\n' )
01367                 sscanf( &p_oggpacket->packet[42], "%1024s\r\n",
01368                         content_type_string );
01369         }
01370 
01371         msg_Dbg( p_this, "AnxData packet info: "I64Fd" / "I64Fd", %d, ``%s''",
01372                  granule_rate_numerator, granule_rate_denominator,
01373                  p_stream->secondary_header_packets, content_type_string );
01374 
01375         p_stream->f_rate = (float) granule_rate_numerator /
01376             (float) granule_rate_denominator;
01377 
01378         /* What type of file do we have?
01379          * strcmp is safe to use here because we've extracted
01380          * content_type_string from the stream manually */
01381         if( !strncmp(content_type_string, "audio/x-wav", 11) )
01382         {
01383             /* n.b. WAVs are unsupported right now */
01384             p_stream->fmt.i_cat = UNKNOWN_ES;
01385         }
01386         else if( !strncmp(content_type_string, "audio/x-vorbis", 14) )
01387         {
01388             p_stream->fmt.i_cat = AUDIO_ES;
01389             p_stream->fmt.i_codec = VLC_FOURCC( 'v','o','r','b' );
01390 
01391             p_stream->b_force_backup = 1;
01392         }
01393         else if( !strncmp(content_type_string, "audio/x-speex", 14) )
01394         {
01395             p_stream->fmt.i_cat = AUDIO_ES;
01396             p_stream->fmt.i_codec = VLC_FOURCC( 's','p','x',' ' );
01397 
01398             p_stream->b_force_backup = 1;
01399         }
01400         else if( !strncmp(content_type_string, "video/x-theora", 14) )
01401         {
01402             p_stream->fmt.i_cat = VIDEO_ES;
01403             p_stream->fmt.i_codec = VLC_FOURCC( 't','h','e','o' );
01404 
01405             p_stream->b_force_backup = 1;
01406         }
01407         else if( !strncmp(content_type_string, "video/x-xvid", 14) )
01408         {
01409             p_stream->fmt.i_cat = VIDEO_ES;
01410             p_stream->fmt.i_codec = VLC_FOURCC( 'x','v','i','d' );
01411 
01412             p_stream->b_force_backup = 1;
01413         }
01414         else if( !strncmp(content_type_string, "video/mpeg", 14) )
01415         {
01416             /* n.b. MPEG streams are unsupported right now */
01417             p_stream->fmt.i_cat = VIDEO_ES;
01418             p_stream->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );
01419         }
01420         else if( !strncmp(content_type_string, "text/x-cmml", 11) )
01421         {
01422             ogg_stream_packetout( &p_stream->os, p_oggpacket );
01423             p_stream->fmt.i_cat = SPU_ES;
01424             p_stream->fmt.i_codec = VLC_FOURCC( 'c','m','m','l' );
01425         }
01426     }
01427 }

Generated on Tue Dec 20 10:14:35 2005 for vlc-0.8.4a by  doxygen 1.4.2