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-2013 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   void testStreamCode(unsigned char ourStreamCode,
00048                       unsigned char* ptr, unsigned size);
00049   unsigned parseFrame(unsigned& numTruncatedBytes);
00050      // returns the size of the frame that was acquired, or 0 if none was
00051 
00052   void registerReadInterest(unsigned char* to, unsigned maxSize);
00053 
00054   AC3FrameParams const& currentFrame() const { return fCurrentFrame; }
00055 
00056   Boolean haveParsedAFrame() const { return fHaveParsedAFrame; }
00057   void readAndSaveAFrame();
00058 
00059 private:
00060   static void afterGettingSavedFrame(void* clientData, unsigned frameSize,
00061                                      unsigned numTruncatedBytes,
00062                                      struct timeval presentationTime,
00063                                      unsigned durationInMicroseconds);
00064   void afterGettingSavedFrame1(unsigned frameSize);
00065   static void onSavedFrameClosure(void* clientData);
00066   void onSavedFrameClosure1();
00067 
00068 private:
00069   AC3AudioStreamFramer* fUsingSource;
00070   unsigned char* fTo;
00071   unsigned fMaxSize;
00072 
00073   Boolean fHaveParsedAFrame;
00074   unsigned char* fSavedFrame;
00075   unsigned fSavedFrameSize;
00076   char fSavedFrameFlag;
00077 
00078   // Parameters of the most recently read frame:
00079   AC3FrameParams fCurrentFrame;
00080 };
00081 
00082 
00084 
00085 AC3AudioStreamFramer::AC3AudioStreamFramer(UsageEnvironment& env,
00086                                            FramedSource* inputSource,
00087                                            unsigned char streamCode)
00088   : FramedFilter(env, inputSource), fOurStreamCode(streamCode) {
00089   // Use the current wallclock time as the initial 'presentation time':
00090   gettimeofday(&fNextFramePresentationTime, NULL);
00091 
00092   fParser = new AC3AudioStreamParser(this, inputSource);
00093 }
00094 
00095 AC3AudioStreamFramer::~AC3AudioStreamFramer() {
00096   delete fParser;
00097 }
00098 
00099 AC3AudioStreamFramer*
00100 AC3AudioStreamFramer::createNew(UsageEnvironment& env,
00101                                 FramedSource* inputSource,
00102                                 unsigned char streamCode) {
00103   // Need to add source type checking here???  #####
00104   return new AC3AudioStreamFramer(env, inputSource, streamCode);
00105 }
00106 
00107 unsigned AC3AudioStreamFramer::samplingRate() {
00108   if (!fParser->haveParsedAFrame()) {
00109     // Because we haven't yet parsed a frame, we don't yet know the input
00110     // stream's sampling rate.  So, we first need to read a frame
00111     // (into a special buffer that we keep around for later use).
00112     fParser->readAndSaveAFrame();
00113   }
00114 
00115   return fParser->currentFrame().samplingFreq;
00116 }
00117 
00118 void AC3AudioStreamFramer::flushInput() {
00119   fParser->flushInput();
00120 }
00121 
00122 void AC3AudioStreamFramer::doGetNextFrame() {
00123   fParser->registerReadInterest(fTo, fMaxSize);
00124   parseNextFrame();
00125 }
00126 
00127 #define MILLION 1000000
00128 
00129 struct timeval AC3AudioStreamFramer::currentFramePlayTime() const {
00130   AC3FrameParams const& fr = fParser->currentFrame();
00131   unsigned const numSamples = 1536;
00132   unsigned const freq = fr.samplingFreq;
00133 
00134   // result is numSamples/freq
00135   unsigned const uSeconds = (freq == 0) ? 0
00136     : ((numSamples*2*MILLION)/freq + 1)/2; // rounds to nearest integer
00137 
00138   struct timeval result;
00139   result.tv_sec = uSeconds/MILLION;
00140   result.tv_usec = uSeconds%MILLION;
00141   return result;
00142 }
00143 
00144 void AC3AudioStreamFramer
00145 ::handleNewData(void* clientData, unsigned char* ptr, unsigned size,
00146                 struct timeval /*presentationTime*/) {
00147   AC3AudioStreamFramer* framer = (AC3AudioStreamFramer*)clientData;
00148   framer->handleNewData(ptr, size);
00149 }
00150 
00151 void AC3AudioStreamFramer
00152 ::handleNewData(unsigned char* ptr, unsigned size) {
00153   fParser->testStreamCode(fOurStreamCode, ptr, size);
00154 
00155   parseNextFrame();
00156 }
00157 
00158 void AC3AudioStreamFramer::parseNextFrame() {
00159   unsigned acquiredFrameSize = fParser->parseFrame(fNumTruncatedBytes);
00160   if (acquiredFrameSize > 0) {
00161     // We were able to acquire a frame from the input.
00162     // It has already been copied to the reader's space.
00163     fFrameSize = acquiredFrameSize;
00164 
00165     // Also set the presentation time, and increment it for next time,
00166     // based on the length of this frame:
00167     fPresentationTime = fNextFramePresentationTime;
00168 
00169     struct timeval framePlayTime = currentFramePlayTime();
00170     fDurationInMicroseconds = framePlayTime.tv_sec*MILLION + framePlayTime.tv_usec;
00171     fNextFramePresentationTime.tv_usec += framePlayTime.tv_usec;
00172     fNextFramePresentationTime.tv_sec
00173       += framePlayTime.tv_sec + fNextFramePresentationTime.tv_usec/MILLION;
00174     fNextFramePresentationTime.tv_usec %= MILLION;
00175 
00176     // Call our own 'after getting' function.  Because we're not a 'leaf'
00177     // source, we can call this directly, without risking infinite recursion.
00178     afterGetting(this);
00179   } else {
00180     // We were unable to parse a complete frame from the input, because:
00181     // - we had to read more data from the source stream, or
00182     // - the source stream has ended.
00183   }
00184 }
00185 
00186 
00188 
00189 static int const kbpsTable[] = {32,  40,  48,  56,  64,  80,  96, 112,
00190                                 128, 160, 192, 224, 256, 320, 384, 448,
00191                                 512, 576, 640};
00192 
00193 void AC3FrameParams::setParamsFromHeader() {
00194   unsigned char byte4 = hdr1 >> 24;
00195 
00196   unsigned char kbpsIndex = (byte4&0x3E) >> 1;
00197   if (kbpsIndex > 18) kbpsIndex = 18;
00198   kbps = kbpsTable[kbpsIndex];
00199 
00200   unsigned char samplingFreqIndex = (byte4&0xC0) >> 6;
00201   switch (samplingFreqIndex) {
00202   case 0:
00203     samplingFreq = 48000;
00204     frameSize = 4*kbps;
00205     break;
00206   case 1:
00207     samplingFreq = 44100;
00208     frameSize = 2*(320*kbps/147 + (byte4&1));
00209     break;
00210   case 2:
00211   case 3: // not legal?
00212     samplingFreq = 32000;
00213     frameSize = 6*kbps;
00214   }
00215 }
00216 
00217 AC3AudioStreamParser
00218 ::AC3AudioStreamParser(AC3AudioStreamFramer* usingSource,
00219                         FramedSource* inputSource)
00220   : StreamParser(inputSource, FramedSource::handleClosure, usingSource,
00221                  &AC3AudioStreamFramer::handleNewData, usingSource),
00222     fUsingSource(usingSource), fHaveParsedAFrame(False),
00223     fSavedFrame(NULL), fSavedFrameSize(0) {
00224 }
00225 
00226 AC3AudioStreamParser::~AC3AudioStreamParser() {
00227 }
00228 
00229 void AC3AudioStreamParser::registerReadInterest(unsigned char* to,
00230                                                  unsigned maxSize) {
00231   fTo = to;
00232   fMaxSize = maxSize;
00233 }
00234 
00235 void AC3AudioStreamParser
00236 ::testStreamCode(unsigned char ourStreamCode,
00237                  unsigned char* ptr, unsigned size) {
00238   if (ourStreamCode == 0) return; // we assume that there's no stream code at the beginning of the data
00239 
00240   if (size < 4) return;
00241   unsigned char streamCode = *ptr;
00242 
00243   if (streamCode == ourStreamCode) {
00244     // Remove the first 4 bytes from the stream:
00245     memmove(ptr, ptr + 4, size - 4);
00246     totNumValidBytes() = totNumValidBytes() - 4;
00247   } else {
00248     // Discard all of the data that was just read:
00249     totNumValidBytes() = totNumValidBytes() - size;
00250   }
00251 }
00252 
00253 unsigned AC3AudioStreamParser::parseFrame(unsigned& numTruncatedBytes) {
00254   if (fSavedFrameSize > 0) {
00255     // We've already read and parsed a frame.  Use it instead:
00256     memmove(fTo, fSavedFrame, fSavedFrameSize);
00257     delete[] fSavedFrame; fSavedFrame = NULL;
00258     unsigned frameSize = fSavedFrameSize;
00259     fSavedFrameSize = 0;
00260     return frameSize;
00261   }
00262 
00263   try {
00264     saveParserState();
00265 
00266     // We expect an AC3 audio header (first 2 bytes == 0x0B77) at the start:
00267     while (1) {
00268       unsigned next4Bytes = test4Bytes();
00269       if (next4Bytes>>16 == 0x0B77) break;
00270       skipBytes(1);
00271       saveParserState();
00272     }
00273     fCurrentFrame.hdr0 = get4Bytes();
00274     fCurrentFrame.hdr1 = test4Bytes();
00275 
00276     fCurrentFrame.setParamsFromHeader();
00277     fHaveParsedAFrame = True;
00278 
00279     // Copy the frame to the requested destination:
00280     unsigned frameSize = fCurrentFrame.frameSize;
00281     if (frameSize > fMaxSize) {
00282       numTruncatedBytes = frameSize - fMaxSize;
00283       frameSize = fMaxSize;
00284     } else {
00285       numTruncatedBytes = 0;
00286     }
00287 
00288     fTo[0] = fCurrentFrame.hdr0 >> 24;
00289     fTo[1] = fCurrentFrame.hdr0 >> 16;
00290     fTo[2] = fCurrentFrame.hdr0 >> 8;
00291     fTo[3] = fCurrentFrame.hdr0;
00292     getBytes(&fTo[4], frameSize-4);
00293     skipBytes(numTruncatedBytes);
00294 
00295     return frameSize;
00296   } catch (int /*e*/) {
00297 #ifdef DEBUG
00298     fUsingSource->envir() << "AC3AudioStreamParser::parseFrame() EXCEPTION (This is normal behavior - *not* an error)\n";
00299 #endif
00300     return 0;  // the parsing got interrupted
00301   }
00302 }
00303 
00304 void AC3AudioStreamParser::readAndSaveAFrame() {
00305   unsigned const maxAC3FrameSize = 4000;
00306   fSavedFrame = new unsigned char[maxAC3FrameSize];
00307   fSavedFrameSize = 0;
00308 
00309   fSavedFrameFlag = 0;
00310   fUsingSource->getNextFrame(fSavedFrame, maxAC3FrameSize,
00311                              afterGettingSavedFrame, this,
00312                              onSavedFrameClosure, this);
00313   fUsingSource->envir().taskScheduler().doEventLoop(&fSavedFrameFlag);
00314 }
00315 
00316 void AC3AudioStreamParser
00317 ::afterGettingSavedFrame(void* clientData, unsigned frameSize,
00318                          unsigned /*numTruncatedBytes*/,
00319                          struct timeval /*presentationTime*/,
00320                          unsigned /*durationInMicroseconds*/) {
00321   AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
00322   parser->afterGettingSavedFrame1(frameSize);
00323 }
00324 
00325 void AC3AudioStreamParser
00326 ::afterGettingSavedFrame1(unsigned frameSize) {
00327   fSavedFrameSize = frameSize;
00328   fSavedFrameFlag = ~0;
00329 }
00330 
00331 void AC3AudioStreamParser::onSavedFrameClosure(void* clientData) {
00332   AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
00333   parser->onSavedFrameClosure1();
00334 }
00335 
00336 void AC3AudioStreamParser::onSavedFrameClosure1() {
00337   delete[] fSavedFrame; fSavedFrame = NULL;
00338   fSavedFrameSize = 0;
00339   fSavedFrameFlag = ~0;
00340 }

Generated on Mon Apr 29 13:28:00 2013 for live by  doxygen 1.5.2