Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

dts.c

00001 /*****************************************************************************
00002  * dts.c: parse DTS audio sync info and packetize the stream
00003  *****************************************************************************
00004  * Copyright (C) 2003-2005 the VideoLAN team
00005  * $Id: dts.c 12089 2005-08-09 15:18:44Z jpsaman $
00006  *
00007  * Authors: Jon Lech Johansen <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <vlc/vlc.h>
00029 #include <vlc/decoder.h>
00030 
00031 #include "vlc_block_helper.h"
00032 
00033 #define DTS_HEADER_SIZE 14
00034 
00035 /*****************************************************************************
00036  * decoder_sys_t : decoder descriptor
00037  *****************************************************************************/
00038 struct decoder_sys_t
00039 {
00040     /* Module mode */
00041     vlc_bool_t b_packetizer;
00042 
00043     /*
00044      * Input properties
00045      */
00046     int i_state;
00047 
00048     block_bytestream_t bytestream;
00049 
00050     /*
00051      * Common properties
00052      */
00053     audio_date_t   end_date;
00054 
00055     mtime_t i_pts;
00056 
00057     unsigned int i_bit_rate;
00058     unsigned int i_frame_size;
00059     unsigned int i_frame_length;
00060     unsigned int i_rate;
00061     unsigned int i_channels;
00062     unsigned int i_channels_conf;
00063 };
00064 
00065 enum {
00066 
00067     STATE_NOSYNC,
00068     STATE_SYNC,
00069     STATE_HEADER,
00070     STATE_NEXT_SYNC,
00071     STATE_GET_DATA,
00072     STATE_SEND_DATA
00073 };
00074 
00075 /****************************************************************************
00076  * Local prototypes
00077  ****************************************************************************/
00078 static int  OpenDecoder   ( vlc_object_t * );
00079 static int  OpenPacketizer( vlc_object_t * );
00080 static void CloseDecoder  ( vlc_object_t * );
00081 static void *DecodeBlock  ( decoder_t *, block_t ** );
00082 
00083 static inline int SyncCode( const uint8_t * );
00084 static int  SyncInfo      ( const uint8_t *, unsigned int *, unsigned int *,
00085                             unsigned int *, unsigned int *, unsigned int * );
00086 
00087 static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
00088 static aout_buffer_t *GetAoutBuffer( decoder_t * );
00089 static block_t       *GetSoutBuffer( decoder_t * );
00090 
00091 /*****************************************************************************
00092  * Module descriptor
00093  *****************************************************************************/
00094 vlc_module_begin();
00095     set_description( _("DTS parser") );
00096     set_capability( "decoder", 100 );
00097     set_callbacks( OpenDecoder, CloseDecoder );
00098 
00099     add_submodule();
00100     set_description( _("DTS audio packetizer") );
00101     set_capability( "packetizer", 10 );
00102     set_callbacks( OpenPacketizer, NULL );
00103 vlc_module_end();
00104 
00105 /*****************************************************************************
00106  * OpenDecoder: probe the decoder and return score
00107  *****************************************************************************/
00108 static int OpenDecoder( vlc_object_t *p_this )
00109 {
00110     decoder_t *p_dec = (decoder_t*)p_this;
00111     decoder_sys_t *p_sys;
00112 
00113     if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s',' ')
00114          && p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') )
00115     {
00116         return VLC_EGENERIC;
00117     }
00118 
00119     /* Allocate the memory needed to store the decoder's structure */
00120     if( ( p_dec->p_sys = p_sys =
00121           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00122     {
00123         msg_Err( p_dec, "out of memory" );
00124         return VLC_EGENERIC;
00125     }
00126 
00127     /* Misc init */
00128     p_sys->b_packetizer = VLC_FALSE;
00129     p_sys->i_state = STATE_NOSYNC;
00130     aout_DateSet( &p_sys->end_date, 0 );
00131 
00132     p_sys->bytestream = block_BytestreamInit( p_dec );
00133 
00134     /* Set output properties */
00135     p_dec->fmt_out.i_cat = AUDIO_ES;
00136     p_dec->fmt_out.i_codec = VLC_FOURCC('d','t','s',' ');
00137     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
00138 
00139     /* Set callback */
00140     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
00141         DecodeBlock;
00142     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
00143         DecodeBlock;
00144 
00145     return VLC_SUCCESS;
00146 }
00147 
00148 static int OpenPacketizer( vlc_object_t *p_this )
00149 {
00150     decoder_t *p_dec = (decoder_t*)p_this;
00151 
00152     int i_ret = OpenDecoder( p_this );
00153 
00154     if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
00155 
00156     return i_ret;
00157 }
00158 
00159 /****************************************************************************
00160  * DecodeBlock: the whole thing
00161  ****************************************************************************
00162  * This function is called just after the thread is launched.
00163  ****************************************************************************/
00164 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
00165 {
00166     decoder_sys_t *p_sys = p_dec->p_sys;
00167     uint8_t p_header[DTS_HEADER_SIZE];
00168     uint8_t *p_buf;
00169     void *p_out_buffer;
00170 
00171     if( !pp_block || !*pp_block ) return NULL;
00172 
00173     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
00174     {
00175         /* We've just started the stream, wait for the first PTS. */
00176         block_Release( *pp_block );
00177         return NULL;
00178     }
00179 
00180     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
00181     {
00182         p_sys->i_state = STATE_NOSYNC;
00183     }
00184 
00185     block_BytestreamPush( &p_sys->bytestream, *pp_block );
00186 
00187     while( 1 )
00188     {
00189         switch( p_sys->i_state )
00190         {
00191         case STATE_NOSYNC:
00192             /* Look for sync code - should be 0x7ffe8001 */
00193             while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
00194                    == VLC_SUCCESS )
00195             {
00196                 if( SyncCode( p_header ) == VLC_SUCCESS )
00197                 {
00198                     p_sys->i_state = STATE_SYNC;
00199                     break;
00200                 }
00201                 block_SkipByte( &p_sys->bytestream );
00202             }
00203             if( p_sys->i_state != STATE_SYNC )
00204             {
00205                 block_BytestreamFlush( &p_sys->bytestream );
00206 
00207                 /* Need more data */
00208                 return NULL;
00209             }
00210 
00211         case STATE_SYNC:
00212             /* New frame, set the Presentation Time Stamp */
00213             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
00214             if( p_sys->i_pts != 0 &&
00215                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
00216             {
00217                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
00218             }
00219             p_sys->i_state = STATE_HEADER;
00220 
00221         case STATE_HEADER:
00222             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
00223             if( block_PeekBytes( &p_sys->bytestream, p_header,
00224                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
00225             {
00226                 /* Need more data */
00227                 return NULL;
00228             }
00229 
00230             /* Check if frame is valid and get frame info */
00231             p_sys->i_frame_size = SyncInfo( p_header,
00232                                             &p_sys->i_channels,
00233                                             &p_sys->i_channels_conf,
00234                                             &p_sys->i_rate,
00235                                             &p_sys->i_bit_rate,
00236                                             &p_sys->i_frame_length );
00237             if( !p_sys->i_frame_size )
00238             {
00239                 msg_Dbg( p_dec, "emulated sync word" );
00240                 block_SkipByte( &p_sys->bytestream );
00241                 p_sys->i_state = STATE_NOSYNC;
00242                 break;
00243             }
00244             p_sys->i_state = STATE_NEXT_SYNC;
00245 
00246         case STATE_NEXT_SYNC:
00247             /* TODO: If pp_block == NULL, flush the buffer without checking the
00248              * next sync word */
00249 
00250             /* Check if next expected frame contains the sync word */
00251             if( block_PeekOffsetBytes( &p_sys->bytestream,
00252                                        p_sys->i_frame_size, p_header, 6 )
00253                 != VLC_SUCCESS )
00254             {
00255                 /* Need more data */
00256                 return NULL;
00257             }
00258 
00259             if( SyncCode( p_header ) != VLC_SUCCESS )
00260             {
00261                 msg_Dbg( p_dec, "emulated sync word "
00262                          "(no sync on following frame): %2.2x%2.2x%2.2x%2.2x",
00263                          (int)p_header[0], (int)p_header[1],
00264                          (int)p_header[2], (int)p_header[3] );
00265                 p_sys->i_state = STATE_NOSYNC;
00266                 block_SkipByte( &p_sys->bytestream );
00267                 break;
00268             }
00269             p_sys->i_state = STATE_SEND_DATA;
00270             break;
00271 
00272         case STATE_GET_DATA:
00273             /* Make sure we have enough data.
00274              * (Not useful if we went through NEXT_SYNC) */
00275             if( block_WaitBytes( &p_sys->bytestream,
00276                                  p_sys->i_frame_size ) != VLC_SUCCESS )
00277             {
00278                 /* Need more data */
00279                 return NULL;
00280             }
00281             p_sys->i_state = STATE_SEND_DATA;
00282 
00283         case STATE_SEND_DATA:
00284             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
00285             {
00286                 //p_dec->b_error = VLC_TRUE;
00287                 return NULL;
00288             }
00289 
00290             /* Copy the whole frame into the buffer. When we reach this point
00291              * we already know we have enough data available. */
00292             block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
00293 
00294             /* Make sure we don't reuse the same pts twice */
00295             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
00296                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
00297 
00298             p_sys->i_state = STATE_NOSYNC;
00299 
00300             /* So p_block doesn't get re-added several times */
00301             *pp_block = block_BytestreamPop( &p_sys->bytestream );
00302 
00303             return p_out_buffer;
00304         }
00305     }
00306 
00307     return NULL;
00308 }
00309 
00310 /*****************************************************************************
00311  * CloseDecoder: clean up the decoder
00312  *****************************************************************************/
00313 static void CloseDecoder( vlc_object_t *p_this )
00314 {
00315     decoder_t *p_dec = (decoder_t*)p_this;
00316     decoder_sys_t *p_sys = p_dec->p_sys;
00317 
00318     block_BytestreamRelease( &p_sys->bytestream );
00319 
00320     free( p_sys );
00321 }
00322 
00323 /*****************************************************************************
00324  * GetOutBuffer:
00325  *****************************************************************************/
00326 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
00327 {
00328     decoder_sys_t *p_sys = p_dec->p_sys;
00329     uint8_t *p_buf;
00330 
00331     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
00332     {
00333         msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
00334                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
00335 
00336         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
00337         aout_DateSet( &p_sys->end_date, p_sys->i_pts );
00338     }
00339 
00340     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
00341     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
00342     /* Hack for DTS S/PDIF filter which needs to pad the DTS frames */
00343     p_dec->fmt_out.audio.i_bytes_per_frame =
00344         __MAX( p_sys->i_frame_size, p_sys->i_frame_length * 4 );
00345     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
00346 
00347     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
00348     p_dec->fmt_out.audio.i_physical_channels =
00349         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
00350 
00351     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
00352 
00353     if( p_sys->b_packetizer )
00354     {
00355         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
00356         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
00357         *pp_out_buffer = p_sout_buffer;
00358     }
00359     else
00360     {
00361         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
00362         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
00363         *pp_out_buffer = p_aout_buffer;
00364     }
00365 
00366     return p_buf;
00367 }
00368 
00369 /*****************************************************************************
00370  * GetAoutBuffer:
00371  *****************************************************************************/
00372 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
00373 {
00374     decoder_sys_t *p_sys = p_dec->p_sys;
00375     aout_buffer_t *p_buf;
00376 
00377     /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time
00378      * (plus a few header bytes) */
00379     p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 4 );
00380     if( p_buf == NULL ) return NULL;
00381     p_buf->i_nb_samples = p_sys->i_frame_length;
00382     p_buf->i_nb_bytes = p_sys->i_frame_size;
00383 
00384     p_buf->start_date = aout_DateGet( &p_sys->end_date );
00385     p_buf->end_date =
00386         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
00387 
00388     return p_buf;
00389 }
00390 
00391 /*****************************************************************************
00392  * GetSoutBuffer:
00393  *****************************************************************************/
00394 static block_t *GetSoutBuffer( decoder_t *p_dec )
00395 {
00396     decoder_sys_t *p_sys = p_dec->p_sys;
00397     block_t *p_block;
00398 
00399     p_block = block_New( p_dec, p_sys->i_frame_size );
00400     if( p_block == NULL ) return NULL;
00401 
00402     p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
00403 
00404     p_block->i_length = aout_DateIncrement( &p_sys->end_date,
00405         p_sys->i_frame_length ) - p_block->i_pts;
00406 
00407     return p_block;
00408 }
00409 
00410 /*****************************************************************************
00411  * SyncInfo: parse DTS sync info
00412  *****************************************************************************/
00413 static const unsigned int ppi_dts_samplerate[] =
00414 {
00415     0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
00416     12000, 24000, 48000, 96000, 192000
00417 };
00418 
00419 static const unsigned int ppi_dts_bitrate[] =
00420 {
00421     32000, 56000, 64000, 96000, 112000, 128000,
00422     192000, 224000, 256000, 320000, 384000,
00423     448000, 512000, 576000, 640000, 768000,
00424     896000, 1024000, 1152000, 1280000, 1344000,
00425     1408000, 1411200, 1472000, 1536000, 1920000,
00426     2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/
00427 };
00428 
00429 static int SyncInfo16be( const uint8_t *p_buf,
00430                          unsigned int *pi_audio_mode,
00431                          unsigned int *pi_sample_rate,
00432                          unsigned int *pi_bit_rate,
00433                          unsigned int *pi_frame_length )
00434 {
00435     unsigned int i_frame_size;
00436     unsigned int i_lfe;
00437 
00438     *pi_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
00439     i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
00440                    (p_buf[7] >> 4);
00441 
00442     *pi_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
00443     *pi_sample_rate = (p_buf[8] >> 2) & 0x0f;
00444     *pi_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
00445 
00446     i_lfe = (p_buf[10] >> 1) & 0x03;
00447     if( i_lfe ) *pi_audio_mode |= 0x10000;
00448 
00449     return i_frame_size + 1;
00450 }
00451 
00452 static void BufLeToBe( uint8_t *p_out, const uint8_t *p_in, int i_in )
00453 {
00454     int i;
00455 
00456     for( i = 0; i < i_in/2; i++  )
00457     {
00458         p_out[i*2] = p_in[i*2+1];
00459         p_out[i*2+1] = p_in[i*2];
00460     }
00461 }
00462 
00463 static int Buf14To16( uint8_t *p_out, const uint8_t *p_in, int i_in, int i_le )
00464 {
00465     unsigned char tmp, cur = 0;
00466     int bits_in, bits_out = 0;
00467     int i, i_out = 0;
00468 
00469     for( i = 0; i < i_in; i++  )
00470     {
00471         if( i%2 )
00472         {
00473             tmp = p_in[i-i_le];
00474             bits_in = 8;
00475         }
00476         else
00477         {
00478             tmp = p_in[i+i_le] & 0x3F;
00479             bits_in = 8 - 2;
00480         }
00481 
00482         if( bits_out < 8 )
00483         {
00484             int need = __MIN( 8 - bits_out, bits_in );
00485             cur <<= need;
00486             cur |= ( tmp >> (bits_in - need) );
00487             tmp <<= (8 - bits_in + need);
00488             tmp >>= (8 - bits_in + need);
00489             bits_in -= need;
00490             bits_out += need;
00491         }
00492 
00493         if( bits_out == 8 )
00494         {
00495             p_out[i_out] = cur;
00496             cur = 0;
00497             bits_out = 0;
00498             i_out++;
00499         }
00500 
00501         bits_out += bits_in;
00502         cur <<= bits_in;
00503         cur |= tmp;
00504     }
00505 
00506     return i_out;
00507 }
00508 
00509 static inline int SyncCode( const uint8_t *p_buf )
00510 {
00511     /* 14 bits, little endian version of the bitstream */
00512     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
00513         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
00514         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
00515     {
00516         return VLC_SUCCESS;
00517     }
00518     /* 14 bits, big endian version of the bitstream */
00519     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
00520              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
00521              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
00522     {
00523         return VLC_SUCCESS;
00524     }
00525     /* 16 bits, big endian version of the bitstream */
00526     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
00527              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
00528     {
00529         return VLC_SUCCESS;
00530     }
00531     /* 16 bits, little endian version of the bitstream */
00532     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
00533              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
00534     {
00535         return VLC_SUCCESS;
00536     }
00537     else return VLC_EGENERIC;
00538 }
00539 
00540 static int SyncInfo( const uint8_t *p_buf,
00541                      unsigned int *pi_channels,
00542                      unsigned int *pi_channels_conf,
00543                      unsigned int *pi_sample_rate,
00544                      unsigned int *pi_bit_rate,
00545                      unsigned int *pi_frame_length )
00546 {
00547     unsigned int i_audio_mode;
00548     unsigned int i_frame_size;
00549 
00550     /* 14 bits, little endian version of the bitstream */
00551     if( p_buf[0] == 0xff && p_buf[1] == 0x1f &&
00552         p_buf[2] == 0x00 && p_buf[3] == 0xe8 &&
00553         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
00554     {
00555         uint8_t conv_buf[DTS_HEADER_SIZE];
00556         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 1 );
00557         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
00558                                      pi_bit_rate, pi_frame_length );
00559         i_frame_size = i_frame_size * 8 / 14 * 2;
00560     }
00561     /* 14 bits, big endian version of the bitstream */
00562     else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
00563              p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
00564              p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
00565     {
00566         uint8_t conv_buf[DTS_HEADER_SIZE];
00567         Buf14To16( conv_buf, p_buf, DTS_HEADER_SIZE, 0 );
00568         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
00569                                      pi_bit_rate, pi_frame_length );
00570         i_frame_size = i_frame_size * 8 / 14 * 2;
00571     }
00572     /* 16 bits, big endian version of the bitstream */
00573     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
00574              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
00575     {
00576         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
00577                                      pi_bit_rate, pi_frame_length );
00578     }
00579     /* 16 bits, little endian version of the bitstream */
00580     else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
00581              p_buf[2] == 0x01 && p_buf[3] == 0x80 )
00582     {
00583         uint8_t conv_buf[DTS_HEADER_SIZE];
00584         BufLeToBe( conv_buf, p_buf, DTS_HEADER_SIZE );
00585         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
00586                                      pi_bit_rate, pi_frame_length );
00587     }
00588     else return 0;
00589 
00590     switch( i_audio_mode & 0xFFFF )
00591     {
00592         case 0x0:
00593             /* Mono */
00594             *pi_channels_conf = AOUT_CHAN_CENTER;
00595             break;
00596         case 0x1:
00597             /* Dual-mono = stereo + dual-mono */
00598             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00599                            AOUT_CHAN_DUALMONO;
00600             break;
00601         case 0x2:
00602         case 0x3:
00603         case 0x4:
00604             /* Stereo */
00605             *pi_channels = 2;
00606             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
00607             break;
00608         case 0x5:
00609             /* 3F */
00610             *pi_channels = 3;
00611             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00612                                 AOUT_CHAN_CENTER;
00613             break;
00614         case 0x6:
00615             /* 2F/1R */
00616             *pi_channels = 3;
00617             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00618                                 AOUT_CHAN_REARCENTER;
00619             break;
00620         case 0x7:
00621             /* 3F/1R */
00622             *pi_channels = 4;
00623             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00624                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER;
00625             break;
00626         case 0x8:
00627             /* 2F2R */
00628             *pi_channels = 4;
00629             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00630                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
00631             break;
00632         case 0x9:
00633             /* 3F2R */
00634             *pi_channels = 5;
00635             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00636                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
00637                                 AOUT_CHAN_REARRIGHT;
00638             break;
00639         case 0xA:
00640         case 0xB:
00641             /* 2F2M2R */
00642             *pi_channels = 6;
00643             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00644                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
00645                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
00646             break;
00647         case 0xC:
00648             /* 3F2M2R */
00649             *pi_channels = 7;
00650             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00651                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
00652                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
00653                                 AOUT_CHAN_REARRIGHT;
00654             break;
00655         case 0xD:
00656         case 0xE:
00657             /* 3F2M2R/LFE */
00658             *pi_channels = 8;
00659             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
00660                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
00661                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
00662                                 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
00663             break;
00664 
00665         default:
00666             if( i_audio_mode <= 63 )
00667             {
00668                 /* User defined */
00669                 *pi_channels = 0;
00670                 *pi_channels_conf = 0;
00671             }
00672             else return 0;
00673             break;
00674     }
00675 
00676     if( i_audio_mode & 0x10000 )
00677     {
00678         (*pi_channels)++;
00679         *pi_channels_conf |= AOUT_CHAN_LFE;
00680     }
00681 
00682     if( *pi_sample_rate >= sizeof( ppi_dts_samplerate ) /
00683                            sizeof( ppi_dts_samplerate[0] ) )
00684     {
00685         return 0;
00686     }
00687     *pi_sample_rate = ppi_dts_samplerate[ *pi_sample_rate ];
00688     if( !*pi_sample_rate ) return 0;
00689 
00690     if( *pi_bit_rate >= sizeof( ppi_dts_bitrate ) /
00691                         sizeof( ppi_dts_bitrate[0] ) )
00692     {
00693         return 0;
00694     }
00695     *pi_bit_rate = ppi_dts_bitrate[ *pi_bit_rate ];
00696     if( !*pi_bit_rate ) return 0;
00697 
00698     *pi_frame_length = (*pi_frame_length + 1) * 32;
00699 
00700     return i_frame_size;
00701 }

Generated on Tue Dec 20 10:14:29 2005 for vlc-0.8.4a by  doxygen 1.4.2