]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
* modules/codec/dts.c: fixes a buffer overflow with s/pdif.
[vlc] / modules / codec / dts.c
1 /*****************************************************************************
2  * dts.c: parse DTS audio sync info and packetize the stream
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: dts.c,v 1.16 2004/02/06 18:15:44 gbazin Exp $
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <vlc/vlc.h>
29 #include <vlc/decoder.h>
30
31 #include "vlc_block_helper.h"
32
33 #define DTS_HEADER_SIZE 14
34
35 /*****************************************************************************
36  * decoder_sys_t : decoder descriptor
37  *****************************************************************************/
38 struct decoder_sys_t
39 {
40     /* Module mode */
41     vlc_bool_t b_packetizer;
42
43     /*
44      * Input properties
45      */
46     int i_state;
47
48     block_bytestream_t bytestream;
49
50     /*
51      * Common properties
52      */
53     audio_date_t   end_date;
54
55     mtime_t i_pts;
56
57     int i_frame_size, i_bit_rate;
58     unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
59 };
60
61 enum {
62
63     STATE_NOSYNC,
64     STATE_SYNC,
65     STATE_HEADER,
66     STATE_NEXT_SYNC,
67     STATE_GET_DATA,
68     STATE_SEND_DATA
69 };
70
71 /****************************************************************************
72  * Local prototypes
73  ****************************************************************************/
74 static int  OpenDecoder   ( vlc_object_t * );
75 static int  OpenPacketizer( vlc_object_t * );
76 static void CloseDecoder  ( vlc_object_t * );
77 static void *DecodeBlock  ( decoder_t *, block_t ** );
78
79 static inline int SyncCode( const uint8_t * );
80 static int  SyncInfo      ( const uint8_t *, unsigned int *, unsigned int *,
81                             unsigned int *, unsigned int *, unsigned int * );
82
83 static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
84 static aout_buffer_t *GetAoutBuffer( decoder_t * );
85 static block_t       *GetSoutBuffer( decoder_t * );
86
87 /*****************************************************************************
88  * Module descriptor
89  *****************************************************************************/
90 vlc_module_begin();
91     set_description( _("DTS parser") );
92     set_capability( "decoder", 100 );
93     set_callbacks( OpenDecoder, CloseDecoder );
94
95     add_submodule();
96     set_description( _("DTS audio packetizer") );
97     set_capability( "packetizer", 10 );
98     set_callbacks( OpenPacketizer, NULL );
99 vlc_module_end();
100
101 /*****************************************************************************
102  * OpenDecoder: probe the decoder and return score
103  *****************************************************************************/
104 static int OpenDecoder( vlc_object_t *p_this )
105 {
106     decoder_t *p_dec = (decoder_t*)p_this;
107     decoder_sys_t *p_sys;
108
109     if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s',' ')
110          && p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') )
111     {
112         return VLC_EGENERIC;
113     }
114
115     /* Allocate the memory needed to store the decoder's structure */
116     if( ( p_dec->p_sys = p_sys =
117           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
118     {
119         msg_Err( p_dec, "out of memory" );
120         return VLC_EGENERIC;
121     }
122
123     /* Misc init */
124     p_sys->b_packetizer = VLC_FALSE;
125     p_sys->i_state = STATE_NOSYNC;
126     aout_DateSet( &p_sys->end_date, 0 );
127
128     p_sys->bytestream = block_BytestreamInit( p_dec );
129
130     /* Set output properties */
131     p_dec->fmt_out.i_cat = AUDIO_ES;
132     p_dec->fmt_out.i_codec = VLC_FOURCC('d','t','s',' ');
133
134     /* Set callback */
135     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
136         DecodeBlock;
137     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
138         DecodeBlock;
139
140     return VLC_SUCCESS;
141 }
142
143 static int OpenPacketizer( vlc_object_t *p_this )
144 {
145     decoder_t *p_dec = (decoder_t*)p_this;
146
147     int i_ret = OpenDecoder( p_this );
148
149     if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
150
151     return i_ret;
152 }
153
154 /****************************************************************************
155  * DecodeBlock: the whole thing
156  ****************************************************************************
157  * This function is called just after the thread is launched.
158  ****************************************************************************/
159 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
160 {
161     decoder_sys_t *p_sys = p_dec->p_sys;
162     uint8_t p_header[DTS_HEADER_SIZE];
163     uint8_t *p_buf;
164     void *p_out_buffer;
165
166     if( !pp_block || !*pp_block ) return NULL;
167
168     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
169     {
170         /* We've just started the stream, wait for the first PTS. */
171         block_Release( *pp_block );
172         return NULL;
173     }
174
175     if( (*pp_block)->b_discontinuity )
176     {
177         p_sys->i_state = STATE_NOSYNC;
178     }
179
180     block_BytestreamPush( &p_sys->bytestream, *pp_block );
181
182     while( 1 )
183     {
184         switch( p_sys->i_state )
185         {
186         case STATE_NOSYNC:
187             /* Look for sync code - should be 0x7ffe8001 */
188             while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
189                    == VLC_SUCCESS )
190             {
191                 if( SyncCode( p_header ) == VLC_SUCCESS )
192                 {
193                     p_sys->i_state = STATE_SYNC;
194                     break;
195                 }
196                 block_SkipByte( &p_sys->bytestream );
197             }
198             if( p_sys->i_state != STATE_SYNC )
199             {
200                 block_BytestreamFlush( &p_sys->bytestream );
201
202                 /* Need more data */
203                 return NULL;
204             }
205
206         case STATE_SYNC:
207             /* New frame, set the Presentation Time Stamp */
208             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
209             if( p_sys->i_pts != 0 &&
210                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
211             {
212                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
213             }
214             p_sys->i_state = STATE_HEADER;
215
216         case STATE_HEADER:
217             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
218             if( block_PeekBytes( &p_sys->bytestream, p_header,
219                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
220             {
221                 /* Need more data */
222                 return NULL;
223             }
224
225             /* Check if frame is valid and get frame info */
226             p_sys->i_frame_size = SyncInfo( p_header,
227                                             &p_sys->i_channels,
228                                             &p_sys->i_channels_conf,
229                                             &p_sys->i_rate,
230                                             &p_sys->i_bit_rate,
231                                             &p_sys->i_frame_length );
232             if( !p_sys->i_frame_size )
233             {
234                 msg_Dbg( p_dec, "emulated sync word" );
235                 block_SkipByte( &p_sys->bytestream );
236                 p_sys->i_state = STATE_NOSYNC;
237                 break;
238             }
239             p_sys->i_state = STATE_NEXT_SYNC;
240
241         case STATE_NEXT_SYNC:
242             /* TODO: If pp_block == NULL, flush the buffer without checking the
243              * next sync word */
244
245             /* Check if next expected frame contains the sync word */
246             if( block_PeekOffsetBytes( &p_sys->bytestream,
247                                        p_sys->i_frame_size, p_header, 6 )
248                 != VLC_SUCCESS )
249             {
250                 /* Need more data */
251                 return NULL;
252             }
253
254             if( SyncCode( p_header ) != VLC_SUCCESS )
255             {
256                 msg_Dbg( p_dec, "emulated sync word "
257                          "(no sync on following frame): %2.2x%2.2x%2.2x%2.2x",
258                          (int)p_header[0], (int)p_header[1],
259                          (int)p_header[2], (int)p_header[3] );
260                 p_sys->i_state = STATE_NOSYNC;
261                 block_SkipByte( &p_sys->bytestream );
262                 break;
263             }
264             p_sys->i_state = STATE_SEND_DATA;
265             break;
266
267         case STATE_GET_DATA:
268             /* Make sure we have enough data.
269              * (Not useful if we went through NEXT_SYNC) */
270             if( block_WaitBytes( &p_sys->bytestream,
271                                  p_sys->i_frame_size ) != VLC_SUCCESS )
272             {
273                 /* Need more data */
274                 return NULL;
275             }
276             p_sys->i_state = STATE_SEND_DATA;
277
278         case STATE_SEND_DATA:
279             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
280             {
281                 //p_dec->b_error = VLC_TRUE;
282                 return NULL;
283             }
284
285             /* Copy the whole frame into the buffer. When we reach this point
286              * we already know we have enough data available. */
287             block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
288
289             /* Make sure we don't reuse the same pts twice */
290             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
291                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
292
293             p_sys->i_state = STATE_NOSYNC;
294
295             /* So p_block doesn't get re-added several times */
296             *pp_block = block_BytestreamPop( &p_sys->bytestream );
297
298             return p_out_buffer;
299         }
300     }
301
302     return NULL;
303 }
304
305 /*****************************************************************************
306  * CloseDecoder: clean up the decoder
307  *****************************************************************************/
308 static void CloseDecoder( vlc_object_t *p_this )
309 {
310     decoder_t *p_dec = (decoder_t*)p_this;
311     decoder_sys_t *p_sys = p_dec->p_sys;
312
313     block_BytestreamRelease( &p_sys->bytestream );
314
315     free( p_sys );
316 }
317
318 /*****************************************************************************
319  * GetOutBuffer:
320  *****************************************************************************/
321 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
322 {
323     decoder_sys_t *p_sys = p_dec->p_sys;
324     uint8_t *p_buf;
325
326     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
327     {
328         msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
329                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
330
331         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
332         aout_DateSet( &p_sys->end_date, p_sys->i_pts );
333     }
334
335     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
336     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
337     p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
338     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
339
340     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
341     p_dec->fmt_out.audio.i_physical_channels =
342         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
343
344     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
345
346     if( p_sys->b_packetizer )
347     {
348         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
349         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
350         *pp_out_buffer = p_sout_buffer;
351     }
352     else
353     {
354         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
355         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
356         *pp_out_buffer = p_aout_buffer;
357     }
358
359     return p_buf;
360 }
361
362 /*****************************************************************************
363  * GetAoutBuffer:
364  *****************************************************************************/
365 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
366 {
367     decoder_sys_t *p_sys = p_dec->p_sys;
368     aout_buffer_t *p_buf;
369
370     /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time
371      * (plus a few header bytes) */
372     p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 4 );
373     if( p_buf == NULL ) return NULL;
374     p_buf->i_nb_samples = p_sys->i_frame_length;
375     p_buf->i_nb_bytes = p_sys->i_frame_size;
376
377     p_buf->start_date = aout_DateGet( &p_sys->end_date );
378     p_buf->end_date =
379         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
380
381     return p_buf;
382 }
383
384 /*****************************************************************************
385  * GetSoutBuffer:
386  *****************************************************************************/
387 static block_t *GetSoutBuffer( decoder_t *p_dec )
388 {
389     decoder_sys_t *p_sys = p_dec->p_sys;
390     block_t *p_block;
391
392     p_block = block_New( p_dec, p_sys->i_frame_size );
393     if( p_block == NULL ) return NULL;
394
395     p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
396
397     p_block->i_length = aout_DateIncrement( &p_sys->end_date,
398         p_sys->i_frame_length ) - p_block->i_pts;
399
400     return p_block;
401 }
402
403 /*****************************************************************************
404  * SyncInfo: parse DTS sync info
405  *****************************************************************************/
406 static const unsigned int ppi_dts_samplerate[] =
407 {
408     0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
409     12000, 24000, 48000, 96000, 192000
410 };
411
412 static const unsigned int ppi_dts_bitrate[] =
413 {
414     32000, 56000, 64000, 96000, 112000, 128000,
415     192000, 224000, 256000, 320000, 384000,
416     448000, 512000, 576000, 640000, 768000,
417     896000, 1024000, 1152000, 1280000, 1344000,
418     1408000, 1411200, 1472000, 1536000, 1920000,
419     2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/
420 };
421
422 static int SyncInfo16be( const uint8_t *p_buf,
423                          unsigned int *pi_audio_mode,
424                          unsigned int *pi_sample_rate,
425                          unsigned int *pi_bit_rate,
426                          unsigned int *pi_frame_length )
427 {
428     unsigned int i_frame_size;
429     unsigned int i_lfe;
430
431     *pi_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
432     i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
433                    (p_buf[7] >> 4);
434
435     *pi_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
436     *pi_sample_rate = (p_buf[8] >> 2) & 0x0f;
437     *pi_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
438
439     i_lfe = (p_buf[10] >> 1) & 0x03;
440     if( i_lfe ) *pi_audio_mode |= 0x10000;
441
442     return i_frame_size + 1;
443 }
444
445 static void BufLeToBe( uint8_t *p_out, const uint8_t *p_in, int i_in )
446 {
447     int i;
448
449     for( i = 0; i < i_in/2; i++  )
450     {
451         p_out[i*2] = p_in[i*2+1];
452         p_out[i*2+1] = p_in[i*2];
453     }
454 }
455
456 static int Buf14To16( uint8_t *p_out, const uint8_t *p_in, int i_in, int i_le )
457 {
458     unsigned char tmp, cur = 0;
459     int bits_in, bits_out = 0;
460     int i, i_out = 0;
461
462     for( i = 0; i < i_in; i++  )
463     {
464         if( i%2 )
465         {
466             tmp = p_in[i-i_le];
467             bits_in = 8;
468         }
469         else
470         {
471             tmp = p_in[i+i_le] & 0x3F;
472             bits_in = 8 - 2;
473         }
474
475         if( bits_out < 8 )
476         {
477             int need = __MIN( 8 - bits_out, bits_in );
478             cur <<= need;
479             cur |= ( tmp >> (bits_in - need) );
480             tmp <<= (8 - bits_in + need);
481             tmp >>= (8 - bits_in + need);
482             bits_in -= need;
483             bits_out += need;
484         }
485
486         if( bits_out == 8 )
487         {
488             p_out[i_out] = cur;
489             cur = 0;
490             bits_out = 0;
491             i_out++;
492         }
493
494         bits_out += bits_in;
495         cur <<= bits_in;
496         cur |= tmp;
497     }
498
499     return i_out;
500 }
501
502 static inline int SyncCode( const uint8_t *p_buf )
503 {
504     /* 14 bits, little endian version of the bitstream */
505     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
506         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
507         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
508     {
509         return VLC_SUCCESS;
510     }
511     /* 14 bits, big endian version of the bitstream */
512     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
513              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
514              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
515     {
516         return VLC_SUCCESS;
517     }
518     /* 16 bits, big endian version of the bitstream */
519     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
520              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
521     {
522         return VLC_SUCCESS;
523     }
524     /* 16 bits, little endian version of the bitstream */
525     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
526              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
527     {
528         return VLC_SUCCESS;
529     }
530     else return VLC_EGENERIC;
531 }
532
533 static int SyncInfo( const uint8_t *p_buf,
534                      unsigned int *pi_channels,
535                      unsigned int *pi_channels_conf,
536                      unsigned int *pi_sample_rate,
537                      unsigned int *pi_bit_rate,
538                      unsigned int *pi_frame_length )
539 {
540     unsigned int i_audio_mode;
541     unsigned int i_frame_size;
542
543     /* 14 bits, little endian version of the bitstream */
544     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
545         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
546         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
547     {
548         uint8_t conv_buf[DTS_HEADER_SIZE];
549         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 1 );
550         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
551                                      pi_bit_rate, pi_frame_length );
552         i_frame_size = i_frame_size * 8 / 14 * 2;
553     }
554     /* 14 bits, big endian version of the bitstream */
555     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
556              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
557              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
558     {
559         uint8_t conv_buf[DTS_HEADER_SIZE];
560         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 0 );
561         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
562                                      pi_bit_rate, pi_frame_length );
563         i_frame_size = i_frame_size * 8 / 14 * 2;
564     }
565     /* 16 bits, big endian version of the bitstream */
566     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
567              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
568     {
569         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
570                                      pi_bit_rate, pi_frame_length );
571     }
572     /* 16 bits, little endian version of the bitstream */
573     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
574              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
575     {
576         uint8_t conv_buf[DTS_HEADER_SIZE];
577         BufLeToBe( conv_buf, p_buf, DTS_HEADER_SIZE );
578         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
579                                      pi_bit_rate, pi_frame_length );
580     }
581     else return 0;
582
583     switch( i_audio_mode & 0xFFFF )
584     {
585         case 0x0:
586             /* Mono */
587             *pi_channels_conf = AOUT_CHAN_CENTER;
588             break;
589         case 0x1:
590             /* Dual-mono = stereo + dual-mono */
591             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
592                            AOUT_CHAN_DUALMONO;
593             break;
594         case 0x2:
595         case 0x3:
596         case 0x4:
597             /* Stereo */
598             *pi_channels = 2;
599             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
600             break;
601         case 0x5:
602             /* 3F */
603             *pi_channels = 3;
604             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
605                                 AOUT_CHAN_CENTER;
606             break;
607         case 0x6:
608             /* 2F/1R */
609             *pi_channels = 3;
610             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
611                                 AOUT_CHAN_REARCENTER;
612             break;
613         case 0x7:
614             /* 3F/1R */
615             *pi_channels = 4;
616             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
617                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER;
618             break;
619         case 0x8:
620             /* 2F2R */
621             *pi_channels = 4;
622             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
623                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
624             break;
625         case 0x9:
626             /* 3F2R */
627             *pi_channels = 5;
628             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
629                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
630                                 AOUT_CHAN_REARRIGHT;
631             break;
632         case 0xA:
633         case 0xB:
634             /* 2F2M2R */
635             *pi_channels = 6;
636             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
637                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
638                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
639             break;
640         case 0xC:
641             /* 3F2M2R */
642             *pi_channels = 7;
643             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
644                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
645                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
646                                 AOUT_CHAN_REARRIGHT;
647             break;
648         case 0xD:
649         case 0xE:
650             /* 3F2M2R/LFE */
651             *pi_channels = 8;
652             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
653                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
654                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
655                                 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
656             break;
657
658         default:
659             if( i_audio_mode <= 63 )
660             {
661                 /* User defined */
662                 *pi_channels = 0;
663                 *pi_channels_conf = 0;
664             }
665             else return 0;
666             break;
667     }
668
669     if( i_audio_mode & 0x10000 )
670     {
671         (*pi_channels)++;
672         *pi_channels_conf |= AOUT_CHAN_LFE;
673     }
674
675     if( *pi_sample_rate >= sizeof( ppi_dts_samplerate ) /
676                            sizeof( ppi_dts_samplerate[0] ) )
677     {
678         return 0;
679     }
680     *pi_sample_rate = ppi_dts_samplerate[ *pi_sample_rate ];
681     if( !*pi_sample_rate ) return 0;
682
683     if( *pi_bit_rate >= sizeof( ppi_dts_bitrate ) /
684                         sizeof( ppi_dts_bitrate[0] ) )
685     {
686         return 0;
687     }
688     *pi_bit_rate = ppi_dts_bitrate[ *pi_bit_rate ];
689     if( !*pi_bit_rate ) return 0;
690
691     *pi_frame_length = (*pi_frame_length + 1) * 32;
692
693     return i_frame_size;
694 }