]> git.sesse.net Git - vlc/blob - modules/demux/a52.c
Don't include config.h from the headers - refs #297.
[vlc] / modules / demux / a52.c
1 /*****************************************************************************
2  * a52.c : raw A/52 stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc/vlc.h>
32 #include <vlc_demux.h>
33 #include <vlc_codec.h>
34
35 #ifdef HAVE_UNISTD_H
36 #   include <unistd.h>
37 #endif
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 static int  Open  ( vlc_object_t * );
43 static void Close ( vlc_object_t * );
44
45 vlc_module_begin();
46     set_category( CAT_INPUT );
47     set_subcategory( SUBCAT_INPUT_DEMUX );
48     set_description( _("Raw A/52 demuxer") );
49     set_capability( "demux2", 145 );
50     set_callbacks( Open, Close );
51     add_shortcut( "a52" );
52 vlc_module_end();
53
54 /*****************************************************************************
55  * Local prototypes
56  *****************************************************************************/
57 static int Demux  ( demux_t * );
58 static int Control( demux_t *, int, va_list );
59
60 struct demux_sys_t
61 {
62     vlc_bool_t  b_start;
63     es_out_id_t *p_es;
64
65     /* Packetizer */
66     decoder_t *p_packetizer;
67
68     int i_mux_rate;
69     vlc_bool_t b_big_endian;
70 };
71
72 static int CheckSync( const uint8_t *p_peek, vlc_bool_t *p_big_endian );
73
74 #define PCM_FRAME_SIZE (1536 * 4)
75 #define A52_PACKET_SIZE (4 * PCM_FRAME_SIZE)
76 #define A52_MAX_HEADER_SIZE 10
77
78
79 /*****************************************************************************
80  * Open: initializes ES structures
81  *****************************************************************************/
82 static int Open( vlc_object_t * p_this )
83 {
84     demux_t     *p_demux = (demux_t*)p_this;
85     demux_sys_t *p_sys;
86     const byte_t*p_peek;
87     int         i_peek = 0;
88     vlc_bool_t  b_big_endian = 0; /* Arbitrary initialisation */
89
90     /* Check if we are dealing with a WAV file */
91     if( stream_Peek( p_demux->s, &p_peek, 12 ) == 12 &&
92         !memcmp( p_peek, "RIFF", 4 ) && !memcmp( p_peek + 8, "WAVE", 4 ) )
93     {
94         int i_size;
95
96         /* Skip the wave header */
97         i_peek = 12 + 8;
98         while( stream_Peek( p_demux->s, &p_peek, i_peek ) == i_peek &&
99                memcmp( p_peek + i_peek - 8, "data", 4 ) )
100         {
101             i_peek += GetDWLE( p_peek + i_peek - 4 ) + 8;
102         }
103
104         /* TODO: should check wave format and sample_rate */
105
106         /* Some A52 wav files don't begin with a sync code so we do a more
107          * extensive search */
108         i_size = stream_Peek( p_demux->s, &p_peek, i_peek + A52_PACKET_SIZE * 2);
109         i_size -= (PCM_FRAME_SIZE + A52_MAX_HEADER_SIZE);
110
111         while( i_peek < i_size )
112         {
113             if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
114                 /* The data is stored in 16 bits words */
115                 i_peek += 2;
116             else
117             {
118                 /* Check following sync code */
119                 if( CheckSync( p_peek + i_peek + PCM_FRAME_SIZE,
120                                &b_big_endian ) != VLC_SUCCESS )
121                 {
122                     i_peek += 2;
123                     continue;
124                 }
125
126                 break;
127             }
128         }
129     }
130
131     /* Have a peep at the show. */
132     CHECK_PEEK( p_peek, i_peek + A52_MAX_HEADER_SIZE * 2 );
133
134     if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
135     {
136         if( !p_demux->b_force )
137             return VLC_EGENERIC;
138
139         /* User forced */
140         msg_Err( p_demux, "this doesn't look like a A52 audio stream, "
141                  "continuing anyway" );
142     }
143
144     /* Fill p_demux fields */
145     DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;
146     p_sys->b_start = VLC_TRUE;
147     p_sys->i_mux_rate = 0;
148     p_sys->b_big_endian = b_big_endian;
149
150     /* Load the A52 packetizer */
151     INIT_APACKETIZER( p_sys->p_packetizer, 'a', '5', '2', ' ' );
152     LOAD_PACKETIZER_OR_FAIL( p_sys->p_packetizer, "A52" );
153
154     /* Create one program */
155     p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );
156
157     return VLC_SUCCESS;
158 }
159
160 /*****************************************************************************
161  * Close: frees unused data
162  *****************************************************************************/
163 static void Close( vlc_object_t * p_this )
164 {
165     demux_t        *p_demux = (demux_t*)p_this;
166     demux_sys_t    *p_sys = p_demux->p_sys;
167
168     DESTROY_PACKETIZER( p_sys->p_packetizer );
169     free( p_sys );
170 }
171
172 /*****************************************************************************
173  * Demux: reads and demuxes data packets
174  *****************************************************************************
175  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
176  *****************************************************************************/
177 static int Demux( demux_t *p_demux )
178 {
179     demux_sys_t *p_sys = p_demux->p_sys;
180     block_t     *p_block_in, *p_block_out;
181
182      /* Align stream */
183     int64_t i_pos = stream_Tell( p_demux->s );
184     if( i_pos % 2 ) stream_Read( p_demux->s, NULL, 1 );
185
186     if( !( p_block_in = stream_Block( p_demux->s, A52_PACKET_SIZE ) ) )
187     {
188         return 0;
189     }
190
191     if( !p_sys->b_big_endian && p_block_in->i_buffer )
192     {
193         /* Convert to big endian */
194
195 #ifdef HAVE_SWAB
196         swab(p_block_in->p_buffer, p_block_in->p_buffer, p_block_in->i_buffer);
197
198 #else
199         int i;
200         byte_t *p_tmp, tmp;
201         p_tmp = p_block_in->p_buffer;
202         for( i = p_block_in->i_buffer / 2 ; i-- ; )
203         {
204             tmp = p_tmp[0];
205             p_tmp[0] = p_tmp[1];
206             p_tmp[1] = tmp;
207             p_tmp += 2;
208         }
209 #endif
210     }
211
212     if( p_sys->b_start )
213         p_block_in->i_pts = p_block_in->i_dts = 1;
214     else
215         p_block_in->i_pts = p_block_in->i_dts = 0;
216
217     while( (p_block_out = p_sys->p_packetizer->pf_packetize(
218                 p_sys->p_packetizer, &p_block_in )) )
219     {
220         p_sys->b_start = VLC_FALSE;
221
222         while( p_block_out )
223         {
224             block_t *p_next = p_block_out->p_next;
225
226             /* We assume a constant bitrate */
227             if( p_block_out->i_length )
228             {
229                 p_sys->i_mux_rate =
230                     p_block_out->i_buffer * I64C(1000000)/p_block_out->i_length;
231             }
232
233             /* set PCR */
234             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
235
236             es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
237
238             p_block_out = p_next;
239         }
240     }
241
242     return 1;
243 }
244
245 /*****************************************************************************
246  * Control:
247  *****************************************************************************/
248 static int Control( demux_t *p_demux, int i_query, va_list args )
249 {
250     demux_sys_t *p_sys  = p_demux->p_sys;
251     if( i_query == DEMUX_SET_TIME )
252     {
253         return VLC_EGENERIC;
254     }
255     else if( i_query == DEMUX_HAS_UNSUPPORTED_META )
256     {
257         vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
258         *pb_bool = VLC_TRUE;
259         return VLC_SUCCESS;
260     }
261     else
262     {
263         return demux2_vaControlHelper( p_demux->s,
264                                        0, -1,
265                                        8*p_sys->i_mux_rate, 1, i_query, args );
266     }
267 }
268
269 /*****************************************************************************
270  * CheckSync: Check if buffer starts with an A52 sync code
271  *****************************************************************************/
272 static int CheckSync( const uint8_t *p_peek, vlc_bool_t *p_big_endian )
273 {
274     /* Little endian version of the bitstream */
275     if( p_peek[0] == 0x77 && p_peek[1] == 0x0b &&
276         p_peek[4] < 0x60 /* bsid < 12 */ )
277     {
278         *p_big_endian = VLC_FALSE;
279         return VLC_SUCCESS;
280     }
281     /* Big endian version of the bitstream */
282     else if( p_peek[0] == 0x0b && p_peek[1] == 0x77 &&
283              p_peek[5] < 0x60 /* bsid < 12 */ )
284     {
285         *p_big_endian = VLC_TRUE;
286         return VLC_SUCCESS;
287     }
288
289     return VLC_EGENERIC;
290 }
291
292