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