]> git.sesse.net Git - vlc/blob - modules/codec/mpeg_audio.c
* modules/packetizer/mpegaudio.c: updated mpegaudio to the new decoder api.
[vlc] / modules / codec / mpeg_audio.c
1 /*****************************************************************************
2  * mpeg_audio.c: parse MPEG audio sync info and packetize the stream
3  *****************************************************************************
4  * Copyright (C) 2001-2003 VideoLAN
5  * $Id: mpeg_audio.c,v 1.18 2003/10/04 12:04:06 gbazin Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *          Christophe Massiot <massiot@via.ecp.fr>
10  *          Gildas Bazin <gbazin@netcourrier.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <stdlib.h>                                      /* malloc(), free() */
31 #include <string.h>                                              /* strdup() */
32
33 #include <vlc/vlc.h>
34 #include <vlc/decoder.h>
35 #include <vlc/input.h>
36 #include <vlc/aout.h>
37 #include <vlc/sout.h>
38
39 #include "vlc_block_helper.h"
40
41 /*****************************************************************************
42  * decoder_sys_t : decoder descriptor
43  *****************************************************************************/
44 struct decoder_sys_t
45 {
46     /* Module mode */
47     vlc_bool_t b_packetizer;
48
49     /*
50      * Input properties
51      */
52     int        i_state;
53
54     block_t *p_chain;
55     block_bytestream_t bytestream;
56
57     /*
58      * Decoder output properties
59      */
60     aout_instance_t *     p_aout;                                  /* opaque */
61     aout_input_t *        p_aout_input;                            /* opaque */
62     audio_sample_format_t aout_format;
63     aout_buffer_t *       p_aout_buffer; /* current aout buffer being filled */
64
65     /*
66      * Packetizer output properties
67      */
68     sout_packetizer_input_t *p_sout_input;
69     sout_format_t           sout_format;
70     sout_buffer_t *         p_sout_buffer;            /* current sout buffer */
71
72     /*
73      * Common properties
74      */
75     uint8_t               *p_out_buffer;                    /* output buffer */
76     audio_date_t          end_date;
77     unsigned int          i_current_layer;
78
79     mtime_t pts;
80
81     int i_frame_size, i_free_frame_size;
82     unsigned int i_channels_conf, i_channels;
83     unsigned int i_rate, i_max_frame_size, i_frame_length;
84     unsigned int i_layer, i_bit_rate;
85 };
86
87 enum {
88
89     STATE_NOSYNC,
90     STATE_SYNC,
91     STATE_HEADER,
92     STATE_NEXT_SYNC,
93     STATE_DATA
94 };
95
96 #define MAX_FRAME_SIZE 10000
97 /* This isn't the place to put mad-specific stuff. However, it makes the
98  * mad plug-in's life much easier if we put 8 extra bytes at the end of the
99  * buffer, because that way it doesn't have to copy the aout_buffer_t to a
100  * bigger buffer. This has no implication on other plug-ins, and we only
101  * lose 8 bytes per frame. --Meuuh */
102 #define MAD_BUFFER_GUARD 8
103 #define MPGA_HEADER_SIZE 4
104
105 /****************************************************************************
106  * Local prototypes
107  ****************************************************************************/
108 static int OpenDecoder   ( vlc_object_t * );
109 static int OpenPacketizer( vlc_object_t * );
110
111 static int InitDecoder   ( decoder_t * );
112 static int RunDecoder    ( decoder_t *, block_t * );
113 static int EndDecoder    ( decoder_t * );
114
115 static int GetOutBuffer ( decoder_t *, uint8_t ** );
116 static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
117 static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
118 static int SendOutBuffer( decoder_t * );
119
120 static int SyncInfo( uint32_t i_header, unsigned int * pi_channels,
121                      unsigned int * pi_sample_rate, unsigned int * pi_bit_rate,
122                      unsigned int * pi_frame_length,
123                      unsigned int * pi_current_frame_length,
124                      unsigned int * pi_layer );
125
126 /*****************************************************************************
127  * Module descriptor
128  *****************************************************************************/
129 vlc_module_begin();
130     set_description( _("MPEG audio layer I/II/III parser") );
131     set_capability( "decoder", 100 );
132     set_callbacks( OpenDecoder, NULL );
133
134     add_submodule();
135     set_description( _("MPEG audio layer I/II/III packetizer") );
136     set_capability( "packetizer", 10 );
137     set_callbacks( OpenPacketizer, NULL );
138 vlc_module_end();
139
140 /*****************************************************************************
141  * OpenDecoder: probe the decoder and return score
142  *****************************************************************************/
143 static int OpenDecoder( vlc_object_t *p_this )
144 {
145     decoder_t *p_dec = (decoder_t*)p_this;
146
147     if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') )
148     {
149         return VLC_EGENERIC;
150     }
151
152     p_dec->pf_init = InitDecoder;
153     p_dec->pf_decode = RunDecoder;
154     p_dec->pf_end = EndDecoder;
155
156     /* Allocate the memory needed to store the decoder's structure */
157     if( ( p_dec->p_sys =
158           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
159     {
160         msg_Err( p_dec, "out of memory" );
161         return VLC_EGENERIC;
162     }
163     p_dec->p_sys->b_packetizer = VLC_FALSE;
164
165     return VLC_SUCCESS;
166 }
167
168 static int OpenPacketizer( vlc_object_t *p_this )
169 {
170     decoder_t *p_dec = (decoder_t*)p_this;
171
172     int i_ret = OpenDecoder( p_this );
173
174     if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
175
176     return i_ret;
177 }
178
179 /*****************************************************************************
180  * InitDecoder: Initalize the decoder
181  *****************************************************************************/
182 static int InitDecoder( decoder_t *p_dec )
183 {
184     p_dec->p_sys->i_state = STATE_NOSYNC;
185
186     p_dec->p_sys->p_out_buffer = NULL;
187     aout_DateSet( &p_dec->p_sys->end_date, 0 );
188
189     p_dec->p_sys->p_aout = NULL;
190     p_dec->p_sys->p_aout_input = NULL;
191     p_dec->p_sys->p_aout_buffer = NULL;
192     p_dec->p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','a');
193
194     p_dec->p_sys->p_sout_input = NULL;
195     p_dec->p_sys->p_sout_buffer = NULL;
196     p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
197     p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC('m','p','g','a');
198
199     /* Start with the inimum size for a free bitrate frame */
200     p_dec->p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
201
202     p_dec->p_sys->p_chain = NULL;
203
204     return VLC_SUCCESS;
205 }
206
207 /****************************************************************************
208  * RunDecoder: the whole thing
209  ****************************************************************************
210  * This function is called just after the thread is launched.
211  ****************************************************************************/
212 static int RunDecoder( decoder_t *p_dec, block_t *p_block )
213 {
214     decoder_sys_t *p_sys = p_dec->p_sys;
215     uint8_t p_header[MAD_BUFFER_GUARD];
216     uint32_t i_header;
217
218     if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
219     {
220         /* We've just started the stream, wait for the first PTS. */
221         block_Release( p_block );
222         return VLC_SUCCESS;
223     }
224
225     if( p_sys->p_chain )
226     {
227         block_ChainAppend( &p_sys->p_chain, p_block );
228     }
229     else
230     {
231         block_ChainAppend( &p_sys->p_chain, p_block );
232         p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
233     }
234
235     while( 1 )
236     {
237         switch( p_sys->i_state )
238         {
239
240         case STATE_NOSYNC:
241             while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
242                    == VLC_SUCCESS )
243             {
244                 /* Look for sync word - should be 0xffe */
245                 if( p_header[0] == 0xff && (p_header[1] & 0xe0) == 0xe0 )
246                 {
247                     p_sys->i_state = STATE_SYNC;
248                     break;
249                 }
250                 block_SkipByte( &p_sys->bytestream );
251             }
252             if( p_sys->i_state != STATE_SYNC )
253             {
254                 block_ChainRelease( p_sys->p_chain );
255                 p_sys->p_chain = NULL;
256
257                 /* Need more data */
258                 return VLC_SUCCESS;
259             }
260
261         case STATE_SYNC:
262             /* New frame, set the Presentation Time Stamp */
263             p_sys->pts = p_sys->bytestream.p_block->i_pts;
264             if( p_sys->pts != 0 &&
265                 p_sys->pts != aout_DateGet( &p_sys->end_date ) )
266             {
267                 aout_DateSet( &p_sys->end_date, p_sys->pts );
268             }
269             p_sys->i_state = STATE_HEADER;
270             break;
271
272         case STATE_HEADER:
273             /* Get MPGA frame header (MPGA_HEADER_SIZE bytes) */
274             if( block_PeekBytes( &p_sys->bytestream, p_header,
275                                  MPGA_HEADER_SIZE ) != VLC_SUCCESS )
276             {
277                 /* Need more data */
278                 return VLC_SUCCESS;
279             }
280
281             /* Build frame header */
282             i_header = (p_header[0]<<24)|(p_header[1]<<16)|(p_header[2]<<8)
283                        |p_header[3];
284
285             /* Check if frame is valid and get frame info */
286             p_sys->i_frame_size = SyncInfo( i_header,
287                                             &p_sys->i_channels_conf,
288                                             &p_sys->i_rate,
289                                             &p_sys->i_bit_rate,
290                                             &p_sys->i_frame_length,
291                                             &p_sys->i_frame_size,
292                                             &p_sys->i_layer );
293
294             if( p_sys->i_frame_size == -1 )
295             {
296                 msg_Dbg( p_dec, "emulated start code" );
297                 block_SkipByte( &p_sys->bytestream );
298                 p_sys->i_state = STATE_NOSYNC;
299                 break;
300             }
301
302             if( p_sys->i_bit_rate == 0 )
303             {
304                 /* Free birate, but 99% emulated startcode :( */
305                 if( p_dec->p_sys->i_free_frame_size == MPGA_HEADER_SIZE )
306                 {
307                     msg_Dbg( p_dec, "free bitrate mode");
308                 }
309                 p_sys->i_frame_size = p_sys->i_free_frame_size;
310             }
311
312             p_sys->i_state = STATE_NEXT_SYNC;
313
314         case STATE_NEXT_SYNC:
315             /* TODO: If p_block == NULL, flush the buffer without checking the
316              * next sync word */
317
318             /* Check if next expected frame contains the sync word */
319             if( block_PeekOffsetBytes( &p_sys->bytestream,
320                                        p_sys->i_frame_size, p_header,
321                                        MAD_BUFFER_GUARD ) != VLC_SUCCESS )
322             {
323                 /* Need more data */
324                 return VLC_SUCCESS;
325             }
326
327             if( p_header[0] == 0xff && (p_header[1] & 0xe0) == 0xe0 )
328             {
329                 /* Startcode is fine, let's try the header as an extra check */
330                 int i_next_frame_size;
331                 unsigned int i_next_channels, i_next_rate, i_next_bit_rate;
332                 unsigned int i_next_frame_length, i_next_max_frame_size;
333                 unsigned int i_next_layer;
334
335                 /* Build frame header */
336                 i_header = (p_header[0]<<24)|(p_header[1]<<16)|(p_header[2]<<8)
337                            |p_header[3];
338
339                 i_next_frame_size = SyncInfo( i_header,
340                                               &i_next_channels,
341                                               &i_next_rate,
342                                               &i_next_bit_rate,
343                                               &i_next_frame_length,
344                                               &i_next_max_frame_size,
345                                               &i_next_layer );
346
347                 if( i_next_frame_size == -1 )
348                 {
349                     msg_Dbg( p_dec, "emulated start code on next frame" );
350                     block_SkipByte( &p_sys->bytestream );
351                     p_sys->i_state = STATE_NOSYNC;
352                     break;
353                 }
354
355                 /* Free bitrate only */
356                 if( p_sys->i_bit_rate == 0 )
357                 {
358                     if( i_next_bit_rate != 0 )
359                     {
360                         p_sys->i_frame_size++;
361                         break;
362                     }
363
364                     if( (unsigned int)p_sys->i_frame_size >
365                         p_sys->i_max_frame_size )
366                     {
367                         msg_Dbg( p_dec, "frame too big %d > %d "
368                                  "(emulated startcode ?)", p_sys->i_frame_size,
369                                  p_sys->i_max_frame_size );
370                         block_SkipByte( &p_sys->bytestream );
371                         p_sys->i_state = STATE_NOSYNC;
372                         p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
373                         break;
374                     }
375                 }
376
377                 /* Check info is in sync with previous one */
378                 if( i_next_channels != p_sys->i_channels_conf ||
379                     i_next_rate != p_sys->i_rate ||
380                     i_next_layer != p_sys->i_layer ||
381                     i_next_frame_length != p_sys->i_frame_length )
382                 {
383                     /* Free bitrate only */
384                     if( p_sys->i_bit_rate == 0 )
385                     {
386                         p_sys->i_frame_size++;
387                         break;
388                     }
389
390                     msg_Dbg( p_dec, "parameters changed unexpectedly "
391                              "(emulated startcode ?)" );
392                     block_SkipByte( &p_sys->bytestream );
393                     p_sys->i_state = STATE_NOSYNC;
394                     break;
395                 }
396             }
397             else
398             {
399                 msg_Dbg( p_dec, "emulated startcode "
400                          "(no startcode on following frame)" );
401                 p_sys->i_state = STATE_NOSYNC;
402                 block_SkipByte( &p_sys->bytestream );
403                 break;
404             }
405
406             if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS )
407             {
408                 return VLC_EGENERIC;
409             }
410
411             /* Free bitrate only */
412             if( p_sys->i_bit_rate == 0 )
413             {
414                 p_sys->i_free_frame_size = p_sys->i_frame_size;
415             }
416
417             p_sys->i_state = STATE_DATA;
418
419         case STATE_DATA:
420             /* Copy the whole frame into the buffer */
421             if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer,
422                                 p_sys->i_frame_size ) != VLC_SUCCESS )
423             {
424                 /* Need more data */
425                 return VLC_SUCCESS;
426             }
427
428             p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream );
429
430             /* Get beginning of next frame for libmad */
431             if( !p_sys->b_packetizer )
432             {
433                 memcpy( p_sys->p_out_buffer + p_sys->i_frame_size,
434                         p_header, MAD_BUFFER_GUARD );
435             }
436
437             SendOutBuffer( p_dec );
438             p_sys->i_state = STATE_NOSYNC;
439
440             /* Make sure we don't reuse the same pts twice */
441             if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
442                 p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
443         }
444     }
445
446     return VLC_SUCCESS;
447 }
448
449 /*****************************************************************************
450  * GetOutBuffer:
451  *****************************************************************************/
452 static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
453 {
454     decoder_sys_t *p_sys = p_dec->p_sys;
455     int i_ret;
456
457     if( p_sys->b_packetizer )
458     {
459         i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
460         *pp_out_buffer =
461             p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
462     }
463     else
464     {
465         i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
466         *pp_out_buffer =
467             p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
468     }
469
470     return i_ret;
471 }
472
473 /*****************************************************************************
474  * GetAoutBuffer:
475  *****************************************************************************/
476 static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
477 {
478     decoder_sys_t *p_sys = p_dec->p_sys;
479
480     if( p_sys->p_aout_input != NULL &&
481         ( p_sys->aout_format.i_rate != p_sys->i_rate
482         || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
483         || (int)p_sys->aout_format.i_bytes_per_frame !=
484            p_sys->i_max_frame_size + MAD_BUFFER_GUARD
485         || p_sys->aout_format.i_frame_length != p_sys->i_frame_length
486         || p_sys->i_current_layer != p_sys->i_layer ) )
487     {
488         /* Parameters changed - this should not happen. */
489         aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
490         p_sys->p_aout_input = NULL;
491     }
492
493     /* Creating the audio input if not created yet. */
494     if( p_sys->p_aout_input == NULL )
495     {
496         p_sys->i_current_layer = p_sys->i_layer;
497         if( p_sys->i_layer == 3 )
498         {
499             p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','3');
500         }
501         else
502         {
503             p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','a');
504         }
505
506         p_sys->aout_format.i_rate = p_sys->i_rate;
507         p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
508         p_sys->aout_format.i_physical_channels
509             = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
510         p_sys->aout_format.i_bytes_per_frame = p_sys->i_max_frame_size
511             + MAD_BUFFER_GUARD;
512         p_sys->aout_format.i_frame_length = p_sys->i_frame_length;
513         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
514         aout_DateSet( &p_sys->end_date, p_sys->pts );
515         p_sys->p_aout_input = aout_DecNew( p_dec,
516                                            &p_sys->p_aout,
517                                            &p_sys->aout_format );
518         if( p_sys->p_aout_input == NULL )
519         {
520             *pp_buffer = NULL;
521             return VLC_EGENERIC;
522         }
523     }
524
525     *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
526                                     p_sys->i_frame_length );
527     if( *pp_buffer == NULL )
528     {
529         return VLC_EGENERIC;
530     }
531
532     (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
533     (*pp_buffer)->end_date =
534          aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
535
536     return VLC_SUCCESS;
537 }
538
539 /*****************************************************************************
540  * GetSoutBuffer:
541  *****************************************************************************/
542 static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
543 {
544     decoder_sys_t *p_sys = p_dec->p_sys;
545
546     if( p_sys->p_sout_input != NULL &&
547         ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
548           || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
549     {
550         /* Parameters changed - this should not happen. */
551     }
552
553     /* Creating the sout input if not created yet. */
554     if( p_sys->p_sout_input == NULL )
555     {
556         p_sys->sout_format.i_sample_rate = p_sys->i_rate;
557         p_sys->sout_format.i_channels    = p_sys->i_channels;
558         p_sys->sout_format.i_block_align = 0;
559         p_sys->sout_format.i_bitrate     = p_sys->i_bit_rate;
560         p_sys->sout_format.i_extra_data  = 0;
561         p_sys->sout_format.p_extra_data  = NULL;
562
563         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
564         aout_DateSet( &p_sys->end_date, p_sys->pts );
565
566         p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
567         if( p_sys->p_sout_input == NULL )
568         {
569             msg_Err( p_dec, "cannot add a new stream" );
570             *pp_buffer = NULL;
571             return VLC_EGENERIC;
572         }
573         msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
574                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
575     }
576
577     *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
578                                  p_sys->i_frame_size );
579     if( *pp_buffer == NULL )
580     {
581         return VLC_EGENERIC;
582     }
583
584     (*pp_buffer)->i_pts =
585         (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
586
587     (*pp_buffer)->i_length =
588         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length )
589         - (*pp_buffer)->i_pts;
590
591     return VLC_SUCCESS;
592 }
593
594 /*****************************************************************************
595  * SendOutBuffer:
596  *****************************************************************************/
597 static int SendOutBuffer( decoder_t *p_dec )
598 {
599     decoder_sys_t *p_sys = p_dec->p_sys;
600
601     if( p_sys->b_packetizer )
602     {
603         sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
604         p_sys->p_sout_buffer = NULL;
605     }
606     else
607     {
608         /* We have all we need, send the buffer to the aout core. */
609         aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
610                       p_sys->p_aout_buffer );
611         p_sys->p_aout_buffer = NULL;
612     }
613
614     p_sys->p_out_buffer = NULL;
615
616     return VLC_SUCCESS;
617 }
618
619 /*****************************************************************************
620  * EndDecoder: clean up the decoder
621  *****************************************************************************/
622 static int EndDecoder( decoder_t *p_dec )
623 {
624     if( p_dec->p_sys->p_aout_input != NULL )
625     {
626         if( p_dec->p_sys->p_aout_buffer )
627         {
628             aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
629                                   p_dec->p_sys->p_aout_input,
630                                   p_dec->p_sys->p_aout_buffer );
631         }
632
633         aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
634     }
635
636     if( p_dec->p_sys->p_sout_input != NULL )
637     {
638         if( p_dec->p_sys->p_sout_buffer )
639         {
640             sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
641                                p_dec->p_sys->p_sout_buffer );
642         }
643
644         sout_InputDelete( p_dec->p_sys->p_sout_input );
645     }
646
647     if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain );
648
649     free( p_dec->p_sys );
650
651     return VLC_SUCCESS;
652 }
653
654 /*****************************************************************************
655  * SyncInfo: parse MPEG audio sync info
656  *****************************************************************************/
657 static int SyncInfo( uint32_t i_header, unsigned int * pi_channels,
658                      unsigned int * pi_sample_rate, unsigned int * pi_bit_rate,
659                      unsigned int * pi_frame_length,
660                      unsigned int * pi_frame_size, unsigned int * pi_layer )
661 {
662     static const int pppi_mpegaudio_bitrate[2][3][16] =
663     {
664         {
665             /* v1 l1 */
666             { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384,
667               416, 448, 0},
668             /* v1 l2 */
669             { 0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256,
670               320, 384, 0},
671             /* v1 l3 */
672             { 0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224,
673               256, 320, 0}
674         },
675
676         {
677             /* v2 l1 */
678             { 0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192,
679               224, 256, 0},
680             /* v2 l2 */
681             { 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128,
682               144, 160, 0},
683             /* v2 l3 */
684             { 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128,
685               144, 160, 0}
686         }
687     };
688
689     static const int ppi_mpegaudio_samplerate[2][4] = /* version 1 then 2 */
690     {
691         { 44100, 48000, 32000, 0 },
692         { 22050, 24000, 16000, 0 }
693     };
694
695     int i_version, i_mode, i_emphasis;
696     vlc_bool_t b_padding, b_mpeg_2_5;
697     int i_current_frame_size = 0;
698     int i_bitrate_index, i_samplerate_index;
699     int i_max_bit_rate;
700
701     b_mpeg_2_5  = 1 - ((i_header & 0x100000) >> 20);
702     i_version   = 1 - ((i_header & 0x80000) >> 19);
703     *pi_layer   = 4 - ((i_header & 0x60000) >> 17);
704     /* CRC */
705     i_bitrate_index = (i_header & 0xf000) >> 12;
706     i_samplerate_index = (i_header & 0xc00) >> 10;
707     b_padding   = (i_header & 0x200) >> 9;
708     /* Extension */
709     i_mode      = (i_header & 0xc0) >> 6;
710     /* Modeext, copyright & original */
711     i_emphasis  = i_header & 0x3;
712
713     if( *pi_layer != 4 &&
714         i_bitrate_index < 0x0f &&
715         i_samplerate_index != 0x03 &&
716         i_emphasis != 0x02 )
717     {
718         switch ( i_mode )
719         {
720         case 0: /* stereo */
721         case 1: /* joint stereo */
722             *pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
723             break;
724         case 2: /* dual-mono */
725             *pi_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
726                             | AOUT_CHAN_DUALMONO;
727             break;
728         case 3: /* mono */
729             *pi_channels = AOUT_CHAN_CENTER;
730             break;
731         }
732         *pi_bit_rate = pppi_mpegaudio_bitrate[i_version][*pi_layer-1][i_bitrate_index];
733         i_max_bit_rate = pppi_mpegaudio_bitrate[i_version][*pi_layer-1][14];
734         *pi_sample_rate = ppi_mpegaudio_samplerate[i_version][i_samplerate_index];
735
736         if ( b_mpeg_2_5 )
737         {
738             *pi_sample_rate >>= 1;
739         }
740
741         switch( *pi_layer )
742         {
743         case 1:
744             i_current_frame_size = ( 12000 * *pi_bit_rate /
745                                      *pi_sample_rate + b_padding ) * 4;
746             *pi_frame_size = ( 12000 * i_max_bit_rate /
747                                *pi_sample_rate + 1 ) * 4;
748             *pi_frame_length = 384;
749             break;
750
751         case 2:
752             i_current_frame_size = 144000 * *pi_bit_rate /
753                                    *pi_sample_rate + b_padding;
754             *pi_frame_size = 144000 * i_max_bit_rate / *pi_sample_rate + 1;
755             *pi_frame_length = 1152;
756             break;
757
758         case 3:
759             i_current_frame_size = ( i_version ? 72000 : 144000 ) *
760                                    *pi_bit_rate / *pi_sample_rate + b_padding;
761             *pi_frame_size = ( i_version ? 72000 : 144000 ) *
762                                  i_max_bit_rate / *pi_sample_rate + 1;
763             *pi_frame_length = i_version ? 576 : 1152;
764             break;
765
766         default:
767             break;
768         }
769     }
770     else
771     {
772         return -1;
773     }
774
775     return i_current_frame_size;
776 }