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