]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
Merge branch 1.0-bugfix into master
[vlc] / modules / codec / dts.c
1 /*****************************************************************************
2  * dts.c: parse DTS audio sync info and packetize the stream
3  *****************************************************************************
4  * Copyright (C) 2003-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
36 #include <vlc_aout.h>
37 #include <vlc_block_helper.h>
38 #include <vlc_bits.h>
39
40 /*****************************************************************************
41  * Module descriptor
42  *****************************************************************************/
43 static int  OpenDecoder   ( vlc_object_t * );
44 static int  OpenPacketizer( vlc_object_t * );
45 static void CloseCommon   ( vlc_object_t * );
46
47 vlc_module_begin ()
48     set_description( N_("DTS parser") )
49     set_capability( "decoder", 100 )
50     set_callbacks( OpenDecoder, CloseCommon )
51
52     add_submodule ()
53     set_description( N_("DTS audio packetizer") )
54     set_capability( "packetizer", 10 )
55     set_callbacks( OpenPacketizer, CloseCommon )
56 vlc_module_end ()
57
58 /*****************************************************************************
59  * decoder_sys_t : decoder descriptor
60  *****************************************************************************/
61 struct decoder_sys_t
62 {
63     /* Module mode */
64     bool b_packetizer;
65
66     /*
67      * Input properties
68      */
69     int i_state;
70
71     block_bytestream_t bytestream;
72
73     /*
74      * Common properties
75      */
76     audio_date_t   end_date;
77
78     mtime_t i_pts;
79
80     bool         b_dts_hd;  /* Is the current frame a DTS HD one */
81     unsigned int i_bit_rate;
82     unsigned int i_frame_size;
83     unsigned int i_frame_length;
84     unsigned int i_rate;
85     unsigned int i_channels;
86     unsigned int i_channels_conf;
87 };
88
89 enum {
90
91     STATE_NOSYNC,
92     STATE_SYNC,
93     STATE_HEADER,
94     STATE_NEXT_SYNC,
95     STATE_GET_DATA,
96     STATE_SEND_DATA
97 };
98
99 #define DTS_HEADER_SIZE 14
100
101 /****************************************************************************
102  * Local prototypes
103  ****************************************************************************/
104 static int OpenCommon( vlc_object_t *, bool b_packetizer );
105 static void *DecodeBlock( decoder_t *, block_t ** );
106
107 static inline int SyncCode( const uint8_t * );
108 static int  SyncInfo( const uint8_t *, bool *, unsigned int *, unsigned int *,
109                       unsigned int *, unsigned int *, unsigned int * );
110
111 static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
112 static aout_buffer_t *GetAoutBuffer( decoder_t * );
113 static block_t       *GetSoutBuffer( decoder_t * );
114
115 /*****************************************************************************
116  * OpenDecoder: probe the decoder
117  *****************************************************************************/
118 static int OpenDecoder( vlc_object_t *p_this )
119 {
120     /* HACK: Don't use this codec if we don't have an dts audio filter */
121     if( !module_exists( "dtstofloat32" ) )
122         return VLC_EGENERIC;
123
124     return OpenCommon( p_this, false );
125 }
126
127 /*****************************************************************************
128  * OpenPacketizer: probe the packetizer
129  *****************************************************************************/
130 static int OpenPacketizer( vlc_object_t *p_this )
131 {
132     return OpenCommon( p_this, true );
133 }
134
135 /*****************************************************************************
136  * OpenCommon:
137  *****************************************************************************/
138 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
139 {
140     decoder_t *p_dec = (decoder_t*)p_this;
141     decoder_sys_t *p_sys;
142
143     if( p_dec->fmt_in.i_codec != VLC_CODEC_DTS )
144         return VLC_EGENERIC;
145
146     /* Allocate the memory needed to store the decoder's structure */
147     if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
148         return VLC_ENOMEM;
149
150     /* Misc init */
151     p_sys->b_packetizer = b_packetizer;
152     p_sys->i_state = STATE_NOSYNC;
153     aout_DateSet( &p_sys->end_date, 0 );
154     p_sys->b_dts_hd = false;
155
156     p_sys->bytestream = block_BytestreamInit();
157
158     /* Set output properties */
159     p_dec->fmt_out.i_cat = AUDIO_ES;
160     p_dec->fmt_out.i_codec = VLC_CODEC_DTS;
161     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
162
163     /* Set callback */
164     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
165         DecodeBlock;
166     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
167         DecodeBlock;
168
169     return VLC_SUCCESS;
170 }
171
172 /****************************************************************************
173  * DecodeBlock: the whole thing
174  ****************************************************************************/
175 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
176 {
177     decoder_sys_t *p_sys = p_dec->p_sys;
178     uint8_t p_header[DTS_HEADER_SIZE];
179     uint8_t *p_buf;
180     void *p_out_buffer;
181
182     if( !pp_block || !*pp_block )
183         return NULL;
184
185     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
186     {
187         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
188         {
189             p_sys->i_state = STATE_NOSYNC;
190             block_BytestreamEmpty( &p_sys->bytestream );
191         }
192         aout_DateSet( &p_sys->end_date, 0 );
193         block_Release( *pp_block );
194         return NULL;
195     }
196
197     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
198     {
199         /* We've just started the stream, wait for the first PTS. */
200         block_Release( *pp_block );
201         return NULL;
202     }
203
204     block_BytestreamPush( &p_sys->bytestream, *pp_block );
205
206     while( 1 )
207     {
208         switch( p_sys->i_state )
209         {
210         case STATE_NOSYNC:
211             /* Look for sync code - should be 0x7ffe8001 */
212             while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
213                    == VLC_SUCCESS )
214             {
215                 if( SyncCode( p_header ) == VLC_SUCCESS )
216                 {
217                     p_sys->i_state = STATE_SYNC;
218                     break;
219                 }
220                 block_SkipByte( &p_sys->bytestream );
221             }
222             if( p_sys->i_state != STATE_SYNC )
223             {
224                 block_BytestreamFlush( &p_sys->bytestream );
225
226                 /* Need more data */
227                 return NULL;
228             }
229
230         case STATE_SYNC:
231             /* New frame, set the Presentation Time Stamp */
232             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
233             if( p_sys->i_pts != 0 &&
234                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
235             {
236                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
237             }
238             p_sys->i_state = STATE_HEADER;
239
240         case STATE_HEADER:
241             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
242             if( block_PeekBytes( &p_sys->bytestream, p_header,
243                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
244             {
245                 /* Need more data */
246                 return NULL;
247             }
248
249             /* Check if frame is valid and get frame info */
250             p_sys->i_frame_size = SyncInfo( p_header,
251                                             &p_sys->b_dts_hd,
252                                             &p_sys->i_channels,
253                                             &p_sys->i_channels_conf,
254                                             &p_sys->i_rate,
255                                             &p_sys->i_bit_rate,
256                                             &p_sys->i_frame_length );
257             if( !p_sys->i_frame_size )
258             {
259                 msg_Dbg( p_dec, "emulated sync word" );
260                 block_SkipByte( &p_sys->bytestream );
261                 p_sys->i_state = STATE_NOSYNC;
262                 break;
263             }
264             p_sys->i_state = STATE_NEXT_SYNC;
265
266         case STATE_NEXT_SYNC:
267             /* TODO: If pp_block == NULL, flush the buffer without checking the
268              * next sync word */
269
270             /* Check if next expected frame contains the sync word */
271             if( block_PeekOffsetBytes( &p_sys->bytestream,
272                                        p_sys->i_frame_size, p_header, 6 )
273                 != VLC_SUCCESS )
274             {
275                 /* Need more data */
276                 return NULL;
277             }
278
279             if( SyncCode( p_header ) != VLC_SUCCESS )
280             {
281                 msg_Dbg( p_dec, "emulated sync word "
282                          "(no sync on following frame): %2.2x%2.2x%2.2x%2.2x",
283                          (int)p_header[0], (int)p_header[1],
284                          (int)p_header[2], (int)p_header[3] );
285                 p_sys->i_state = STATE_NOSYNC;
286                 block_SkipByte( &p_sys->bytestream );
287                 break;
288             }
289             p_sys->i_state = STATE_SEND_DATA;
290             break;
291
292         case STATE_GET_DATA:
293             /* Make sure we have enough data.
294              * (Not useful if we went through NEXT_SYNC) */
295             if( block_WaitBytes( &p_sys->bytestream,
296                                  p_sys->i_frame_size ) != VLC_SUCCESS )
297             {
298                 /* Need more data */
299                 return NULL;
300             }
301             p_sys->i_state = STATE_SEND_DATA;
302
303         case STATE_SEND_DATA:
304             if( p_sys->b_dts_hd  )
305             {
306                 /* Ignore DTS-HD */
307                 block_SkipBytes( &p_sys->bytestream, p_sys->i_frame_size );
308                 p_sys->i_state = STATE_NOSYNC;
309                 break;
310             }
311
312             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
313             {
314                 //p_dec->b_error = true;
315                 return NULL;
316             }
317
318             /* Copy the whole frame into the buffer. When we reach this point
319              * we already know we have enough data available. */
320             block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
321
322             /* Make sure we don't reuse the same pts twice */
323             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
324                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
325
326             p_sys->i_state = STATE_NOSYNC;
327
328             /* So p_block doesn't get re-added several times */
329             *pp_block = block_BytestreamPop( &p_sys->bytestream );
330
331             return p_out_buffer;
332         }
333     }
334
335     return NULL;
336 }
337
338 /*****************************************************************************
339  * CloseCommon: clean up the decoder
340  *****************************************************************************/
341 static void CloseCommon( vlc_object_t *p_this )
342 {
343     decoder_t *p_dec = (decoder_t*)p_this;
344     decoder_sys_t *p_sys = p_dec->p_sys;
345
346     block_BytestreamRelease( &p_sys->bytestream );
347
348     free( p_sys );
349 }
350
351 /*****************************************************************************
352  * GetOutBuffer:
353  *****************************************************************************/
354 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
355 {
356     decoder_sys_t *p_sys = p_dec->p_sys;
357     uint8_t *p_buf;
358
359     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
360     {
361         msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
362                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
363
364         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
365         aout_DateSet( &p_sys->end_date, p_sys->i_pts );
366     }
367
368     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
369     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
370     /* Hack for DTS S/PDIF filter which needs to pad the DTS frames */
371     p_dec->fmt_out.audio.i_bytes_per_frame =
372         __MAX( p_sys->i_frame_size, p_sys->i_frame_length * 4 );
373     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
374
375     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
376     p_dec->fmt_out.audio.i_physical_channels =
377         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
378
379     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
380
381     if( p_sys->b_packetizer )
382     {
383         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
384         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
385         *pp_out_buffer = p_sout_buffer;
386     }
387     else
388     {
389         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
390         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
391         *pp_out_buffer = p_aout_buffer;
392     }
393
394     return p_buf;
395 }
396
397 /*****************************************************************************
398  * GetAoutBuffer:
399  *****************************************************************************/
400 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
401 {
402     decoder_sys_t *p_sys = p_dec->p_sys;
403     aout_buffer_t *p_buf;
404
405     /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time
406      * (plus a few header bytes) */
407     p_buf = decoder_NewAudioBuffer( p_dec, p_sys->i_frame_length * 4 );
408     if( p_buf == NULL ) return NULL;
409     p_buf->i_nb_samples = p_sys->i_frame_length;
410     p_buf->i_nb_bytes = p_sys->i_frame_size;
411
412     p_buf->start_date = aout_DateGet( &p_sys->end_date );
413     p_buf->end_date =
414         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
415
416     return p_buf;
417 }
418
419 /*****************************************************************************
420  * GetSoutBuffer:
421  *****************************************************************************/
422 static block_t *GetSoutBuffer( decoder_t *p_dec )
423 {
424     decoder_sys_t *p_sys = p_dec->p_sys;
425     block_t *p_block;
426
427     p_block = block_New( p_dec, p_sys->i_frame_size );
428     if( p_block == NULL ) return NULL;
429
430     p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
431
432     p_block->i_length = aout_DateIncrement( &p_sys->end_date,
433         p_sys->i_frame_length ) - p_block->i_pts;
434
435     return p_block;
436 }
437
438 /*****************************************************************************
439  * SyncInfo: parse DTS sync info
440  *****************************************************************************/
441 static const unsigned int ppi_dts_samplerate[] =
442 {
443     0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
444     12000, 24000, 48000, 96000, 192000
445 };
446
447 static const unsigned int ppi_dts_bitrate[] =
448 {
449     32000, 56000, 64000, 96000, 112000, 128000,
450     192000, 224000, 256000, 320000, 384000,
451     448000, 512000, 576000, 640000, 768000,
452     896000, 1024000, 1152000, 1280000, 1344000,
453     1408000, 1411200, 1472000, 1536000, 1920000,
454     2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/
455 };
456
457 static int SyncInfo16be( const uint8_t *p_buf,
458                          unsigned int *pi_audio_mode,
459                          unsigned int *pi_sample_rate,
460                          unsigned int *pi_bit_rate,
461                          unsigned int *pi_frame_length )
462 {
463     unsigned int i_frame_size;
464     unsigned int i_lfe;
465
466     *pi_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
467     i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
468                    (p_buf[7] >> 4);
469
470     *pi_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
471     *pi_sample_rate = (p_buf[8] >> 2) & 0x0f;
472     *pi_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
473
474     i_lfe = (p_buf[10] >> 1) & 0x03;
475     if( i_lfe ) *pi_audio_mode |= 0x10000;
476
477     return i_frame_size + 1;
478 }
479
480 static void BufLeToBe( uint8_t *p_out, const uint8_t *p_in, int i_in )
481 {
482     int i;
483
484     for( i = 0; i < i_in/2; i++  )
485     {
486         p_out[i*2] = p_in[i*2+1];
487         p_out[i*2+1] = p_in[i*2];
488     }
489 }
490
491 static int Buf14To16( uint8_t *p_out, const uint8_t *p_in, int i_in, int i_le )
492 {
493     unsigned char tmp, cur = 0;
494     int bits_in, bits_out = 0;
495     int i, i_out = 0;
496
497     for( i = 0; i < i_in; i++  )
498     {
499         if( i%2 )
500         {
501             tmp = p_in[i-i_le];
502             bits_in = 8;
503         }
504         else
505         {
506             tmp = p_in[i+i_le] & 0x3F;
507             bits_in = 8 - 2;
508         }
509
510         if( bits_out < 8 )
511         {
512             int need = __MIN( 8 - bits_out, bits_in );
513             cur <<= need;
514             cur |= ( tmp >> (bits_in - need) );
515             tmp <<= (8 - bits_in + need);
516             tmp >>= (8 - bits_in + need);
517             bits_in -= need;
518             bits_out += need;
519         }
520
521         if( bits_out == 8 )
522         {
523             p_out[i_out] = cur;
524             cur = 0;
525             bits_out = 0;
526             i_out++;
527         }
528
529         bits_out += bits_in;
530         cur <<= bits_in;
531         cur |= tmp;
532     }
533
534     return i_out;
535 }
536
537 static inline int SyncCode( const uint8_t *p_buf )
538 {
539     /* 14 bits, little endian version of the bitstream */
540     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
541         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
542         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
543     {
544         return VLC_SUCCESS;
545     }
546     /* 14 bits, big endian version of the bitstream */
547     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
548              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
549              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
550     {
551         return VLC_SUCCESS;
552     }
553     /* 16 bits, big endian version of the bitstream */
554     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
555              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
556     {
557         return VLC_SUCCESS;
558     }
559     /* 16 bits, little endian version of the bitstream */
560     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
561              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
562     {
563         return VLC_SUCCESS;
564     }
565     /* DTS-HD */
566     else if( p_buf[0] == 0x64 && p_buf[1] ==  0x58 &&
567              p_buf[2] == 0x20 && p_buf[3] ==  0x25 )
568     {
569         return VLC_SUCCESS;
570     }
571
572     return VLC_EGENERIC;
573 }
574
575 static int SyncInfo( const uint8_t *p_buf,
576                      bool *pb_dts_hd,
577                      unsigned int *pi_channels,
578                      unsigned int *pi_channels_conf,
579                      unsigned int *pi_sample_rate,
580                      unsigned int *pi_bit_rate,
581                      unsigned int *pi_frame_length )
582 {
583     unsigned int i_audio_mode;
584     unsigned int i_frame_size;
585
586     /* 14 bits, little endian version of the bitstream */
587     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
588         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
589         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
590     {
591         uint8_t conv_buf[DTS_HEADER_SIZE];
592         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 1 );
593         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
594                                      pi_bit_rate, pi_frame_length );
595         i_frame_size = i_frame_size * 8 / 14 * 2;
596     }
597     /* 14 bits, big endian version of the bitstream */
598     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
599              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
600              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
601     {
602         uint8_t conv_buf[DTS_HEADER_SIZE];
603         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 0 );
604         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
605                                      pi_bit_rate, pi_frame_length );
606         i_frame_size = i_frame_size * 8 / 14 * 2;
607     }
608     /* 16 bits, big endian version of the bitstream */
609     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
610              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
611     {
612         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
613                                      pi_bit_rate, pi_frame_length );
614     }
615     /* 16 bits, little endian version of the bitstream */
616     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
617              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
618     {
619         uint8_t conv_buf[DTS_HEADER_SIZE];
620         BufLeToBe( conv_buf, p_buf, DTS_HEADER_SIZE );
621         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
622                                      pi_bit_rate, pi_frame_length );
623     }
624     /* DTS-HD */
625     else if( p_buf[0] == 0x64 && p_buf[1] ==  0x58 &&
626              p_buf[2] == 0x20 && p_buf[3] ==  0x25 )
627     {
628         int i_dts_hd_size;
629         bs_t s;
630         bs_init( &s, &p_buf[4], DTS_HEADER_SIZE - 4 );
631
632         bs_skip( &s, 8 + 2 );
633
634         if( bs_read1( &s ) )
635         {
636             bs_skip( &s, 12 );
637             i_dts_hd_size = bs_read( &s, 20 ) + 1;
638         }
639         else
640         {
641             bs_skip( &s, 8 );
642             i_dts_hd_size = bs_read( &s, 16 ) + 1;
643         }
644         //uint16_t s0 = bs_read( &s, 16 );
645         //uint16_t s1 = bs_read( &s, 16 );
646         //fprintf( stderr, "DTS HD=%d : %x %x\n", i_dts_hd_size, s0, s1 );
647
648         *pb_dts_hd = true;
649         /* As we ignore the stream, do not modify those variables:
650         *pi_channels = ;
651         *pi_channels_conf = ;
652         *pi_sample_rate = ;
653         *pi_bit_rate = ;
654         *pi_frame_length = ;
655         */
656         return i_dts_hd_size;
657     }
658
659     *pb_dts_hd = false;
660
661     switch( i_audio_mode & 0xFFFF )
662     {
663         case 0x0:
664             /* Mono */
665             *pi_channels_conf = AOUT_CHAN_CENTER;
666             break;
667         case 0x1:
668             /* Dual-mono = stereo + dual-mono */
669             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
670                            AOUT_CHAN_DUALMONO;
671             break;
672         case 0x2:
673         case 0x3:
674         case 0x4:
675             /* Stereo */
676             *pi_channels = 2;
677             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
678             break;
679         case 0x5:
680             /* 3F */
681             *pi_channels = 3;
682             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
683                                 AOUT_CHAN_CENTER;
684             break;
685         case 0x6:
686             /* 2F/1R */
687             *pi_channels = 3;
688             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
689                                 AOUT_CHAN_REARCENTER;
690             break;
691         case 0x7:
692             /* 3F/1R */
693             *pi_channels = 4;
694             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
695                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER;
696             break;
697         case 0x8:
698             /* 2F2R */
699             *pi_channels = 4;
700             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
701                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
702             break;
703         case 0x9:
704             /* 3F2R */
705             *pi_channels = 5;
706             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
707                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
708                                 AOUT_CHAN_REARRIGHT;
709             break;
710         case 0xA:
711         case 0xB:
712             /* 2F2M2R */
713             *pi_channels = 6;
714             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
715                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
716                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
717             break;
718         case 0xC:
719             /* 3F2M2R */
720             *pi_channels = 7;
721             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
722                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
723                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
724                                 AOUT_CHAN_REARRIGHT;
725             break;
726         case 0xD:
727         case 0xE:
728             /* 3F2M2R/LFE */
729             *pi_channels = 8;
730             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
731                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
732                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
733                                 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
734             break;
735
736         default:
737             if( i_audio_mode <= 63 )
738             {
739                 /* User defined */
740                 *pi_channels = 0;
741                 *pi_channels_conf = 0;
742             }
743             else return 0;
744             break;
745     }
746
747     if( i_audio_mode & 0x10000 )
748     {
749         (*pi_channels)++;
750         *pi_channels_conf |= AOUT_CHAN_LFE;
751     }
752
753     if( *pi_sample_rate >= sizeof( ppi_dts_samplerate ) /
754                            sizeof( ppi_dts_samplerate[0] ) )
755     {
756         return 0;
757     }
758     *pi_sample_rate = ppi_dts_samplerate[ *pi_sample_rate ];
759     if( !*pi_sample_rate ) return 0;
760
761     if( *pi_bit_rate >= sizeof( ppi_dts_bitrate ) /
762                         sizeof( ppi_dts_bitrate[0] ) )
763     {
764         return 0;
765     }
766     *pi_bit_rate = ppi_dts_bitrate[ *pi_bit_rate ];
767     if( !*pi_bit_rate ) return 0;
768
769     *pi_frame_length = (*pi_frame_length + 1) * 32;
770
771     return i_frame_size;
772 }