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