/**********
|
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 3 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-2017 Live Networks, Inc. All rights reserved.
|
// Abstract class for parsing a byte stream
|
// C++ header
|
|
#ifndef _STREAM_PARSER_HH
|
#define _STREAM_PARSER_HH
|
|
#ifndef _FRAMED_SOURCE_HH
|
#include "FramedSource.hh"
|
#endif
|
|
class StreamParser {
|
public:
|
virtual void flushInput();
|
|
protected: // we're a virtual base class
|
typedef void (clientContinueFunc)(void* clientData,
|
unsigned char* ptr, unsigned size,
|
struct timeval presentationTime);
|
StreamParser(FramedSource* inputSource,
|
FramedSource::onCloseFunc* onInputCloseFunc,
|
void* onInputCloseClientData,
|
clientContinueFunc* clientContinueFunc,
|
void* clientContinueClientData);
|
virtual ~StreamParser();
|
|
void saveParserState();
|
virtual void restoreSavedParserState();
|
|
u_int32_t get4Bytes() { // byte-aligned; returned in big-endian order
|
u_int32_t result = test4Bytes();
|
fCurParserIndex += 4;
|
fRemainingUnparsedBits = 0;
|
|
return result;
|
}
|
u_int32_t test4Bytes() { // as above, but doesn't advance ptr
|
ensureValidBytes(4);
|
|
unsigned char const* ptr = nextToParse();
|
return (ptr[0]<<24)|(ptr[1]<<16)|(ptr[2]<<8)|ptr[3];
|
}
|
|
u_int16_t get2Bytes() {
|
ensureValidBytes(2);
|
|
unsigned char const* ptr = nextToParse();
|
u_int16_t result = (ptr[0]<<8)|ptr[1];
|
|
fCurParserIndex += 2;
|
fRemainingUnparsedBits = 0;
|
|
return result;
|
}
|
|
u_int8_t get1Byte() { // byte-aligned
|
ensureValidBytes(1);
|
fRemainingUnparsedBits = 0;
|
return curBank()[fCurParserIndex++];
|
}
|
u_int8_t test1Byte() { // as above, but doesn't advance ptr
|
ensureValidBytes(1);
|
return nextToParse()[0];
|
}
|
|
void getBytes(u_int8_t* to, unsigned numBytes) {
|
testBytes(to, numBytes);
|
fCurParserIndex += numBytes;
|
fRemainingUnparsedBits = 0;
|
}
|
void testBytes(u_int8_t* to, unsigned numBytes) { // as above, but doesn't advance ptr
|
ensureValidBytes(numBytes);
|
memmove(to, nextToParse(), numBytes);
|
}
|
void skipBytes(unsigned numBytes) {
|
ensureValidBytes(numBytes);
|
fCurParserIndex += numBytes;
|
}
|
|
void skipBits(unsigned numBits);
|
unsigned getBits(unsigned numBits);
|
// numBits <= 32; returns data into low-order bits of result
|
|
unsigned curOffset() const { return fCurParserIndex; }
|
|
unsigned& totNumValidBytes() { return fTotNumValidBytes; }
|
|
Boolean haveSeenEOF() const { return fHaveSeenEOF; }
|
|
unsigned bankSize() const;
|
|
private:
|
unsigned char* curBank() { return fCurBank; }
|
unsigned char* nextToParse() { return &curBank()[fCurParserIndex]; }
|
unsigned char* lastParsed() { return &curBank()[fCurParserIndex-1]; }
|
|
// makes sure that at least "numBytes" valid bytes remain:
|
void ensureValidBytes(unsigned numBytesNeeded) {
|
// common case: inlined:
|
if (fCurParserIndex + numBytesNeeded <= fTotNumValidBytes) return;
|
|
ensureValidBytes1(numBytesNeeded);
|
}
|
void ensureValidBytes1(unsigned numBytesNeeded);
|
|
static void afterGettingBytes(void* clientData, unsigned numBytesRead,
|
unsigned numTruncatedBytes,
|
struct timeval presentationTime,
|
unsigned durationInMicroseconds);
|
void afterGettingBytes1(unsigned numBytesRead, struct timeval presentationTime);
|
|
static void onInputClosure(void* clientData);
|
void onInputClosure1();
|
|
private:
|
FramedSource* fInputSource; // should be a byte-stream source??
|
FramedSource::onCloseFunc* fClientOnInputCloseFunc;
|
void* fClientOnInputCloseClientData;
|
clientContinueFunc* fClientContinueFunc;
|
void* fClientContinueClientData;
|
|
// Use a pair of 'banks', and swap between them as they fill up:
|
unsigned char* fBank[2];
|
unsigned char fCurBankNum;
|
unsigned char* fCurBank;
|
|
// The most recent 'saved' parse position:
|
unsigned fSavedParserIndex; // <= fCurParserIndex
|
unsigned char fSavedRemainingUnparsedBits;
|
|
// The current position of the parser within the current bank:
|
unsigned fCurParserIndex; // <= fTotNumValidBytes
|
unsigned char fRemainingUnparsedBits; // in previous byte: [0,7]
|
|
// The total number of valid bytes stored in the current bank:
|
unsigned fTotNumValidBytes; // <= BANK_SIZE
|
|
// Whether we have seen EOF on the input source:
|
Boolean fHaveSeenEOF;
|
|
struct timeval fLastSeenPresentationTime; // hack used for EOF handling
|
};
|
|
#endif
|