text: ﻿/**********
  This library is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the
  Free Software Foundation; either version 2.1 of the License, or (at your
  option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
  
  This library is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
  more details.
  
  You should have received a copy of the GNU Lesser General Public License
  along with this library; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
  **********/
  // "liveMedia"
  // Copyright (c) 1996-2012 Live Networks, Inc.  All rights reserved.
  // A filter that breaks up an AC3 audio elementary stream into frames
  // Implementation
  
  #include "AC3AudioStreamFramer.hh"
  #include "StreamParser.hh"
  #include <GroupsockHelper.hh>
  
  ////////// AC3AudioStreamParser definition //////////
  
  class AC3FrameParams {
  public:
    AC3FrameParams() : samplingFreq(0) {}
    // 8-byte header at the start of each frame:
    //  u_int32_t hdr0, hdr1;
    unsigned hdr0, hdr1;
  
    // parameters derived from the headers
    unsigned kbps, samplingFreq, frameSize;
  
    void setParamsFromHeader();
  };
  
  class AC3AudioStreamParser: public StreamParser {
  public:
    AC3AudioStreamParser(AC3AudioStreamFramer* usingSource,
  			FramedSource* inputSource);
    virtual ~AC3AudioStreamParser();
  
  public:
    void testStreamCode(unsigned char ourStreamCode,
  		      unsigned char* ptr, unsigned size);
    unsigned parseFrame(unsigned& numTruncatedBytes);
       // returns the size of the frame that was acquired, or 0 if none was
  
    void registerReadInterest(unsigned char* to, unsigned maxSize);
  
    AC3FrameParams const& currentFrame() const { return fCurrentFrame; }
  
    Boolean haveParsedAFrame() const { return fHaveParsedAFrame; }
    void readAndSaveAFrame();
  
  private:
    static void afterGettingSavedFrame(void* clientData, unsigned frameSize,
  				     unsigned numTruncatedBytes,
                                       struct timeval presentationTime,
  				     unsigned durationInMicroseconds);
    void afterGettingSavedFrame1(unsigned frameSize);
    static void onSavedFrameClosure(void* clientData);
    void onSavedFrameClosure1();
  
  private:
    AC3AudioStreamFramer* fUsingSource;
    unsigned char* fTo;
    unsigned fMaxSize;
  
    Boolean fHaveParsedAFrame;
    unsigned char* fSavedFrame;
    unsigned fSavedFrameSize;
    char fSavedFrameFlag;
  
    // Parameters of the most recently read frame:
    AC3FrameParams fCurrentFrame;
  };
  
  
  ////////// AC3AudioStreamFramer implementation //////////
  
  AC3AudioStreamFramer::AC3AudioStreamFramer(UsageEnvironment& env,
  					   FramedSource* inputSource,
  					   unsigned char streamCode)
    : FramedFilter(env, inputSource), fOurStreamCode(streamCode) {
    // Use the current wallclock time as the initial 'presentation time':
    gettimeofday(&fNextFramePresentationTime, NULL);
  
    fParser = new AC3AudioStreamParser(this, inputSource);
  }
  
  AC3AudioStreamFramer::~AC3AudioStreamFramer() {
    delete fParser;
  }
  
  AC3AudioStreamFramer*
  AC3AudioStreamFramer::createNew(UsageEnvironment& env,
  				FramedSource* inputSource,
  				unsigned char streamCode) {
    // Need to add source type checking here???  #####
    return new AC3AudioStreamFramer(env, inputSource, streamCode);
  }
  
  unsigned AC3AudioStreamFramer::samplingRate() {
    if (!fParser->haveParsedAFrame()) {
      // Because we haven't yet parsed a frame, we don't yet know the input
      // stream's sampling rate.  So, we first need to read a frame
      // (into a special buffer that we keep around for later use).
      fParser->readAndSaveAFrame();
    }
  
    return fParser->currentFrame().samplingFreq;
  }
  
  void AC3AudioStreamFramer::flushInput() {
    fParser->flushInput();
  }
  
  void AC3AudioStreamFramer::doGetNextFrame() {
    fParser->registerReadInterest(fTo, fMaxSize);
    parseNextFrame();
  }
  
  #define MILLION 1000000
  
  struct timeval AC3AudioStreamFramer::currentFramePlayTime() const {
    AC3FrameParams const& fr = fParser->currentFrame();
    unsigned const numSamples = 1536;
    unsigned const freq = fr.samplingFreq;
  
    // result is numSamples/freq
    unsigned const uSeconds = (freq == 0) ? 0
      : ((numSamples*2*MILLION)/freq + 1)/2; // rounds to nearest integer
  
    struct timeval result;
    result.tv_sec = uSeconds/MILLION;
    result.tv_usec = uSeconds%MILLION;
    return result;
  }
  
  void AC3AudioStreamFramer
  ::handleNewData(void* clientData, unsigned char* ptr, unsigned size,
  		struct timeval /*presentationTime*/) {
    AC3AudioStreamFramer* framer = (AC3AudioStreamFramer*)clientData;
    framer->handleNewData(ptr, size);
  }
  
  void AC3AudioStreamFramer
  ::handleNewData(unsigned char* ptr, unsigned size) {
    fParser->testStreamCode(fOurStreamCode, ptr, size);
  
    parseNextFrame();
  }
  
  void AC3AudioStreamFramer::parseNextFrame() {
    unsigned acquiredFrameSize = fParser->parseFrame(fNumTruncatedBytes);
    if (acquiredFrameSize > 0) {
      // We were able to acquire a frame from the input.
      // It has already been copied to the reader's space.
      fFrameSize = acquiredFrameSize;
  
      // Also set the presentation time, and increment it for next time,
      // based on the length of this frame:
      fPresentationTime = fNextFramePresentationTime;
  
      struct timeval framePlayTime = currentFramePlayTime();
      fDurationInMicroseconds = framePlayTime.tv_sec*MILLION + framePlayTime.tv_usec;
      fNextFramePresentationTime.tv_usec += framePlayTime.tv_usec;
      fNextFramePresentationTime.tv_sec
        += framePlayTime.tv_sec + fNextFramePresentationTime.tv_usec/MILLION;
      fNextFramePresentationTime.tv_usec %= MILLION;
  
      // Call our own 'after getting' function.  Because we're not a 'leaf'
      // source, we can call this directly, without risking infinite recursion.
      afterGetting(this);
    } else {
      // We were unable to parse a complete frame from the input, because:
      // - we had to read more data from the source stream, or
      // - the source stream has ended.
    }
  }
  
  
  ////////// AC3AudioStreamParser implementation //////////
  
  static int const kbpsTable[] = {32,  40,  48,  56,  64,  80,  96, 112,
  				128, 160, 192, 224, 256, 320, 384, 448,
  				512, 576, 640};
  
  void AC3FrameParams::setParamsFromHeader() {
    unsigned char byte4 = hdr1 >> 24;
  
    unsigned char kbpsIndex = (byte4&0x3E) >> 1;
    if (kbpsIndex > 18) kbpsIndex = 18;
    kbps = kbpsTable[kbpsIndex];
  
    unsigned char samplingFreqIndex = (byte4&0xC0) >> 6;
    switch (samplingFreqIndex) {
    case 0:
      samplingFreq = 48000;
      frameSize = 4*kbps;
      break;
    case 1:
      samplingFreq = 44100;
      frameSize = 2*(320*kbps/147 + (byte4&1));
      break;
    case 2:
    case 3: // not legal?
      samplingFreq = 32000;
      frameSize = 6*kbps;
    }
  }
  
  AC3AudioStreamParser
  ::AC3AudioStreamParser(AC3AudioStreamFramer* usingSource,
  			FramedSource* inputSource)
    : StreamParser(inputSource, FramedSource::handleClosure, usingSource,
  		 &AC3AudioStreamFramer::handleNewData, usingSource),
      fUsingSource(usingSource), fHaveParsedAFrame(False),
      fSavedFrame(NULL), fSavedFrameSize(0) {
  }
  
  AC3AudioStreamParser::~AC3AudioStreamParser() {
  }
  
  void AC3AudioStreamParser::registerReadInterest(unsigned char* to,
  						 unsigned maxSize) {
    fTo = to;
    fMaxSize = maxSize;
  }
  
  void AC3AudioStreamParser
  ::testStreamCode(unsigned char ourStreamCode,
  		 unsigned char* ptr, unsigned size) {
    if (ourStreamCode == 0) return; // we assume that there's no stream code at the beginning of the data
  
    if (size < 4) return;
    unsigned char streamCode = *ptr;
  
    if (streamCode == ourStreamCode) {
      // Remove the first 4 bytes from the stream:
      memmove(ptr, ptr + 4, size - 4);
      totNumValidBytes() = totNumValidBytes() - 4;
    } else {
      // Discard all of the data that was just read:
      totNumValidBytes() = totNumValidBytes() - size;
    }
  }
  
  unsigned AC3AudioStreamParser::parseFrame(unsigned& numTruncatedBytes) {
    if (fSavedFrameSize > 0) {
      // We've already read and parsed a frame.  Use it instead:
      memmove(fTo, fSavedFrame, fSavedFrameSize);
      delete[] fSavedFrame; fSavedFrame = NULL;
      unsigned frameSize = fSavedFrameSize;
      fSavedFrameSize = 0;
      return frameSize;
    }
  
    try {
      saveParserState();
  
      // We expect an AC3 audio header (first 2 bytes == 0x0B77) at the start:
      while (1) {
        unsigned next4Bytes = test4Bytes();
        if (next4Bytes>>16 == 0x0B77) break;
        skipBytes(1);
        saveParserState();
      }
      fCurrentFrame.hdr0 = get4Bytes();
      fCurrentFrame.hdr1 = test4Bytes();
  
      fCurrentFrame.setParamsFromHeader();
      fHaveParsedAFrame = True;
  
      // Copy the frame to the requested destination:
      unsigned frameSize = fCurrentFrame.frameSize;
      if (frameSize > fMaxSize) {
        numTruncatedBytes = frameSize - fMaxSize;
        frameSize = fMaxSize;
      } else {
        numTruncatedBytes = 0;
      }
  
      fTo[0] = fCurrentFrame.hdr0 >> 24;
      fTo[1] = fCurrentFrame.hdr0 >> 16;
      fTo[2] = fCurrentFrame.hdr0 >> 8;
      fTo[3] = fCurrentFrame.hdr0;
      getBytes(&fTo[4], frameSize-4);
      skipBytes(numTruncatedBytes);
  
      return frameSize;
    } catch (int /*e*/) {
  #ifdef DEBUG
      fUsingSource->envir() << "AC3AudioStreamParser::parseFrame() EXCEPTION (This is normal behavior - *not* an error)\n";
  #endif
      return 0;  // the parsing got interrupted
    }
  }
  
  void AC3AudioStreamParser::readAndSaveAFrame() {
    unsigned const maxAC3FrameSize = 4000;
    fSavedFrame = new unsigned char[maxAC3FrameSize];
    fSavedFrameSize = 0;
  
    fSavedFrameFlag = 0;
    fUsingSource->getNextFrame(fSavedFrame, maxAC3FrameSize,
  			     afterGettingSavedFrame, this,
  			     onSavedFrameClosure, this);
    fUsingSource->envir().taskScheduler().doEventLoop(&fSavedFrameFlag);
  }
  
  void AC3AudioStreamParser
  ::afterGettingSavedFrame(void* clientData, unsigned frameSize,
  			 unsigned /*numTruncatedBytes*/,
  			 struct timeval /*presentationTime*/,
  			 unsigned /*durationInMicroseconds*/) {
    AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
    parser->afterGettingSavedFrame1(frameSize);
  }
  
  void AC3AudioStreamParser
  ::afterGettingSavedFrame1(unsigned frameSize) {
    fSavedFrameSize = frameSize;
    fSavedFrameFlag = ~0;
  }
  
  void AC3AudioStreamParser::onSavedFrameClosure(void* clientData) {
    AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
    parser->onSavedFrameClosure1();
  }
  
  void AC3AudioStreamParser::onSavedFrameClosure1() {
    delete[] fSavedFrame; fSavedFrame = NULL;
    fSavedFrameSize = 0;
    fSavedFrameFlag = ~0;
  }
  