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

voc.c

00001 /*****************************************************************************
00002  * voc.c : Creative Voice File (.VOC) demux module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  * $Id: voc.c 11666 2005-07-09 18:54:38Z courmisch $
00006  *
00007  * Authors: Remi Denis-Courmont <rem # videolan.org>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <stdlib.h>                                      /* malloc(), free() */
00028 
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031 #include <vlc/aout.h>
00032 
00033 #include <codecs.h>
00034 
00035 /*****************************************************************************
00036  * Module descriptor
00037  *****************************************************************************/
00038 static int  Open ( vlc_object_t * );
00039 static void Close( vlc_object_t * );
00040 
00041 vlc_module_begin();
00042     set_description( _("VOC demuxer") );
00043     set_category( CAT_INPUT );
00044     set_subcategory( SUBCAT_INPUT_DEMUX );
00045     set_capability( "demux2", 10 );
00046     set_callbacks( Open, Close );
00047 vlc_module_end();
00048 
00049 /*****************************************************************************
00050  * Local prototypes
00051  *****************************************************************************/
00052 static int Demux  ( demux_t * );
00053 static int Control( demux_t *, int i_query, va_list args );
00054 
00055 struct demux_sys_t
00056 {
00057     es_format_t     fmt;
00058     es_out_id_t     *p_es;
00059 
00060     int64_t         i_block_start;
00061     int64_t         i_block_end;
00062 
00063     int64_t         i_loop_offset;
00064     unsigned        i_loop_count;
00065     unsigned        i_silence_countdown;
00066 
00067     date_t          pts;
00068 };
00069 
00070 static const char ct_header[] = "Creative Voice File\x1a";
00071 
00072 /*****************************************************************************
00073  * Open: check file and initializes structures
00074  *****************************************************************************/
00075 static int Open( vlc_object_t * p_this )
00076 {
00077     demux_t     *p_demux = (demux_t*)p_this;
00078     demux_sys_t *p_sys;
00079     uint8_t     *p_buf;
00080     uint16_t    i_data_offset, i_version;
00081 
00082     if( stream_Peek( p_demux->s, &p_buf, 26 ) < 26 )
00083         return VLC_EGENERIC;
00084 
00085     if( memcmp( p_buf, ct_header, 20 ) )
00086         return VLC_EGENERIC;
00087     p_buf += 20;
00088 
00089     i_data_offset = GetWLE( p_buf );
00090     if ( i_data_offset < 26 /* not enough room for full VOC header */ )
00091         return VLC_EGENERIC;
00092     p_buf += 2;
00093 
00094     i_version = GetWLE( p_buf );
00095     if( ( i_version != 0x10A ) && ( i_version != 0x114 ) )
00096         return VLC_EGENERIC; /* unknown VOC version */
00097     p_buf += 2;
00098 
00099     if( GetWLE( p_buf ) != (uint16_t)(0x1234 + ~i_version) )
00100         return VLC_EGENERIC;
00101 
00102     /* We have a valid VOC header */
00103     msg_Dbg( p_demux, "CT Voice file v%d.%d", i_version >> 8,
00104              i_version & 0xff );
00105 
00106     /* skip VOC header */
00107     if( stream_Read( p_demux->s, NULL, i_data_offset ) < i_data_offset )
00108         return VLC_EGENERIC;
00109 
00110     p_demux->pf_demux   = Demux;
00111     p_demux->pf_control = Control;
00112     p_demux->p_sys      = p_sys = malloc( sizeof( demux_sys_t ) );
00113     if( p_sys == NULL )
00114         return VLC_ENOMEM;
00115 
00116     p_sys->i_silence_countdown = p_sys->i_block_start = p_sys->i_block_end =
00117     p_sys->i_loop_count = 0;
00118     p_sys->p_es = NULL;
00119 
00120     date_Init( &p_sys->pts, 1, 1 );
00121     date_Set( &p_sys->pts, 1 );
00122 
00123     es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
00124 
00125     return VLC_SUCCESS;
00126 }
00127 
00128 
00129 static int fmtcmp( es_format_t *ofmt, es_format_t *nfmt )
00130 {
00131     return (ofmt->audio.i_bitspersample != nfmt->audio.i_bitspersample)
00132         || (ofmt->audio.i_rate != nfmt->audio.i_rate)
00133         || (ofmt->audio.i_channels != nfmt->audio.i_channels);
00134 }
00135 
00136 
00137 /*
00138  * Converts old-style VOC sample rates to commonly used ones
00139  * so as not to confuse sound card drivers.
00140  * (I assume 16k, 24k and 32k are never found in .VOC files)
00141  */
00142 static unsigned int fix_voc_sr( unsigned int sr )
00143 {
00144     switch( sr )
00145     {
00146         /*case 8000:
00147             return 8000;*/
00148         case 11111:
00149             return 11025;
00150 
00151         case 22222:
00152             return 22050;
00153 
00154         case 44444:
00155             return 44100;
00156     }
00157     return sr;
00158 }
00159         
00160 
00161 static int ReadBlockHeader( demux_t *p_demux )
00162 {
00163     es_format_t     new_fmt;
00164     uint8_t buf[8];
00165     int32_t i_block_size;
00166     demux_sys_t *p_sys = p_demux->p_sys;
00167 
00168     if( stream_Read( p_demux->s, buf, 4 ) < 4 )
00169         return VLC_EGENERIC; /* EOF */
00170 
00171     i_block_size = GetDWLE( buf ) >> 8;
00172     msg_Dbg( p_demux, "new block: type: %u, size: %u",
00173              (unsigned)*buf, i_block_size );
00174 
00175     es_format_Init( &new_fmt, AUDIO_ES, 0 );
00176 
00177     switch( *buf )
00178     {
00179         case 0: /* not possible : caught with earlier stream_Read */
00180             goto corrupt;
00181 
00182         case 1:
00183             if( i_block_size < 2 )
00184                 goto corrupt;
00185             i_block_size -= 2;
00186 
00187             if( stream_Read( p_demux->s, buf, 2 ) < 2 )
00188                 goto corrupt;
00189 
00190             if( buf[1] )
00191             {
00192                 msg_Err( p_demux, "Unsupported compression" );
00193                 return VLC_EGENERIC;
00194             }
00195 
00196             new_fmt.i_codec = VLC_FOURCC('u','8',' ',' ');
00197             new_fmt.audio.i_rate = fix_voc_sr( 1000000L / (256L - buf[0]) );
00198             new_fmt.audio.i_bytes_per_frame = 1;
00199             new_fmt.audio.i_frame_length = 1;
00200             new_fmt.audio.i_channels = 1;
00201             new_fmt.audio.i_blockalign = 1;
00202             new_fmt.audio.i_bitspersample = 8;
00203             new_fmt.i_bitrate = new_fmt.audio.i_rate * 8;
00204             break;
00205 
00206         case 2: /* data block with same format as the previous one */
00207             if( p_sys->p_es == NULL )
00208                 goto corrupt; /* no previous block! */
00209 
00210             memcpy( &new_fmt, &p_sys->fmt, sizeof( new_fmt ) );
00211             break;
00212 
00213         case 3: /* silence block */
00214             if( ( i_block_size != 3 )
00215              || ( stream_Read( p_demux->s, buf, 3 ) < 3 ) )
00216                 goto corrupt;
00217 
00218             i_block_size = 0;
00219             p_sys->i_silence_countdown = GetWLE( buf );
00220 
00221             new_fmt.i_codec = VLC_FOURCC('u','8',' ',' ');
00222             new_fmt.audio.i_rate = fix_voc_sr( 1000000L / (256L - buf[0]) );
00223             new_fmt.audio.i_bytes_per_frame = 1;
00224             new_fmt.audio.i_frame_length = 1;
00225             new_fmt.audio.i_channels = 1;
00226             new_fmt.audio.i_blockalign = 1;
00227             new_fmt.audio.i_bitspersample = 8;
00228             new_fmt.i_bitrate = new_fmt.audio.i_rate * 8;
00229             break;
00230 
00231         case 6: /* repeat block */
00232             if( ( i_block_size != 2 )
00233              || ( stream_Read( p_demux->s, buf, 2 ) < 2 ) )
00234                 goto corrupt;
00235 
00236             i_block_size = 0;
00237             p_sys->i_loop_count = GetWLE( buf );
00238             p_sys->i_loop_offset = stream_Tell( p_demux->s );
00239             break;
00240 
00241         case 7: /* repeat end block */
00242             if( i_block_size != 0 )
00243                 goto corrupt;
00244 
00245             if( p_sys->i_loop_count > 0 )
00246             {
00247                 if( stream_Seek( p_demux->s, p_sys->i_loop_offset ) )
00248                     msg_Warn( p_demux, "cannot loop: seek failed" );
00249                 else
00250                     p_sys->i_loop_count--;
00251             }
00252             break;
00253 
00254         case 8: 
00255             /* 
00256              * Block 8 is a big kludge to add stereo support to block 1 :
00257              * A block of type 8 is always followed by a block of type 1
00258              * and specifies the number of channels in that 1-block
00259              * (normally block 1 are always mono). In practice, block type 9
00260              * is used for stereo rather than 8
00261              */
00262             if( ( i_block_size != 4 )
00263              || ( stream_Read( p_demux->s, buf, 4 ) < 4 ) )
00264                 goto corrupt;
00265 
00266             if( buf[2] )
00267             {
00268                 msg_Err( p_demux, "Unsupported compression" );
00269                 return VLC_EGENERIC;
00270             }
00271 
00272             new_fmt.i_codec = VLC_FOURCC('u','8',' ',' ');
00273             new_fmt.audio.i_channels = buf[3] + 1; /* can't be nul */
00274             new_fmt.audio.i_rate = 256000000L /
00275                           ((65536L - GetWLE(buf)) * new_fmt.audio.i_channels);
00276             new_fmt.audio.i_bytes_per_frame = new_fmt.audio.i_channels;
00277             new_fmt.audio.i_frame_length = 1;
00278             new_fmt.audio.i_blockalign = new_fmt.audio.i_bytes_per_frame;
00279             new_fmt.audio.i_bitspersample = 8 * new_fmt.audio.i_bytes_per_frame;
00280             new_fmt.i_bitrate = new_fmt.audio.i_rate * 8;
00281 
00282             /* read subsequent block 1 */
00283             if( stream_Read( p_demux->s, buf, 4 ) < 4 )
00284                 return VLC_EGENERIC; /* EOF */
00285         
00286             i_block_size = GetDWLE( buf ) >> 8;
00287             msg_Dbg( p_demux, "new block: type: %u, size: %u",
00288                     (unsigned)*buf, i_block_size );
00289             if( i_block_size < 2 )
00290                 goto corrupt;
00291             i_block_size -= 2;
00292 
00293             if( stream_Read( p_demux->s, buf, 2 ) < 2 )
00294                 goto corrupt;
00295 
00296             if( buf[1] )
00297             {
00298                 msg_Err( p_demux, "Unsupported compression" );
00299                 return VLC_EGENERIC;
00300             }
00301 
00302             break;
00303 
00304         case 9: /* newer data block with channel number and bits resolution */
00305             if( i_block_size < 12 )
00306                 goto corrupt;
00307             i_block_size -= 12;
00308 
00309             if( ( stream_Read( p_demux->s, buf, 8 ) < 8 )
00310              || ( stream_Read( p_demux->s, NULL, 4 ) < 4 ) )
00311                 goto corrupt;
00312 
00313             new_fmt.audio.i_rate = GetDWLE( buf );
00314             new_fmt.audio.i_bitspersample = buf[4];
00315             new_fmt.audio.i_channels = buf[5];
00316 
00317             switch( GetWLE( &buf[6] ) ) /* format */
00318             {
00319                 case 0x0000: /* PCM */
00320                     switch( new_fmt.audio.i_bitspersample )
00321                     {
00322                         case 8:
00323                             new_fmt.i_codec = VLC_FOURCC('u','8',' ',' ');
00324                             break;
00325 
00326                         case 16:
00327                             new_fmt.i_codec = VLC_FOURCC('u','1','6','l');
00328                             break;
00329 
00330                         default:
00331                             msg_Err( p_demux, "Unsupported bit res.: %u bits",
00332                                      new_fmt.audio.i_bitspersample );
00333                             return VLC_EGENERIC;
00334                     }
00335                     break;
00336 
00337                 case 0x0004: /* signed */
00338                     switch( new_fmt.audio.i_bitspersample )
00339                     {
00340                         case 8:
00341                             new_fmt.i_codec = VLC_FOURCC('s','8',' ',' ');
00342                             break;
00343 
00344                         case 16:
00345                             new_fmt.i_codec = VLC_FOURCC('s','1','6','l');
00346                             break;
00347 
00348                         default:
00349                             msg_Err( p_demux, "Unsupported bit res.: %u bits",
00350                                      new_fmt.audio.i_bitspersample );
00351                             return VLC_EGENERIC;
00352                     }
00353                     break;
00354 
00355                 default: 
00356                     msg_Err( p_demux, "Unsupported compression" );
00357                     return VLC_EGENERIC;
00358             }
00359 
00360             new_fmt.audio.i_bytes_per_frame = new_fmt.audio.i_channels
00361                 * (new_fmt.audio.i_bitspersample / 8);
00362             new_fmt.audio.i_frame_length = 1;
00363             new_fmt.audio.i_blockalign = new_fmt.audio.i_bytes_per_frame;
00364             new_fmt.i_bitrate = 8 * new_fmt.audio.i_rate
00365                                      * new_fmt.audio.i_bytes_per_frame;
00366             break;
00367 
00368         default:
00369             msg_Dbg( p_demux, "Unknown block type %u - skipping block",
00370                      (unsigned)*buf);
00371         case 4: /* blocks of non-audio types can be skipped */
00372         case 5:
00373             if( stream_Read( p_demux->s, NULL, i_block_size ) < i_block_size )
00374                 goto corrupt;
00375             i_block_size = 0;
00376             break;
00377     }
00378 
00379     p_sys->i_block_start = stream_Tell( p_demux->s );
00380     p_sys->i_block_end = p_sys->i_block_start + i_block_size;
00381 
00382     if( i_block_size || p_sys->i_silence_countdown )
00383     {
00384         /* we've read a block with data in it - update decoder */
00385         msg_Dbg( p_demux, "fourcc: %4.4s, channels: %d, "
00386                  "freq: %d Hz, bitrate: %dKo/s, blockalign: %d, "
00387                  "bits/samples: %d", (char *)&new_fmt.i_codec,
00388                  new_fmt.audio.i_channels, new_fmt.audio.i_rate,
00389                  new_fmt.i_bitrate / 8192, new_fmt.audio.i_blockalign,
00390                  new_fmt.audio.i_bitspersample );
00391 
00392         if( ( p_sys->p_es != NULL ) && fmtcmp( &p_sys->fmt, &new_fmt ) )
00393         {
00394             msg_Dbg( p_demux, "codec change needed" );
00395             es_out_Del( p_demux->out, p_sys->p_es );
00396             p_sys->p_es = NULL;
00397         }
00398 
00399         if( p_sys->p_es == NULL )
00400         {
00401             memcpy( &p_sys->fmt, &new_fmt, sizeof( p_sys->fmt ) );
00402             date_Change( &p_sys->pts, p_sys->fmt.audio.i_rate, 1 );
00403             p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt );
00404         }
00405     }
00406 
00407     return VLC_SUCCESS;
00408 
00409 corrupt:
00410     msg_Err( p_demux, "corrupted file - halting demux" );
00411     return VLC_EGENERIC;
00412 }
00413 
00414 /*****************************************************************************
00415  * Demux: read packet and send them to decoders
00416  *****************************************************************************
00417  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
00418  *****************************************************************************/
00419 #define SAMPLES_BUFFER 1000
00420 static int Demux( demux_t *p_demux )
00421 {
00422     demux_sys_t *p_sys = p_demux->p_sys;
00423     block_t     *p_block;
00424     int64_t     i_offset, i;
00425 
00426     i_offset = stream_Tell( p_demux->s );
00427 
00428     while( ( i_offset >= p_sys->i_block_end )
00429          && ( p_sys->i_silence_countdown == 0 ) )
00430         if( ReadBlockHeader( p_demux ) != VLC_SUCCESS )
00431             return 0;
00432 
00433     if( p_sys->i_silence_countdown == 0 )
00434     {
00435         i = ( p_sys->i_block_end - i_offset )
00436             / p_sys->fmt.audio.i_bytes_per_frame;
00437         if( i > SAMPLES_BUFFER )
00438             i = SAMPLES_BUFFER;
00439 
00440         p_block = stream_Block( p_demux->s,
00441                                 p_sys->fmt.audio.i_bytes_per_frame * i );
00442         if( p_block == NULL )
00443         {
00444             msg_Warn( p_demux, "cannot read data" );
00445             return 0;
00446         }
00447     }
00448     else
00449     {   /* emulates silence from the stream */
00450         i = p_sys->i_silence_countdown;
00451         if( i > SAMPLES_BUFFER )
00452             i = SAMPLES_BUFFER;
00453 
00454         p_block = block_New( p_demux, i );
00455         if( p_block == NULL )
00456             return VLC_ENOMEM;
00457 
00458         memset( p_block->p_buffer, 0, i );
00459         p_sys->i_silence_countdown -= i;
00460     }
00461 
00462     p_block->i_dts = p_block->i_pts =
00463         date_Increment( &p_sys->pts, p_sys->fmt.audio.i_frame_length * i );
00464 
00465     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
00466 
00467     es_out_Send( p_demux->out, p_sys->p_es, p_block );
00468 
00469     return 1;
00470 }
00471 
00472 /*****************************************************************************
00473  * Close: frees unused data
00474  *****************************************************************************/
00475 static void Close ( vlc_object_t * p_this )
00476 {
00477     demux_sys_t *p_sys  = ((demux_t *)p_this)->p_sys;
00478 
00479     free( p_sys );
00480 }
00481 
00482 /*****************************************************************************
00483  * Control:
00484  *****************************************************************************/
00485 static int Control( demux_t *p_demux, int i_query, va_list args )
00486 {
00487     demux_sys_t *p_sys  = p_demux->p_sys;
00488 
00489     return demux2_vaControlHelper( p_demux->s, p_sys->i_block_start,
00490                                    p_sys->i_block_end,
00491                                    p_sys->fmt.i_bitrate,
00492                                    p_sys->fmt.audio.i_blockalign,
00493                                    i_query, args );
00494 }

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