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