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

au.c

00001 /*****************************************************************************
00002  * au.c : au file input module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2001-2003 the VideoLAN team
00005  * $Id: au.c 11685 2005-07-10 10:51:28Z zorglub $
00006  *
00007  * Authors: Laurent Aimar <[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 <stdlib.h>                                      /* malloc(), free() */
00028 
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031 
00032 /* TODO:
00033  *  - all adpcm things (I _NEED_ samples)
00034  *  - ...
00035  */
00036 
00037 /*****************************************************************************
00038  * Module descriptor
00039  *****************************************************************************/
00040 static int  Open ( vlc_object_t * );
00041 static void Close( vlc_object_t * );
00042 
00043 vlc_module_begin();
00044     set_category( CAT_INPUT );
00045     set_subcategory( SUBCAT_INPUT_DEMUX );
00046     set_description( _("AU demuxer") );
00047     set_capability( "demux2", 10 );
00048     set_callbacks( Open, Close );
00049     add_shortcut( "au" );
00050 vlc_module_end();
00051 
00052 /*****************************************************************************
00053  * Local prototypes
00054  *****************************************************************************/
00055 enum AuType_e
00056 {
00057     AU_UNKNOWN      =  0,
00058     AU_MULAW_8      =  1,  /* 8-bit ISDN u-law */
00059     AU_LINEAR_8     =  2,  /* 8-bit linear PCM */
00060     AU_LINEAR_16    =  3,  /* 16-bit linear PCM */
00061     AU_LINEAR_24    =  4,  /* 24-bit linear PCM */
00062     AU_LINEAR_32    =  5,  /* 32-bit linear PCM */
00063     AU_FLOAT        =  6,  /* 32-bit IEEE floating point */
00064     AU_DOUBLE       =  7,  /* 64-bit IEEE floating point */
00065     AU_ADPCM_G721   =  23, /* 4-bit CCITT g.721 ADPCM */
00066     AU_ADPCM_G722   =  24, /* CCITT g.722 ADPCM */
00067     AU_ADPCM_G723_3 =  25, /* CCITT g.723 3-bit ADPCM */
00068     AU_ADPCM_G723_5 =  26, /* CCITT g.723 5-bit ADPCM */
00069     AU_ALAW_8       =  27  /* 8-bit ISDN A-law */
00070 };
00071 
00072 enum AuCat_e
00073 {
00074     AU_CAT_UNKNOWN  = 0,
00075     AU_CAT_PCM      = 1,
00076     AU_CAT_ADPCM    = 2
00077 };
00078 
00079 struct demux_sys_t
00080 {
00081     es_format_t     fmt;
00082     es_out_id_t     *es;
00083 
00084     mtime_t         i_time;
00085 
00086     int             i_frame_size;
00087     mtime_t         i_frame_length;
00088 
00089     int             i_header_size;
00090 };
00091 
00092 static int DemuxPCM( demux_t * );
00093 static int Control ( demux_t *, int i_query, va_list args );
00094 
00095 /*****************************************************************************
00096  * Open: check file and initializes structures
00097  *****************************************************************************/
00098 static int Open( vlc_object_t *p_this )
00099 {
00100     demux_t     *p_demux = (demux_t*)p_this;
00101     demux_sys_t *p_sys;
00102 
00103     uint8_t      hdr[20];
00104     uint8_t     *p_peek;
00105     int          i_cat;
00106     int          i_samples, i_modulo;
00107 
00108     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
00109 
00110     if( memcmp( p_peek, ".snd", 4 ) )
00111     {
00112         return VLC_EGENERIC;
00113     }
00114 
00115     /* skip signature */
00116     stream_Read( p_demux->s, NULL, 4 );   /* cannot fail */
00117 
00118     /* read header */
00119     if( stream_Read( p_demux->s, hdr, 20 ) < 20 )
00120     {
00121         msg_Err( p_demux, "cannot read" );
00122         return VLC_EGENERIC;
00123     }
00124 
00125     if( GetDWBE( &hdr[0]  ) < 24 )
00126     {
00127         msg_Err( p_demux, "invalid file" );
00128         return VLC_EGENERIC;
00129     }
00130 
00131     p_sys = p_demux->p_sys = malloc( sizeof( demux_sys_t ) );
00132     p_sys->i_time = 1;
00133     p_sys->i_header_size = GetDWBE( &hdr[0] );
00134 
00135     /* skip extra header data */
00136     if( p_sys->i_header_size > 24 )
00137     {
00138         stream_Read( p_demux->s, NULL, p_sys->i_header_size - 24 );
00139     }
00140 
00141     /* init fmt */
00142     es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
00143     p_sys->fmt.audio.i_rate     = GetDWBE( &hdr[12] );
00144     p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] );
00145 
00146 #if 0
00147     p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
00148     p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
00149     p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
00150     p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
00151     p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
00152 #endif
00153     switch( GetDWBE( &hdr[8] ) )
00154     {
00155         case AU_ALAW_8:        /* 8-bit ISDN A-law */
00156             p_sys->fmt.i_codec               = VLC_FOURCC( 'a','l','a','w' );
00157             p_sys->fmt.audio.i_bitspersample = 8;
00158             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
00159             i_cat                    = AU_CAT_PCM;
00160             break;
00161 
00162         case AU_MULAW_8:       /* 8-bit ISDN u-law */
00163             p_sys->fmt.i_codec               = VLC_FOURCC( 'u','l','a','w' );
00164             p_sys->fmt.audio.i_bitspersample = 8;
00165             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
00166             i_cat                    = AU_CAT_PCM;
00167             break;
00168 
00169         case AU_LINEAR_8:      /* 8-bit linear PCM */
00170             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
00171             p_sys->fmt.audio.i_bitspersample = 8;
00172             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
00173             i_cat                    = AU_CAT_PCM;
00174             break;
00175 
00176         case AU_LINEAR_16:     /* 16-bit linear PCM */
00177             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
00178             p_sys->fmt.audio.i_bitspersample = 16;
00179             p_sys->fmt.audio.i_blockalign    = 2 * p_sys->fmt.audio.i_channels;
00180             i_cat                    = AU_CAT_PCM;
00181             break;
00182 
00183         case AU_LINEAR_24:     /* 24-bit linear PCM */
00184             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
00185             p_sys->fmt.audio.i_bitspersample = 24;
00186             p_sys->fmt.audio.i_blockalign    = 3 * p_sys->fmt.audio.i_channels;
00187             i_cat                    = AU_CAT_PCM;
00188             break;
00189 
00190         case AU_LINEAR_32:     /* 32-bit linear PCM */
00191             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
00192             p_sys->fmt.audio.i_bitspersample = 32;
00193             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
00194             i_cat                    = AU_CAT_PCM;
00195             break;
00196 
00197         case AU_FLOAT:         /* 32-bit IEEE floating point */
00198             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
00199             p_sys->fmt.audio.i_bitspersample = 32;
00200             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
00201             i_cat                    = AU_CAT_PCM;
00202             break;
00203 
00204         case AU_DOUBLE:        /* 64-bit IEEE floating point */
00205             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
00206             p_sys->fmt.audio.i_bitspersample = 64;
00207             p_sys->fmt.audio.i_blockalign    = 8 * p_sys->fmt.audio.i_channels;
00208             i_cat                    = AU_CAT_PCM;
00209             break;
00210 
00211         case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
00212             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
00213             p_sys->fmt.audio.i_bitspersample = 0;
00214             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
00215             i_cat                    = AU_CAT_ADPCM;
00216             break;
00217 
00218         case AU_ADPCM_G722:    /* CCITT g.722 ADPCM */
00219             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 );
00220             p_sys->fmt.audio.i_bitspersample = 0;
00221             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
00222             i_cat                    = AU_CAT_ADPCM;
00223             break;
00224 
00225         case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
00226             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 );
00227             p_sys->fmt.audio.i_bitspersample = 0;
00228             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
00229             i_cat                    = AU_CAT_ADPCM;
00230             break;
00231 
00232         case AU_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
00233             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 );
00234             p_sys->fmt.audio.i_bitspersample = 0;
00235             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
00236             i_cat                    = AU_CAT_ADPCM;
00237             break;
00238 
00239         default:
00240             msg_Warn( p_demux, "unknow encoding=0x%x", GetDWBE( &hdr[8] ) );
00241             p_sys->fmt.audio.i_bitspersample = 0;
00242             p_sys->fmt.audio.i_blockalign    = 0;
00243             i_cat                    = AU_CAT_UNKNOWN;
00244             break;
00245     }
00246 
00247     p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate *
00248                            p_sys->fmt.audio.i_channels *
00249                            p_sys->fmt.audio.i_bitspersample;
00250 
00251     if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
00252     {
00253         p_sys->i_frame_size = 0;
00254         p_sys->i_frame_length = 0;
00255 
00256         msg_Err( p_demux, "unsupported codec/type (Please report it)" );
00257         free( p_sys );
00258         return VLC_EGENERIC;
00259     }
00260 
00261     /* add the es */
00262     p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );
00263 
00264     /* calculate 50ms frame size/time */
00265     i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 );
00266     p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels *
00267                           ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 );
00268     if( p_sys->fmt.audio.i_blockalign > 0 )
00269     {
00270         if( ( i_modulo = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign ) != 0 )
00271         {
00272             p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - i_modulo;
00273         }
00274     }
00275     p_sys->i_frame_length = (mtime_t)1000000 *
00276                             (mtime_t)i_samples /
00277                             (mtime_t)p_sys->fmt.audio.i_rate;
00278 
00279     /* finish to set up p_demux */
00280     p_demux->pf_demux   = DemuxPCM;
00281     p_demux->pf_control = Control;
00282 
00283     return VLC_SUCCESS;
00284 }
00285 
00286 /*****************************************************************************
00287  * DemuxPCM: read packet and send them to decoders
00288  *****************************************************************************
00289  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
00290  *****************************************************************************/
00291 static int DemuxPCM( demux_t *p_demux )
00292 {
00293     demux_sys_t *p_sys = p_demux->p_sys;
00294     block_t     *p_block;
00295 
00296     /* set PCR */
00297     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
00298 
00299     if( ( p_block = stream_Block( p_demux->s, p_sys->i_frame_size ) ) == NULL )
00300     {
00301         msg_Warn( p_demux, "cannot read data" );
00302         return 0;
00303     }
00304 
00305     p_block->i_dts =
00306     p_block->i_pts = p_sys->i_time;
00307 
00308     es_out_Send( p_demux->out, p_sys->es, p_block );
00309 
00310     p_sys->i_time += p_sys->i_frame_length;
00311 
00312     return 1;
00313 }
00314 
00315 /*****************************************************************************
00316  * Close: frees unused data
00317  *****************************************************************************/
00318 static void Close( vlc_object_t * p_this )
00319 {
00320     demux_t     *p_demux = (demux_t*)p_this;
00321     demux_sys_t *p_sys = p_demux->p_sys;
00322 
00323     free( p_sys );
00324 }
00325 
00326 /*****************************************************************************
00327  * Control:
00328  *****************************************************************************/
00329 static int Control( demux_t *p_demux, int i_query, va_list args )
00330 {
00331     demux_sys_t *p_sys = p_demux->p_sys;
00332 
00333     return demux2_vaControlHelper( p_demux->s, p_sys->i_header_size, -1,
00334                                    p_sys->fmt.i_bitrate, p_sys->fmt.audio.i_blockalign,
00335                                    i_query, args );
00336 }
00337 

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