CLAM-Development
1.1
|
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