]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
Used VLC_CODEC_* and vlc_fourcc_GetCodec when suitable.
[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         p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') )
145     {
146         return VLC_EGENERIC;
147     }
148
149     /* Allocate the memory needed to store the decoder's structure */
150     if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
151         return VLC_ENOMEM;
152
153     /* Misc init */
154     p_sys->b_packetizer = b_packetizer;
155     p_sys->i_state = STATE_NOSYNC;
156     aout_DateSet( &p_sys->end_date, 0 );
157     p_sys->b_dts_hd = false;
158
159     p_sys->bytestream = block_BytestreamInit();
160
161     /* Set output properties */
162     p_dec->fmt_out.i_cat = AUDIO_ES;
163     p_dec->fmt_out.i_codec = VLC_CODEC_DTS;
164     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
165
166     /* Set callback */
167     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
168         DecodeBlock;
169     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
170         DecodeBlock;
171
172     return VLC_SUCCESS;
173 }
174
175 /****************************************************************************
176  * DecodeBlock: the whole thing
177  ****************************************************************************/
178 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
179 {
180     decoder_sys_t *p_sys = p_dec->p_sys;
181     uint8_t p_header[DTS_HEADER_SIZE];
182     uint8_t *p_buf;
183     void *p_out_buffer;
184
185     if( !pp_block || !*pp_block )
186         return NULL;
187
188     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
189     {
190         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
191         {
192             p_sys->i_state = STATE_NOSYNC;
193             block_BytestreamEmpty( &p_sys->bytestream );
194         }
195         aout_DateSet( &p_sys->end_date, 0 );
196         block_Release( *pp_block );
197         return NULL;
198     }
199
200     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
201     {
202         /* We've just started the stream, wait for the first PTS. */
203         block_Release( *pp_block );
204         return NULL;
205     }
206
207     block_BytestreamPush( &p_sys->bytestream, *pp_block );
208
209     while( 1 )
210     {
211         switch( p_sys->i_state )
212         {
213         case STATE_NOSYNC:
214             /* Look for sync code - should be 0x7ffe8001 */
215             while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
216                    == VLC_SUCCESS )
217             {
218                 if( SyncCode( p_header ) == VLC_SUCCESS )
219                 {
220                     p_sys->i_state = STATE_SYNC;
221                     break;
222                 }
223                 block_SkipByte( &p_sys->bytestream );
224             }
225             if( p_sys->i_state != STATE_SYNC )
226             {
227                 block_BytestreamFlush( &p_sys->bytestream );
228
229                 /* Need more data */
230                 return NULL;
231             }
232
233         case STATE_SYNC:
234             /* New frame, set the Presentation Time Stamp */
235             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
236             if( p_sys->i_pts != 0 &&
237                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
238             {
239                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
240             }
241             p_sys->i_state = STATE_HEADER;
242
243         case STATE_HEADER:
244             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
245             if( block_PeekBytes( &p_sys->bytestream, p_header,
246                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
247             {
248                 /* Need more data */
249                 return NULL;
250             }
251
252             /* Check if frame is valid and get frame info */
253             p_sys->i_frame_size = SyncInfo( p_header,
254                                             &p_sys->b_dts_hd,
255                                             &p_sys->i_channels,
256                                             &p_sys->i_channels_conf,
257                                             &p_sys->i_rate,
258                                             &p_sys->i_bit_rate,
259                                             &p_sys->i_frame_length );
260             if( !p_sys->i_frame_size )
261             {
262                 msg_Dbg( p_dec, "emulated sync word" );
263                 block_SkipByte( &p_sys->bytestream );
264                 p_sys->i_state = STATE_NOSYNC;
265                 break;
266             }
267             p_sys->i_state = STATE_NEXT_SYNC;
268
269         case STATE_NEXT_SYNC:
270             /* TODO: If pp_block == NULL, flush the buffer without checking the
271              * next sync word */
272
273             /* Check if next expected frame contains the sync word */
274             if( block_PeekOffsetBytes( &p_sys->bytestream,
275                                        p_sys->i_frame_size, p_header, 6 )
276                 != VLC_SUCCESS )
277             {
278                 /* Need more data */
279                 return NULL;
280             }
281
282             if( SyncCode( p_header ) != VLC_SUCCESS )
283             {
284                 msg_Dbg( p_dec, "emulated sync word "
285                          "(no sync on following frame): %2.2x%2.2x%2.2x%2.2x",
286                          (int)p_header[0], (int)p_header[1],
287                          (int)p_header[2], (int)p_header[3] );
288                 p_sys->i_state = STATE_NOSYNC;
289                 block_SkipByte( &p_sys->bytestream );
290                 break;
291             }
292             p_sys->i_state = STATE_SEND_DATA;
293             break;
294
295         case STATE_GET_DATA:
296             /* Make sure we have enough data.
297              * (Not useful if we went through NEXT_SYNC) */
298             if( block_WaitBytes( &p_sys->bytestream,
299                                  p_sys->i_frame_size ) != VLC_SUCCESS )
300             {
301                 /* Need more data */
302                 return NULL;
303             }
304             p_sys->i_state = STATE_SEND_DATA;
305
306         case STATE_SEND_DATA:
307             if( p_sys->b_dts_hd  )
308             {
309                 /* Ignore DTS-HD */
310                 block_SkipBytes( &p_sys->bytestream, p_sys->i_frame_size );
311                 p_sys->i_state = STATE_NOSYNC;
312                 break;
313             }
314
315             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
316             {
317                 //p_dec->b_error = true;
318                 return NULL;
319             }
320
321             /* Copy the whole frame into the buffer. When we reach this point
322              * we already know we have enough data available. */
323             block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
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 = 0;
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, void **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         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
368         aout_DateSet( &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_nb_bytes = p_sys->i_frame_size;
414
415     p_buf->start_date = aout_DateGet( &p_sys->end_date );
416     p_buf->end_date =
417         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
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 = aout_DateGet( &p_sys->end_date );
434
435     p_block->i_length = aout_DateIncrement( &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 if( 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 }