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-2008 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 StreamParser::StreamParser(FramedSource* inputSource,
00029                            FramedSource::onCloseFunc* onInputCloseFunc,
00030                            void* onInputCloseClientData,
00031                            clientContinueFunc* clientContinueFunc,
00032                            void* clientContinueClientData)
00033   : fInputSource(inputSource), fOnInputCloseFunc(onInputCloseFunc),
00034     fOnInputCloseClientData(onInputCloseClientData),
00035     fClientContinueFunc(clientContinueFunc),
00036     fClientContinueClientData(clientContinueClientData),
00037     fSavedParserIndex(0), fSavedRemainingUnparsedBits(0),
00038     fCurParserIndex(0), fRemainingUnparsedBits(0),
00039     fTotNumValidBytes(0) {
00040   fBank[0] = new unsigned char[BANK_SIZE];
00041   fBank[1] = new unsigned char[BANK_SIZE];
00042   fCurBankNum = 0;
00043   fCurBank = fBank[fCurBankNum];
00044 }
00045 
00046 StreamParser::~StreamParser() {
00047   delete[] fBank[0]; delete[] fBank[1];
00048 }
00049 
00050 #define NO_MORE_BUFFERED_INPUT 1
00051 
00052 void StreamParser::ensureValidBytes1(unsigned numBytesNeeded) {
00053   // We need to read some more bytes from the input source.
00054   // First, clarify how much data to ask for:
00055   unsigned maxInputFrameSize = fInputSource->maxFrameSize();
00056   if (maxInputFrameSize > numBytesNeeded) numBytesNeeded = maxInputFrameSize;
00057 
00058   // First, check whether these new bytes would overflow the current
00059   // bank.  If so, start using a new bank now.
00060   if (fCurParserIndex + numBytesNeeded > BANK_SIZE) {
00061     // Swap banks, but save any still-needed bytes from the old bank:
00062     unsigned numBytesToSave = fTotNumValidBytes - fSavedParserIndex;
00063     unsigned char const* from = &curBank()[fSavedParserIndex];
00064 
00065     fCurBankNum = (fCurBankNum + 1)%2;
00066     fCurBank = fBank[fCurBankNum];
00067     memmove(curBank(), from, numBytesToSave);
00068     fCurParserIndex = fCurParserIndex - fSavedParserIndex;
00069     fSavedParserIndex = 0;
00070     fTotNumValidBytes = numBytesToSave;
00071   }
00072 
00073   // ASSERT: fCurParserIndex + numBytesNeeded > fTotNumValidBytes
00074   //      && fCurParserIndex + numBytesNeeded <= BANK_SIZE
00075   if (fCurParserIndex + numBytesNeeded > BANK_SIZE) {
00076     // If this happens, it means that we have too much saved parser state.
00077     // To fix this, increase BANK_SIZE as appropriate.
00078     fInputSource->envir() << "StreamParser internal error ("
00079                           << fCurParserIndex << "+ "
00080                           << numBytesNeeded << " > "
00081                           << BANK_SIZE << ")\n";
00082     exit(1);
00083   }
00084 
00085   // Try to read as many new bytes as will fit in the current bank:
00086   unsigned maxNumBytesToRead = BANK_SIZE - fTotNumValidBytes;
00087   fInputSource->getNextFrame(&curBank()[fTotNumValidBytes],
00088                              maxNumBytesToRead,
00089                              afterGettingBytes, this,
00090                              fOnInputCloseFunc, fOnInputCloseClientData);
00091 
00092   throw NO_MORE_BUFFERED_INPUT;
00093 }
00094 
00095 void StreamParser::afterGettingBytes(void* clientData,
00096                                      unsigned numBytesRead,
00097                                      unsigned /*numTruncatedBytes*/,
00098                                      struct timeval presentationTime,
00099                                      unsigned /*durationInMicroseconds*/){
00100   StreamParser* buffer = (StreamParser*)clientData;
00101 
00102   // Sanity check: Make sure we didn't get too many bytes for our bank:
00103   if (buffer->fTotNumValidBytes + numBytesRead > BANK_SIZE) {
00104     buffer->fInputSource->envir()
00105       << "StreamParser::afterGettingBytes() warning: read "
00106       << numBytesRead << " bytes; expected no more than "
00107       << BANK_SIZE - buffer->fTotNumValidBytes << "\n";
00108   }
00109 
00110   unsigned char* ptr = &buffer->curBank()[buffer->fTotNumValidBytes];
00111   buffer->fTotNumValidBytes += numBytesRead;
00112 
00113   // Continue our original calling source where it left off:
00114   buffer->restoreSavedParserState();
00115       // Sigh... this is a crock; things would have been a lot simpler
00116       // here if we were using threads, with synchronous I/O...
00117   buffer->fClientContinueFunc(buffer->fClientContinueClientData,
00118                               ptr, numBytesRead, presentationTime);
00119 }
00120 
00121 void StreamParser::saveParserState() {
00122   fSavedParserIndex = fCurParserIndex;
00123   fSavedRemainingUnparsedBits = fRemainingUnparsedBits;
00124 }
00125 
00126 void StreamParser::restoreSavedParserState() {
00127   fCurParserIndex = fSavedParserIndex;
00128   fRemainingUnparsedBits = fSavedRemainingUnparsedBits;
00129 }
00130 
00131 void StreamParser::skipBits(unsigned numBits) {
00132   if (numBits <= fRemainingUnparsedBits) {
00133     fRemainingUnparsedBits -= numBits;
00134   } else {
00135     numBits -= fRemainingUnparsedBits;
00136 
00137     unsigned numBytesToExamine = (numBits+7)/8; // round up
00138     ensureValidBytes(numBytesToExamine);
00139     fCurParserIndex += numBytesToExamine;
00140 
00141     fRemainingUnparsedBits = 8*numBytesToExamine - numBits;
00142   }
00143 }
00144 
00145 unsigned StreamParser::getBits(unsigned numBits) {
00146   if (numBits <= fRemainingUnparsedBits) {
00147     unsigned char lastByte = *lastParsed();
00148     lastByte >>= (fRemainingUnparsedBits - numBits);
00149     fRemainingUnparsedBits -= numBits;
00150 
00151     return (unsigned)lastByte &~ ((~0)<<numBits);
00152   } else {
00153     unsigned char lastByte;
00154     if (fRemainingUnparsedBits > 0) {
00155       lastByte = *lastParsed();
00156     } else {
00157       lastByte = 0;
00158     }
00159 
00160     unsigned remainingBits = numBits - fRemainingUnparsedBits; // > 0
00161 
00162     // For simplicity, read the next 4 bytes, even though we might not
00163     // need all of them here:
00164     unsigned result = test4Bytes();
00165 
00166     result >>= (32 - remainingBits);
00167     result |= (lastByte << remainingBits);
00168     if (numBits < 32) result &=~ ((~0)<<numBits);
00169 
00170     unsigned const numRemainingBytes = (remainingBits+7)/8;
00171     fCurParserIndex += numRemainingBytes;
00172     fRemainingUnparsedBits = 8*numRemainingBytes - remainingBits;
00173 
00174     return result;
00175   }
00176 }
00177 
00178 void StreamParser::flushInput() {
00179   fCurParserIndex = fSavedParserIndex = 0;
00180   fSavedRemainingUnparsedBits = fRemainingUnparsedBits = 0;
00181   fTotNumValidBytes = 0;
00182 }

Generated on Fri Dec 19 21:58:19 2008 for live by  doxygen 1.5.2