MpegBitstream.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "MpegBitstream.hxx"
00023 #include "Assert.hxx"
00024 #include <cstring>
00025 #include <iostream>
00026 #include <sstream>
00027 #include <iomanip>
00028
00029 namespace CLAM
00030 {
00031
00032 namespace AudioCodecs
00033 {
00034
00035
00036
00037
00038 const int MpegBitstream::mInputBufferSize = 5*8192;
00039
00040
00041 static std::string MadError(enum mad_error error)
00042 {
00043 switch (error) {
00044 case MAD_ERROR_BUFLEN:
00045 case MAD_ERROR_BUFPTR:
00046
00047 break;
00048
00049 case MAD_ERROR_NOMEM: return ("not enough memory");
00050 case MAD_ERROR_LOSTSYNC: return ("lost synchronization");
00051 case MAD_ERROR_BADLAYER: return ("reserved header layer value");
00052 case MAD_ERROR_BADBITRATE: return ("forbidden bitrate value");
00053 case MAD_ERROR_BADSAMPLERATE: return ("reserved sample frequency value");
00054 case MAD_ERROR_BADEMPHASIS: return ("reserved emphasis value");
00055 case MAD_ERROR_BADCRC: return ("CRC check failed");
00056 case MAD_ERROR_BADBITALLOC: return ("forbidden bit allocation value");
00057 case MAD_ERROR_BADSCALEFACTOR: return ("bad scalefactor index");
00058 case MAD_ERROR_BADFRAMELEN: return ("bad frame length");
00059 case MAD_ERROR_BADBIGVALUES: return ("bad big_values count");
00060 case MAD_ERROR_BADBLOCKTYPE: return ("reserved block_type");
00061 case MAD_ERROR_BADSCFSI: return ("bad scalefactor selection info");
00062 case MAD_ERROR_BADDATAPTR: return ("bad main_data_begin pointer");
00063 case MAD_ERROR_BADPART3LEN: return ("bad audio data length");
00064 case MAD_ERROR_BADHUFFTABLE: return ("bad Huffman table select");
00065 case MAD_ERROR_BADHUFFDATA: return ("Huffman data overrun");
00066 case MAD_ERROR_BADSTEREO: return ("incompatible block_type for JS");
00067 default:;
00068 }
00069 std::ostringstream os;
00070 os << "error 0x" << std::setbase(16) << std::setfill('4') << std::setw(4) << error;
00071 return os.str();
00072 }
00073
00074 MpegBitstream::MpegBitstream()
00075 : mpFile(NULL)
00076 {
00077 mInputBuffer = new unsigned char[mInputBufferSize];
00078 }
00079
00080 MpegBitstream::~MpegBitstream()
00081 {
00082 if ( mInputBuffer )
00083 delete [] mInputBuffer;
00084 }
00085
00086 void MpegBitstream::Init( FILE* fp )
00087 {
00088 mpFile = fp;
00089 Init();
00090 }
00091
00092 void MpegBitstream::Init()
00093 {
00094 mad_stream_init( &mBitstream );
00095 mad_frame_init( &mCurrentFrame );
00096 mad_synth_init( &mMpegSynth );
00097 mad_timer_reset( &mStreamTimer );
00098 mFatalError = false;
00099 }
00100
00101 TTime MpegBitstream::Finish()
00102 {
00103 mad_synth_finish( &mMpegSynth );
00104 mad_frame_finish( &mCurrentFrame );
00105 mad_stream_finish( &mBitstream );
00106
00107 return (TTime)mad_timer_count( mStreamTimer, MAD_UNITS_MILLISECONDS );
00108 }
00109
00110 bool MpegBitstream::EOS()
00111 {
00112 if ( feof( mpFile ) )
00113 return true;
00114 return false;
00115 }
00116
00117 bool MpegBitstream::FatalError()
00118 {
00119 return mFatalError || ferror(mpFile)!=0;
00120 }
00121
00122 bool MpegBitstream::EnsureEnoughBufferData()
00123 {
00124 bool firstFrameAfterSeek = mBitstream.buffer == NULL;
00125 bool lastDecodeNeededMoreData = mBitstream.error == MAD_ERROR_BUFLEN;
00126 if ( not firstFrameAfterSeek and not lastDecodeNeededMoreData) return true;
00127
00128 TSize remaining = 0;
00129 if (not firstFrameAfterSeek)
00130 {
00131 remaining = mBitstream.bufend - mBitstream.next_frame;
00132 memmove( mInputBuffer, mBitstream.next_frame, remaining );
00133 }
00134 unsigned char * readStart = mInputBuffer + remaining;
00135 TSize readSize = mInputBufferSize - remaining;
00136 mBufferFileOffset = ftell(mpFile) - remaining;
00137 TSize actuallyRead = fread( readStart, sizeof(unsigned char), readSize, mpFile );
00138
00139 if ( actuallyRead == 0 ) return false;
00140
00141 if ( actuallyRead < readSize )
00142 {
00143 CLAM_ASSERT( readStart + actuallyRead + MAD_BUFFER_GUARD <= mInputBuffer + mInputBufferSize,
00144 "Whoops! no room left for buffer guard bytes" );
00145
00146 memset(readStart+actuallyRead, 0, MAD_BUFFER_GUARD);
00147 actuallyRead += MAD_BUFFER_GUARD;
00148 }
00149
00150 mad_stream_buffer( &mBitstream, mInputBuffer, actuallyRead+remaining );
00151 mBitstream.error = MAD_ERROR_NONE;
00152 return true;
00153 }
00154
00157 bool MpegBitstream::NextFrame()
00158 {
00159 while( not ferror(mpFile) )
00160 {
00161 if (not EnsureEnoughBufferData()) return false;
00162
00163 int error = mad_frame_decode(&mCurrentFrame, &mBitstream);
00164 if (error != -1)
00165 {
00166
00167
00168 mad_timer_add( &mStreamTimer, mCurrentFrame.header.duration );
00169 return true;
00170 }
00171
00172 if ( MAD_RECOVERABLE( mBitstream.error ) )
00173 {
00174
00175 continue;
00176 }
00177 if ( mBitstream.error == MAD_ERROR_BUFLEN ) continue;
00178
00179 mFatalError = true;
00180 std::cerr << "MP3 fatal error: " << MadError(mBitstream.error) << std::endl;
00181 return false;
00182 }
00183 return false;
00184 }
00185
00186 unsigned long MpegBitstream::CurrentFrameFileOffset() const
00187 {
00188 unsigned long frameOffset = mBitstream.this_frame - mInputBuffer;
00189 return mBufferFileOffset + frameOffset;
00190 }
00191
00192 void MpegBitstream::SynthesizeCurrent()
00193 {
00194 mad_synth_frame( &mMpegSynth, &mCurrentFrame );
00195 }
00196
00197 struct mad_frame& MpegBitstream::CurrentFrame()
00198 {
00199 return mCurrentFrame;
00200 }
00201
00202 struct mad_synth& MpegBitstream::CurrentSynthesis()
00203 {
00204 return mMpegSynth;
00205 }
00206
00207 }
00208
00209 }
00210