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