]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
Segregate vout window types
[vlc] / modules / codec / dts.c
1 /*****************************************************************************
2  * dts.c: parse DTS audio sync info and packetize the stream
3  *****************************************************************************
4  * Copyright (C) 2003-2005 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 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_aout.h>
36 #include <vlc_block_helper.h>
37 #include <vlc_bits.h>
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 static int  OpenDecoder   ( vlc_object_t * );
43 static int  OpenPacketizer( vlc_object_t * );
44 static void CloseCommon   ( vlc_object_t * );
45
46 vlc_module_begin ()
47     set_description( N_("DTS parser") )
48     set_capability( "decoder", 100 )
49     set_callbacks( OpenDecoder, CloseCommon )
50
51     add_submodule ()
52     set_description( N_("DTS audio packetizer") )
53     set_capability( "packetizer", 10 )
54     set_callbacks( OpenPacketizer, CloseCommon )
55 vlc_module_end ()
56
57 /*****************************************************************************
58  * decoder_sys_t : decoder descriptor
59  *****************************************************************************/
60 struct decoder_sys_t
61 {
62     /* Module mode */
63     bool b_packetizer;
64
65     /*
66      * Input properties
67      */
68     int i_state;
69
70     block_bytestream_t bytestream;
71
72     /*
73      * Common properties
74      */
75     audio_date_t   end_date;
76
77     mtime_t i_pts;
78
79     bool         b_dts_hd;  /* Is the current frame a DTS HD one */
80     unsigned int i_bit_rate;
81     unsigned int i_frame_size;
82     unsigned int i_frame_length;
83     unsigned int i_rate;
84     unsigned int i_channels;
85     unsigned int i_channels_conf;
86 };
87
88 enum {
89
90     STATE_NOSYNC,
91     STATE_SYNC,
92     STATE_HEADER,
93     STATE_NEXT_SYNC,
94     STATE_GET_DATA,
95     STATE_SEND_DATA
96 };
97
98 #define DTS_HEADER_SIZE 14
99
100 /****************************************************************************
101  * Local prototypes
102  ****************************************************************************/
103 static int OpenCommon( vlc_object_t *, bool b_packetizer );
104 static void *DecodeBlock( decoder_t *, block_t ** );
105
106 static inline int SyncCode( const uint8_t * );
107 static int  SyncInfo( const uint8_t *, bool *, unsigned int *, unsigned int *,
108                       unsigned int *, unsigned int *, unsigned int * );
109
110 static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
111 static aout_buffer_t *GetAoutBuffer( decoder_t * );
112 static block_t       *GetSoutBuffer( decoder_t * );
113
114 /*****************************************************************************
115  * OpenDecoder: probe the decoder
116  *****************************************************************************/
117 static int OpenDecoder( vlc_object_t *p_this )
118 {
119     /* HACK: Don't use this codec if we don't have an dts audio filter */
120     if( !module_exists( "dtstofloat32" ) )
121         return VLC_EGENERIC;
122
123     return OpenCommon( p_this, false );
124 }
125
126 /*****************************************************************************
127  * OpenPacketizer: probe the packetizer
128  *****************************************************************************/
129 static int OpenPacketizer( vlc_object_t *p_this )
130 {
131     return OpenCommon( p_this, true );
132 }
133
134 /*****************************************************************************
135  * OpenCommon:
136  *****************************************************************************/
137 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
138 {
139     decoder_t *p_dec = (decoder_t*)p_this;
140     decoder_sys_t *p_sys;
141
142     if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s',' ') &&
143         p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') )
144     {
145         return VLC_EGENERIC;
146     }
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     aout_DateSet( &p_sys->end_date, 0 );
156     p_sys->b_dts_hd = false;
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_FOURCC('d','t','s',' ');
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_BytestreamFlush( &p_sys->bytestream );
193         }
194         aout_DateSet( &p_sys->end_date, 0 );
195         block_Release( *pp_block );
196         return NULL;
197     }
198
199     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
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 != 0 &&
236                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
237             {
238                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
239             }
240             p_sys->i_state = STATE_HEADER;
241
242         case STATE_HEADER:
243             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
244             if( block_PeekBytes( &p_sys->bytestream, p_header,
245                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
246             {
247                 /* Need more data */
248                 return NULL;
249             }
250
251             /* Check if frame is valid and get frame info */
252             p_sys->i_frame_size = SyncInfo( p_header,
253                                             &p_sys->b_dts_hd,
254                                             &p_sys->i_channels,
255                                             &p_sys->i_channels_conf,
256                                             &p_sys->i_rate,
257                                             &p_sys->i_bit_rate,
258                                             &p_sys->i_frame_length );
259             if( !p_sys->i_frame_size )
260             {
261                 msg_Dbg( p_dec, "emulated sync word" );
262                 block_SkipByte( &p_sys->bytestream );
263                 p_sys->i_state = STATE_NOSYNC;
264                 break;
265             }
266             p_sys->i_state = STATE_NEXT_SYNC;
267
268         case STATE_NEXT_SYNC:
269             /* TODO: If pp_block == NULL, flush the buffer without checking the
270              * next sync word */
271
272             /* Check if next expected frame contains the sync word */
273             if( block_PeekOffsetBytes( &p_sys->bytestream,
274                                        p_sys->i_frame_size, p_header, 6 )
275                 != VLC_SUCCESS )
276             {
277                 /* Need more data */
278                 return NULL;
279             }
280
281             if( SyncCode( p_header ) != VLC_SUCCESS )
282             {
283                 msg_Dbg( p_dec, "emulated sync word "
284                          "(no sync on following frame): %2.2x%2.2x%2.2x%2.2x",
285                          (int)p_header[0], (int)p_header[1],
286                          (int)p_header[2], (int)p_header[3] );
287                 p_sys->i_state = STATE_NOSYNC;
288                 block_SkipByte( &p_sys->bytestream );
289                 break;
290             }
291             p_sys->i_state = STATE_SEND_DATA;
292             break;
293
294         case STATE_GET_DATA:
295             /* Make sure we have enough data.
296              * (Not useful if we went through NEXT_SYNC) */
297             if( block_WaitBytes( &p_sys->bytestream,
298                                  p_sys->i_frame_size ) != VLC_SUCCESS )
299             {
300                 /* Need more data */
301                 return NULL;
302             }
303             p_sys->i_state = STATE_SEND_DATA;
304
305         case STATE_SEND_DATA:
306             if( p_sys->b_dts_hd  )
307             {
308                 /* Ignore DTS-HD */
309                 block_SkipBytes( &p_sys->bytestream, p_sys->i_frame_size );
310                 p_sys->i_state = STATE_NOSYNC;
311                 break;
312             }
313
314             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
315             {
316                 //p_dec->b_error = true;
317                 return NULL;
318             }
319
320             /* Copy the whole frame into the buffer. When we reach this point
321              * we already know we have enough data available. */
322             block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
323
324             /* Make sure we don't reuse the same pts twice */
325             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
326                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
327
328             p_sys->i_state = STATE_NOSYNC;
329
330             /* So p_block doesn't get re-added several times */
331             *pp_block = block_BytestreamPop( &p_sys->bytestream );
332
333             return p_out_buffer;
334         }
335     }
336
337     return NULL;
338 }
339
340 /*****************************************************************************
341  * CloseCommon: clean up the decoder
342  *****************************************************************************/
343 static void CloseCommon( vlc_object_t *p_this )
344 {
345     decoder_t *p_dec = (decoder_t*)p_this;
346     decoder_sys_t *p_sys = p_dec->p_sys;
347
348     block_BytestreamRelease( &p_sys->bytestream );
349
350     free( p_sys );
351 }
352
353 /*****************************************************************************
354  * GetOutBuffer:
355  *****************************************************************************/
356 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
357 {
358     decoder_sys_t *p_sys = p_dec->p_sys;
359     uint8_t *p_buf;
360
361     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
362     {
363         msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
364                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
365
366         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
367         aout_DateSet( &p_sys->end_date, p_sys->i_pts );
368     }
369
370     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
371     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
372     /* Hack for DTS S/PDIF filter which needs to pad the DTS frames */
373     p_dec->fmt_out.audio.i_bytes_per_frame =
374         __MAX( p_sys->i_frame_size, p_sys->i_frame_length * 4 );
375     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
376
377     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
378     p_dec->fmt_out.audio.i_physical_channels =
379         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
380
381     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
382
383     if( p_sys->b_packetizer )
384     {
385         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
386         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
387         *pp_out_buffer = p_sout_buffer;
388     }
389     else
390     {
391         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
392         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
393         *pp_out_buffer = p_aout_buffer;
394     }
395
396     return p_buf;
397 }
398
399 /*****************************************************************************
400  * GetAoutBuffer:
401  *****************************************************************************/
402 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
403 {
404     decoder_sys_t *p_sys = p_dec->p_sys;
405     aout_buffer_t *p_buf;
406
407     /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time
408      * (plus a few header bytes) */
409     p_buf = decoder_NewAudioBuffer( p_dec, p_sys->i_frame_length * 4 );
410     if( p_buf == NULL ) return NULL;
411     p_buf->i_nb_samples = p_sys->i_frame_length;
412     p_buf->i_nb_bytes = p_sys->i_frame_size;
413
414     p_buf->start_date = aout_DateGet( &p_sys->end_date );
415     p_buf->end_date =
416         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
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 = aout_DateGet( &p_sys->end_date );
433
434     p_block->i_length = aout_DateIncrement( &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 if( p_buf[0] == 0x64 && p_buf[1] ==  0x58 &&
628              p_buf[2] == 0x20 && p_buf[3] ==  0x25 )
629     {
630         int i_dts_hd_size;
631         bs_t s;
632         bs_init( &s, &p_buf[4], DTS_HEADER_SIZE - 4 );
633
634         bs_skip( &s, 8 + 2 );
635
636         if( bs_read1( &s ) )
637         {
638             bs_skip( &s, 12 );
639             i_dts_hd_size = bs_read( &s, 20 ) + 1;
640         }
641         else
642         {
643             bs_skip( &s, 8 );
644             i_dts_hd_size = bs_read( &s, 16 ) + 1;
645         }
646         //uint16_t s0 = bs_read( &s, 16 );
647         //uint16_t s1 = bs_read( &s, 16 );
648         //fprintf( stderr, "DTS HD=%d : %x %x\n", i_dts_hd_size, s0, s1 );
649
650         *pb_dts_hd = true;
651         /* As we ignore the stream, do not modify those variables:
652         *pi_channels = ;
653         *pi_channels_conf = ;
654         *pi_sample_rate = ;
655         *pi_bit_rate = ;
656         *pi_frame_length = ;
657         */
658         return i_dts_hd_size;
659     }
660
661     *pb_dts_hd = false;
662
663     switch( i_audio_mode & 0xFFFF )
664     {
665         case 0x0:
666             /* Mono */
667             *pi_channels_conf = AOUT_CHAN_CENTER;
668             break;
669         case 0x1:
670             /* Dual-mono = stereo + dual-mono */
671             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
672                            AOUT_CHAN_DUALMONO;
673             break;
674         case 0x2:
675         case 0x3:
676         case 0x4:
677             /* Stereo */
678             *pi_channels = 2;
679             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
680             break;
681         case 0x5:
682             /* 3F */
683             *pi_channels = 3;
684             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
685                                 AOUT_CHAN_CENTER;
686             break;
687         case 0x6:
688             /* 2F/1R */
689             *pi_channels = 3;
690             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
691                                 AOUT_CHAN_REARCENTER;
692             break;
693         case 0x7:
694             /* 3F/1R */
695             *pi_channels = 4;
696             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
697                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER;
698             break;
699         case 0x8:
700             /* 2F2R */
701             *pi_channels = 4;
702             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
703                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
704             break;
705         case 0x9:
706             /* 3F2R */
707             *pi_channels = 5;
708             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
709                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
710                                 AOUT_CHAN_REARRIGHT;
711             break;
712         case 0xA:
713         case 0xB:
714             /* 2F2M2R */
715             *pi_channels = 6;
716             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
717                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
718                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
719             break;
720         case 0xC:
721             /* 3F2M2R */
722             *pi_channels = 7;
723             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
724                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
725                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
726                                 AOUT_CHAN_REARRIGHT;
727             break;
728         case 0xD:
729         case 0xE:
730             /* 3F2M2R/LFE */
731             *pi_channels = 8;
732             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
733                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
734                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
735                                 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
736             break;
737
738         default:
739             if( i_audio_mode <= 63 )
740             {
741                 /* User defined */
742                 *pi_channels = 0;
743                 *pi_channels_conf = 0;
744             }
745             else return 0;
746             break;
747     }
748
749     if( i_audio_mode & 0x10000 )
750     {
751         (*pi_channels)++;
752         *pi_channels_conf |= AOUT_CHAN_LFE;
753     }
754
755     if( *pi_sample_rate >= sizeof( ppi_dts_samplerate ) /
756                            sizeof( ppi_dts_samplerate[0] ) )
757     {
758         return 0;
759     }
760     *pi_sample_rate = ppi_dts_samplerate[ *pi_sample_rate ];
761     if( !*pi_sample_rate ) return 0;
762
763     if( *pi_bit_rate >= sizeof( ppi_dts_bitrate ) /
764                         sizeof( ppi_dts_bitrate[0] ) )
765     {
766         return 0;
767     }
768     *pi_bit_rate = ppi_dts_bitrate[ *pi_bit_rate ];
769     if( !*pi_bit_rate ) return 0;
770
771     *pi_frame_length = (*pi_frame_length + 1) * 32;
772
773     return i_frame_size;
774 }