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