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