]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
23b3558e31676ea3ab6ad432961a9eb6ffcf2067
[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.14 2004/02/03 23:32:45 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     /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time */
338     p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size * 3;
339     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
340
341     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
342     p_dec->fmt_out.audio.i_physical_channels =
343         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
344
345     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
346
347     if( p_sys->b_packetizer )
348     {
349         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
350         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
351         *pp_out_buffer = p_sout_buffer;
352     }
353     else
354     {
355         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
356         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
357         *pp_out_buffer = p_aout_buffer;
358     }
359
360     return p_buf;
361 }
362
363 /*****************************************************************************
364  * GetAoutBuffer:
365  *****************************************************************************/
366 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
367 {
368     decoder_sys_t *p_sys = p_dec->p_sys;
369     aout_buffer_t *p_buf;
370
371     p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length );
372     if( p_buf == NULL ) return NULL;
373
374     p_buf->start_date = aout_DateGet( &p_sys->end_date );
375     p_buf->end_date =
376         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
377
378     return p_buf;
379 }
380
381 /*****************************************************************************
382  * GetSoutBuffer:
383  *****************************************************************************/
384 static block_t *GetSoutBuffer( decoder_t *p_dec )
385 {
386     decoder_sys_t *p_sys = p_dec->p_sys;
387     block_t *p_block;
388
389     p_block = block_New( p_dec, p_sys->i_frame_size );
390     if( p_block == NULL ) return NULL;
391
392     p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
393
394     p_block->i_length = aout_DateIncrement( &p_sys->end_date,
395         p_sys->i_frame_length ) - p_block->i_pts;
396
397     return p_block;
398 }
399
400 /*****************************************************************************
401  * SyncInfo: parse DTS sync info
402  *****************************************************************************/
403 static const unsigned int ppi_dts_samplerate[] =
404 {
405     0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
406     12000, 24000, 48000, 96000, 192000
407 };
408
409 static const unsigned int ppi_dts_bitrate[] =
410 {
411     32000, 56000, 64000, 96000, 112000, 128000,
412     192000, 224000, 256000, 320000, 384000,
413     448000, 512000, 576000, 640000, 768000,
414     896000, 1024000, 1152000, 1280000, 1344000,
415     1408000, 1411200, 1472000, 1536000, 1920000,
416     2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/
417 };
418
419 static int SyncInfo16be( const uint8_t *p_buf,
420                          unsigned int *pi_audio_mode,
421                          unsigned int *pi_sample_rate,
422                          unsigned int *pi_bit_rate,
423                          unsigned int *pi_frame_length )
424 {
425     unsigned int i_frame_size;
426     unsigned int i_lfe;
427
428     *pi_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
429     i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
430                    (p_buf[7] >> 4);
431
432     *pi_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
433     *pi_sample_rate = (p_buf[8] >> 2) & 0x0f;
434     *pi_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
435
436     i_lfe = (p_buf[10] >> 1) & 0x03;
437     if( i_lfe ) *pi_audio_mode |= 0x10000;
438
439     return i_frame_size + 1;
440 }
441
442 static void BufLeToBe( uint8_t *p_out, const uint8_t *p_in, int i_in )
443 {
444     int i;
445
446     for( i = 0; i < i_in/2; i++  )
447     {
448         p_out[i*2] = p_in[i*2+1];
449         p_out[i*2+1] = p_in[i*2];
450     }
451 }
452
453 static int Buf14To16( uint8_t *p_out, const uint8_t *p_in, int i_in, int i_le )
454 {
455     unsigned char tmp, cur = 0;
456     int bits_in, bits_out = 0;
457     int i, i_out = 0;
458
459     for( i = 0; i < i_in; i++  )
460     {
461         if( i%2 )
462         {
463             tmp = p_in[i-i_le];
464             bits_in = 8;
465         }
466         else
467         {
468             tmp = p_in[i+i_le] & 0x3F;
469             bits_in = 8 - 2;
470         }
471
472         if( bits_out < 8 )
473         {
474             int need = __MIN( 8 - bits_out, bits_in );
475             cur <<= need;
476             cur |= ( tmp >> (bits_in - need) );
477             tmp <<= (8 - bits_in + need);
478             tmp >>= (8 - bits_in + need);
479             bits_in -= need;
480             bits_out += need;
481         }
482
483         if( bits_out == 8 )
484         {
485             p_out[i_out] = cur;
486             cur = 0;
487             bits_out = 0;
488             i_out++;
489         }
490
491         bits_out += bits_in;
492         cur <<= bits_in;
493         cur |= tmp;
494     }
495
496     return i_out;
497 }
498
499 static inline int SyncCode( const uint8_t *p_buf )
500 {
501     /* 14 bits, little endian version of the bitstream */
502     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
503         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
504         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
505     {
506         return VLC_SUCCESS;
507     }
508     /* 14 bits, big endian version of the bitstream */
509     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
510              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
511              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
512     {
513         return VLC_SUCCESS;
514     }
515     /* 16 bits, big endian version of the bitstream */
516     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
517              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
518     {
519         return VLC_SUCCESS;
520     }
521     /* 16 bits, little endian version of the bitstream */
522     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
523              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
524     {
525         return VLC_SUCCESS;
526     }
527     else return VLC_EGENERIC;
528 }
529
530 static int SyncInfo( const uint8_t *p_buf,
531                      unsigned int *pi_channels,
532                      unsigned int *pi_channels_conf,
533                      unsigned int *pi_sample_rate,
534                      unsigned int *pi_bit_rate,
535                      unsigned int *pi_frame_length )
536 {
537     unsigned int i_audio_mode;
538     unsigned int i_frame_size;
539
540     /* 14 bits, little endian version of the bitstream */
541     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
542         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
543         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
544     {
545         uint8_t conv_buf[DTS_HEADER_SIZE];
546         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 1 );
547         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
548                                      pi_bit_rate, pi_frame_length );
549         i_frame_size = i_frame_size * 8 / 14 * 2;
550     }
551     /* 14 bits, big endian version of the bitstream */
552     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
553              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
554              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
555     {
556         uint8_t conv_buf[DTS_HEADER_SIZE];
557         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 0 );
558         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
559                                      pi_bit_rate, pi_frame_length );
560         i_frame_size = i_frame_size * 8 / 14 * 2;
561     }
562     /* 16 bits, big endian version of the bitstream */
563     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
564              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
565     {
566         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
567                                      pi_bit_rate, pi_frame_length );
568     }
569     /* 16 bits, little endian version of the bitstream */
570     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
571              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
572     {
573         uint8_t conv_buf[DTS_HEADER_SIZE];
574         BufLeToBe( conv_buf, p_buf, DTS_HEADER_SIZE );
575         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
576                                      pi_bit_rate, pi_frame_length );
577     }
578     else return 0;
579
580     switch( i_audio_mode & 0xFFFF )
581     {
582         case 0x0:
583             /* Mono */
584             *pi_channels_conf = AOUT_CHAN_CENTER;
585             break;
586         case 0x1:
587             /* Dual-mono = stereo + dual-mono */
588             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
589                            AOUT_CHAN_DUALMONO;
590             break;
591         case 0x2:
592         case 0x3:
593         case 0x4:
594             /* Stereo */
595             *pi_channels = 2;
596             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
597             break;
598         case 0x5:
599             /* 3F */
600             *pi_channels = 3;
601             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
602                                 AOUT_CHAN_CENTER;
603             break;
604         case 0x6:
605             /* 2F/1R */
606             *pi_channels = 3;
607             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
608                                 AOUT_CHAN_REARCENTER;
609             break;
610         case 0x7:
611             /* 3F/1R */
612             *pi_channels = 4;
613             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
614                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER;
615             break;
616         case 0x8:
617             /* 2F2R */
618             *pi_channels = 4;
619             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
620                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
621             break;
622         case 0x9:
623             /* 3F2R */
624             *pi_channels = 5;
625             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
626                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
627                                 AOUT_CHAN_REARRIGHT;
628             break;
629         case 0xA:
630         case 0xB:
631             /* 2F2M2R */
632             *pi_channels = 6;
633             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
634                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
635                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
636             break;
637         case 0xC:
638             /* 3F2M2R */
639             *pi_channels = 7;
640             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
641                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
642                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
643                                 AOUT_CHAN_REARRIGHT;
644             break;
645         case 0xD:
646         case 0xE:
647             /* 3F2M2R/LFE */
648             *pi_channels = 8;
649             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
650                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
651                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
652                                 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
653             break;
654
655         default:
656             if( i_audio_mode <= 63 )
657             {
658                 /* User defined */
659                 *pi_channels = 0;
660                 *pi_channels_conf = 0;
661             }
662             else return 0;
663             break;
664     }
665
666     if( i_audio_mode & 0x10000 )
667     {
668         (*pi_channels)++;
669         *pi_channels_conf |= AOUT_CHAN_LFE;
670     }
671
672     if( *pi_sample_rate >= sizeof( ppi_dts_samplerate ) /
673                            sizeof( ppi_dts_samplerate[0] ) )
674     {
675         return 0;
676     }
677     *pi_sample_rate = ppi_dts_samplerate[ *pi_sample_rate ];
678     if( !*pi_sample_rate ) return 0;
679
680     if( *pi_bit_rate >= sizeof( ppi_dts_bitrate ) /
681                         sizeof( ppi_dts_bitrate[0] ) )
682     {
683         return 0;
684     }
685     *pi_bit_rate = ppi_dts_bitrate[ *pi_bit_rate ];
686     if( !*pi_bit_rate ) return 0;
687
688     *pi_frame_length = (*pi_frame_length + 1) * 32;
689
690     return i_frame_size;
691 }