liveMedia/StreamParser.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 // Abstract class for parsing a byte stream
00019 // Implementation
00020 
00021 #include "StreamParser.hh"
00022 
00023 #include <string.h>
00024 #include <stdlib.h>
00025 
00026 #define BANK_SIZE 150000
00027 
00028 void StreamParser::flushInput() {
00029   fCurParserIndex = fSavedParserIndex = 0;
00030   fSavedRemainingUnparsedBits = fRemainingUnparsedBits = 0;
00031   fTotNumValidBytes = 0;
00032 }
00033 
00034 StreamParser::StreamParser(FramedSource* inputSource,
00035                            FramedSource::onCloseFunc* onInputCloseFunc,
00036                            void* onInputCloseClientData,
00037                            clientContinueFunc* clientContinueFunc,
00038                            void* clientContinueClientData)
00039   : fInputSource(inputSource), fClientOnInputCloseFunc(onInputCloseFunc),
00040     fClientOnInputCloseClientData(onInputCloseClientData),
00041     fClientContinueFunc(clientContinueFunc),
00042     fClientContinueClientData(clientContinueClientData),
00043     fSavedParserIndex(0), fSavedRemainingUnparsedBits(0),
00044     fCurParserIndex(0), fRemainingUnparsedBits(0),
00045     fTotNumValidBytes(0), fHaveSeenEOF(False) {
00046   fBank[0] = new unsigned char[BANK_SIZE];
00047   fBank[1] = new unsigned char[BANK_SIZE];
00048   fCurBankNum = 0;
00049   fCurBank = fBank[fCurBankNum];
00050 
00051   fLastSeenPresentationTime.tv_sec = 0; fLastSeenPresentationTime.tv_usec = 0;
00052 }
00053 
00054 StreamParser::~StreamParser() {
00055   delete[] fBank[0]; delete[] fBank[1];
00056 }
00057 
00058 void StreamParser::saveParserState() {
00059   fSavedParserIndex = fCurParserIndex;
00060   fSavedRemainingUnparsedBits = fRemainingUnparsedBits;
00061 }
00062 
00063 void StreamParser::restoreSavedParserState() {
00064   fCurParserIndex = fSavedParserIndex;
00065   fRemainingUnparsedBits = fSavedRemainingUnparsedBits;
00066 }
00067 
00068 void StreamParser::skipBits(unsigned numBits) {
00069   if (numBits <= fRemainingUnparsedBits) {
00070     fRemainingUnparsedBits -= numBits;
00071   } else {
00072     numBits -= fRemainingUnparsedBits;
00073 
00074     unsigned numBytesToExamine = (numBits+7)/8; // round up
00075     ensureValidBytes(numBytesToExamine);
00076     fCurParserIndex += numBytesToExamine;
00077 
00078     fRemainingUnparsedBits = 8*numBytesToExamine - numBits;
00079   }
00080 }
00081 
00082 unsigned StreamParser::getBits(unsigned numBits) {
00083   if (numBits <= fRemainingUnparsedBits) {
00084     unsigned char lastByte = *lastParsed();
00085     lastByte >>= (fRemainingUnparsedBits - numBits);
00086     fRemainingUnparsedBits -= numBits;
00087 
00088     return (unsigned)lastByte &~ ((~0)<<numBits);
00089   } else {
00090     unsigned char lastByte;
00091     if (fRemainingUnparsedBits > 0) {
00092       lastByte = *lastParsed();
00093     } else {
00094       lastByte = 0;
00095     }
00096 
00097     unsigned remainingBits = numBits - fRemainingUnparsedBits; // > 0
00098 
00099     // For simplicity, read the next 4 bytes, even though we might not
00100     // need all of them here:
00101     unsigned result = test4Bytes();
00102 
00103     result >>= (32 - remainingBits);
00104     result |= (lastByte << remainingBits);
00105     if (numBits < 32) result &=~ ((~0)<<numBits);
00106 
00107     unsigned const numRemainingBytes = (remainingBits+7)/8;
00108     fCurParserIndex += numRemainingBytes;
00109     fRemainingUnparsedBits = 8*numRemainingBytes - remainingBits;
00110 
00111     return result;
00112   }
00113 }
00114 
00115 unsigned StreamParser::bankSize() const {
00116   return BANK_SIZE;
00117 }
00118 
00119 #define NO_MORE_BUFFERED_INPUT 1
00120 
00121 void StreamParser::ensureValidBytes1(unsigned numBytesNeeded) {
00122   // We need to read some more bytes from the input source.
00123   // First, clarify how much data to ask for:
00124   unsigned maxInputFrameSize = fInputSource->maxFrameSize();
00125   if (maxInputFrameSize > numBytesNeeded) numBytesNeeded = maxInputFrameSize;
00126 
00127   // First, check whether these new bytes would overflow the current
00128   // bank.  If so, start using a new bank now.
00129   if (fCurParserIndex + numBytesNeeded > BANK_SIZE) {
00130     // Swap banks, but save any still-needed bytes from the old bank:
00131     unsigned numBytesToSave = fTotNumValidBytes - fSavedParserIndex;
00132     unsigned char const* from = &curBank()[fSavedParserIndex];
00133 
00134     fCurBankNum = (fCurBankNum + 1)%2;
00135     fCurBank = fBank[fCurBankNum];
00136     memmove(curBank(), from, numBytesToSave);
00137     fCurParserIndex = fCurParserIndex - fSavedParserIndex;
00138     fSavedParserIndex = 0;
00139     fTotNumValidBytes = numBytesToSave;
00140   }
00141 
00142   // ASSERT: fCurParserIndex + numBytesNeeded > fTotNumValidBytes
00143   //      && fCurParserIndex + numBytesNeeded <= BANK_SIZE
00144   if (fCurParserIndex + numBytesNeeded > BANK_SIZE) {
00145     // If this happens, it means that we have too much saved parser state.
00146     // To fix this, increase BANK_SIZE as appropriate.
00147     fInputSource->envir() << "StreamParser internal error ("
00148                           << fCurParserIndex << " + "
00149                           << numBytesNeeded << " > "
00150                           << BANK_SIZE << ")\n";
00151     fInputSource->envir().internalError();
00152   }
00153 
00154   // Try to read as many new bytes as will fit in the current bank:
00155   unsigned maxNumBytesToRead = BANK_SIZE - fTotNumValidBytes;
00156   fInputSource->getNextFrame(&curBank()[fTotNumValidBytes],
00157                              maxNumBytesToRead,
00158                              afterGettingBytes, this,
00159                              onInputClosure, this);
00160 
00161   throw NO_MORE_BUFFERED_INPUT;
00162 }
00163 
00164 void StreamParser::afterGettingBytes(void* clientData,
00165                                      unsigned numBytesRead,
00166                                      unsigned /*numTruncatedBytes*/,
00167                                      struct timeval presentationTime,
00168                                      unsigned /*durationInMicroseconds*/){
00169   StreamParser* parser = (StreamParser*)clientData;
00170   if (parser != NULL) parser->afterGettingBytes1(numBytesRead, presentationTime);
00171 }
00172 
00173 void StreamParser::afterGettingBytes1(unsigned numBytesRead, struct timeval presentationTime) {
00174   // Sanity check: Make sure we didn't get too many bytes for our bank:
00175   if (fTotNumValidBytes + numBytesRead > BANK_SIZE) {
00176     fInputSource->envir()
00177       << "StreamParser::afterGettingBytes() warning: read "
00178       << numBytesRead << " bytes; expected no more than "
00179       << BANK_SIZE - fTotNumValidBytes << "\n";
00180   }
00181 
00182   fLastSeenPresentationTime = presentationTime;
00183 
00184   unsigned char* ptr = &curBank()[fTotNumValidBytes];
00185   fTotNumValidBytes += numBytesRead;
00186 
00187   // Continue our original calling source where it left off:
00188   restoreSavedParserState();
00189       // Sigh... this is a crock; things would have been a lot simpler
00190       // here if we were using threads, with synchronous I/O...
00191   fClientContinueFunc(fClientContinueClientData, ptr, numBytesRead, presentationTime);
00192 }
00193 
00194 void StreamParser::onInputClosure(void* clientData) {
00195   StreamParser* parser = (StreamParser*)clientData;
00196   if (parser != NULL) parser->onInputClosure1();
00197 }
00198 
00199 void StreamParser::onInputClosure1() {
00200   if (!fHaveSeenEOF) {
00201     // We're hitting EOF for the first time.  Set our 'EOF' flag, and continue parsing, as if we'd just read 0 bytes of data.
00202     // This allows the parser to re-parse any remaining unparsed data (perhaps while testing for EOF at the end):
00203     fHaveSeenEOF = True;
00204     afterGettingBytes1(0, fLastSeenPresentationTime);
00205   } else {
00206     // We're hitting EOF for the second time.  Now, we handle the source input closure:
00207     fHaveSeenEOF = False;
00208     if (fClientOnInputCloseFunc != NULL) (*fClientOnInputCloseFunc)(fClientOnInputCloseClientData);
00209   }
00210 }

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