/********** 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 .) 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-2015 Live Networks, Inc. All rights reserved. // RTP sink for a common kind of payload format: Those which pack multiple, // complete codec frames (as many as possible) into each RTP packet. // C++ header #ifndef _MULTI_FRAMED_RTP_SINK_HH #define _MULTI_FRAMED_RTP_SINK_HH #ifndef _RTP_SINK_HH #include "RTPSink.hh" #endif class MultiFramedRTPSink: public RTPSink { public: void setPacketSizes(unsigned preferredPacketSize, unsigned maxPacketSize); typedef void (onSendErrorFunc)(void* clientData); void setOnSendErrorFunc(onSendErrorFunc* onSendErrorFunc, void* onSendErrorFuncData) { // Can be used to set a callback function to be called if there's an error sending RTP packets on our socket. fOnSendErrorFunc = onSendErrorFunc; fOnSendErrorData = onSendErrorFuncData; } protected: MultiFramedRTPSink(UsageEnvironment& env, Groupsock* rtpgs, unsigned char rtpPayloadType, unsigned rtpTimestampFrequency, char const* rtpPayloadFormatName, unsigned numChannels = 1); // we're a virtual base class virtual ~MultiFramedRTPSink(); virtual void doSpecialFrameHandling(unsigned fragmentationOffset, unsigned char* frameStart, unsigned numBytesInFrame, struct timeval framePresentationTime, unsigned numRemainingBytes); // perform any processing specific to the particular payload format virtual Boolean allowFragmentationAfterStart() const; // whether a frame can be fragmented if other frame(s) appear earlier // in the packet (by default: False) virtual Boolean allowOtherFramesAfterLastFragment() const; // whether other frames can be packed into a packet following the // final fragment of a previous, fragmented frame (by default: False) virtual Boolean frameCanAppearAfterPacketStart(unsigned char const* frameStart, unsigned numBytesInFrame) const; // whether this frame can appear in position >1 in a pkt (default: True) virtual unsigned specialHeaderSize() const; // returns the size of any special header used (following the RTP header) (default: 0) virtual unsigned frameSpecificHeaderSize() const; // returns the size of any frame-specific header used (before each frame // within the packet) (default: 0) virtual unsigned computeOverflowForNewFrame(unsigned newFrameSize) const; // returns the number of overflow bytes that would be produced by adding a new // frame of size "newFrameSize" to the current RTP packet. // (By default, this just calls "numOverflowBytes()", but subclasses can redefine // this to (e.g.) impose a granularity upon RTP payload fragments.) // Functions that might be called by doSpecialFrameHandling(), or other subclass virtual functions: Boolean isFirstPacket() const { return fIsFirstPacket; } Boolean isFirstFrameInPacket() const { return fNumFramesUsedSoFar == 0; } unsigned curFragmentationOffset() const { return fCurFragmentationOffset; } void setMarkerBit(); void setTimestamp(struct timeval framePresentationTime); void setSpecialHeaderWord(unsigned word, /* 32 bits, in host order */ unsigned wordPosition = 0); void setSpecialHeaderBytes(unsigned char const* bytes, unsigned numBytes, unsigned bytePosition = 0); void setFrameSpecificHeaderWord(unsigned word, /* 32 bits, in host order */ unsigned wordPosition = 0); void setFrameSpecificHeaderBytes(unsigned char const* bytes, unsigned numBytes, unsigned bytePosition = 0); void setFramePadding(unsigned numPaddingBytes); unsigned numFramesUsedSoFar() const { return fNumFramesUsedSoFar; } unsigned ourMaxPacketSize() const { return fOurMaxPacketSize; } public: // redefined virtual functions: virtual void stopPlaying(); protected: // redefined virtual functions: virtual Boolean continuePlaying(); private: void buildAndSendPacket(Boolean isFirstPacket); void packFrame(); void sendPacketIfNecessary(); static void sendNext(void* firstArg); friend void sendNext(void*); static void afterGettingFrame(void* clientData, unsigned numBytesRead, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds); void afterGettingFrame1(unsigned numBytesRead, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds); Boolean isTooBigForAPacket(unsigned numBytes) const; static void ourHandleClosure(void* clientData); private: OutPacketBuffer* fOutBuf; Boolean fNoFramesLeft; unsigned fNumFramesUsedSoFar; unsigned fCurFragmentationOffset; Boolean fPreviousFrameEndedFragmentation; Boolean fIsFirstPacket; struct timeval fNextSendTime; unsigned fTimestampPosition; unsigned fSpecialHeaderPosition; unsigned fSpecialHeaderSize; // size in bytes of any special header used unsigned fCurFrameSpecificHeaderPosition; unsigned fCurFrameSpecificHeaderSize; // size in bytes of cur frame-specific header unsigned fTotalFrameSpecificHeaderSizes; // size of all frame-specific hdrs in pkt unsigned fOurMaxPacketSize; onSendErrorFunc* fOnSendErrorFunc; void* fOnSendErrorData; }; #endif