MpegBitstream.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include "MpegBitstream.hxx"
00023 #include "Assert.hxx"
00024 #include <cstring>
00025 #include <iostream>
00026 
00027 namespace CLAM
00028 {
00029 
00030 namespace AudioCodecs
00031 {
00032         // MRJ: This number was extracted from Underbit's own
00033         // mp3 player code ( mad-0.14.2b2, player.c:86 ). As they
00034         // say: 40000 bytes is worth 2.5 secs of audio on a stream
00035         // with 128 kpbs, 1s with 320 kbps
00036         const int MpegBitstream::mInputBufferSize = 5*8192;
00037         
00038         MpegBitstream::MpegBitstream( FILE* bitstream )
00039                 : mpFile( bitstream )
00040         {
00041                 mInputBuffer = new unsigned char[mInputBufferSize];
00042         }
00043 
00044         MpegBitstream::MpegBitstream()
00045         {
00046                 mInputBuffer = new unsigned char[mInputBufferSize];
00047         }
00048         
00049         MpegBitstream::~MpegBitstream()
00050         {
00051                 if ( mInputBuffer )
00052                         delete [] mInputBuffer;
00053         }
00054 
00055         void MpegBitstream::Init( FILE* fp )
00056         {
00057                 mpFile = fp;
00058                 Init();
00059         }
00060 
00061         void MpegBitstream::Init()
00062         {
00063                 mad_stream_init( &mBitstream );
00064                 mad_frame_init( &mCurrentFrame );
00065                 mad_synth_init( &mMpegSynth );
00066                 mad_timer_reset( &mStreamTimer );
00067                 mFatalError = false;
00068         }
00069 
00070         TTime MpegBitstream::Finish()
00071         {
00072                 mad_synth_finish( &mMpegSynth );
00073                 mad_frame_finish( &mCurrentFrame );
00074                 mad_stream_finish( &mBitstream );
00075 
00076                 return (TTime)mad_timer_count( mStreamTimer, MAD_UNITS_MILLISECONDS );
00077         }
00078 
00079         bool MpegBitstream::EOS()
00080         {
00081                 if ( feof( mpFile ) ) // no more frames
00082                         return true;
00083                 return false;
00084                                 
00085         }
00086 
00087         bool MpegBitstream::NextFrame()
00088         {
00089                 bool validFrameFound = false;
00090 
00091                 while( !validFrameFound && !FatalError() )
00092                 {
00093                         // the first condition ( mStream.buffer == NULL ) handles the first time we 
00094                         // seek a new Mpeg frame since the stream object does not have a buffer attached.                       
00095                         // Last time we tried to decode a frame, there wasn't enough data on the buffer,
00096                         // so we must re-read from the file.
00097 
00098                         if ( mBitstream.buffer == NULL 
00099                              || mBitstream.error == MAD_ERROR_BUFLEN ) 
00100                         {
00101 
00102                                 TSize readSize, remaining;
00103                                 unsigned char*  readStart;
00104                         
00105                                 if ( mBitstream.next_frame != NULL )
00106                                 {
00107                                         remaining = mBitstream.bufend - mBitstream.next_frame;
00108                                         memmove( mInputBuffer, mBitstream.next_frame, remaining );
00109                                         readStart = mInputBuffer+remaining;
00110                                         readSize = mInputBufferSize - remaining;
00111                                 }
00112                                 else
00113                                 {
00114                                         readSize = mInputBufferSize;
00115                                         readStart = mInputBuffer;
00116                                         remaining = 0;
00117                                 }
00118                                 
00119                                 TSize readbytes = fread( readStart, sizeof(unsigned char), readSize, mpFile );
00120                         
00121                                 if ( readbytes == 0 ) // Nothing read
00122                                         return false;
00123                                 else if ( readbytes < readSize ) // Less bytes than expected were read
00124                                 {
00125                                         CLAM_DEBUG_ASSERT( readStart + readbytes + MAD_BUFFER_GUARD <=
00126                                                            mInputBuffer + mInputBufferSize,
00127                                                            "Whoops! no room left for buffer guard bytes" );
00128                                         unsigned char* startPadding = readStart + readbytes;
00129 
00130                                         for ( int i = 0; i < MAD_BUFFER_GUARD; i++ )
00131                                                 startPadding[i] = 0;
00132 
00133                                         readSize = readbytes + MAD_BUFFER_GUARD;
00134                                 }
00135                                 else
00136                                         readSize = readbytes;
00137 
00138                         
00139                                 mad_stream_buffer( &mBitstream, mInputBuffer, readSize+remaining );
00140                                 mBitstream.error = MAD_ERROR_NONE;
00141                         }
00142                         
00143                         
00144                         if (mad_frame_decode( &mCurrentFrame, &mBitstream )==-1 ) // error
00145                         {
00146                                 // some *recoverable* error occured
00147                                 if ( !MAD_RECOVERABLE( mBitstream.error ) )
00148                                         if ( mBitstream.error != MAD_ERROR_BUFLEN )                                     
00149                                                 mFatalError = true;                                                             
00150                         }
00151                         else // frame was decoded right
00152                         {
00153                                 // we signal that a good frame has been decoded
00154                                 validFrameFound = true;
00155                                 // we add this frame duration to the bitstream internal timer
00156                                 mad_timer_add( &mStreamTimer, mCurrentFrame.header.duration );
00157                         }
00158 
00159 
00160                 }
00161 
00162                 return validFrameFound;
00163 
00164         }
00165 
00166         bool MpegBitstream::FatalError()
00167         {
00168                 return mFatalError || ferror(mpFile)!=0;
00169         }
00170 
00171         bool MpegBitstream::SynthesizeCurrent()
00172         {
00173                 mad_synth_frame( &mMpegSynth, &mCurrentFrame );
00174 
00175                 return true;
00176         }
00177 
00178         struct mad_frame& MpegBitstream::CurrentFrame()
00179         {
00180                 return mCurrentFrame;
00181         }
00182 
00183         struct mad_synth& MpegBitstream::CurrentSynthesis()
00184         {
00185                 return mMpegSynth;
00186         }
00187         
00188 }
00189 
00190 }
00191 

Generated on Tue Aug 12 22:33:43 2008 for CLAM by  doxygen 1.5.5