]> git.sesse.net Git - vlc/blob - modules/demux/a52sys.c
8b60ee59a36a9d98a11dd21b09a1975152eed780
[vlc] / modules / demux / a52sys.c
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 $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31
32 #include <ninput.h>
33
34 /*****************************************************************************
35  * Module descriptor
36  *****************************************************************************/
37 static int  Open    ( vlc_object_t * );
38 static void Close  ( vlc_object_t * );
39
40 vlc_module_begin();
41     set_description( _("A52 demuxer" ) );
42     set_capability( "demux", 100 );
43     set_callbacks( Open, Close );
44     add_shortcut( "a52" );
45 vlc_module_end();
46
47 /* TODO:
48  *
49  */
50
51 /*****************************************************************************
52  * Local prototypes
53  *****************************************************************************/
54 static int  Demux       ( input_thread_t * );
55
56 struct demux_sys_t
57 {
58     stream_t        *s;
59     mtime_t         i_time;
60
61     es_descriptor_t *p_es;
62 };
63
64 static inline int HeaderCheck( const uint8_t * p )
65 {
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 ) )
70     {
71         return VLC_FALSE;
72     }
73     return VLC_TRUE;
74 }
75
76 static int HeaderInfo( const uint8_t * p,
77                        int *pi_channels,
78                        int *pi_sample_rate,
79                        int *pi_frame_size );
80
81 /*****************************************************************************
82  * Open: initializes AAC demux structures
83  *****************************************************************************/
84 static int Open( vlc_object_t * p_this )
85 {
86     input_thread_t *p_input = (input_thread_t *)p_this;
87     demux_sys_t    *p_sys;
88     int            b_forced = VLC_FALSE;
89
90     uint8_t        *p_peek;
91
92     module_t       *p_id3;
93
94
95     if( p_input->psz_demux && !strncmp( p_input->psz_demux, "a52", 3 ) )
96     {
97         b_forced = VLC_TRUE;
98     }
99     if( p_input->psz_name )
100     {
101         int  i_len = strlen( p_input->psz_name );
102
103         if( i_len > 4 && !strcasecmp( &p_input->psz_name[i_len - 4], ".a52" ) )
104         {
105             b_forced = VLC_TRUE;
106         }
107     }
108
109     /* skip possible id3 header */
110     p_id3 = module_Need( p_input, "id3", NULL );
111     if ( p_id3 )
112     {
113         module_Unneed( p_input, p_id3 );
114     }
115
116     /* see if it could be 52 */
117     if( !b_forced )
118     {
119         if( input_Peek( p_input, &p_peek, 6 ) < 6 )
120         {
121             msg_Err( p_input, "cannot peek" );
122             return VLC_EGENERIC;
123         }
124         if( !HeaderCheck( p_peek ) )
125         {
126             msg_Warn( p_input, "A52 module discarded" );
127             return VLC_EGENERIC;
128         }
129     }
130
131     p_input->pf_demux = Demux;
132
133     p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) );
134     p_sys->i_time = 0;
135
136     if( ( p_sys->s = stream_OpenInput( p_input ) ) == NULL )
137     {
138         msg_Err( p_input, "cannot create stream" );
139         goto error;
140     }
141
142     if( stream_Peek( p_sys->s, &p_peek, 6 ) < 6 )
143     {
144         msg_Err( p_input, "cannot peek" );
145         goto error;
146     }
147
148     if( HeaderCheck( p_peek ) )
149     {
150         int i_channels, i_sample_rate, i_frame_size;
151         input_info_category_t * p_category;
152
153         HeaderInfo( p_peek, &i_channels, &i_sample_rate, &i_frame_size );
154
155         msg_Dbg( p_input,
156                  "a52 channels=%d sample_rate=%d",
157                  i_channels, i_sample_rate );
158
159         vlc_mutex_lock( &p_input->stream.stream_lock );
160
161         p_category = input_InfoCategory( p_input, _("A52") );
162
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 );
166
167         vlc_mutex_unlock( &p_input->stream.stream_lock );
168     }
169
170     vlc_mutex_lock( &p_input->stream.stream_lock );
171     if( input_InitStream( p_input, 0 ) == -1)
172     {
173         vlc_mutex_unlock( &p_input->stream.stream_lock );
174         msg_Err( p_input, "cannot init stream" );
175         goto error;
176     }
177     if( input_AddProgram( p_input, 0, 0) == NULL )
178     {
179         vlc_mutex_unlock( &p_input->stream.stream_lock );
180         msg_Err( p_input, "cannot add program" );
181         goto error;
182     }
183     p_input->stream.pp_programs[0]->b_is_ok = 0;
184     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
185
186     p_input->stream.i_mux_rate = 0 / 50;
187
188     p_sys->p_es = input_AddES( p_input,
189                                p_input->stream.p_selected_program,
190                                1 , AUDIO_ES, NULL, 0 );
191
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 );
195
196     p_input->stream.p_selected_program->b_is_ok = 1;
197     vlc_mutex_unlock( &p_input->stream.stream_lock );
198
199     return VLC_SUCCESS;
200
201 error:
202     if( p_sys->s )
203     {
204         stream_Release( p_sys->s );
205     }
206     free( p_sys );
207     return VLC_EGENERIC;
208 }
209
210
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 )
217 {
218     demux_sys_t  *p_sys = p_input->p_demux_data;
219     pes_packet_t *p_pes;
220
221     int i_channels, i_sample_rate, i_frame_size;
222
223     uint8_t      *p_peek;
224
225     if( stream_Peek( p_sys->s, &p_peek, 6 ) < 6 )
226     {
227         msg_Warn( p_input, "cannot peek" );
228         return 0;
229     }
230
231     if( !HeaderCheck( p_peek ) )
232     {
233         /* we need to resynch */
234         vlc_bool_t  b_ok = VLC_FALSE;
235         int         i_skip = 0;
236         int         i_peek;
237
238         i_peek = stream_Peek( p_sys->s, &p_peek, 8096 );
239         if( i_peek < 8 )
240         {
241             msg_Warn( p_input, "cannot peek" );
242             return 0;
243         }
244
245         while( i_peek >= 8 )
246         {
247             if( HeaderCheck( p_peek ) )
248             {
249                 b_ok = VLC_TRUE;
250                 break;
251             }
252
253             p_peek++;
254             i_peek--;
255             i_skip++;
256         }
257
258         msg_Warn( p_input, "garbage=%d bytes", i_skip );
259         stream_Read( p_sys->s, NULL, i_skip );
260         return 1;
261     }
262
263     HeaderInfo( p_peek, &i_channels, &i_sample_rate, &i_frame_size );
264
265     input_ClockManageRef( p_input,
266                           p_input->stream.p_selected_program,
267                           p_sys->i_time * 9 / 100 );
268
269     if( ( p_pes = stream_PesPacket( p_sys->s, i_frame_size ) ) == NULL )
270     {
271         msg_Warn( p_input, "cannot read data" );
272         return 0;
273     }
274
275     p_pes->i_dts =
276     p_pes->i_pts = input_ClockGetTS( p_input,
277                                      p_input->stream.p_selected_program,
278                                      p_sys->i_time * 9 / 100 );
279
280     if( !p_sys->p_es->p_decoder_fifo )
281     {
282         msg_Err( p_input, "no audio decoder" );
283         input_DeletePES( p_input->p_method_data, p_pes );
284         return( -1 );
285     }
286
287     input_DecodePES( p_sys->p_es->p_decoder_fifo, p_pes );
288     p_sys->i_time += (mtime_t)1000000 *
289                      (mtime_t)1536 /
290                      (mtime_t)i_sample_rate;
291     return( 1 );
292 }
293
294 /*****************************************************************************
295  * Close: frees unused data
296  *****************************************************************************/
297 static void Close( vlc_object_t * p_this )
298 {
299     input_thread_t *p_input = (input_thread_t*)p_this;
300     demux_sys_t    *p_sys = p_input->p_demux_data;
301
302     if( p_sys->s )
303     {
304         stream_Release( p_sys->s );
305     }
306     free( p_sys );
307 }
308
309
310
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,
317                         int *pi_channels,
318                         int *pi_sample_rate,
319                         int *pi_frame_size )
320 {
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,
324                                 512, 576, 640 };
325     static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
326                                       0x04, 0x01, 0x04, 0x01 };
327     int frmsizecod;
328     int bitrate;
329     int half;
330     int acmod;
331
332     if ((p[0] != 0x0b) || (p[1] != 0x77))        /* syncword */
333         return VLC_FALSE;
334
335     if (p[5] >= 0x60)                /* bsid >= 12 */
336         return VLC_FALSE;
337     half = halfrate[p[5] >> 3];
338
339     /* acmod, dsurmod and lfeon */
340     acmod = p[6] >> 5;
341     if ( (p[6] & 0xf8) == 0x50 )
342     {
343         /* Dolby surround = stereo + Dolby */
344         *pi_channels = 2;
345     }
346     else
347     {
348         static const int acmod_to_channels[8] =
349         {
350             2 /* dual mono */, 1 /* mono */, 2 /* stereo */,
351             3 /* 3F */, 3 /* 2f1R */,
352             4 /* 3F1R */, 4, /* 2F2R */
353             5 /* 3F2R */
354         };
355
356         *pi_channels = acmod_to_channels[acmod];
357     }
358
359     if ( p[6] & lfeon[acmod] ) (*pi_channels)++;    /* LFE */
360
361     frmsizecod = p[4] & 63;
362     if (frmsizecod >= 38)
363         return VLC_FALSE;
364     bitrate = rate[frmsizecod >> 1];
365
366     switch (p[4] & 0xc0) {
367     case 0:
368         *pi_sample_rate = 48000 >> half;
369         *pi_frame_size = 4 * bitrate;
370         return VLC_TRUE;
371     case 0x40:
372         *pi_sample_rate = 44100 >> half;
373         *pi_frame_size = 2 * (320 * bitrate / 147 + (frmsizecod & 1));
374         return VLC_TRUE;
375     case 0x80:
376         *pi_sample_rate = 32000 >> half;
377         *pi_frame_size =6 * bitrate;
378         return VLC_TRUE;
379     default:
380         return VLC_FALSE;
381     }
382 }
383