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 <vlc/vlc.h>
00028 #include <vlc/input.h>
00029 #include <vlc_codec.h>
00030
00031 #ifdef HAVE_UNISTD_H
00032 # include <unistd.h>
00033 #endif
00034
00035
00036
00037
00038 static int Open ( vlc_object_t * );
00039 static void Close ( vlc_object_t * );
00040
00041 vlc_module_begin();
00042 set_category( CAT_INPUT );
00043 set_subcategory( SUBCAT_INPUT_DEMUX );
00044 set_description( _("Raw A/52 demuxer") );
00045 set_capability( "demux2", 145 );
00046 set_callbacks( Open, Close );
00047 add_shortcut( "a52" );
00048 vlc_module_end();
00049
00050
00051
00052
00053 static int Demux ( demux_t * );
00054 static int Control( demux_t *, int, va_list );
00055
00056 struct demux_sys_t
00057 {
00058 vlc_bool_t b_start;
00059 es_out_id_t *p_es;
00060
00061
00062 decoder_t *p_packetizer;
00063
00064 int i_mux_rate;
00065 vlc_bool_t b_big_endian;
00066 };
00067
00068 static int CheckSync( uint8_t *p_peek, vlc_bool_t *p_big_endian );
00069
00070 #define PCM_FRAME_SIZE (1536 * 4)
00071 #define A52_PACKET_SIZE (4 * PCM_FRAME_SIZE)
00072 #define A52_MAX_HEADER_SIZE 10
00073
00074
00075
00076
00077
00078 static int Open( vlc_object_t * p_this )
00079 {
00080 demux_t *p_demux = (demux_t*)p_this;
00081 demux_sys_t *p_sys;
00082 byte_t *p_peek;
00083 int i_peek = 0;
00084 vlc_bool_t b_big_endian = 0;
00085
00086
00087 if( stream_Peek( p_demux->s, &p_peek, 12 ) == 12 &&
00088 !memcmp( p_peek, "RIFF", 4 ) && !memcmp( p_peek + 8, "WAVE", 4 ) )
00089 {
00090 int i_size;
00091
00092
00093 i_peek = 12 + 8;
00094 while( stream_Peek( p_demux->s, &p_peek, i_peek ) == i_peek &&
00095 memcmp( p_peek + i_peek - 8, "data", 4 ) )
00096 {
00097 i_peek += GetDWLE( p_peek + i_peek - 4 ) + 8;
00098 }
00099
00100
00101
00102
00103
00104 i_size = stream_Peek( p_demux->s, &p_peek, i_peek + A52_PACKET_SIZE * 2);
00105 i_size -= (PCM_FRAME_SIZE + A52_MAX_HEADER_SIZE);
00106
00107 while( i_peek < i_size )
00108 {
00109 if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
00110
00111 i_peek += 2;
00112 else
00113 {
00114
00115 if( CheckSync( p_peek + i_peek + PCM_FRAME_SIZE,
00116 &b_big_endian ) != VLC_SUCCESS )
00117 {
00118 i_peek += 2;
00119 continue;
00120 }
00121
00122 break;
00123 }
00124 }
00125 }
00126
00127
00128 if( stream_Peek( p_demux->s, &p_peek, i_peek + A52_MAX_HEADER_SIZE * 2 ) <
00129 i_peek + A52_MAX_HEADER_SIZE * 2 )
00130 {
00131
00132 msg_Warn( p_demux, "cannot peek()" );
00133 return VLC_EGENERIC;
00134 }
00135
00136 if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
00137 {
00138 if( strncmp( p_demux->psz_demux, "a52", 3 ) )
00139 {
00140 return VLC_EGENERIC;
00141 }
00142
00143
00144 msg_Err( p_demux, "this doesn't look like a A52 audio stream, "
00145 "continuing anyway" );
00146 }
00147
00148
00149 p_demux->pf_demux = Demux;
00150 p_demux->pf_control = Control;
00151 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00152 p_sys->b_start = VLC_TRUE;
00153 p_sys->i_mux_rate = 0;
00154 p_sys->b_big_endian = b_big_endian;
00155
00156
00157
00158
00159 p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_DECODER );
00160 p_sys->p_packetizer->pf_decode_audio = 0;
00161 p_sys->p_packetizer->pf_decode_video = 0;
00162 p_sys->p_packetizer->pf_decode_sub = 0;
00163 p_sys->p_packetizer->pf_packetize = 0;
00164
00165
00166 es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES,
00167 VLC_FOURCC( 'a', '5', '2', ' ' ) );
00168
00169 p_sys->p_packetizer->p_module =
00170 module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );
00171 if( !p_sys->p_packetizer->p_module )
00172 {
00173 msg_Err( p_demux, "cannot find A52 packetizer" );
00174 return VLC_EGENERIC;
00175 }
00176
00177
00178 p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );
00179
00180 return VLC_SUCCESS;
00181 }
00182
00183
00184
00185
00186 static void Close( vlc_object_t * p_this )
00187 {
00188 demux_t *p_demux = (demux_t*)p_this;
00189 demux_sys_t *p_sys = p_demux->p_sys;
00190
00191
00192 module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module );
00193
00194
00195 vlc_object_destroy( p_sys->p_packetizer );
00196
00197 free( p_sys );
00198 }
00199
00200
00201
00202
00203
00204
00205 static int Demux( demux_t *p_demux )
00206 {
00207 demux_sys_t *p_sys = p_demux->p_sys;
00208 block_t *p_block_in, *p_block_out;
00209
00210
00211 int64_t i_pos = stream_Tell( p_demux->s );
00212 if( i_pos % 2 ) stream_Read( p_demux->s, NULL, 1 );
00213
00214 if( !( p_block_in = stream_Block( p_demux->s, A52_PACKET_SIZE ) ) )
00215 {
00216 return 0;
00217 }
00218
00219 if( !p_sys->b_big_endian && p_block_in->i_buffer )
00220 {
00221
00222
00223 #ifdef HAVE_SWAB
00224 swab(p_block_in->p_buffer, p_block_in->p_buffer, p_block_in->i_buffer);
00225
00226 #else
00227 int i;
00228 byte_t *p_tmp, tmp;
00229 p_tmp = p_block_in->p_buffer;
00230 for( i = p_block_in->i_buffer / 2 ; i-- ; )
00231 {
00232 tmp = p_tmp[0];
00233 p_tmp[0] = p_tmp[1];
00234 p_tmp[1] = tmp;
00235 p_tmp += 2;
00236 }
00237 #endif
00238 }
00239
00240 if( p_sys->b_start )
00241 p_block_in->i_pts = p_block_in->i_dts = 1;
00242 else
00243 p_block_in->i_pts = p_block_in->i_dts = 0;
00244
00245 while( (p_block_out = p_sys->p_packetizer->pf_packetize(
00246 p_sys->p_packetizer, &p_block_in )) )
00247 {
00248 p_sys->b_start = VLC_FALSE;
00249
00250 while( p_block_out )
00251 {
00252 block_t *p_next = p_block_out->p_next;
00253
00254
00255 if( p_block_out->i_length )
00256 {
00257 p_sys->i_mux_rate =
00258 p_block_out->i_buffer * I64C(1000000)/p_block_out->i_length;
00259 }
00260
00261
00262 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
00263
00264 es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
00265
00266 p_block_out = p_next;
00267 }
00268 }
00269
00270 return 1;
00271 }
00272
00273
00274
00275
00276 static int Control( demux_t *p_demux, int i_query, va_list args )
00277 {
00278 demux_sys_t *p_sys = p_demux->p_sys;
00279 if( i_query == DEMUX_SET_TIME )
00280 return VLC_EGENERIC;
00281 else
00282 return demux2_vaControlHelper( p_demux->s,
00283 0, -1,
00284 8*p_sys->i_mux_rate, 1, i_query, args );
00285 }
00286
00287
00288
00289
00290 static int CheckSync( uint8_t *p_peek, vlc_bool_t *p_big_endian )
00291 {
00292
00293 if( p_peek[0] == 0x77 && p_peek[1] == 0x0b &&
00294 p_peek[4] < 0x60 )
00295 {
00296 *p_big_endian = VLC_FALSE;
00297 return VLC_SUCCESS;
00298 }
00299
00300 else if( p_peek[0] == 0x0b && p_peek[1] == 0x77 &&
00301 p_peek[5] < 0x60 )
00302 {
00303 *p_big_endian = VLC_TRUE;
00304 return VLC_SUCCESS;
00305 }
00306
00307 return VLC_EGENERIC;
00308 }
00309
00310