MadMP3Decoder Class Reference

Adaptor class MadMP3Decoder decodes bypassing MPEG-1/2 layer 3 audio packets to raw PCM sample blocks using the libmad <short description="">. More...

#include <MadMP3Decoder.hpp>

Inheritance diagram for MadMP3Decoder:

AudioAdaptor Adaptor List of all members.

Public Member Functions

 MadMP3Decoder (AudioESInfo *es)
list< Frame * > adapt (Frame *frm)
 Accepts as input a frame, and checks if it can adapt the frame, If the frame is modified, a new Frame object is created and inserted into the return list.
Adaptorclone ()
 Create a shallow copy of the Adaptor.
void initialize ()
 Initialize internal data structures.
list< Frame * > close ()
 Close and destroy an Adaptor.
u32 getTranscodingCosts () const
 returns adaptation costs (CPU only).

Static Protected Member Functions

signed short MadFixedToSshort (mad_fixed_t Fixed)
void PrintFrameInfo (struct mad_header *Header)

Protected Attributes

mad_stream Stream
mad_frame madFrame
mad_synth Synth
mad_timer_t Timer
unsigned char * inputBuffer
unsigned char * guardPtr
int Status
unsigned long FrameCount
u32 numInFrames
bool initialized
u32 lastTS
AU * pAU

Detailed Description

Adaptor class MadMP3Decoder decodes bypassing MPEG-1/2 layer 3 audio packets to raw PCM sample blocks using the libmad <short description="">.

Author:
Michael Kropfberger
Version:
Id
MadMP3Decoder.hpp,v 1.3 2006/01/20 15:37:17 mkropfbe Exp

Definition at line 67 of file MadMP3Decoder.hpp.


Member Function Documentation

list< Frame * > MadMP3Decoder::adapt Frame frm  )  [virtual]
 

Accepts as input a frame, and checks if it can adapt the frame, If the frame is modified, a new Frame object is created and inserted into the return list.

This new frame is returned only, if the size of the payload is larger than zero. If the frame was not modified, it is also inserted into the list. For more complex adaptors, it will happen, that the adaptor caches up one complete GOP and returns the full GOP in network order. A caching adaptor has to create deep-copies for each frames. Never directly modify the payload of the input frm, always create copies!!!

Parameters:
frm object to adapt. An Adaptor is never allowed to free the input frame. This has to be done in the caller.
Returns:
List of adapted Frame objects

Reimplemented from Adaptor.

Definition at line 89 of file MadMP3Decoder.cpp.

References Frame::getAU(), Frame::getMediaTimeScale(), initialize(), Frame::setAU(), and Frame::setMediaTimeScale().

00089 { 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 }

Adaptor* MadMP3Decoder::clone  )  [inline, virtual]
 

Create a shallow copy of the Adaptor.

Creates an Adaptor with the same setup (without copying the current status).

Returns:
An Adaptor object.

Implements Adaptor.

Definition at line 81 of file MadMP3Decoder.hpp.

00081 { return new MadMP3Decoder(es); };

list< Frame * > MadMP3Decoder::close  )  [inline, virtual]
 

Close and destroy an Adaptor.

Releases all internally buffered frame objects, and deallocate all allocated memory. The Adaptor must not be used after calling the close method!!!

Returns:
List of adapted Frame objects.

Reimplemented from Adaptor.

Definition at line 85 of file MadMP3Decoder.hpp.

00085 { 00086 list < Frame * >tmp; 00087 return tmp; 00088 };

u32 MadMP3Decoder::getTranscodingCosts  )  const [inline, virtual]
 

returns adaptation costs (CPU only).

This adaptor causes hd costs, which are currently ignored. as CPU side effect we can only guess but it should depend on the bytes of the video

Implements Adaptor.

Definition at line 95 of file MadMP3Decoder.hpp.

00095 { 00096 return es->getAvgBandwidth()/8; 00097 }

void MadMP3Decoder::initialize  )  [virtual]
 

Initialize internal data structures.

Implements Adaptor.

Definition at line 71 of file MadMP3Decoder.cpp.

Referenced by adapt().

00071 { 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 }


The documentation for this class was generated from the following files: