]> git.sesse.net Git - vlc/blob - modules/codec/lpcm.c
Minor comment cleanup.
[vlc] / modules / codec / lpcm.c
1 /*****************************************************************************
2  * lpcm.c: lpcm decoder/packetizer module
3  *****************************************************************************
4  * Copyright (C) 1999-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Henri Fallon <henri@videolan.org>
9  *          Christophe Massiot <massiot@via.ecp.fr>
10  *          Gildas Bazin <gbazin@videolan.org>
11  *          Lauren Aimar <fenrir _AT_ videolan _DOT_ org >
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_codec.h>
38 #include <vlc_aout.h>
39 #include <assert.h>
40
41 /*****************************************************************************
42  * Module descriptor
43  *****************************************************************************/
44 static int  OpenDecoder   ( vlc_object_t * );
45 static int  OpenPacketizer( vlc_object_t * );
46 static void CloseCommon   ( vlc_object_t * );
47
48 #ifdef ENABLE_SOUT
49 static int  OpenEncoder   ( vlc_object_t * );
50 static void CloseEncoder  ( vlc_object_t * );
51 static block_t *EncodeFrames( encoder_t *, aout_buffer_t * );
52 #endif
53
54 vlc_module_begin ()
55
56     set_category( CAT_INPUT )
57     set_subcategory( SUBCAT_INPUT_ACODEC )
58     set_description( N_("Linear PCM audio decoder") )
59     set_capability( "decoder", 100 )
60     set_callbacks( OpenDecoder, CloseCommon )
61
62     add_submodule ()
63     set_description( N_("Linear PCM audio packetizer") )
64     set_capability( "packetizer", 100 )
65     set_callbacks( OpenPacketizer, CloseCommon )
66
67     add_submodule ()
68     set_description( N_("Linear PCM audio encoder") )
69     set_capability( "encoder", 100 )
70     set_callbacks( OpenEncoder, CloseEncoder )
71     add_shortcut( "lpcm" )
72
73 vlc_module_end ()
74
75
76 /*****************************************************************************
77  * decoder_sys_t : lpcm decoder descriptor
78  *****************************************************************************/
79 struct decoder_sys_t
80 {
81     /* Module mode */
82     bool b_packetizer;
83
84     /*
85      * Output properties
86      */
87     date_t   end_date;
88
89     /* */
90     unsigned i_header_size;
91     int      i_type;
92 };
93
94 struct encoder_sys_t
95 {
96     int     i_channels;
97     int     i_rate;
98
99     int     i_frame_samples;
100     uint8_t *p_buffer;
101     int     i_buffer_used;
102     int     i_frame_num;
103 };
104
105 /*
106  * LPCM DVD header :
107  * - number of frames in this packet (8 bits)
108  * - first access unit (16 bits) == 0x0003 ?
109  * - emphasis (1 bit)
110  * - mute (1 bit)
111  * - reserved (1 bit)
112  * - current frame (5 bits)
113  * - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal
114  * - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz
115  * - reserved (1 bit)
116  * - number of channels - 1 (3 bits) 1 == 2 channels
117  * - dynamic range (8 bits) 0x80 == neutral
118  *
119  * LPCM DVD-A header (http://dvd-audio.sourceforge.net/spec/aob.shtml)
120  * - continuity counter (8 bits, clipped to 0x00-0x1f)
121  * - header size (16 bits)
122  * - byte pointer to start of first audio frame.
123  * - unknown (8bits, 0x10 for stereo, 0x00 for surround)
124  * - sample size (4+4 bits)
125  * - samplerate (4+4 bits)
126  * - unknown (8 bits)
127  * - group assignment (8 bits)
128  * - unknown (8 bits)
129  * - padding(variable)
130  *
131  * LPCM BD header :
132  * - unkown (16 bits)
133  * - number of channels (4 bits)
134  * - frequency (4 bits)
135  * - bits per sample (2 bits)
136  * - unknown (6 bits)
137  */
138
139 #define LPCM_VOB_HEADER_LEN (6)
140 #define LPCM_AOB_HEADER_LEN (11)
141 #define LPCM_BD_HEADER_LEN (4)
142
143 enum
144 {
145     LPCM_VOB,
146     LPCM_AOB,
147     LPCM_BD,
148 };
149
150 typedef struct
151 {
152     unsigned i_channels;
153     bool     b_used;
154     unsigned pi_position[6];
155 } aob_group_t;
156
157 /*****************************************************************************
158  * Local prototypes
159  *****************************************************************************/
160 static void *DecodeFrame  ( decoder_t *, block_t ** );
161
162 /* */
163 static int VobHeader( unsigned *pi_rate,
164                       unsigned *pi_channels, unsigned *pi_original_channels,
165                       unsigned *pi_bits,
166                       const uint8_t *p_header );
167 static void VobExtract( aout_buffer_t *, block_t *, unsigned i_bits );
168 /* */
169 static int AobHeader( unsigned *pi_rate,
170                       unsigned *pi_channels, unsigned *pi_layout,
171                       unsigned *pi_bits,
172                       unsigned *pi_padding,
173                       aob_group_t g[2],
174                       const uint8_t *p_header );
175 static void AobExtract( aout_buffer_t *, block_t *, unsigned i_bits, aob_group_t p_group[2] );
176 /* */
177 static int BdHeader( unsigned *pi_rate,
178                      unsigned *pi_channels, unsigned *pi_original_channels,
179                      unsigned *pi_bits,
180                      const uint8_t *p_header );
181 static void BdExtract( aout_buffer_t *, block_t * );
182
183
184 /*****************************************************************************
185  * OpenCommon:
186  *****************************************************************************/
187 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
188 {
189     decoder_t *p_dec = (decoder_t*)p_this;
190     decoder_sys_t *p_sys;
191     int i_type;
192     int i_header_size;
193
194     switch( p_dec->fmt_in.i_codec )
195     {
196     /* DVD LPCM */
197     case VLC_CODEC_DVD_LPCM:
198         i_type = LPCM_VOB;
199         i_header_size = LPCM_VOB_HEADER_LEN;
200         break;
201     /* DVD-Audio LPCM */
202     case VLC_CODEC_DVDA_LPCM:
203         i_type = LPCM_AOB;
204         i_header_size = LPCM_AOB_HEADER_LEN;
205         break;
206     /* BD LPCM */
207     case VLC_CODEC_BD_LPCM:
208         i_type = LPCM_BD;
209         i_header_size = LPCM_BD_HEADER_LEN;
210         break;
211     default:
212         return VLC_EGENERIC;
213     }
214
215     /* Allocate the memory needed to store the decoder's structure */
216     if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL )
217         return VLC_ENOMEM;
218
219     /* Misc init */
220     p_sys->b_packetizer = b_packetizer;
221     date_Set( &p_sys->end_date, 0 );
222     p_sys->i_type = i_type;
223     p_sys->i_header_size = i_header_size;
224
225     /* Set output properties */
226     p_dec->fmt_out.i_cat = AUDIO_ES;
227
228     if( b_packetizer )
229     {
230         switch( i_type )
231         {
232         case LPCM_VOB:
233             p_dec->fmt_out.i_codec = VLC_CODEC_DVD_LPCM;
234             break;
235         case LPCM_AOB:
236             p_dec->fmt_out.i_codec = VLC_CODEC_DVDA_LPCM;
237             break;
238         default:
239             assert(0);
240         case LPCM_BD:
241             p_dec->fmt_out.i_codec = VLC_CODEC_BD_LPCM;
242             break;
243         }
244     }
245     else
246     {
247         switch( p_dec->fmt_out.audio.i_bitspersample )
248         {
249         case 24:
250         case 20:
251             p_dec->fmt_out.i_codec = VLC_CODEC_S24B;
252             p_dec->fmt_out.audio.i_bitspersample = 24;
253             break;
254         default:
255             p_dec->fmt_out.i_codec = VLC_CODEC_S16B;
256             p_dec->fmt_out.audio.i_bitspersample = 16;
257             break;
258         }
259     }
260
261     /* Set callback */
262     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
263         DecodeFrame;
264     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
265         DecodeFrame;
266
267     return VLC_SUCCESS;
268 }
269 static int OpenDecoder( vlc_object_t *p_this )
270 {
271     return OpenCommon( p_this, false );
272 }
273 static int OpenPacketizer( vlc_object_t *p_this )
274 {
275     return OpenCommon( p_this, true );
276 }
277
278 /*****************************************************************************
279  * DecodeFrame: decodes an lpcm frame.
280  ****************************************************************************
281  * Beware, this function must be fed with complete frames (PES packet).
282  *****************************************************************************/
283 static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
284 {
285     decoder_sys_t *p_sys = p_dec->p_sys;
286     block_t       *p_block;
287     unsigned int  i_rate = 0, i_original_channels = 0, i_channels = 0, i_bits = 0;
288     int           i_frame_length;
289
290     if( !pp_block || !*pp_block ) return NULL;
291
292     p_block = *pp_block;
293     *pp_block = NULL; /* So the packet doesn't get re-sent */
294
295     /* Date management */
296     if( p_block->i_pts > VLC_TS_INVALID &&
297         p_block->i_pts != date_Get( &p_sys->end_date ) )
298     {
299         date_Set( &p_sys->end_date, p_block->i_pts );
300     }
301
302     if( !date_Get( &p_sys->end_date ) )
303     {
304         /* We've just started the stream, wait for the first PTS. */
305         block_Release( p_block );
306         return NULL;
307     }
308
309     if( p_block->i_buffer <= p_sys->i_header_size )
310     {
311         msg_Err(p_dec, "frame is too short");
312         block_Release( p_block );
313         return NULL;
314     }
315
316     int i_ret;
317     unsigned i_padding = 0;
318     aob_group_t p_aob_group[2];
319     switch( p_sys->i_type )
320     {
321     case LPCM_VOB:
322         i_ret = VobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
323                            p_block->p_buffer );
324         break;
325     case LPCM_AOB:
326         i_ret = AobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, &i_padding,
327                            p_aob_group,
328                            p_block->p_buffer );
329         break;
330     case LPCM_BD:
331         i_ret = BdHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
332                           p_block->p_buffer );
333         break;
334     default:
335         abort();
336     }
337
338     if( i_ret || p_block->i_buffer <= p_sys->i_header_size + i_padding )
339     {
340         msg_Warn( p_dec, "no frame sync or too small frame" );
341         block_Release( p_block );
342         return NULL;
343     }
344
345     /* Set output properties */
346     if( p_dec->fmt_out.audio.i_rate != i_rate )
347     {
348         date_Init( &p_sys->end_date, i_rate, 1 );
349         date_Set( &p_sys->end_date, p_block->i_pts );
350     }
351     p_dec->fmt_out.audio.i_rate = i_rate;
352     p_dec->fmt_out.audio.i_channels = i_channels;
353     p_dec->fmt_out.audio.i_original_channels = i_original_channels;
354     p_dec->fmt_out.audio.i_physical_channels = i_original_channels & AOUT_CHAN_PHYSMASK;
355
356     i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) / i_channels * 8 / i_bits;
357
358     if( p_sys->b_packetizer )
359     {
360         p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
361         p_block->i_length =
362             date_Increment( &p_sys->end_date, i_frame_length ) -
363             p_block->i_pts;
364
365         /* Just pass on the incoming frame */
366         return p_block;
367     }
368     else
369     {
370         /* */
371         if( i_bits == 16 )
372         {
373             p_dec->fmt_out.i_codec = VLC_CODEC_S16B;
374             p_dec->fmt_out.audio.i_bitspersample = 16;
375         }
376         else
377         {
378             p_dec->fmt_out.i_codec = VLC_CODEC_S24B;
379             p_dec->fmt_out.audio.i_bitspersample = 24;
380         }
381
382         /* */
383         aout_buffer_t *p_aout_buffer;
384         p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length );
385         if( !p_aout_buffer )
386             return NULL;
387
388         p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
389         p_aout_buffer->i_length =
390             date_Increment( &p_sys->end_date, i_frame_length )
391             - p_aout_buffer->i_pts;
392
393         p_block->p_buffer += p_sys->i_header_size + i_padding;
394         p_block->i_buffer -= p_sys->i_header_size + i_padding;
395
396         switch( p_sys->i_type )
397         {
398         case LPCM_VOB:
399             VobExtract( p_aout_buffer, p_block, i_bits );
400             break;
401         case LPCM_AOB:
402             AobExtract( p_aout_buffer, p_block, i_bits, p_aob_group );
403             break;
404         default:
405             assert(0);
406         case LPCM_BD:
407             BdExtract( p_aout_buffer, p_block );
408             break;
409         }
410
411         block_Release( p_block );
412         return p_aout_buffer;
413     }
414 }
415
416 /*****************************************************************************
417  * CloseCommon : lpcm decoder destruction
418  *****************************************************************************/
419 static void CloseCommon( vlc_object_t *p_this )
420 {
421     decoder_t *p_dec = (decoder_t*)p_this;
422     free( p_dec->p_sys );
423 }
424
425 /*****************************************************************************
426  * OpenEncoder: lpcm encoder construction
427  *****************************************************************************/
428 static int OpenEncoder( vlc_object_t *p_this )
429 {
430     encoder_t *p_enc = (encoder_t *)p_this;
431     encoder_sys_t *p_sys;
432
433     /* We only support DVD LPCM yet. */
434     if( p_enc->fmt_out.i_codec != VLC_CODEC_DVD_LPCM ||
435         ( p_enc->fmt_in.audio.i_rate != 48000 &&
436           p_enc->fmt_in.audio.i_rate != 96000 &&
437           p_enc->fmt_in.audio.i_rate != 44100 &&
438           p_enc->fmt_in.audio.i_rate != 32000 ) ||
439        p_enc->fmt_in.audio.i_channels > 8 )
440         return VLC_EGENERIC;
441
442     /* Allocate the memory needed to store the encoder's structure */
443     if( ( p_enc->p_sys = p_sys =
444           (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
445         return VLC_ENOMEM;
446
447     p_enc->pf_encode_audio = EncodeFrames;
448     p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec;
449
450     p_enc->fmt_in.audio.i_bitspersample = 16;
451     p_enc->fmt_in.i_codec = VLC_CODEC_S16B;
452
453     p_enc->fmt_out.i_bitrate =
454         p_enc->fmt_in.audio.i_channels *
455         p_enc->fmt_in.audio.i_rate *
456         p_enc->fmt_in.audio.i_bitspersample;
457     
458     p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
459     p_sys->i_rate = p_enc->fmt_in.audio.i_rate;
460     
461     /* In DVD LCPM, a frame is always 150 PTS ticks. */
462     p_sys->i_frame_samples = p_enc->fmt_in.audio.i_rate * 150 / 90000;
463     p_sys->p_buffer = (uint8_t *)malloc(
464         p_sys->i_frame_samples *
465         p_enc->fmt_in.audio.i_channels *
466         p_enc->fmt_in.audio.i_bitspersample);
467     p_sys->i_buffer_used = 0;
468     p_sys->i_frame_num = 0;
469
470     return VLC_SUCCESS;
471 }
472
473 /*****************************************************************************
474  * CloseEncoder: lpcm encoder destruction
475  *****************************************************************************/
476 static void CloseEncoder ( vlc_object_t *p_this )
477 {
478     VLC_UNUSED(p_this);
479 }
480
481 /*****************************************************************************
482  * EncodeFrames: encode zero or more LCPM audio packets
483  *****************************************************************************/
484 static block_t *EncodeFrames( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
485 {
486     encoder_sys_t *p_sys = p_enc->p_sys;
487     block_t *p_first_block = NULL, *p_last_block = NULL;
488
489     if( !p_aout_buf || !p_aout_buf->i_buffer ) return NULL;
490
491     const int i_num_frames = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) /
492         p_sys->i_frame_samples;
493     const int i_leftover_samples = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) %
494         p_sys->i_frame_samples;
495     const int i_frame_size = p_sys->i_frame_samples * p_sys->i_channels * 2 + LPCM_VOB_HEADER_LEN;
496
497     uint8_t i_freq_code = 0;
498
499     switch( p_sys->i_rate ) {
500     case 48000:
501         i_freq_code = 0;
502         break;
503     case 96000:
504         i_freq_code = 1;
505         break;
506     case 44100:
507         i_freq_code = 2;
508         break;
509     case 32000:
510         i_freq_code = 3;
511         break;
512     }
513
514     int i_bytes_consumed = 0;
515
516     for ( int i = 0; i < i_num_frames; ++i )
517     {
518         block_t *p_block = block_New( p_enc, i_frame_size );
519         if( !p_block )
520             return NULL;
521
522         uint8_t *frame = (uint8_t *)p_block->p_buffer;
523         frame[0] = 1;  /* one frame in packet */
524         frame[1] = 0;
525         frame[2] = 0;  /* no first access unit */
526         frame[3] = (p_sys->i_frame_num + i) & 0x1f;  /* no emphasis, no mute */
527         frame[4] = (i_freq_code << 4) | (p_sys->i_channels - 1);
528         frame[5] = 0x80;  /* neutral dynamic range */
529
530         const int i_consume_samples = p_sys->i_frame_samples - p_sys->i_buffer_used;
531         const int i_kept_bytes = p_sys->i_buffer_used * p_sys->i_channels * 2;
532         const int i_consume_bytes = i_consume_samples * p_sys->i_channels * 2;
533
534         memcpy( frame + 6, p_sys->p_buffer, i_kept_bytes );
535         memcpy( frame + 6 + i_kept_bytes, p_aout_buf->p_buffer + i_bytes_consumed, i_consume_bytes );
536      
537         p_sys->i_frame_num++;
538         p_sys->i_buffer_used = 0;
539         i_bytes_consumed += i_consume_bytes;
540
541         /* 
542          * The pts is strictly not correct if we have samples kept from
543          * a previous buffer, but the frames are so small it should be OK.
544          */
545         p_block->i_dts = p_block->i_pts = p_aout_buf->i_pts + i * p_sys->i_frame_samples * CLOCK_FREQ / p_sys->i_rate;
546         p_block->i_length = p_sys->i_frame_samples * CLOCK_FREQ / p_sys->i_rate;
547     
548         if( !p_first_block )
549             p_first_block = p_last_block = p_block;
550         else
551             block_ChainLastAppend( &p_last_block, p_block );
552     }
553
554     memcpy( p_sys->p_buffer,
555             p_aout_buf->p_buffer + i_bytes_consumed,
556             i_leftover_samples * p_sys->i_channels * 2 );
557     p_sys->i_buffer_used = i_leftover_samples;
558
559     return p_first_block;
560 }
561
562 /*****************************************************************************
563  *
564  *****************************************************************************/
565 static int VobHeader( unsigned *pi_rate,
566                       unsigned *pi_channels, unsigned *pi_original_channels,
567                       unsigned *pi_bits,
568                       const uint8_t *p_header )
569 {
570     const uint8_t i_header = p_header[4];
571
572     switch( (i_header >> 4) & 0x3 )
573     {
574     case 0:
575         *pi_rate = 48000;
576         break;
577     case 1:
578         *pi_rate = 96000;
579         break;
580     case 2:
581         *pi_rate = 44100;
582         break;
583     case 3:
584         *pi_rate = 32000;
585         break;
586     }
587
588     *pi_channels = (i_header & 0x7) + 1;
589     switch( *pi_channels - 1 )
590     {
591     case 0:
592         *pi_original_channels = AOUT_CHAN_CENTER;
593         break;
594     case 1:
595         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
596         break;
597     case 2:
598         /* This is unsure. */
599         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
600         break;
601     case 3:
602         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
603                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
604         break;
605     case 4:
606         /* This is unsure. */
607         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
608                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
609                                | AOUT_CHAN_LFE;
610         break;
611     case 5:
612         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
613                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
614                                | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
615         break;
616     case 6:
617         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
618                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
619                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
620                                | AOUT_CHAN_MIDDLERIGHT;
621         break;
622     case 7:
623         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
624                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
625                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
626                                | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
627         break;
628     }
629
630     switch( (i_header >> 6) & 0x3 )
631     {
632     case 2:
633         *pi_bits = 24;
634         break;
635     case 1:
636         *pi_bits = 20;
637         break;
638     case 0:
639     default:
640         *pi_bits = 16;
641         break;
642     }
643
644     /* Check frame sync and drop it. */
645     if( p_header[5] != 0x80 )
646         return -1;
647     return 0;
648 }
649
650 static const unsigned p_aob_group1[21][6] = {
651     { AOUT_CHAN_CENTER, 0 },
652     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
653     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
654     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
655     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
656     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
657     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
658     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
659     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
660     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
661     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
662     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
663     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
664     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
665     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
666     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
667     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
668     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   0 },
669     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
670     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
671     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
672 };
673 static const unsigned p_aob_group2[21][6] = {
674     { 0 },
675     { 0 },
676     { AOUT_CHAN_REARCENTER, 0 },
677     { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
678     { AOUT_CHAN_LFE,        0 },
679     { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
680     { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
681     { AOUT_CHAN_CENTER,     0 },
682     { AOUT_CHAN_CENTER,     AOUT_CHAN_REARCENTER, 0 },
683     { AOUT_CHAN_CENTER,     AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
684     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        0 },
685     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
686     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
687     { AOUT_CHAN_REARCENTER, 0 },
688     { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
689     { AOUT_CHAN_LFE,        0 },
690     { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
691     { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
692     { AOUT_CHAN_LFE,        0 },
693     { AOUT_CHAN_CENTER,     0 },
694     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,          0 },
695 };
696
697 static int AobHeader( unsigned *pi_rate,
698                       unsigned *pi_channels, unsigned *pi_layout,
699                       unsigned *pi_bits,
700                       unsigned *pi_padding,
701                       aob_group_t g[2],
702                       const uint8_t *p_header )
703 {
704     const unsigned i_header_size = GetWBE( &p_header[1] );
705     if( i_header_size + 3 < LPCM_AOB_HEADER_LEN )
706         return VLC_EGENERIC;
707
708     *pi_padding = 3+i_header_size - LPCM_AOB_HEADER_LEN;
709
710     const int i_index_size_g1 = (p_header[6] >> 4) & 0x0f;
711     const int i_index_size_g2 = (p_header[6]     ) & 0x0f;
712     const int i_index_rate_g1 = (p_header[7] >> 4) & 0x0f;
713     const int i_index_rate_g2 = (p_header[7]     ) & 0x0f;
714     const int i_assignment     = p_header[9];
715
716     /* Validate */
717     if( i_index_size_g1 > 0x02 ||
718         ( i_index_size_g2 != 0x0f && i_index_size_g2 > 0x02 ) )
719         return VLC_EGENERIC;
720     if( (i_index_rate_g1 & 0x07) > 0x02 ||
721         ( i_index_rate_g2 != 0x0f && (i_index_rate_g1 & 0x07) > 0x02 ) )
722         return VLC_EGENERIC;
723     if( i_assignment > 20 )
724         return VLC_EGENERIC;
725
726     /* */
727     *pi_bits = 16 + 4 * i_index_size_g1;
728     if( i_index_rate_g1 & 0x08 )
729         *pi_rate = 44100 << (i_index_rate_g1 & 0x07);
730     else
731         *pi_rate = 48000 << (i_index_rate_g1 & 0x07);
732
733
734     /* Group1 */
735     unsigned i_channels1 = 0;
736     unsigned i_layout1 = 0;
737     for( int i = 0; p_aob_group1[i_assignment][i] != 0; i++ )
738     {
739         i_channels1++;
740         i_layout1 |= p_aob_group1[i_assignment][i];
741     }
742     /* Group2 */
743     unsigned i_channels2 = 0;
744     unsigned i_layout2 = 0;
745     if( i_index_size_g2 != 0x0f && i_index_rate_g2 != 0x0f )
746     {
747         for( int i = 0; p_aob_group2[i_assignment][i] != 0; i++ )
748         {
749             i_channels2++;
750             i_layout2 |= p_aob_group2[i_assignment][i];
751         }
752         assert( (i_layout1 & i_layout2) == 0 );
753     }
754     /* It is enabled only when presents and compatible wih group1 */
755     const bool b_group2_used = i_index_size_g1 == i_index_size_g2 &&
756                                i_index_rate_g1 == i_index_rate_g2;
757
758     /* */
759     *pi_channels = i_channels1 + ( b_group2_used ? i_channels2 : 0 );
760     *pi_layout   = i_layout1   | ( b_group2_used ? i_layout2   : 0 );
761
762     /* */
763     for( unsigned i = 0; i < 2; i++ )
764     {
765         const unsigned *p_aob = i == 0 ? p_aob_group1[i_assignment] :
766                                          p_aob_group2[i_assignment];
767         g[i].i_channels = i == 0 ? i_channels1 :
768                                    i_channels2;
769
770         g[i].b_used = i == 0 || b_group2_used;
771         if( !g[i].b_used )
772             continue;
773         for( unsigned j = 0; j < g[i].i_channels; j++ )
774         {
775             g[i].pi_position[j] = 0;
776             for( int k = 0; pi_vlc_chan_order_wg4[k] != 0; k++ )
777             {
778                 const unsigned i_channel = pi_vlc_chan_order_wg4[k];
779                 if( i_channel == p_aob[j] )
780                     break;
781                 if( (*pi_layout) & i_channel )
782                     g[i].pi_position[j]++;
783             }
784         }
785     }
786     return VLC_SUCCESS;
787 }
788
789 static int BdHeader( unsigned *pi_rate,
790                      unsigned *pi_channels, unsigned *pi_original_channels,
791                      unsigned *pi_bits,
792                      const uint8_t *p_header )
793 {
794     const uint32_t h = GetDWBE( p_header );
795     switch( ( h & 0xf000) >> 12 )
796     {
797     case 1:
798         *pi_channels = 1;
799         *pi_original_channels = AOUT_CHAN_CENTER;
800         break;
801     case 3:
802         *pi_channels = 2;
803         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
804         break;
805     case 4:
806         *pi_channels = 3;
807         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER;
808         break;
809     case 5:
810         *pi_channels = 3;
811         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER;
812         break;
813     case 6:
814         *pi_channels = 4;
815         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
816                                 AOUT_CHAN_REARCENTER;
817         break;
818     case 7:
819         *pi_channels = 4;
820         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
821                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
822         break;
823     case 8:
824         *pi_channels = 5;
825         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
826                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
827         break;
828     case 9:
829         *pi_channels = 6;
830         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
831                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
832                                 AOUT_CHAN_LFE;
833         break;
834     case 10:
835         *pi_channels = 7;
836         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
837                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
838                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
839         break;
840     case 11:
841         *pi_channels = 8;
842         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
843                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
844                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
845                                 AOUT_CHAN_LFE;
846         break;
847
848     default:
849         return -1;
850     }
851     switch( (h >> 6) & 0x03 )
852     {
853     case 1:
854         *pi_bits = 16;
855         break;
856     case 2: /* 20 bits but samples are stored on 24 bits */
857     case 3: /* 24 bits */
858         *pi_bits = 24;
859         break;
860     default:
861         return -1;
862     }
863     switch( (h >> 8) & 0x0f ) 
864     {
865     case 1:
866         *pi_rate = 48000;
867         break;
868     case 4:
869         *pi_rate = 96000;
870         break;
871     case 5:
872         *pi_rate = 192000;
873         break;
874     default:
875         return -1;
876     }
877     return 0;
878 }
879
880 static void VobExtract( aout_buffer_t *p_aout_buffer, block_t *p_block,
881                         unsigned i_bits )
882 {
883     uint8_t *p_out = p_aout_buffer->p_buffer;
884
885     /* 20/24 bits LPCM use special packing */
886     if( i_bits == 24 )
887     {
888         while( p_block->i_buffer / 12 )
889         {
890             /* Sample 1 */
891             p_out[0] = p_block->p_buffer[0];
892             p_out[1] = p_block->p_buffer[1];
893             p_out[2] = p_block->p_buffer[8];
894             /* Sample 2 */
895             p_out[3] = p_block->p_buffer[2];
896             p_out[4] = p_block->p_buffer[3];
897             p_out[5] = p_block->p_buffer[9];
898             /* Sample 3 */
899             p_out[6] = p_block->p_buffer[4];
900             p_out[7] = p_block->p_buffer[5];
901             p_out[8] = p_block->p_buffer[10];
902             /* Sample 4 */
903             p_out[9] = p_block->p_buffer[6];
904             p_out[10] = p_block->p_buffer[7];
905             p_out[11] = p_block->p_buffer[11];
906
907             p_block->i_buffer -= 12;
908             p_block->p_buffer += 12;
909             p_out += 12;
910         }
911     }
912     else if( i_bits == 20 )
913     {
914         while( p_block->i_buffer / 10 )
915         {
916             /* Sample 1 */
917             p_out[0] = p_block->p_buffer[0];
918             p_out[1] = p_block->p_buffer[1];
919             p_out[2] = p_block->p_buffer[8] & 0xF0;
920             /* Sample 2 */
921             p_out[3] = p_block->p_buffer[2];
922             p_out[4] = p_block->p_buffer[3];
923             p_out[5] = p_block->p_buffer[8] << 4;
924             /* Sample 3 */
925             p_out[6] = p_block->p_buffer[4];
926             p_out[7] = p_block->p_buffer[5];
927             p_out[8] = p_block->p_buffer[9] & 0xF0;
928             /* Sample 4 */
929             p_out[9] = p_block->p_buffer[6];
930             p_out[10] = p_block->p_buffer[7];
931             p_out[11] = p_block->p_buffer[9] << 4;
932
933             p_block->i_buffer -= 10;
934             p_block->p_buffer += 10;
935             p_out += 12;
936         }
937     }
938     else
939     {
940         assert( i_bits == 16 );
941         memcpy( p_out, p_block->p_buffer, p_block->i_buffer );
942     }
943 }
944 static void AobExtract( aout_buffer_t *p_aout_buffer,
945                         block_t *p_block, unsigned i_bits, aob_group_t p_group[2] )
946 {
947     const unsigned i_channels = p_group[0].i_channels +
948                                 ( p_group[1].b_used ? p_group[1].i_channels : 0 );
949     uint8_t *p_out = p_aout_buffer->p_buffer;
950
951     while( p_block->i_buffer > 0 )
952     {
953         for( int i = 0; i < 2; i++ )
954         {
955             const aob_group_t *g = &p_group[1-i];
956             const unsigned int i_group_size = 2 * g->i_channels * i_bits / 8;
957
958             if( p_block->i_buffer < i_group_size )
959             {
960                 p_block->i_buffer = 0;
961                 break;
962             }
963             for( unsigned n = 0; n < 2; n++ )
964             {
965                 for( unsigned j = 0; j < g->i_channels && g->b_used; j++ )
966                 {
967                     const int i_src = n * g->i_channels + j;
968                     const int i_dst = n * i_channels + g->pi_position[j];
969
970                     if( i_bits == 24 )
971                     {
972                         p_out[3*i_dst+0] = p_block->p_buffer[2*i_src+0];
973                         p_out[3*i_dst+1] = p_block->p_buffer[2*i_src+1];
974                         p_out[3*i_dst+2] = p_block->p_buffer[4*g->i_channels+i_src];
975                     }
976                     else if( i_bits == 20 )
977                     {
978                         p_out[3*i_dst+0] = p_block->p_buffer[2*i_src+0];
979                         p_out[3*i_dst+1] = p_block->p_buffer[2*i_src+1];
980                         if( n == 0 )
981                             p_out[3*i_dst+2] = (p_block->p_buffer[4*g->i_channels+i_src]     ) & 0xf0;
982                         else
983                             p_out[3*i_dst+2] = (p_block->p_buffer[4*g->i_channels+i_src] << 4) & 0xf0;
984                     }
985                     else
986                     {
987                         assert( i_bits == 16 );
988                         p_out[2*i_dst+0] = p_block->p_buffer[2*i_src+0];
989                         p_out[2*i_dst+1] = p_block->p_buffer[2*i_src+1];
990                     }
991                 }
992             }
993
994             p_block->i_buffer -= i_group_size;
995             p_block->p_buffer += i_group_size;
996         }
997         /* */
998         p_out += (i_bits == 16 ? 2 : 3) * i_channels * 2;
999
1000     }
1001 }
1002 static void BdExtract( aout_buffer_t *p_aout_buffer, block_t *p_block )
1003 {
1004     memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer );
1005 }
1006