Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members
MadMP3Decoder.cpp
00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: MadMP3Decoder.cpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 #include "MadMP3Decoder.hpp" 00045 #include "Frame.hpp" 00046 #include "UncompressedAudioFrame.hpp" 00047 00048 00049 MadMP3Decoder::MadMP3Decoder(AudioESInfo* es) { 00050 00051 this->es = es; 00052 strcpy(name,"MadMP3Decoder"); 00053 FrameCount = 0; 00054 Status = 0; 00055 initialized = false; 00056 lastTS=0; 00057 inputBuffer = new unsigned char[MAD_INPUT_BUFFER_SIZE + MAD_BUFFER_GUARD]; 00058 } 00059 00060 00061 MadMP3Decoder::~MadMP3Decoder() { 00062 if (initialized) { 00063 mad_synth_finish(&Synth); 00064 mad_frame_finish(&madFrame); 00065 mad_stream_finish(&Stream); 00066 } 00067 delete [] inputBuffer; 00068 } 00069 00070 00071 void MadMP3Decoder::initialize() { 00072 /* First the structures used by libmad must be initialized. */ 00073 mad_stream_init(&Stream); 00074 mad_frame_init(&madFrame); 00075 mad_synth_init(&Synth); 00076 #ifndef WINCE 00077 mad_timer_reset(&Timer); 00078 #endif 00079 00080 guardPtr = NULL; 00081 00082 initialized=true; 00083 numInFrames = 0; 00084 } 00085 00086 00087 00088 /***************************************************************/ 00089 list < Frame * > MadMP3Decoder::adapt(Frame * frm) { 00090 list < Frame * >tmp; 00091 u32 thisCTS; 00092 int thisSec; 00093 00094 //initialize decoder 00095 if (numInFrames == 0) { 00096 initialize(); 00097 } 00098 00099 if (frm->getAU() == NULL) return tmp; 00100 00101 thisCTS = frm->getAU()->cts; 00102 thisSec = (int)floor((double)thisCTS / es->getMediaTimeScale()); 00103 dprintf_full("MadMP3Decoder::adapt frame %i (size %i) CTS %i, VOP increment %i, samplerate %i Hz Channels: %i\n", numInFrames, frm->getAU()->size, thisCTS, es->getVOPTimeIncrement(), es->getSampleRate(), es->getAudioChannels()); 00104 00105 numInFrames++; 00106 00107 //FIXME: assert(isAudioFrame) 00108 00109 assert(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN); 00110 00111 if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) { 00112 size_t ReadSize, Remaining; 00113 unsigned char *ReadStart; 00114 00115 if(Stream.next_frame!=NULL) { 00116 Remaining = Stream.bufend - Stream.next_frame; 00117 //dprintf_full("MadMP3Decoder::adapt ... pre-pend old data %i bytes (bufsize %i offs %i)\n",Remaining, Stream.bufend - inputBuffer, Stream.next_frame - inputBuffer); 00118 memmove(inputBuffer, Stream.next_frame, Remaining); //move to beginning 00119 ReadStart = inputBuffer+Remaining; //add new data behind old data 00120 ReadSize = MAD_INPUT_BUFFER_SIZE - Remaining; //space left 00121 } 00122 else { 00123 ReadSize = MAD_INPUT_BUFFER_SIZE; 00124 ReadStart = inputBuffer; 00125 Remaining = 0; 00126 } 00127 //dprintf_full("MadMP3Decoder::adapt ... adding incoming frame to decoding buffer (adding %i bytes)\n",frm->getAU()->size); 00128 assert( frm->getAU()->size <= ReadSize); 00129 memcpy(ReadStart, frm->getAU()->payload, frm->getAU()->size); 00130 ReadSize = (size_t)frm->getAU()->size; 00131 00132 if(0==1 /* EOF */) { 00133 dprintf_full("MadMP3Decoder::adapt ... adding guard 8 zero bytes\n"); 00134 guardPtr=ReadStart+ReadSize; 00135 memset(guardPtr,0,MAD_BUFFER_GUARD); 00136 ReadSize+=MAD_BUFFER_GUARD; 00137 } 00138 00139 /* Pipe the new buffer content to libmad's stream decoder 00140 * facility. 00141 */ 00142 mad_stream_buffer(&Stream, inputBuffer, ReadSize+Remaining); 00143 Stream.error=MAD_ERROR_NONE; 00144 } 00145 00146 00147 lastTS = thisCTS; 00148 pAU = new AU(frm->getAU()); 00149 pAU->cts = pAU->dts = lastTS; //we are always a little behind... 00150 //lastTS += (u32)((es->getMediaTimeScale()/(float)es->getSampleRate())*Synth.pcm.length); 00151 pAU->size = 0; 00152 u8 *outputBuffer = NULL; 00153 00154 do { 00155 //dprintf_full("MadMP3Decoder::adapt ...decoding lastBufSize %i offs %i)\n",Stream.bufend - inputBuffer, Stream.next_frame - inputBuffer); 00156 00157 if(mad_frame_decode(&madFrame, &Stream)) { 00158 if(MAD_RECOVERABLE(Stream.error)) { 00159 /* Do not print a message if the error is a loss of 00160 * synchronization and this loss is due to the end of 00161 * stream guard bytes. (See the comments marked {3} 00162 * supra for more informations about guard bytes.) 00163 */ 00164 if((Stream.error!=MAD_ERROR_LOSTSYNC) || (Stream.this_frame!=guardPtr)) { 00165 dprintf_err("MadMP3Decoder::adapt: recoverable frame level error (%s) at offs %i\n",mad_stream_errorstr(&Stream),Stream.next_frame-inputBuffer); 00166 } 00167 //lastTS += (u32)((es->getMediaTimeScale()/(float)es->getSampleRate())*1152); 00168 continue; 00169 } 00170 else 00171 if(Stream.error==MAD_ERROR_BUFLEN) { 00172 //this is not serious, just not enough data.... going into next round.... 00173 00174 //dprintf_err("MadMP3Decoder::adapt: recoverable frame level error BUFLEN (%s) at offs %i\n",mad_stream_errorstr(&Stream),Stream.next_frame-inputBuffer); 00175 break; 00176 } else 00177 { 00178 dprintf_err("MadMP3Decoder::adapt: unrecoverable frame level error (%s).\n",mad_stream_errorstr(&Stream)); 00179 Status=1; 00180 ::exit(1); 00181 } 00182 } 00183 00184 00185 if(FrameCount==0) //the first is representative for all other frames 00186 PrintFrameInfo(&madFrame.header); 00187 00188 FrameCount++; 00189 #ifndef WINCE 00190 mad_timer_add(&Timer,madFrame.header.duration); 00191 #endif 00192 mad_synth_frame(&Synth,&madFrame); 00193 00194 //dprintf_full("MadMP3Decoder::adapt sampling %i raw pcm samples\n", Synth.pcm.length); 00195 00196 //DO NOT SEND 1st FRAME (the header) to the audio-output 00197 #ifdef WINCE 00198 if (FrameCount == 1) { 00199 outputBuffer = NULL; 00200 } else { 00201 #endif 00202 00203 u32 numChannels = es->getAudioChannels(); 00204 pAU->size += Synth.pcm.length * 2 * numChannels; //if it's 16bit stereo --> * 4 00205 outputBuffer = (u8*)realloc(outputBuffer, pAU->size); //get more space, if necessary 00206 pAU->payload = outputBuffer; 00207 u8 *outputPtr = outputBuffer + pAU->size - Synth.pcm.length * 2 * numChannels; // begin of new block 00208 00209 for(int i=0;i<Synth.pcm.length;i++) { 00210 signed short Sample; 00211 00212 /* Left channel */ 00213 Sample=MadFixedToSshort(Synth.pcm.samples[0][i]); 00214 *(outputPtr++)=Sample&0xff; //little endian, so toggle 00215 *(outputPtr++)=Sample>>8; 00216 00217 if (numChannels == 2) { //stereo 00218 /* Right channel. If the decoded stream is monophonic then 00219 * the right output channel is the same as the left one. 00220 */ 00221 if(MAD_NCHANNELS(&madFrame.header)==2) 00222 Sample=MadFixedToSshort(Synth.pcm.samples[1][i]); 00223 *(outputPtr++)=Sample&0xff; //little endian, so toggle 00224 *(outputPtr++)=Sample>>8; 00225 } 00226 } 00227 #ifdef WINCE 00228 } 00229 #endif 00230 00231 } while(1); 00232 00233 00234 if (outputBuffer) { 00235 dprintf_full("MadMP3Decoder::adapt got full decoded (raw pcm) frame number %li (CTS %i) size %i bytes!\n", FrameCount, pAU->cts, pAU->size); 00236 UncompressedAudioFrame * decFrame = new UncompressedAudioFrame(Frame::RAW_AUDIO); 00237 decFrame->setAU(pAU); 00238 decFrame->setMediaTimeScale(frm->getMediaTimeScale()); 00239 tmp.push_back(decFrame); 00240 } 00241 return tmp; 00242 } 00243 00244 00245 /**************************************************************************** 00246 * Converts a sample from libmad's fixed point number format to a signed * 00247 * short (16 bits). * 00248 ****************************************************************************/ 00249 signed short MadMP3Decoder::MadFixedToSshort(mad_fixed_t Fixed) { 00250 /* A fixed point number is formed of the following bit pattern: 00251 * 00252 * SWWWFFFFFFFFFFFFFFFFFFFFFFFFFFFF 00253 * MSB LSB 00254 * S ==> Sign (0 is positive, 1 is negative) 00255 * W ==> Whole part bits 00256 * F ==> Fractional part bits 00257 * 00258 * This pattern contains MAD_F_FRACBITS fractional bits, one 00259 * should alway use this macro when working on the bits of a fixed 00260 * point number. It is not guaranteed to be constant over the 00261 * different platforms supported by libmad. 00262 * 00263 * The signed short value is formed, after clipping, by the least 00264 * significant whole part bit, followed by the 15 most significant 00265 * fractional part bits. Warning: this is a quick and dirty way to 00266 * compute the 16-bit number, madplay includes much better 00267 * algorithms. 00268 */ 00269 00270 /* Clipping */ 00271 if(Fixed>=MAD_F_ONE) 00272 return(SHRT_MAX); 00273 if(Fixed<=-MAD_F_ONE) 00274 return(-SHRT_MAX); 00275 00276 /* Conversion. */ 00277 Fixed=Fixed>>(MAD_F_FRACBITS-15); 00278 return((signed short)Fixed); 00279 } 00280 00281 00282 /**************************************************************************** 00283 * Print human readable informations about an audio MPEG frame. * 00284 ****************************************************************************/ 00285 void MadMP3Decoder::PrintFrameInfo(struct mad_header *Header) { 00286 const char *Layer, 00287 *Mode, 00288 *Emphasis; 00289 00290 /* Convert the layer number to it's printed representation. */ 00291 switch(Header->layer) { 00292 case MAD_LAYER_I: 00293 Layer="I"; 00294 break; 00295 case MAD_LAYER_II: 00296 Layer="II"; 00297 break; 00298 case MAD_LAYER_III: 00299 Layer="III"; 00300 break; 00301 default: 00302 Layer="(unexpected layer value)"; 00303 break; 00304 } 00305 00306 /* Convert the audio mode to it's printed representation. */ 00307 switch(Header->mode) { 00308 case MAD_MODE_SINGLE_CHANNEL: 00309 Mode="single channel"; 00310 break; 00311 case MAD_MODE_DUAL_CHANNEL: 00312 Mode="dual channel"; 00313 break; 00314 case MAD_MODE_JOINT_STEREO: 00315 Mode="joint (MS/intensity) stereo"; 00316 break; 00317 case MAD_MODE_STEREO: 00318 Mode="normal LR stereo"; 00319 break; 00320 default: 00321 Mode="(unexpected mode value)"; 00322 break; 00323 } 00324 00325 /* Convert the emphasis to it's printed representation. Note that 00326 * the MAD_EMPHASIS_RESERVED enumeration value appeared in libmad 00327 * version 0.15.0b. 00328 */ 00329 switch(Header->emphasis) { 00330 case MAD_EMPHASIS_NONE: 00331 Emphasis="no"; 00332 break; 00333 case MAD_EMPHASIS_50_15_US: 00334 Emphasis="50/15 us"; 00335 break; 00336 case MAD_EMPHASIS_CCITT_J_17: 00337 Emphasis="CCITT J.17"; 00338 break; 00339 #if (MAD_VERSION_MAJOR>=1) || \ 00340 ((MAD_VERSION_MAJOR==0) && (MAD_VERSION_MINOR>=15)) 00341 case MAD_EMPHASIS_RESERVED: 00342 Emphasis="reserved(!)"; 00343 break; 00344 #endif 00345 default: 00346 Emphasis="(unexpected emphasis value)"; 00347 break; 00348 } 00349 00350 dprintf_full("MadMP3Decoder::PrintFrame %lu kb/s audio MPEG layer %s stream %s CRC, " 00351 "%s with %s emphasis at %d Hz sample rate\n", 00352 Header->bitrate,Layer, 00353 Header->flags&MAD_FLAG_PROTECTION?"with":"without", 00354 Mode,Emphasis,Header->samplerate); 00355 return; 00356 } 00357