liveMedia/AC3AudioStreamFramer.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2008 Live Networks, Inc.  All rights reserved.
00018 // A filter that breaks up an AC3 audio elementary stream into frames
00019 // Implementation
00020 
00021 #include "AC3AudioStreamFramer.hh"
00022 #include "StreamParser.hh"
00023 #include <GroupsockHelper.hh>
00024 
00026 
00027 class AC3FrameParams {
00028 public:
00029   AC3FrameParams() : samplingFreq(0) {}
00030   // 8-byte header at the start of each frame:
00031   //  u_int32_t hdr0, hdr1;
00032   unsigned hdr0, hdr1;
00033 
00034   // parameters derived from the headers
00035   unsigned kbps, samplingFreq, frameSize;
00036 
00037   void setParamsFromHeader();
00038 };
00039 
00040 class AC3AudioStreamParser: public StreamParser {
00041 public:
00042   AC3AudioStreamParser(AC3AudioStreamFramer* usingSource,
00043                         FramedSource* inputSource);
00044   virtual ~AC3AudioStreamParser();
00045 
00046 public:
00047   Boolean testStreamCode(unsigned char ourStreamCode,
00048                          unsigned char* ptr, unsigned size);
00049      // returns True iff the initial stream code is ours
00050   unsigned parseFrame(unsigned& numTruncatedBytes);
00051      // returns the size of the frame that was acquired, or 0 if none was
00052 
00053   void registerReadInterest(unsigned char* to, unsigned maxSize);
00054 
00055   AC3FrameParams const& currentFrame() const { return fCurrentFrame; }
00056 
00057   Boolean haveParsedAFrame() const { return fHaveParsedAFrame; }
00058   void readAndSaveAFrame();
00059 
00060 private:
00061   static void afterGettingSavedFrame(void* clientData, unsigned frameSize,
00062                                      unsigned numTruncatedBytes,
00063                                      struct timeval presentationTime,
00064                                      unsigned durationInMicroseconds);
00065   void afterGettingSavedFrame1(unsigned frameSize);
00066   static void onSavedFrameClosure(void* clientData);
00067   void onSavedFrameClosure1();
00068 
00069 private:
00070   AC3AudioStreamFramer* fUsingSource;
00071   unsigned char* fTo;
00072   unsigned fMaxSize;
00073 
00074   Boolean fHaveParsedAFrame;
00075   unsigned char* fSavedFrame;
00076   unsigned fSavedFrameSize;
00077   char fSavedFrameFlag;
00078 
00079   // Parameters of the most recently read frame:
00080   AC3FrameParams fCurrentFrame;
00081 };
00082 
00083 
00085 
00086 AC3AudioStreamFramer::AC3AudioStreamFramer(UsageEnvironment& env,
00087                                            FramedSource* inputSource,
00088                                            unsigned char streamCode)
00089   : FramedFilter(env, inputSource), fOurStreamCode(streamCode) {
00090   // Use the current wallclock time as the initial 'presentation time':
00091   gettimeofday(&fNextFramePresentationTime, NULL);
00092 
00093   fParser = new AC3AudioStreamParser(this, inputSource);
00094 }
00095 
00096 AC3AudioStreamFramer::~AC3AudioStreamFramer() {
00097   delete fParser;
00098 }
00099 
00100 AC3AudioStreamFramer*
00101 AC3AudioStreamFramer::createNew(UsageEnvironment& env,
00102                                 FramedSource* inputSource,
00103                                 unsigned char streamCode) {
00104   // Need to add source type checking here???  #####
00105   return new AC3AudioStreamFramer(env, inputSource, streamCode);
00106 }
00107 
00108 unsigned AC3AudioStreamFramer::samplingRate() {
00109   if (!fParser->haveParsedAFrame()) {
00110     // Because we haven't yet parsed a frame, we don't yet know the input
00111     // stream's sampling rate.  So, we first need to read a frame
00112     // (into a special buffer that we keep around for later use).
00113     fParser->readAndSaveAFrame();
00114   }
00115 
00116   return fParser->currentFrame().samplingFreq;
00117 }
00118 
00119 void AC3AudioStreamFramer::flushInput() {
00120   fParser->flushInput();
00121 }
00122 
00123 void AC3AudioStreamFramer::doGetNextFrame() {
00124   fParser->registerReadInterest(fTo, fMaxSize);
00125   parseNextFrame();
00126 }
00127 
00128 #define MILLION 1000000
00129 
00130 struct timeval AC3AudioStreamFramer::currentFramePlayTime() const {
00131   AC3FrameParams const& fr = fParser->currentFrame();
00132   unsigned const numSamples = 1536;
00133   unsigned const freq = fr.samplingFreq;
00134 
00135   // result is numSamples/freq
00136   unsigned const uSeconds = (freq == 0) ? 0
00137     : ((numSamples*2*MILLION)/freq + 1)/2; // rounds to nearest integer
00138 
00139   struct timeval result;
00140   result.tv_sec = uSeconds/MILLION;
00141   result.tv_usec = uSeconds%MILLION;
00142   return result;
00143 }
00144 
00145 void AC3AudioStreamFramer
00146 ::handleNewData(void* clientData, unsigned char* ptr, unsigned size,
00147                 struct timeval /*presentationTime*/) {
00148   AC3AudioStreamFramer* framer = (AC3AudioStreamFramer*)clientData;
00149   framer->handleNewData(ptr, size);
00150 }
00151 
00152 void AC3AudioStreamFramer
00153 ::handleNewData(unsigned char* ptr, unsigned size) {
00154   if (!fParser->testStreamCode(fOurStreamCode, ptr, size)) {
00155     // This block of data is not for us; try again:
00156     parseNextFrame();
00157     return;
00158   }
00159 
00160   // Now that we know that this data is for us, get the next frame:
00161   parseNextFrame();
00162 }
00163 
00164 void AC3AudioStreamFramer::parseNextFrame() {
00165   unsigned acquiredFrameSize = fParser->parseFrame(fNumTruncatedBytes);
00166   if (acquiredFrameSize > 0) {
00167     // We were able to acquire a frame from the input.
00168     // It has already been copied to the reader's space.
00169     fFrameSize = acquiredFrameSize;
00170 
00171     // Also set the presentation time, and increment it for next time,
00172     // based on the length of this frame:
00173     fPresentationTime = fNextFramePresentationTime;
00174 
00175     struct timeval framePlayTime = currentFramePlayTime();
00176     fDurationInMicroseconds = framePlayTime.tv_sec*MILLION + framePlayTime.tv_usec;
00177     fNextFramePresentationTime.tv_usec += framePlayTime.tv_usec;
00178     fNextFramePresentationTime.tv_sec
00179       += framePlayTime.tv_sec + fNextFramePresentationTime.tv_usec/MILLION;
00180     fNextFramePresentationTime.tv_usec %= MILLION;
00181 
00182     // Call our own 'after getting' function.  Because we're not a 'leaf'
00183     // source, we can call this directly, without risking infinite recursion.
00184     afterGetting(this);
00185   } else {
00186     // We were unable to parse a complete frame from the input, because:
00187     // - we had to read more data from the source stream, or
00188     // - the source stream has ended.
00189   }
00190 }
00191 
00192 
00194 
00195 static int const kbpsTable[] = {32,  40,  48,  56,  64,  80,  96, 112,
00196                                 128, 160, 192, 224, 256, 320, 384, 448,
00197                                 512, 576, 640};
00198 
00199 void AC3FrameParams::setParamsFromHeader() {
00200   unsigned char byte4 = hdr1 >> 24;
00201 
00202   unsigned char kbpsIndex = (byte4&0x3E) >> 1;
00203   if (kbpsIndex > 18) kbpsIndex = 18;
00204   kbps = kbpsTable[kbpsIndex];
00205 
00206   unsigned char samplingFreqIndex = (byte4&0xC0) >> 6;
00207   switch (samplingFreqIndex) {
00208   case 0:
00209     samplingFreq = 48000;
00210     frameSize = 4*kbps;
00211     break;
00212   case 1:
00213     samplingFreq = 44100;
00214     frameSize = 2*(320*kbps/147 + (byte4&1));
00215     break;
00216   case 2:
00217   case 3: // not legal?
00218     samplingFreq = 32000;
00219     frameSize = 6*kbps;
00220   }
00221 }
00222 
00223 AC3AudioStreamParser
00224 ::AC3AudioStreamParser(AC3AudioStreamFramer* usingSource,
00225                         FramedSource* inputSource)
00226   : StreamParser(inputSource, FramedSource::handleClosure, usingSource,
00227                  &AC3AudioStreamFramer::handleNewData, usingSource),
00228     fUsingSource(usingSource), fHaveParsedAFrame(False),
00229     fSavedFrame(NULL), fSavedFrameSize(0) {
00230 }
00231 
00232 AC3AudioStreamParser::~AC3AudioStreamParser() {
00233 }
00234 
00235 void AC3AudioStreamParser::registerReadInterest(unsigned char* to,
00236                                                  unsigned maxSize) {
00237   fTo = to;
00238   fMaxSize = maxSize;
00239 }
00240 
00241 Boolean AC3AudioStreamParser
00242 ::testStreamCode(unsigned char ourStreamCode,
00243                  unsigned char* ptr, unsigned size) {
00244   if (size < 4) return False; // shouldn't happen
00245   unsigned char streamCode = *ptr;
00246 
00247   if (streamCode == ourStreamCode) {
00248     // Remove the first 4 bytes from the stream:
00249     memmove(ptr, ptr + 4, size - 4);
00250     totNumValidBytes() = totNumValidBytes() - 4;
00251 
00252     return True;
00253   } else {
00254     // Discard all of the data that was just read:
00255     totNumValidBytes() = totNumValidBytes() - size;
00256 
00257     return False;
00258   }
00259 }
00260 
00261 unsigned AC3AudioStreamParser::parseFrame(unsigned& numTruncatedBytes) {
00262   if (fSavedFrameSize > 0) {
00263     // We've already read and parsed a frame.  Use it instead:
00264     memmove(fTo, fSavedFrame, fSavedFrameSize);
00265     delete[] fSavedFrame; fSavedFrame = NULL;
00266     unsigned frameSize = fSavedFrameSize;
00267     fSavedFrameSize = 0;
00268     return frameSize;
00269   }
00270 
00271   try {
00272     saveParserState();
00273 
00274     // We expect an AC3 audio header (first 2 bytes == 0x0B77) at the start:
00275     while (1) {
00276       unsigned next4Bytes = test4Bytes();
00277       if (next4Bytes>>16 == 0x0B77) break;
00278       skipBytes(1);
00279       saveParserState();
00280     }
00281     fCurrentFrame.hdr0 = get4Bytes();
00282     fCurrentFrame.hdr1 = test4Bytes();
00283 
00284     fCurrentFrame.setParamsFromHeader();
00285     fHaveParsedAFrame = True;
00286 
00287     // Copy the frame to the requested destination:
00288     unsigned frameSize = fCurrentFrame.frameSize;
00289     if (frameSize > fMaxSize) {
00290       numTruncatedBytes = frameSize - fMaxSize;
00291       frameSize = fMaxSize;
00292     } else {
00293       numTruncatedBytes = 0;
00294     }
00295 
00296     fTo[0] = fCurrentFrame.hdr0 >> 24;
00297     fTo[1] = fCurrentFrame.hdr0 >> 16;
00298     fTo[2] = fCurrentFrame.hdr0 >> 8;
00299     fTo[3] = fCurrentFrame.hdr0;
00300     getBytes(&fTo[4], frameSize-4);
00301     skipBytes(numTruncatedBytes);
00302 
00303     return frameSize;
00304   } catch (int /*e*/) {
00305 #ifdef DEBUG
00306     fUsingSource->envir() << "AC3AudioStreamParser::parseFrame() EXCEPTION (This is normal behavior - *not* an error)\n";
00307 #endif
00308     return 0;  // the parsing got interrupted
00309   }
00310 }
00311 
00312 void AC3AudioStreamParser::readAndSaveAFrame() {
00313   unsigned const maxAC3FrameSize = 4000;
00314   fSavedFrame = new unsigned char[maxAC3FrameSize];
00315   fSavedFrameSize = 0;
00316 
00317   fSavedFrameFlag = 0;
00318   fUsingSource->getNextFrame(fSavedFrame, maxAC3FrameSize,
00319                              afterGettingSavedFrame, this,
00320                              onSavedFrameClosure, this);
00321   fUsingSource->envir().taskScheduler().doEventLoop(&fSavedFrameFlag);
00322 }
00323 
00324 void AC3AudioStreamParser
00325 ::afterGettingSavedFrame(void* clientData, unsigned frameSize,
00326                          unsigned /*numTruncatedBytes*/,
00327                          struct timeval /*presentationTime*/,
00328                          unsigned /*durationInMicroseconds*/) {
00329   AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
00330   parser->afterGettingSavedFrame1(frameSize);
00331 }
00332 
00333 void AC3AudioStreamParser
00334 ::afterGettingSavedFrame1(unsigned frameSize) {
00335   fSavedFrameSize = frameSize;
00336   fSavedFrameFlag = ~0;
00337 }
00338 
00339 void AC3AudioStreamParser::onSavedFrameClosure(void* clientData) {
00340   AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
00341   parser->onSavedFrameClosure1();
00342 }
00343 
00344 void AC3AudioStreamParser::onSavedFrameClosure1() {
00345   delete[] fSavedFrame; fSavedFrame = NULL;
00346   fSavedFrameSize = 0;
00347   fSavedFrameFlag = ~0;
00348 }

Generated on Tue Oct 7 15:38:08 2008 for live by  doxygen 1.5.2