]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
dts: use VLC_TS_INVALID (refs #3135)
[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     p_sys->i_pts = VLC_TS_INVALID;
157
158     p_sys->bytestream = block_BytestreamInit();
159
160     /* Set output properties */
161     p_dec->fmt_out.i_cat = AUDIO_ES;
162     p_dec->fmt_out.i_codec = VLC_CODEC_DTS;
163     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
164
165     /* Set callback */
166     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
167         DecodeBlock;
168     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
169         DecodeBlock;
170
171     return VLC_SUCCESS;
172 }
173
174 /****************************************************************************
175  * DecodeBlock: the whole thing
176  ****************************************************************************/
177 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
178 {
179     decoder_sys_t *p_sys = p_dec->p_sys;
180     uint8_t p_header[DTS_HEADER_SIZE];
181     uint8_t *p_buf;
182     void *p_out_buffer;
183
184     if( !pp_block || !*pp_block )
185         return NULL;
186
187     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
188     {
189         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
190         {
191             p_sys->i_state = STATE_NOSYNC;
192             block_BytestreamEmpty( &p_sys->bytestream );
193         }
194         date_Set( &p_sys->end_date, 0 );
195         block_Release( *pp_block );
196         return NULL;
197     }
198
199     if( !date_Get( &p_sys->end_date ) && (*pp_block)->i_pts <= VLC_TS_INVALID )
200     {
201         /* We've just started the stream, wait for the first PTS. */
202         block_Release( *pp_block );
203         return NULL;
204     }
205
206     block_BytestreamPush( &p_sys->bytestream, *pp_block );
207
208     while( 1 )
209     {
210         switch( p_sys->i_state )
211         {
212         case STATE_NOSYNC:
213             /* Look for sync code - should be 0x7ffe8001 */
214             while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
215                    == VLC_SUCCESS )
216             {
217                 if( SyncCode( p_header ) == VLC_SUCCESS )
218                 {
219                     p_sys->i_state = STATE_SYNC;
220                     break;
221                 }
222                 block_SkipByte( &p_sys->bytestream );
223             }
224             if( p_sys->i_state != STATE_SYNC )
225             {
226                 block_BytestreamFlush( &p_sys->bytestream );
227
228                 /* Need more data */
229                 return NULL;
230             }
231
232         case STATE_SYNC:
233             /* New frame, set the Presentation Time Stamp */
234             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
235             if( p_sys->i_pts > VLC_TS_INVALID &&
236                 p_sys->i_pts != date_Get( &p_sys->end_date ) )
237             {
238                 date_Set( &p_sys->end_date, p_sys->i_pts );
239             }
240             p_sys->i_state = STATE_HEADER;
241
242         case STATE_HEADER:
243             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
244             if( block_PeekBytes( &p_sys->bytestream, p_header,
245                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
246             {
247                 /* Need more data */
248                 return NULL;
249             }
250
251             /* Check if frame is valid and get frame info */
252             p_sys->i_frame_size = SyncInfo( p_header,
253                                             &p_sys->b_dts_hd,
254                                             &p_sys->i_channels,
255                                             &p_sys->i_channels_conf,
256                                             &p_sys->i_rate,
257                                             &p_sys->i_bit_rate,
258                                             &p_sys->i_frame_length );
259             if( !p_sys->i_frame_size )
260             {
261                 msg_Dbg( p_dec, "emulated sync word" );
262                 block_SkipByte( &p_sys->bytestream );
263                 p_sys->i_state = STATE_NOSYNC;
264                 break;
265             }
266             p_sys->i_state = STATE_NEXT_SYNC;
267
268         case STATE_NEXT_SYNC:
269             /* TODO: If pp_block == NULL, flush the buffer without checking the
270              * next sync word */
271
272             /* Check if next expected frame contains the sync word */
273             if( block_PeekOffsetBytes( &p_sys->bytestream,
274                                        p_sys->i_frame_size, p_header, 6 )
275                 != VLC_SUCCESS )
276             {
277                 /* Need more data */
278                 return NULL;
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, p_buf, p_sys->i_frame_size );
323
324             /* Make sure we don't reuse the same pts twice */
325             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
326                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;
327
328             p_sys->i_state = STATE_NOSYNC;
329
330             /* So p_block doesn't get re-added several times */
331             *pp_block = block_BytestreamPop( &p_sys->bytestream );
332
333             return p_out_buffer;
334         }
335     }
336
337     return NULL;
338 }
339
340 /*****************************************************************************
341  * CloseCommon: clean up the decoder
342  *****************************************************************************/
343 static void CloseCommon( vlc_object_t *p_this )
344 {
345     decoder_t *p_dec = (decoder_t*)p_this;
346     decoder_sys_t *p_sys = p_dec->p_sys;
347
348     block_BytestreamRelease( &p_sys->bytestream );
349
350     free( p_sys );
351 }
352
353 /*****************************************************************************
354  * GetOutBuffer:
355  *****************************************************************************/
356 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
357 {
358     decoder_sys_t *p_sys = p_dec->p_sys;
359     uint8_t *p_buf;
360
361     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
362     {
363         msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
364                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
365
366         date_Init( &p_sys->end_date, p_sys->i_rate, 1 );
367         date_Set( &p_sys->end_date, p_sys->i_pts );
368     }
369
370     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
371     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
372     /* Hack for DTS S/PDIF filter which needs to pad the DTS frames */
373     p_dec->fmt_out.audio.i_bytes_per_frame =
374         __MAX( p_sys->i_frame_size, p_sys->i_frame_length * 4 );
375     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
376
377     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
378     p_dec->fmt_out.audio.i_physical_channels =
379         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
380
381     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
382
383     if( p_sys->b_packetizer )
384     {
385         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
386         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
387         *pp_out_buffer = p_sout_buffer;
388     }
389     else
390     {
391         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
392         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
393         *pp_out_buffer = p_aout_buffer;
394     }
395
396     return p_buf;
397 }
398
399 /*****************************************************************************
400  * GetAoutBuffer:
401  *****************************************************************************/
402 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
403 {
404     decoder_sys_t *p_sys = p_dec->p_sys;
405     aout_buffer_t *p_buf;
406
407     /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time
408      * (plus a few header bytes) */
409     p_buf = decoder_NewAudioBuffer( p_dec, p_sys->i_frame_length * 4 );
410     if( p_buf == NULL ) return NULL;
411     p_buf->i_nb_samples = p_sys->i_frame_length;
412     p_buf->i_buffer = p_sys->i_frame_size;
413
414     p_buf->i_pts = date_Get( &p_sys->end_date );
415     p_buf->i_length = date_Increment( &p_sys->end_date, p_sys->i_frame_length )
416                       - p_buf->i_pts;
417
418     return p_buf;
419 }
420
421 /*****************************************************************************
422  * GetSoutBuffer:
423  *****************************************************************************/
424 static block_t *GetSoutBuffer( decoder_t *p_dec )
425 {
426     decoder_sys_t *p_sys = p_dec->p_sys;
427     block_t *p_block;
428
429     p_block = block_New( p_dec, p_sys->i_frame_size );
430     if( p_block == NULL ) return NULL;
431
432     p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
433
434     p_block->i_length = date_Increment( &p_sys->end_date,
435         p_sys->i_frame_length ) - p_block->i_pts;
436
437     return p_block;
438 }
439
440 /*****************************************************************************
441  * SyncInfo: parse DTS sync info
442  *****************************************************************************/
443 static const unsigned int ppi_dts_samplerate[] =
444 {
445     0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
446     12000, 24000, 48000, 96000, 192000
447 };
448
449 static const unsigned int ppi_dts_bitrate[] =
450 {
451     32000, 56000, 64000, 96000, 112000, 128000,
452     192000, 224000, 256000, 320000, 384000,
453     448000, 512000, 576000, 640000, 768000,
454     896000, 1024000, 1152000, 1280000, 1344000,
455     1408000, 1411200, 1472000, 1536000, 1920000,
456     2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/
457 };
458
459 static int SyncInfo16be( const uint8_t *p_buf,
460                          unsigned int *pi_audio_mode,
461                          unsigned int *pi_sample_rate,
462                          unsigned int *pi_bit_rate,
463                          unsigned int *pi_frame_length )
464 {
465     unsigned int i_frame_size;
466     unsigned int i_lfe;
467
468     *pi_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
469     i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
470                    (p_buf[7] >> 4);
471
472     *pi_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
473     *pi_sample_rate = (p_buf[8] >> 2) & 0x0f;
474     *pi_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
475
476     i_lfe = (p_buf[10] >> 1) & 0x03;
477     if( i_lfe ) *pi_audio_mode |= 0x10000;
478
479     return i_frame_size + 1;
480 }
481
482 static void BufLeToBe( uint8_t *p_out, const uint8_t *p_in, int i_in )
483 {
484     int i;
485
486     for( i = 0; i < i_in/2; i++  )
487     {
488         p_out[i*2] = p_in[i*2+1];
489         p_out[i*2+1] = p_in[i*2];
490     }
491 }
492
493 static int Buf14To16( uint8_t *p_out, const uint8_t *p_in, int i_in, int i_le )
494 {
495     unsigned char tmp, cur = 0;
496     int bits_in, bits_out = 0;
497     int i, i_out = 0;
498
499     for( i = 0; i < i_in; i++  )
500     {
501         if( i%2 )
502         {
503             tmp = p_in[i-i_le];
504             bits_in = 8;
505         }
506         else
507         {
508             tmp = p_in[i+i_le] & 0x3F;
509             bits_in = 8 - 2;
510         }
511
512         if( bits_out < 8 )
513         {
514             int need = __MIN( 8 - bits_out, bits_in );
515             cur <<= need;
516             cur |= ( tmp >> (bits_in - need) );
517             tmp <<= (8 - bits_in + need);
518             tmp >>= (8 - bits_in + need);
519             bits_in -= need;
520             bits_out += need;
521         }
522
523         if( bits_out == 8 )
524         {
525             p_out[i_out] = cur;
526             cur = 0;
527             bits_out = 0;
528             i_out++;
529         }
530
531         bits_out += bits_in;
532         cur <<= bits_in;
533         cur |= tmp;
534     }
535
536     return i_out;
537 }
538
539 static inline int SyncCode( const uint8_t *p_buf )
540 {
541     /* 14 bits, little endian version of the bitstream */
542     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
543         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
544         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
545     {
546         return VLC_SUCCESS;
547     }
548     /* 14 bits, big endian version of the bitstream */
549     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
550              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
551              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
552     {
553         return VLC_SUCCESS;
554     }
555     /* 16 bits, big endian version of the bitstream */
556     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
557              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
558     {
559         return VLC_SUCCESS;
560     }
561     /* 16 bits, little endian version of the bitstream */
562     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
563              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
564     {
565         return VLC_SUCCESS;
566     }
567     /* DTS-HD */
568     else if( p_buf[0] == 0x64 && p_buf[1] ==  0x58 &&
569              p_buf[2] == 0x20 && p_buf[3] ==  0x25 )
570     {
571         return VLC_SUCCESS;
572     }
573
574     return VLC_EGENERIC;
575 }
576
577 static int SyncInfo( const uint8_t *p_buf,
578                      bool *pb_dts_hd,
579                      unsigned int *pi_channels,
580                      unsigned int *pi_channels_conf,
581                      unsigned int *pi_sample_rate,
582                      unsigned int *pi_bit_rate,
583                      unsigned int *pi_frame_length )
584 {
585     unsigned int i_audio_mode;
586     unsigned int i_frame_size;
587
588     /* 14 bits, little endian version of the bitstream */
589     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
590         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
591         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
592     {
593         uint8_t conv_buf[DTS_HEADER_SIZE];
594         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 1 );
595         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
596                                      pi_bit_rate, pi_frame_length );
597         i_frame_size = i_frame_size * 8 / 14 * 2;
598     }
599     /* 14 bits, big endian version of the bitstream */
600     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
601              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
602              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
603     {
604         uint8_t conv_buf[DTS_HEADER_SIZE];
605         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 0 );
606         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
607                                      pi_bit_rate, pi_frame_length );
608         i_frame_size = i_frame_size * 8 / 14 * 2;
609     }
610     /* 16 bits, big endian version of the bitstream */
611     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
612              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
613     {
614         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
615                                      pi_bit_rate, pi_frame_length );
616     }
617     /* 16 bits, little endian version of the bitstream */
618     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
619              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
620     {
621         uint8_t conv_buf[DTS_HEADER_SIZE];
622         BufLeToBe( conv_buf, p_buf, DTS_HEADER_SIZE );
623         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
624                                      pi_bit_rate, pi_frame_length );
625     }
626     /* DTS-HD */
627     else
628     {
629         assert( p_buf[0] == 0x64 && p_buf[1] ==  0x58 &&
630                 p_buf[2] == 0x20 && p_buf[3] ==  0x25 );
631
632         int i_dts_hd_size;
633         bs_t s;
634         bs_init( &s, &p_buf[4], DTS_HEADER_SIZE - 4 );
635
636         bs_skip( &s, 8 + 2 );
637
638         if( bs_read1( &s ) )
639         {
640             bs_skip( &s, 12 );
641             i_dts_hd_size = bs_read( &s, 20 ) + 1;
642         }
643         else
644         {
645             bs_skip( &s, 8 );
646             i_dts_hd_size = bs_read( &s, 16 ) + 1;
647         }
648         //uint16_t s0 = bs_read( &s, 16 );
649         //uint16_t s1 = bs_read( &s, 16 );
650         //fprintf( stderr, "DTS HD=%d : %x %x\n", i_dts_hd_size, s0, s1 );
651
652         *pb_dts_hd = true;
653         /* As we ignore the stream, do not modify those variables:
654         *pi_channels = ;
655         *pi_channels_conf = ;
656         *pi_sample_rate = ;
657         *pi_bit_rate = ;
658         *pi_frame_length = ;
659         */
660         return i_dts_hd_size;
661     }
662
663     *pb_dts_hd = false;
664
665     switch( i_audio_mode & 0xFFFF )
666     {
667         case 0x0:
668             /* Mono */
669             *pi_channels = 1;
670             *pi_channels_conf = AOUT_CHAN_CENTER;
671             break;
672         case 0x1:
673             /* Dual-mono = stereo + dual-mono */
674             *pi_channels = 2;
675             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
676                            AOUT_CHAN_DUALMONO;
677             break;
678         case 0x2:
679         case 0x3:
680         case 0x4:
681             /* Stereo */
682             *pi_channels = 2;
683             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
684             break;
685         case 0x5:
686             /* 3F */
687             *pi_channels = 3;
688             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
689                                 AOUT_CHAN_CENTER;
690             break;
691         case 0x6:
692             /* 2F/1R */
693             *pi_channels = 3;
694             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
695                                 AOUT_CHAN_REARCENTER;
696             break;
697         case 0x7:
698             /* 3F/1R */
699             *pi_channels = 4;
700             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
701                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER;
702             break;
703         case 0x8:
704             /* 2F2R */
705             *pi_channels = 4;
706             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
707                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
708             break;
709         case 0x9:
710             /* 3F2R */
711             *pi_channels = 5;
712             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
713                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
714                                 AOUT_CHAN_REARRIGHT;
715             break;
716         case 0xA:
717         case 0xB:
718             /* 2F2M2R */
719             *pi_channels = 6;
720             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
721                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
722                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
723             break;
724         case 0xC:
725             /* 3F2M2R */
726             *pi_channels = 7;
727             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
728                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
729                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
730                                 AOUT_CHAN_REARRIGHT;
731             break;
732         case 0xD:
733         case 0xE:
734             /* 3F2M2R/LFE */
735             *pi_channels = 8;
736             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
737                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
738                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
739                                 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
740             break;
741
742         default:
743             if( i_audio_mode <= 63 )
744             {
745                 /* User defined */
746                 *pi_channels = 0;
747                 *pi_channels_conf = 0;
748             }
749             else return 0;
750             break;
751     }
752
753     if( i_audio_mode & 0x10000 )
754     {
755         (*pi_channels)++;
756         *pi_channels_conf |= AOUT_CHAN_LFE;
757     }
758
759     if( *pi_sample_rate >= sizeof( ppi_dts_samplerate ) /
760                            sizeof( ppi_dts_samplerate[0] ) )
761     {
762         return 0;
763     }
764     *pi_sample_rate = ppi_dts_samplerate[ *pi_sample_rate ];
765     if( !*pi_sample_rate ) return 0;
766
767     if( *pi_bit_rate >= sizeof( ppi_dts_bitrate ) /
768                         sizeof( ppi_dts_bitrate[0] ) )
769     {
770         return 0;
771     }
772     *pi_bit_rate = ppi_dts_bitrate[ *pi_bit_rate ];
773     if( !*pi_bit_rate ) return 0;
774
775     *pi_frame_length = (*pi_frame_length + 1) * 32;
776
777     return i_frame_size;
778 }