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