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