]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
Replace remaining instances of aout_buffer_t with block_t
[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_block_helper.h>
38 #include <vlc_bits.h>
39 #include <vlc_modules.h>
40 #include <vlc_cpu.h>
41
42 #include "../packetizer/packetizer_helper.h"
43
44 /*****************************************************************************
45  * Module descriptor
46  *****************************************************************************/
47 static int  OpenDecoder   ( vlc_object_t * );
48 static int  OpenPacketizer( vlc_object_t * );
49 static void CloseCommon   ( vlc_object_t * );
50
51 vlc_module_begin ()
52     set_description( N_("DTS parser") )
53     set_capability( "decoder", 100 )
54     set_callbacks( OpenDecoder, CloseCommon )
55
56     add_submodule ()
57     set_description( N_("DTS audio packetizer") )
58     set_capability( "packetizer", 10 )
59     set_callbacks( OpenPacketizer, CloseCommon )
60 vlc_module_end ()
61
62 /*****************************************************************************
63  * decoder_sys_t : decoder descriptor
64  *****************************************************************************/
65 struct decoder_sys_t
66 {
67     /* Module mode */
68     bool b_packetizer;
69
70     /*
71      * Input properties
72      */
73     int i_state;
74
75     block_bytestream_t bytestream;
76
77     /*
78      * Common properties
79      */
80     date_t  end_date;
81
82     mtime_t i_pts;
83
84     bool         b_dts_hd;  /* Is the current frame a DTS HD one */
85     unsigned int i_bit_rate;
86     unsigned int i_frame_size;
87     unsigned int i_frame_length;
88     unsigned int i_rate;
89     unsigned int i_channels;
90     unsigned int i_channels_conf;
91 };
92
93 #define DTS_HEADER_SIZE 14
94
95 /****************************************************************************
96  * Local prototypes
97  ****************************************************************************/
98 static int OpenCommon( vlc_object_t *, bool b_packetizer );
99 static block_t *DecodeBlock( decoder_t *, block_t ** );
100
101 static inline int SyncCode( const uint8_t * );
102 static int  SyncInfo( const uint8_t *, bool *, unsigned int *, unsigned int *,
103                       unsigned int *, unsigned int *, unsigned int * );
104
105 static uint8_t *GetOutBuffer ( decoder_t *, block_t ** );
106 static block_t *GetAoutBuffer( decoder_t * );
107 static block_t *GetSoutBuffer( decoder_t * );
108
109 /*****************************************************************************
110  * OpenDecoder: probe the decoder
111  *****************************************************************************/
112 static int OpenDecoder( vlc_object_t *p_this )
113 {
114     /* HACK: Don't use this codec if we don't have an dts audio filter */
115     if( !HAVE_FPU || !module_exists( "dtstofloat32" ) )
116         return VLC_EGENERIC;
117
118     return OpenCommon( p_this, false );
119 }
120
121 /*****************************************************************************
122  * OpenPacketizer: probe the packetizer
123  *****************************************************************************/
124 static int OpenPacketizer( vlc_object_t *p_this )
125 {
126     return OpenCommon( p_this, true );
127 }
128
129 /*****************************************************************************
130  * OpenCommon:
131  *****************************************************************************/
132 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
133 {
134     decoder_t *p_dec = (decoder_t*)p_this;
135     decoder_sys_t *p_sys;
136
137     if( p_dec->fmt_in.i_codec != VLC_CODEC_DTS )
138         return VLC_EGENERIC;
139
140     /* Allocate the memory needed to store the decoder's structure */
141     if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
142         return VLC_ENOMEM;
143
144     /* Misc init */
145     p_sys->b_packetizer = b_packetizer;
146     p_sys->i_state = STATE_NOSYNC;
147     date_Set( &p_sys->end_date, 0 );
148     p_sys->b_dts_hd = false;
149     p_sys->i_pts = VLC_TS_INVALID;
150
151     block_BytestreamInit( &p_sys->bytestream );
152
153     /* Set output properties */
154     p_dec->fmt_out.i_cat = AUDIO_ES;
155     p_dec->fmt_out.i_codec = VLC_CODEC_DTS;
156     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
157
158     /* Set callback */
159     p_dec->pf_decode_audio = DecodeBlock;
160     p_dec->pf_packetize    = DecodeBlock;
161
162     return VLC_SUCCESS;
163 }
164
165 /****************************************************************************
166  * DecodeBlock: the whole thing
167  ****************************************************************************/
168 static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
169 {
170     decoder_sys_t *p_sys = p_dec->p_sys;
171     uint8_t p_header[DTS_HEADER_SIZE];
172     uint8_t *p_buf;
173     block_t *p_out_buffer;
174
175     if( !pp_block || !*pp_block )
176         return NULL;
177
178     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
179     {
180         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
181         {
182             p_sys->i_state = STATE_NOSYNC;
183             block_BytestreamEmpty( &p_sys->bytestream );
184         }
185         date_Set( &p_sys->end_date, 0 );
186         block_Release( *pp_block );
187         return NULL;
188     }
189
190     if( !date_Get( &p_sys->end_date ) && (*pp_block)->i_pts <= VLC_TS_INVALID )
191     {
192         /* We've just started the stream, wait for the first PTS. */
193         block_Release( *pp_block );
194         return NULL;
195     }
196
197     block_BytestreamPush( &p_sys->bytestream, *pp_block );
198
199     while( 1 )
200     {
201         switch( p_sys->i_state )
202         {
203         case STATE_NOSYNC:
204             /* Look for sync code - should be 0x7ffe8001 */
205             while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
206                    == VLC_SUCCESS )
207             {
208                 if( SyncCode( p_header ) == VLC_SUCCESS )
209                 {
210                     p_sys->i_state = STATE_SYNC;
211                     break;
212                 }
213                 block_SkipByte( &p_sys->bytestream );
214             }
215             if( p_sys->i_state != STATE_SYNC )
216             {
217                 block_BytestreamFlush( &p_sys->bytestream );
218
219                 /* Need more data */
220                 return NULL;
221             }
222
223         case STATE_SYNC:
224             /* New frame, set the Presentation Time Stamp */
225             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
226             if( p_sys->i_pts > VLC_TS_INVALID &&
227                 p_sys->i_pts != date_Get( &p_sys->end_date ) )
228             {
229                 date_Set( &p_sys->end_date, p_sys->i_pts );
230             }
231             p_sys->i_state = STATE_HEADER;
232
233         case STATE_HEADER:
234             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
235             if( block_PeekBytes( &p_sys->bytestream, p_header,
236                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
237             {
238                 /* Need more data */
239                 return NULL;
240             }
241
242             /* Check if frame is valid and get frame info */
243             p_sys->i_frame_size = SyncInfo( p_header,
244                                             &p_sys->b_dts_hd,
245                                             &p_sys->i_channels,
246                                             &p_sys->i_channels_conf,
247                                             &p_sys->i_rate,
248                                             &p_sys->i_bit_rate,
249                                             &p_sys->i_frame_length );
250             if( !p_sys->i_frame_size )
251             {
252                 msg_Dbg( p_dec, "emulated sync word" );
253                 block_SkipByte( &p_sys->bytestream );
254                 p_sys->i_state = STATE_NOSYNC;
255                 break;
256             }
257             p_sys->i_state = STATE_NEXT_SYNC;
258
259         case STATE_NEXT_SYNC:
260             /* TODO: If pp_block == NULL, flush the buffer without checking the
261              * next sync word */
262
263             /* Check if next expected frame contains the sync word */
264             if( block_PeekOffsetBytes( &p_sys->bytestream,
265                                        p_sys->i_frame_size, p_header, 6 )
266                 != VLC_SUCCESS )
267             {
268                 /* Need more data */
269                 return NULL;
270             }
271
272             if( p_sys->b_packetizer &&
273                 p_header[0] == 0 && p_header[1] == 0 )
274             {
275                 /* DTS wav files and audio CD's use stuffing */
276                 p_sys->i_state = STATE_SEND_DATA;
277                 break;
278             }
279
280             if( SyncCode( p_header ) != VLC_SUCCESS )
281             {
282                 msg_Dbg( p_dec, "emulated sync word "
283                          "(no sync on following frame): %2.2x%2.2x%2.2x%2.2x",
284                          (int)p_header[0], (int)p_header[1],
285                          (int)p_header[2], (int)p_header[3] );
286                 p_sys->i_state = STATE_NOSYNC;
287                 block_SkipByte( &p_sys->bytestream );
288                 break;
289             }
290             p_sys->i_state = STATE_SEND_DATA;
291             break;
292
293         case STATE_GET_DATA:
294             /* Make sure we have enough data.
295              * (Not useful if we went through NEXT_SYNC) */
296             if( block_WaitBytes( &p_sys->bytestream,
297                                  p_sys->i_frame_size ) != VLC_SUCCESS )
298             {
299                 /* Need more data */
300                 return NULL;
301             }
302             p_sys->i_state = STATE_SEND_DATA;
303
304         case STATE_SEND_DATA:
305             if( p_sys->b_dts_hd  )
306             {
307                 /* Ignore DTS-HD */
308                 block_SkipBytes( &p_sys->bytestream, p_sys->i_frame_size );
309                 p_sys->i_state = STATE_NOSYNC;
310                 break;
311             }
312
313             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
314             {
315                 //p_dec->b_error = true;
316                 return NULL;
317             }
318
319             /* Copy the whole frame into the buffer. When we reach this point
320              * we already know we have enough data available. */
321             block_GetBytes( &p_sys->bytestream,
322                             p_buf, __MIN( p_sys->i_frame_size, p_out_buffer->i_buffer ) );
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, block_t **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         block_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 block_t *GetAoutBuffer( decoder_t *p_dec )
403 {
404     decoder_sys_t *p_sys = p_dec->p_sys;
405     block_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 }