]> git.sesse.net Git - vlc/blob - modules/codec/a52.c
* modules/demux/util/sub.c: fix when no subs specified.
[vlc] / modules / codec / a52.c
1 /*****************************************************************************
2  * a52.c: A/52 basic parser
3  *****************************************************************************
4  * Copyright (C) 2001-2002 VideoLAN
5  * $Id: a52.c,v 1.27 2003/10/08 21:03:36 gbazin Exp $
6  *
7  * Authors: Stéphane Borel <stef@via.ecp.fr>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>                                              /* memcpy() */
32 #include <fcntl.h>
33
34 #include <vlc/vlc.h>
35 #include <vlc/decoder.h>
36 #include <vlc/input.h>
37 #include <vlc/aout.h>
38 #include <vlc/sout.h>
39
40 #include "vlc_block_helper.h"
41
42 #define A52_HEADER_SIZE 7
43
44 /*****************************************************************************
45  * decoder_sys_t : decoder descriptor
46  *****************************************************************************/
47 struct decoder_sys_t
48 {
49     /* Module mode */
50     vlc_bool_t b_packetizer;
51
52     /*
53      * Input properties
54      */
55     int        i_state;
56     vlc_bool_t b_synchro;
57
58     block_t *p_chain;
59     block_bytestream_t bytestream;
60
61     /*
62      * Decoder output properties
63      */
64     aout_instance_t *     p_aout;                                  /* opaque */
65     aout_input_t *        p_aout_input;                            /* opaque */
66     audio_sample_format_t aout_format;
67     aout_buffer_t *       p_aout_buffer; /* current aout buffer being filled */
68
69     /*
70      * Packetizer output properties
71      */
72     sout_packetizer_input_t *p_sout_input;
73     sout_format_t           sout_format;
74     sout_buffer_t *         p_sout_buffer;            /* current sout buffer */
75
76     /*
77      * Common properties
78      */
79     uint8_t               *p_out_buffer;                    /* output buffer */
80     audio_date_t          end_date;
81
82     mtime_t pts;
83     int i_frame_size, i_bit_rate;
84     unsigned int i_rate, i_channels, i_channels_conf;
85
86 };
87
88 enum {
89
90     STATE_NOSYNC,
91     STATE_SYNC,
92     STATE_HEADER,
93     STATE_DATA
94 };
95
96 /****************************************************************************
97  * Local prototypes
98  ****************************************************************************/
99 static int  OpenDecoder   ( vlc_object_t * );
100 static int  OpenPacketizer( vlc_object_t * );
101
102 static int  InitDecoder   ( decoder_t * );
103 static int  RunDecoder    ( decoder_t *, block_t * );
104 static int  EndDecoder    ( decoder_t * );
105
106 static int  SyncInfo      ( const byte_t *, int *, int *, int *,int * );
107
108 static int GetOutBuffer ( decoder_t *, uint8_t ** );
109 static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
110 static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
111 static int SendOutBuffer( decoder_t * );
112
113 /*****************************************************************************
114  * Module descriptor
115  *****************************************************************************/
116 vlc_module_begin();
117     set_description( _("A/52 parser") );
118     set_capability( "decoder", 100 );
119     set_callbacks( OpenDecoder, NULL );
120
121     add_submodule();
122     set_description( _("A/52 audio packetizer") );
123     set_capability( "packetizer", 10 );
124     set_callbacks( OpenPacketizer, NULL );
125 vlc_module_end();
126
127 /*****************************************************************************
128  * OpenDecoder: probe the decoder and return score
129  *****************************************************************************/
130 static int OpenDecoder( vlc_object_t *p_this )
131 {
132     decoder_t *p_dec = (decoder_t*)p_this;
133
134     if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
135          && p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
136     {
137         return VLC_EGENERIC;
138     }
139
140     p_dec->pf_init = InitDecoder;
141     p_dec->pf_decode = RunDecoder;
142     p_dec->pf_end = EndDecoder;
143
144     /* Allocate the memory needed to store the decoder's structure */
145     if( ( p_dec->p_sys =
146           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
147     {
148         msg_Err( p_dec, "out of memory" );
149         return VLC_EGENERIC;
150     }
151     p_dec->p_sys->b_packetizer = VLC_FALSE;
152
153     return VLC_SUCCESS;
154 }
155
156 static int OpenPacketizer( vlc_object_t *p_this )
157 {
158     decoder_t *p_dec = (decoder_t*)p_this;
159
160     int i_ret = OpenDecoder( p_this );
161
162     if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
163
164     return i_ret;
165 }
166
167 /*****************************************************************************
168  * InitDecoder: Initalize the decoder
169  *****************************************************************************/
170 static int InitDecoder( decoder_t *p_dec )
171 {
172     p_dec->p_sys->i_state = STATE_NOSYNC;
173     p_dec->p_sys->b_synchro = VLC_FALSE;
174
175     p_dec->p_sys->p_out_buffer = NULL;
176     aout_DateSet( &p_dec->p_sys->end_date, 0 );
177
178     p_dec->p_sys->p_aout = NULL;
179     p_dec->p_sys->p_aout_input = NULL;
180     p_dec->p_sys->p_aout_buffer = NULL;
181     p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' ');
182
183     p_dec->p_sys->p_sout_input = NULL;
184     p_dec->p_sys->p_sout_buffer = NULL;
185     p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
186     p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
187
188     p_dec->p_sys->p_chain = NULL;
189
190     return VLC_SUCCESS;
191 }
192
193 /****************************************************************************
194  * RunDecoder: the whole thing
195  ****************************************************************************
196  * This function is called just after the thread is launched.
197  ****************************************************************************/
198 static int RunDecoder( decoder_t *p_dec, block_t *p_block )
199 {
200     decoder_sys_t *p_sys = p_dec->p_sys;
201     uint8_t p_header[A52_HEADER_SIZE];
202
203     if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
204     {
205         /* We've just started the stream, wait for the first PTS. */
206         block_Release( p_block );
207         return VLC_SUCCESS;
208     }
209
210     if( p_sys->p_chain )
211     {
212         block_ChainAppend( &p_sys->p_chain, p_block );
213     }
214     else
215     {
216         block_ChainAppend( &p_sys->p_chain, p_block );
217         p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
218     }
219
220     while( 1 )
221     {
222         switch( p_sys->i_state )
223         {
224
225         case STATE_NOSYNC:
226             while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
227                    == VLC_SUCCESS )
228             {
229                 if( p_header[0] == 0x0b && p_header[1] == 0x77 )
230                 {
231                     p_sys->i_state = STATE_SYNC;
232                     break;
233                 }
234                 block_SkipByte( &p_sys->bytestream );
235                 p_sys->b_synchro = VLC_FALSE;
236             }
237             if( p_sys->i_state != STATE_SYNC )
238             {
239                 block_ChainRelease( p_sys->p_chain );
240                 p_sys->p_chain = NULL;
241
242                 /* Need more data */
243                 return VLC_SUCCESS;
244             }
245
246         case STATE_SYNC:
247             /* New frame, set the Presentation Time Stamp */
248             p_sys->pts = p_sys->bytestream.p_block->i_pts;
249             if( p_sys->pts != 0 &&
250                 p_sys->pts != aout_DateGet( &p_sys->end_date ) )
251             {
252                 aout_DateSet( &p_sys->end_date, p_sys->pts );
253             }
254             p_sys->i_state = STATE_HEADER;
255             break;
256
257         case STATE_HEADER:
258             /* Get A/52 frame header (A52_HEADER_SIZE bytes) */
259             if( block_PeekBytes( &p_sys->bytestream, p_header,
260                                  A52_HEADER_SIZE ) != VLC_SUCCESS )
261             {
262                 /* Need more data */
263                 return VLC_SUCCESS;
264             }
265
266             /* Check if frame is valid and get frame info */
267             p_sys->i_frame_size = SyncInfo( p_header,
268                                             &p_sys->i_channels,
269                                             &p_sys->i_channels_conf,
270                                             &p_sys->i_rate,
271                                             &p_sys->i_bit_rate );
272             if( !p_sys->i_frame_size )
273             {
274                 msg_Dbg( p_dec, "emulated sync word" );
275                 block_SkipByte( &p_sys->bytestream );
276                 p_sys->i_state = STATE_NOSYNC;
277                 p_sys->b_synchro = VLC_FALSE;
278                 break;
279             }
280             p_sys->i_state = STATE_DATA;
281
282         case STATE_DATA:
283             /* TODO: If p_block == NULL, flush the buffer without checking the
284              * next sync word */
285
286             if( !p_sys->b_synchro )
287             {
288                 /* Check if next expected frame contains the sync word */
289                 if( block_PeekOffsetBytes( &p_sys->bytestream,
290                                            p_sys->i_frame_size, p_header, 2 )
291                     != VLC_SUCCESS )
292                 {
293                     /* Need more data */
294                     return VLC_SUCCESS;
295                 }
296
297                 if( p_header[0] != 0x0b || p_header[1] != 0x77 )
298                 {
299                     msg_Dbg( p_dec, "emulated sync word "
300                              "(no sync on following frame)" );
301                     p_sys->i_state = STATE_NOSYNC;
302                     block_SkipByte( &p_sys->bytestream );
303                     p_sys->b_synchro = VLC_FALSE;
304                     break;
305                 }
306             }
307
308             if( !p_sys->p_out_buffer )
309             if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS )
310             {
311                 return VLC_EGENERIC;
312             }
313
314             /* Copy the whole frame into the buffer */
315             if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer,
316                                 p_sys->i_frame_size ) != VLC_SUCCESS )
317             {
318                 /* Need more data */
319                 return VLC_SUCCESS;
320             }
321
322             p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream );
323
324             SendOutBuffer( p_dec );
325             p_sys->i_state = STATE_NOSYNC;
326             p_sys->b_synchro = VLC_TRUE;
327
328             /* Make sure we don't reuse the same pts twice */
329             if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
330                 p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
331         }
332     }
333
334     return VLC_SUCCESS;
335 }
336
337 /*****************************************************************************
338  * EndDecoder: clean up the decoder
339  *****************************************************************************/
340 static int EndDecoder( decoder_t *p_dec )
341 {
342     if( p_dec->p_sys->p_aout_input != NULL )
343     {
344         if( p_dec->p_sys->p_aout_buffer )
345         {
346             aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
347                                   p_dec->p_sys->p_aout_input,
348                                   p_dec->p_sys->p_aout_buffer );
349         }
350
351         aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
352     }
353
354     if( p_dec->p_sys->p_sout_input != NULL )
355     {
356         if( p_dec->p_sys->p_sout_buffer )
357         {
358             sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
359                                p_dec->p_sys->p_sout_buffer );
360         }
361
362         sout_InputDelete( p_dec->p_sys->p_sout_input );
363     }
364
365     if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain );
366
367     free( p_dec->p_sys );
368
369     return VLC_SUCCESS;
370 }
371
372 /*****************************************************************************
373  * GetOutBuffer:
374  *****************************************************************************/
375 static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
376 {
377     decoder_sys_t *p_sys = p_dec->p_sys;
378     int i_ret;
379
380     if( p_sys->b_packetizer )
381     {
382         i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
383         *pp_out_buffer =
384             p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
385     }
386     else
387     {
388         i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
389         *pp_out_buffer =
390             p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
391     }
392
393     return i_ret;
394 }
395
396 /*****************************************************************************
397  * GetAoutBuffer:
398  *****************************************************************************/
399 static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
400 {
401     decoder_sys_t *p_sys = p_dec->p_sys;
402
403     if( p_sys->p_aout_input != NULL &&
404         ( p_sys->aout_format.i_rate != p_sys->i_rate
405         || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
406         || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
407     {
408         /* Parameters changed - this should not happen. */
409         aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
410         p_sys->p_aout_input = NULL;
411     }
412
413     /* Creating the audio input if not created yet. */
414     if( p_sys->p_aout_input == NULL )
415     {
416         p_sys->aout_format.i_rate = p_sys->i_rate;
417         p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
418         p_sys->aout_format.i_physical_channels
419             = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
420         p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
421         p_sys->aout_format.i_frame_length = A52_FRAME_NB;
422         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
423         aout_DateSet( &p_sys->end_date, p_sys->pts );
424         p_sys->p_aout_input = aout_DecNew( p_dec,
425                                            &p_sys->p_aout,
426                                            &p_sys->aout_format );
427         if( p_sys->p_aout_input == NULL )
428         {
429             *pp_buffer = NULL;
430             return VLC_EGENERIC;
431         }
432     }
433
434     *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
435                                     A52_FRAME_NB );
436     if( *pp_buffer == NULL )
437     {
438         return VLC_EGENERIC;
439     }
440
441     (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
442     (*pp_buffer)->end_date =
443          aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
444
445     return VLC_SUCCESS;
446 }
447
448 /*****************************************************************************
449  * GetSoutBuffer:
450  *****************************************************************************/
451 static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
452 {
453     decoder_sys_t *p_sys = p_dec->p_sys;
454
455     if( p_sys->p_sout_input != NULL &&
456         ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
457           || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
458     {
459         /* Parameters changed - this should not happen. */
460     }
461
462     /* Creating the sout input if not created yet. */
463     if( p_sys->p_sout_input == NULL )
464     {
465         p_sys->sout_format.i_sample_rate = p_sys->i_rate;
466         p_sys->sout_format.i_channels    = p_sys->i_channels;
467         p_sys->sout_format.i_block_align = 0;
468         p_sys->sout_format.i_bitrate     = p_sys->i_bit_rate;
469         p_sys->sout_format.i_extra_data  = 0;
470         p_sys->sout_format.p_extra_data  = NULL;
471
472         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
473         aout_DateSet( &p_sys->end_date, p_sys->pts );
474
475         p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
476         if( p_sys->p_sout_input == NULL )
477         {
478             msg_Err( p_dec, "cannot add a new stream" );
479             *pp_buffer = NULL;
480             return VLC_EGENERIC;
481         }
482         msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
483                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
484     }
485
486     *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
487                                  p_sys->i_frame_size );
488     if( *pp_buffer == NULL )
489     {
490         return VLC_EGENERIC;
491     }
492
493     (*pp_buffer)->i_pts =
494         (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
495
496     (*pp_buffer)->i_length =
497         aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB )
498         - (*pp_buffer)->i_pts;
499
500     return VLC_SUCCESS;
501 }
502
503 /*****************************************************************************
504  * SendOutBuffer:
505  *****************************************************************************/
506 static int SendOutBuffer( decoder_t *p_dec )
507 {
508     decoder_sys_t *p_sys = p_dec->p_sys;
509
510     if( p_sys->b_packetizer )
511     {
512         sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
513         p_sys->p_sout_buffer = NULL;
514     }
515     else
516     {
517         /* We have all we need, send the buffer to the aout core. */
518         aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
519                       p_sys->p_aout_buffer );
520         p_sys->p_aout_buffer = NULL;
521     }
522
523     p_sys->p_out_buffer = NULL;
524
525     return VLC_SUCCESS;
526 }
527
528 /*****************************************************************************
529  * SyncInfo: parse A/52 sync info
530  *****************************************************************************
531  * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
532  * since we don't want to oblige S/PDIF people to use liba52 just to get
533  * their SyncInfo...
534  *****************************************************************************/
535 static int SyncInfo( const byte_t * p_buf,
536                      int * pi_channels, int * pi_channels_conf,
537                      int * pi_sample_rate, int * pi_bit_rate )
538 {
539     static const uint8_t halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
540     static const int rate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
541                                 128, 160, 192, 224, 256, 320, 384, 448,
542                                 512, 576, 640 };
543     static const uint8_t lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
544                                       0x04, 0x01, 0x04, 0x01 };
545     int frmsizecod;
546     int bitrate;
547     int half;
548     int acmod;
549
550     if ((p_buf[0] != 0x0b) || (p_buf[1] != 0x77))        /* syncword */
551         return 0;
552
553     if (p_buf[5] >= 0x60)                /* bsid >= 12 */
554         return 0;
555     half = halfrate[p_buf[5] >> 3];
556
557     /* acmod, dsurmod and lfeon */
558     acmod = p_buf[6] >> 5;
559     if ( (p_buf[6] & 0xf8) == 0x50 )
560     {
561         /* Dolby surround = stereo + Dolby */
562         *pi_channels = 2;
563         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
564                             | AOUT_CHAN_DOLBYSTEREO;
565     }
566     else switch ( acmod )
567     {
568     case 0x0:
569         /* Dual-mono = stereo + dual-mono */
570         *pi_channels = 2;
571         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
572                             | AOUT_CHAN_DUALMONO;
573         break;
574     case 0x1:
575         /* Mono */
576         *pi_channels = 1;
577         *pi_channels_conf = AOUT_CHAN_CENTER;
578         break;
579     case 0x2:
580         /* Stereo */
581         *pi_channels = 2;
582         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
583         break;
584     case 0x3:
585         /* 3F */
586         *pi_channels = 3;
587         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
588                             | AOUT_CHAN_CENTER;
589         break;
590     case 0x4:
591         /* 2F1R */
592         *pi_channels = 3;
593         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
594                             | AOUT_CHAN_REARCENTER;
595         break;
596     case 0x5:
597         /* 3F1R */
598         *pi_channels = 4;
599         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
600                             | AOUT_CHAN_REARCENTER;
601         break;
602     case 0x6:
603         /* 2F2R */
604         *pi_channels = 4;
605         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
606                             | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
607         break;
608     case 0x7:
609         /* 3F2R */
610         *pi_channels = 5;
611         *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
612                             | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
613         break;
614     default:
615         return 0;
616     }
617
618     if ( p_buf[6] & lfeon[acmod] )
619     {
620         (*pi_channels)++;
621         *pi_channels_conf |= AOUT_CHAN_LFE;
622     }
623
624     frmsizecod = p_buf[4] & 63;
625     if (frmsizecod >= 38)
626         return 0;
627     bitrate = rate [frmsizecod >> 1];
628     *pi_bit_rate = (bitrate * 1000) >> half;
629
630     switch (p_buf[4] & 0xc0) {
631     case 0:
632         *pi_sample_rate = 48000 >> half;
633         return 4 * bitrate;
634     case 0x40:
635         *pi_sample_rate = 44100 >> half;
636         return 2 * (320 * bitrate / 147 + (frmsizecod & 1));
637     case 0x80:
638         *pi_sample_rate = 32000 >> half;
639         return 6 * bitrate;
640     default:
641         return 0;
642     }
643 }