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