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

flac.c

00001 /*****************************************************************************
00002  * flac.c : FLAC demux module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2001-2003 the VideoLAN team
00005  * $Id: flac.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <vlc/vlc.h>
00028 #include <vlc/input.h>
00029 #include <vlc_codec.h>
00030 
00031 /*****************************************************************************
00032  * Module descriptor
00033  *****************************************************************************/
00034 static int  Open  ( vlc_object_t * );
00035 static void Close ( vlc_object_t * );
00036 
00037 vlc_module_begin();
00038     set_description( _("FLAC demuxer") );
00039     set_capability( "demux2", 155 );
00040     set_category( CAT_INPUT );
00041     set_subcategory( SUBCAT_INPUT_DEMUX );
00042     set_callbacks( Open, Close );
00043     add_shortcut( "flac" );
00044 vlc_module_end();
00045 
00046 /*****************************************************************************
00047  * Local prototypes
00048  *****************************************************************************/
00049 static int Demux  ( demux_t * );
00050 static int Control( demux_t *, int, va_list );
00051 
00052 struct demux_sys_t
00053 {
00054     vlc_bool_t  b_start;
00055     es_out_id_t *p_es;
00056 
00057     /* Packetizer */
00058     decoder_t *p_packetizer;
00059     vlc_meta_t *p_meta;
00060 };
00061 
00062 #define STREAMINFO_SIZE 38
00063 #define FLAC_PACKET_SIZE 16384
00064 
00065 /*****************************************************************************
00066  * Open: initializes ES structures
00067  *****************************************************************************/
00068 static int Open( vlc_object_t * p_this )
00069 {
00070     demux_t     *p_demux = (demux_t*)p_this;
00071     module_t    *p_id3;
00072     demux_sys_t *p_sys;
00073     int          i_peek;
00074     byte_t      *p_peek;
00075     es_format_t  fmt;
00076 
00077     /* Have a peep at the show. */
00078     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
00079 
00080     if( p_peek[0]!='f' || p_peek[1]!='L' || p_peek[2]!='a' || p_peek[3]!='C' )
00081     {
00082         if( !p_demux->b_force ) return VLC_EGENERIC;
00083 
00084         /* User forced */
00085         msg_Err( p_demux, "this doesn't look like a flac stream, "
00086                  "continuing anyway" );
00087     }
00088 
00089     p_demux->pf_demux   = Demux;
00090     p_demux->pf_control = Control;
00091     p_demux->p_sys      = p_sys = malloc( sizeof( demux_sys_t ) );
00092     es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'f', 'l', 'a', 'c' ) );
00093     p_sys->b_start = VLC_TRUE;
00094     p_sys->p_meta = 0;
00095 
00096     /* We need to read and store the STREAMINFO metadata */
00097     i_peek = stream_Peek( p_demux->s, &p_peek, 8 );
00098     if( p_peek[4] & 0x7F )
00099     {
00100         msg_Err( p_demux, "this isn't a STREAMINFO metadata block" );
00101         return VLC_EGENERIC;
00102     }
00103 
00104     if( ((p_peek[5]<<16)+(p_peek[6]<<8)+p_peek[7]) != (STREAMINFO_SIZE - 4) )
00105     {
00106         msg_Err( p_demux, "invalid size for a STREAMINFO metadata block" );
00107         return VLC_EGENERIC;
00108     }
00109 
00110     /*
00111      * Load the FLAC packetizer
00112      */
00113     p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_DECODER );
00114     p_sys->p_packetizer->pf_decode_audio = 0;
00115     p_sys->p_packetizer->pf_decode_video = 0;
00116     p_sys->p_packetizer->pf_decode_sub = 0;
00117     p_sys->p_packetizer->pf_packetize = 0;
00118 
00119     /* Initialization of decoder structure */
00120     es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES,
00121                     VLC_FOURCC( 'f', 'l', 'a', 'c' ) );
00122 
00123     /* Store STREAMINFO for the decoder and packetizer */
00124     p_sys->p_packetizer->fmt_in.i_extra = fmt.i_extra = STREAMINFO_SIZE + 4;
00125     p_sys->p_packetizer->fmt_in.p_extra = malloc( STREAMINFO_SIZE + 4 );
00126     stream_Read( p_demux->s, p_sys->p_packetizer->fmt_in.p_extra,
00127                  STREAMINFO_SIZE + 4 );
00128 
00129     /* Fake this as the last metadata block */
00130     ((uint8_t*)p_sys->p_packetizer->fmt_in.p_extra)[4] |= 0x80;
00131     fmt.p_extra = malloc( STREAMINFO_SIZE + 4 );
00132     memcpy( fmt.p_extra, p_sys->p_packetizer->fmt_in.p_extra,
00133             STREAMINFO_SIZE + 4 );
00134 
00135     p_sys->p_packetizer->p_module =
00136         module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );
00137     if( !p_sys->p_packetizer->p_module )
00138     {
00139         if( p_sys->p_packetizer->fmt_in.p_extra )
00140             free( p_sys->p_packetizer->fmt_in.p_extra );
00141         vlc_object_destroy( p_sys->p_packetizer );
00142 
00143         msg_Err( p_demux, "cannot find flac packetizer" );
00144         return VLC_EGENERIC;
00145     }
00146 
00147     p_sys->p_es = es_out_Add( p_demux->out, &fmt );
00148 
00149     /* Parse possible id3 header */
00150     if( ( p_id3 = module_Need( p_demux, "id3", NULL, 0 ) ) )
00151     {
00152         p_sys->p_meta = (vlc_meta_t *)p_demux->p_private;
00153         p_demux->p_private = NULL;
00154         module_Unneed( p_demux, p_id3 );
00155     }
00156 
00157     return VLC_SUCCESS;
00158 }
00159 
00160 /*****************************************************************************
00161  * Close: frees unused data
00162  *****************************************************************************/
00163 static void Close( vlc_object_t * p_this )
00164 {
00165     demux_t     *p_demux = (demux_t*)p_this;
00166     demux_sys_t *p_sys = p_demux->p_sys;
00167 
00168     /* Unneed module */
00169     module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module );
00170 
00171     if( p_sys->p_packetizer->fmt_in.p_extra )
00172         free( p_sys->p_packetizer->fmt_in.p_extra );
00173 
00174     /* Delete the decoder */
00175     vlc_object_destroy( p_sys->p_packetizer );
00176     if( p_sys->p_meta ) vlc_meta_Delete( p_sys->p_meta );
00177     free( p_sys );
00178 }
00179 
00180 /*****************************************************************************
00181  * Demux: reads and demuxes data packets
00182  *****************************************************************************
00183  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
00184  *****************************************************************************/
00185 static int Demux( demux_t *p_demux )
00186 {
00187     demux_sys_t *p_sys = p_demux->p_sys;
00188     block_t     *p_block_in, *p_block_out;
00189 
00190     if( !( p_block_in = stream_Block( p_demux->s, FLAC_PACKET_SIZE ) ) )
00191     {
00192         return 0;
00193     }
00194 
00195     if( p_sys->b_start )
00196     {
00197         p_block_in->i_pts = p_block_in->i_dts = 1;
00198         p_sys->b_start = VLC_FALSE;
00199     }
00200     else
00201     {
00202         p_block_in->i_pts = p_block_in->i_dts = 0;
00203     }
00204 
00205     while( (p_block_out = p_sys->p_packetizer->pf_packetize(
00206                 p_sys->p_packetizer, &p_block_in )) )
00207     {
00208         while( p_block_out )
00209         {
00210             block_t *p_next = p_block_out->p_next;
00211 
00212             /* set PCR */
00213             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
00214 
00215             es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
00216 
00217             p_block_out = p_next;
00218         }
00219     }
00220 
00221     return 1;
00222 }
00223 
00224 /*****************************************************************************
00225  * Control:
00226  *****************************************************************************/
00227 static int Control( demux_t *p_demux, int i_query, va_list args )
00228 {
00229     /* demux_sys_t *p_sys  = p_demux->p_sys; */
00230     /* FIXME bitrate */
00231     if( i_query == DEMUX_SET_TIME ) return VLC_EGENERIC;
00232     else if( i_query == DEMUX_GET_META )
00233     {        
00234         vlc_meta_t **pp_meta = (vlc_meta_t **)va_arg( args, vlc_meta_t** );
00235         if( p_demux->p_sys->p_meta )
00236             *pp_meta = vlc_meta_Duplicate( p_demux->p_sys->p_meta );
00237         else *pp_meta = NULL;
00238         return VLC_SUCCESS;
00239     }
00240     else return demux2_vaControlHelper( p_demux->s, 0, -1,
00241                                         8*0, 1, i_query, args );
00242 }
00243 

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