00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031
00032
00033
00034
00035
00036
00037
00038
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
00054
00055 enum AuType_e
00056 {
00057 AU_UNKNOWN = 0,
00058 AU_MULAW_8 = 1,
00059 AU_LINEAR_8 = 2,
00060 AU_LINEAR_16 = 3,
00061 AU_LINEAR_24 = 4,
00062 AU_LINEAR_32 = 5,
00063 AU_FLOAT = 6,
00064 AU_DOUBLE = 7,
00065 AU_ADPCM_G721 = 23,
00066 AU_ADPCM_G722 = 24,
00067 AU_ADPCM_G723_3 = 25,
00068 AU_ADPCM_G723_5 = 26,
00069 AU_ALAW_8 = 27
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
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
00116 stream_Read( p_demux->s, NULL, 4 );
00117
00118
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
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
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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
00262 p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );
00263
00264
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
00280 p_demux->pf_demux = DemuxPCM;
00281 p_demux->pf_control = Control;
00282
00283 return VLC_SUCCESS;
00284 }
00285
00286
00287
00288
00289
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
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
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
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