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