1 /*****************************************************************************
2 * a52.c : Raw a52 Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: a52sys.c,v 1.4 2003/08/01 00:04:28 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
30 #include <vlc/input.h>
34 /*****************************************************************************
36 *****************************************************************************/
37 static int Open ( vlc_object_t * );
38 static void Close ( vlc_object_t * );
41 set_description( _("A52 demuxer" ) );
42 set_capability( "demux", 100 );
43 set_callbacks( Open, Close );
44 add_shortcut( "a52" );
51 /*****************************************************************************
53 *****************************************************************************/
54 static int Demux ( input_thread_t * );
61 es_descriptor_t *p_es;
64 static inline int HeaderCheck( const uint8_t * p )
66 if( (p[0] != 0x0b) || (p[1] != 0x77) || /* syncword */
67 (p[5] >= 0x60) || /* bsid >= 12 */
68 (p[4] & 63) >= 38 || /* frmsizecod */
69 ( (p[4] & 0xc0) != 0 && (p[4] & 0xc0) != 0x40 && (p[4] & 0xc0) != 0x80 ) )
76 static int HeaderInfo( const uint8_t * p,
81 /*****************************************************************************
82 * Open: initializes AAC demux structures
83 *****************************************************************************/
84 static int Open( vlc_object_t * p_this )
86 input_thread_t *p_input = (input_thread_t *)p_this;
88 int b_forced = VLC_FALSE;
95 if( p_input->psz_demux && !strncmp( p_input->psz_demux, "a52", 3 ) )
99 if( p_input->psz_name )
101 int i_len = strlen( p_input->psz_name );
103 if( i_len > 4 && !strcasecmp( &p_input->psz_name[i_len - 4], ".a52" ) )
109 /* skip possible id3 header */
110 p_id3 = module_Need( p_input, "id3", NULL );
113 module_Unneed( p_input, p_id3 );
116 /* see if it could be 52 */
119 if( input_Peek( p_input, &p_peek, 6 ) < 6 )
121 msg_Err( p_input, "cannot peek" );
124 if( !HeaderCheck( p_peek ) )
126 msg_Warn( p_input, "A52 module discarded" );
131 p_input->pf_demux = Demux;
133 p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) );
136 if( ( p_sys->s = stream_OpenInput( p_input ) ) == NULL )
138 msg_Err( p_input, "cannot create stream" );
142 if( stream_Peek( p_sys->s, &p_peek, 6 ) < 6 )
144 msg_Err( p_input, "cannot peek" );
148 if( HeaderCheck( p_peek ) )
150 int i_channels, i_sample_rate, i_frame_size;
151 input_info_category_t * p_category;
153 HeaderInfo( p_peek, &i_channels, &i_sample_rate, &i_frame_size );
156 "a52 channels=%d sample_rate=%d",
157 i_channels, i_sample_rate );
159 vlc_mutex_lock( &p_input->stream.stream_lock );
161 p_category = input_InfoCategory( p_input, _("A52") );
163 input_AddInfo( p_category, _("Input Type"), "A52" );
164 input_AddInfo( p_category, _("Channels"), "%d", i_channels );
165 input_AddInfo( p_category, _("Sample Rate"), "%dHz", i_sample_rate );
167 vlc_mutex_unlock( &p_input->stream.stream_lock );
170 vlc_mutex_lock( &p_input->stream.stream_lock );
171 if( input_InitStream( p_input, 0 ) == -1)
173 vlc_mutex_unlock( &p_input->stream.stream_lock );
174 msg_Err( p_input, "cannot init stream" );
177 if( input_AddProgram( p_input, 0, 0) == NULL )
179 vlc_mutex_unlock( &p_input->stream.stream_lock );
180 msg_Err( p_input, "cannot add program" );
183 p_input->stream.pp_programs[0]->b_is_ok = 0;
184 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
186 p_input->stream.i_mux_rate = 0 / 50;
188 p_sys->p_es = input_AddES( p_input,
189 p_input->stream.p_selected_program,
190 1 , AUDIO_ES, NULL, 0 );
192 p_sys->p_es->i_stream_id = 1;
193 p_sys->p_es->i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
194 input_SelectES( p_input, p_sys->p_es );
196 p_input->stream.p_selected_program->b_is_ok = 1;
197 vlc_mutex_unlock( &p_input->stream.stream_lock );
204 stream_Release( p_sys->s );
211 /*****************************************************************************
212 * Demux: reads and demuxes data packets
213 *****************************************************************************
214 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
215 *****************************************************************************/
216 static int Demux( input_thread_t * p_input )
218 demux_sys_t *p_sys = p_input->p_demux_data;
221 int i_channels, i_sample_rate, i_frame_size;
225 if( stream_Peek( p_sys->s, &p_peek, 6 ) < 6 )
227 msg_Warn( p_input, "cannot peek" );
231 if( !HeaderCheck( p_peek ) )
233 /* we need to resynch */
234 vlc_bool_t b_ok = VLC_FALSE;
238 i_peek = stream_Peek( p_sys->s, &p_peek, 8096 );
241 msg_Warn( p_input, "cannot peek" );
247 if( HeaderCheck( p_peek ) )
258 msg_Warn( p_input, "garbage=%d bytes", i_skip );
259 stream_Read( p_sys->s, NULL, i_skip );
263 HeaderInfo( p_peek, &i_channels, &i_sample_rate, &i_frame_size );
265 input_ClockManageRef( p_input,
266 p_input->stream.p_selected_program,
267 p_sys->i_time * 9 / 100 );
269 if( ( p_pes = stream_PesPacket( p_sys->s, i_frame_size ) ) == NULL )
271 msg_Warn( p_input, "cannot read data" );
276 p_pes->i_pts = input_ClockGetTS( p_input,
277 p_input->stream.p_selected_program,
278 p_sys->i_time * 9 / 100 );
280 if( !p_sys->p_es->p_decoder_fifo )
282 msg_Err( p_input, "no audio decoder" );
283 input_DeletePES( p_input->p_method_data, p_pes );
287 input_DecodePES( p_sys->p_es->p_decoder_fifo, p_pes );
288 p_sys->i_time += (mtime_t)1000000 *
290 (mtime_t)i_sample_rate;
294 /*****************************************************************************
295 * Close: frees unused data
296 *****************************************************************************/
297 static void Close( vlc_object_t * p_this )
299 input_thread_t *p_input = (input_thread_t*)p_this;
300 demux_sys_t *p_sys = p_input->p_demux_data;
304 stream_Release( p_sys->s );
311 /*****************************************************************************
312 * SyncInfo: parse A/52 sync info
313 *****************************************************************************
314 * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
315 *****************************************************************************/
316 static int HeaderInfo( const uint8_t * p,
321 static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
322 static const int rate[] = { 32, 40, 48, 56, 64, 80, 96, 112,
323 128, 160, 192, 224, 256, 320, 384, 448,
325 static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
326 0x04, 0x01, 0x04, 0x01 };
332 if ((p[0] != 0x0b) || (p[1] != 0x77)) /* syncword */
335 if (p[5] >= 0x60) /* bsid >= 12 */
337 half = halfrate[p[5] >> 3];
339 /* acmod, dsurmod and lfeon */
341 if ( (p[6] & 0xf8) == 0x50 )
343 /* Dolby surround = stereo + Dolby */
348 static const int acmod_to_channels[8] =
350 2 /* dual mono */, 1 /* mono */, 2 /* stereo */,
351 3 /* 3F */, 3 /* 2f1R */,
352 4 /* 3F1R */, 4, /* 2F2R */
356 *pi_channels = acmod_to_channels[acmod];
359 if ( p[6] & lfeon[acmod] ) (*pi_channels)++; /* LFE */
361 frmsizecod = p[4] & 63;
362 if (frmsizecod >= 38)
364 bitrate = rate[frmsizecod >> 1];
366 switch (p[4] & 0xc0) {
368 *pi_sample_rate = 48000 >> half;
369 *pi_frame_size = 4 * bitrate;
372 *pi_sample_rate = 44100 >> half;
373 *pi_frame_size = 2 * (320 * bitrate / 147 + (frmsizecod & 1));
376 *pi_sample_rate = 32000 >> half;
377 *pi_frame_size =6 * bitrate;