]> git.sesse.net Git - vlc/blob - modules/codec/lpcm.c
block_ChainLastAppend is just weird; a simple pointer dereference instead.
[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     const int i_start_offset = -p_sys->i_buffer_used;
497
498     uint8_t i_freq_code = 0;
499
500     switch( p_sys->i_rate ) {
501     case 48000:
502         i_freq_code = 0;
503         break;
504     case 96000:
505         i_freq_code = 1;
506         break;
507     case 44100:
508         i_freq_code = 2;
509         break;
510     case 32000:
511         i_freq_code = 3;
512         break;
513     }
514
515     int i_bytes_consumed = 0;
516
517     for ( int i = 0; i < i_num_frames; ++i )
518     {
519         block_t *p_block = block_New( p_enc, i_frame_size );
520         if( !p_block )
521             return NULL;
522
523         uint8_t *frame = (uint8_t *)p_block->p_buffer;
524         frame[0] = 1;  /* one frame in packet */
525         frame[1] = 0;
526         frame[2] = 0;  /* no first access unit */
527         frame[3] = (p_sys->i_frame_num + i) & 0x1f;  /* no emphasis, no mute */
528         frame[4] = (i_freq_code << 4) | (p_sys->i_channels - 1);
529         frame[5] = 0x80;  /* neutral dynamic range */
530
531         const int i_consume_samples = p_sys->i_frame_samples - p_sys->i_buffer_used;
532         const int i_kept_bytes = p_sys->i_buffer_used * p_sys->i_channels * 2;
533         const int i_consume_bytes = i_consume_samples * p_sys->i_channels * 2;
534
535         memcpy( frame + 6, p_sys->p_buffer, i_kept_bytes );
536         memcpy( frame + 6 + i_kept_bytes, p_aout_buf->p_buffer + i_bytes_consumed, i_consume_bytes );
537      
538         p_sys->i_frame_num++;
539         p_sys->i_buffer_used = 0;
540         i_bytes_consumed += i_consume_bytes;
541
542         p_block->i_dts = p_block->i_pts = p_aout_buf->i_pts +
543             (i * p_sys->i_frame_samples + i_start_offset) * CLOCK_FREQ / p_sys->i_rate;
544         p_block->i_length = p_sys->i_frame_samples * CLOCK_FREQ / p_sys->i_rate;
545     
546         if( !p_first_block )
547             p_first_block = p_last_block = p_block;
548         else
549             p_last_block = p_last_block->p_next = p_block;
550     }
551
552     memcpy( p_sys->p_buffer,
553             p_aout_buf->p_buffer + i_bytes_consumed,
554             i_leftover_samples * p_sys->i_channels * 2 );
555     p_sys->i_buffer_used = i_leftover_samples;
556
557     return p_first_block;
558 }
559
560 /*****************************************************************************
561  *
562  *****************************************************************************/
563 static int VobHeader( unsigned *pi_rate,
564                       unsigned *pi_channels, unsigned *pi_original_channels,
565                       unsigned *pi_bits,
566                       const uint8_t *p_header )
567 {
568     const uint8_t i_header = p_header[4];
569
570     switch( (i_header >> 4) & 0x3 )
571     {
572     case 0:
573         *pi_rate = 48000;
574         break;
575     case 1:
576         *pi_rate = 96000;
577         break;
578     case 2:
579         *pi_rate = 44100;
580         break;
581     case 3:
582         *pi_rate = 32000;
583         break;
584     }
585
586     *pi_channels = (i_header & 0x7) + 1;
587     switch( *pi_channels - 1 )
588     {
589     case 0:
590         *pi_original_channels = AOUT_CHAN_CENTER;
591         break;
592     case 1:
593         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
594         break;
595     case 2:
596         /* This is unsure. */
597         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
598         break;
599     case 3:
600         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
601                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
602         break;
603     case 4:
604         /* This is unsure. */
605         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
606                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
607                                | AOUT_CHAN_LFE;
608         break;
609     case 5:
610         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
611                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
612                                | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
613         break;
614     case 6:
615         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
616                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
617                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
618                                | AOUT_CHAN_MIDDLERIGHT;
619         break;
620     case 7:
621         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
622                                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
623                                | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
624                                | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
625         break;
626     }
627
628     switch( (i_header >> 6) & 0x3 )
629     {
630     case 2:
631         *pi_bits = 24;
632         break;
633     case 1:
634         *pi_bits = 20;
635         break;
636     case 0:
637     default:
638         *pi_bits = 16;
639         break;
640     }
641
642     /* Check frame sync and drop it. */
643     if( p_header[5] != 0x80 )
644         return -1;
645     return 0;
646 }
647
648 static const unsigned p_aob_group1[21][6] = {
649     { AOUT_CHAN_CENTER, 0 },
650     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 0 },
651     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, 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, AOUT_CHAN_CENTER,   0 },
663     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,   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_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
668     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
669     { AOUT_CHAN_LEFT,   AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0  },
670 };
671 static const unsigned p_aob_group2[21][6] = {
672     { 0 },
673     { 0 },
674     { AOUT_CHAN_REARCENTER, 0 },
675     { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
676     { AOUT_CHAN_LFE,        0 },
677     { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
678     { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
679     { AOUT_CHAN_CENTER,     0 },
680     { AOUT_CHAN_CENTER,     AOUT_CHAN_REARCENTER, 0 },
681     { AOUT_CHAN_CENTER,     AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
682     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        0 },
683     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
684     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
685     { AOUT_CHAN_REARCENTER, 0 },
686     { AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,    0 },
687     { AOUT_CHAN_LFE,        0 },
688     { AOUT_CHAN_LFE,        AOUT_CHAN_REARCENTER,   0 },
689     { AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT,     AOUT_CHAN_REARRIGHT,    0 },
690     { AOUT_CHAN_LFE,        0 },
691     { AOUT_CHAN_CENTER,     0 },
692     { AOUT_CHAN_CENTER,     AOUT_CHAN_LFE,          0 },
693 };
694
695 static int AobHeader( unsigned *pi_rate,
696                       unsigned *pi_channels, unsigned *pi_layout,
697                       unsigned *pi_bits,
698                       unsigned *pi_padding,
699                       aob_group_t g[2],
700                       const uint8_t *p_header )
701 {
702     const unsigned i_header_size = GetWBE( &p_header[1] );
703     if( i_header_size + 3 < LPCM_AOB_HEADER_LEN )
704         return VLC_EGENERIC;
705
706     *pi_padding = 3+i_header_size - LPCM_AOB_HEADER_LEN;
707
708     const int i_index_size_g1 = (p_header[6] >> 4) & 0x0f;
709     const int i_index_size_g2 = (p_header[6]     ) & 0x0f;
710     const int i_index_rate_g1 = (p_header[7] >> 4) & 0x0f;
711     const int i_index_rate_g2 = (p_header[7]     ) & 0x0f;
712     const int i_assignment     = p_header[9];
713
714     /* Validate */
715     if( i_index_size_g1 > 0x02 ||
716         ( i_index_size_g2 != 0x0f && i_index_size_g2 > 0x02 ) )
717         return VLC_EGENERIC;
718     if( (i_index_rate_g1 & 0x07) > 0x02 ||
719         ( i_index_rate_g2 != 0x0f && (i_index_rate_g1 & 0x07) > 0x02 ) )
720         return VLC_EGENERIC;
721     if( i_assignment > 20 )
722         return VLC_EGENERIC;
723
724     /* */
725     *pi_bits = 16 + 4 * i_index_size_g1;
726     if( i_index_rate_g1 & 0x08 )
727         *pi_rate = 44100 << (i_index_rate_g1 & 0x07);
728     else
729         *pi_rate = 48000 << (i_index_rate_g1 & 0x07);
730
731
732     /* Group1 */
733     unsigned i_channels1 = 0;
734     unsigned i_layout1 = 0;
735     for( int i = 0; p_aob_group1[i_assignment][i] != 0; i++ )
736     {
737         i_channels1++;
738         i_layout1 |= p_aob_group1[i_assignment][i];
739     }
740     /* Group2 */
741     unsigned i_channels2 = 0;
742     unsigned i_layout2 = 0;
743     if( i_index_size_g2 != 0x0f && i_index_rate_g2 != 0x0f )
744     {
745         for( int i = 0; p_aob_group2[i_assignment][i] != 0; i++ )
746         {
747             i_channels2++;
748             i_layout2 |= p_aob_group2[i_assignment][i];
749         }
750         assert( (i_layout1 & i_layout2) == 0 );
751     }
752     /* It is enabled only when presents and compatible wih group1 */
753     const bool b_group2_used = i_index_size_g1 == i_index_size_g2 &&
754                                i_index_rate_g1 == i_index_rate_g2;
755
756     /* */
757     *pi_channels = i_channels1 + ( b_group2_used ? i_channels2 : 0 );
758     *pi_layout   = i_layout1   | ( b_group2_used ? i_layout2   : 0 );
759
760     /* */
761     for( unsigned i = 0; i < 2; i++ )
762     {
763         const unsigned *p_aob = i == 0 ? p_aob_group1[i_assignment] :
764                                          p_aob_group2[i_assignment];
765         g[i].i_channels = i == 0 ? i_channels1 :
766                                    i_channels2;
767
768         g[i].b_used = i == 0 || b_group2_used;
769         if( !g[i].b_used )
770             continue;
771         for( unsigned j = 0; j < g[i].i_channels; j++ )
772         {
773             g[i].pi_position[j] = 0;
774             for( int k = 0; pi_vlc_chan_order_wg4[k] != 0; k++ )
775             {
776                 const unsigned i_channel = pi_vlc_chan_order_wg4[k];
777                 if( i_channel == p_aob[j] )
778                     break;
779                 if( (*pi_layout) & i_channel )
780                     g[i].pi_position[j]++;
781             }
782         }
783     }
784     return VLC_SUCCESS;
785 }
786
787 static int BdHeader( unsigned *pi_rate,
788                      unsigned *pi_channels, unsigned *pi_original_channels,
789                      unsigned *pi_bits,
790                      const uint8_t *p_header )
791 {
792     const uint32_t h = GetDWBE( p_header );
793     switch( ( h & 0xf000) >> 12 )
794     {
795     case 1:
796         *pi_channels = 1;
797         *pi_original_channels = AOUT_CHAN_CENTER;
798         break;
799     case 3:
800         *pi_channels = 2;
801         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
802         break;
803     case 4:
804         *pi_channels = 3;
805         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER;
806         break;
807     case 5:
808         *pi_channels = 3;
809         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER;
810         break;
811     case 6:
812         *pi_channels = 4;
813         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
814                                 AOUT_CHAN_REARCENTER;
815         break;
816     case 7:
817         *pi_channels = 4;
818         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
819                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
820         break;
821     case 8:
822         *pi_channels = 5;
823         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
824                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
825         break;
826     case 9:
827         *pi_channels = 6;
828         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
829                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
830                                 AOUT_CHAN_LFE;
831         break;
832     case 10:
833         *pi_channels = 7;
834         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
835                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
836                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
837         break;
838     case 11:
839         *pi_channels = 8;
840         *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
841                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
842                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
843                                 AOUT_CHAN_LFE;
844         break;
845
846     default:
847         return -1;
848     }
849     switch( (h >> 6) & 0x03 )
850     {
851     case 1:
852         *pi_bits = 16;
853         break;
854     case 2: /* 20 bits but samples are stored on 24 bits */
855     case 3: /* 24 bits */
856         *pi_bits = 24;
857         break;
858     default:
859         return -1;
860     }
861     switch( (h >> 8) & 0x0f ) 
862     {
863     case 1:
864         *pi_rate = 48000;
865         break;
866     case 4:
867         *pi_rate = 96000;
868         break;
869     case 5:
870         *pi_rate = 192000;
871         break;
872     default:
873         return -1;
874     }
875     return 0;
876 }
877
878 static void VobExtract( aout_buffer_t *p_aout_buffer, block_t *p_block,
879                         unsigned i_bits )
880 {
881     uint8_t *p_out = p_aout_buffer->p_buffer;
882
883     /* 20/24 bits LPCM use special packing */
884     if( i_bits == 24 )
885     {
886         while( p_block->i_buffer / 12 )
887         {
888             /* Sample 1 */
889             p_out[0] = p_block->p_buffer[0];
890             p_out[1] = p_block->p_buffer[1];
891             p_out[2] = p_block->p_buffer[8];
892             /* Sample 2 */
893             p_out[3] = p_block->p_buffer[2];
894             p_out[4] = p_block->p_buffer[3];
895             p_out[5] = p_block->p_buffer[9];
896             /* Sample 3 */
897             p_out[6] = p_block->p_buffer[4];
898             p_out[7] = p_block->p_buffer[5];
899             p_out[8] = p_block->p_buffer[10];
900             /* Sample 4 */
901             p_out[9] = p_block->p_buffer[6];
902             p_out[10] = p_block->p_buffer[7];
903             p_out[11] = p_block->p_buffer[11];
904
905             p_block->i_buffer -= 12;
906             p_block->p_buffer += 12;
907             p_out += 12;
908         }
909     }
910     else if( i_bits == 20 )
911     {
912         while( p_block->i_buffer / 10 )
913         {
914             /* Sample 1 */
915             p_out[0] = p_block->p_buffer[0];
916             p_out[1] = p_block->p_buffer[1];
917             p_out[2] = p_block->p_buffer[8] & 0xF0;
918             /* Sample 2 */
919             p_out[3] = p_block->p_buffer[2];
920             p_out[4] = p_block->p_buffer[3];
921             p_out[5] = p_block->p_buffer[8] << 4;
922             /* Sample 3 */
923             p_out[6] = p_block->p_buffer[4];
924             p_out[7] = p_block->p_buffer[5];
925             p_out[8] = p_block->p_buffer[9] & 0xF0;
926             /* Sample 4 */
927             p_out[9] = p_block->p_buffer[6];
928             p_out[10] = p_block->p_buffer[7];
929             p_out[11] = p_block->p_buffer[9] << 4;
930
931             p_block->i_buffer -= 10;
932             p_block->p_buffer += 10;
933             p_out += 12;
934         }
935     }
936     else
937     {
938         assert( i_bits == 16 );
939         memcpy( p_out, p_block->p_buffer, p_block->i_buffer );
940     }
941 }
942 static void AobExtract( aout_buffer_t *p_aout_buffer,
943                         block_t *p_block, unsigned i_bits, aob_group_t p_group[2] )
944 {
945     const unsigned i_channels = p_group[0].i_channels +
946                                 ( p_group[1].b_used ? p_group[1].i_channels : 0 );
947     uint8_t *p_out = p_aout_buffer->p_buffer;
948
949     while( p_block->i_buffer > 0 )
950     {
951         for( int i = 0; i < 2; i++ )
952         {
953             const aob_group_t *g = &p_group[1-i];
954             const unsigned int i_group_size = 2 * g->i_channels * i_bits / 8;
955
956             if( p_block->i_buffer < i_group_size )
957             {
958                 p_block->i_buffer = 0;
959                 break;
960             }
961             for( unsigned n = 0; n < 2; n++ )
962             {
963                 for( unsigned j = 0; j < g->i_channels && g->b_used; j++ )
964                 {
965                     const int i_src = n * g->i_channels + j;
966                     const int i_dst = n * i_channels + g->pi_position[j];
967
968                     if( i_bits == 24 )
969                     {
970                         p_out[3*i_dst+0] = p_block->p_buffer[2*i_src+0];
971                         p_out[3*i_dst+1] = p_block->p_buffer[2*i_src+1];
972                         p_out[3*i_dst+2] = p_block->p_buffer[4*g->i_channels+i_src];
973                     }
974                     else if( i_bits == 20 )
975                     {
976                         p_out[3*i_dst+0] = p_block->p_buffer[2*i_src+0];
977                         p_out[3*i_dst+1] = p_block->p_buffer[2*i_src+1];
978                         if( n == 0 )
979                             p_out[3*i_dst+2] = (p_block->p_buffer[4*g->i_channels+i_src]     ) & 0xf0;
980                         else
981                             p_out[3*i_dst+2] = (p_block->p_buffer[4*g->i_channels+i_src] << 4) & 0xf0;
982                     }
983                     else
984                     {
985                         assert( i_bits == 16 );
986                         p_out[2*i_dst+0] = p_block->p_buffer[2*i_src+0];
987                         p_out[2*i_dst+1] = p_block->p_buffer[2*i_src+1];
988                     }
989                 }
990             }
991
992             p_block->i_buffer -= i_group_size;
993             p_block->p_buffer += i_group_size;
994         }
995         /* */
996         p_out += (i_bits == 16 ? 2 : 3) * i_channels * 2;
997
998     }
999 }
1000 static void BdExtract( aout_buffer_t *p_aout_buffer, block_t *p_block )
1001 {
1002     memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer );
1003 }
1004