1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// RTP sink for a common kind of payload format: Those which pack multiple,
19// complete codec frames (as many as possible) into each RTP packet.
20// C++ header
21
22#ifndef _MULTI_FRAMED_RTP_SINK_HH
23#define _MULTI_FRAMED_RTP_SINK_HH
24
25#ifndef _RTP_SINK_HH
26#include "RTPSink.hh"
27#endif
28
29class MultiFramedRTPSink: public RTPSink {
30public:
31 void setPacketSizes(unsigned preferredPacketSize, unsigned maxPacketSize);
32
33 typedef void (onSendErrorFunc)(void* clientData);
34 void setOnSendErrorFunc(onSendErrorFunc* onSendErrorFunc, void* onSendErrorFuncData) {
35 // Can be used to set a callback function to be called if there's an error sending RTP packets on our socket.
36 fOnSendErrorFunc = onSendErrorFunc;
37 fOnSendErrorData = onSendErrorFuncData;
38 }
39
40protected:
41 MultiFramedRTPSink(UsageEnvironment& env,
42 Groupsock* rtpgs, unsigned char rtpPayloadType,
43 unsigned rtpTimestampFrequency,
44 char const* rtpPayloadFormatName,
45 unsigned numChannels = 1);
46 // we're a virtual base class
47
48 virtual ~MultiFramedRTPSink();
49
50 virtual void doSpecialFrameHandling(unsigned fragmentationOffset,
51 unsigned char* frameStart,
52 unsigned numBytesInFrame,
53 struct timeval framePresentationTime,
54 unsigned numRemainingBytes);
55 // perform any processing specific to the particular payload format
56 virtual Boolean allowFragmentationAfterStart() const;
57 // whether a frame can be fragmented if other frame(s) appear earlier
58 // in the packet (by default: False)
59 virtual Boolean allowOtherFramesAfterLastFragment() const;
60 // whether other frames can be packed into a packet following the
61 // final fragment of a previous, fragmented frame (by default: False)
62 virtual Boolean frameCanAppearAfterPacketStart(unsigned char const* frameStart,
63 unsigned numBytesInFrame) const;
64 // whether this frame can appear in position >1 in a pkt (default: True)
65 virtual unsigned specialHeaderSize() const;
66 // returns the size of any special header used (following the RTP header) (default: 0)
67 virtual unsigned frameSpecificHeaderSize() const;
68 // returns the size of any frame-specific header used (before each frame
69 // within the packet) (default: 0)
70 virtual unsigned computeOverflowForNewFrame(unsigned newFrameSize) const;
71 // returns the number of overflow bytes that would be produced by adding a new
72 // frame of size "newFrameSize" to the current RTP packet.
73 // (By default, this just calls "numOverflowBytes()", but subclasses can redefine
74 // this to (e.g.) impose a granularity upon RTP payload fragments.)
75
76 // Functions that might be called by doSpecialFrameHandling(), or other subclass virtual functions:
77 Boolean isFirstPacket() const { return fIsFirstPacket; }
78 Boolean isFirstFrameInPacket() const { return fNumFramesUsedSoFar == 0; }
79 unsigned curFragmentationOffset() const { return fCurFragmentationOffset; }
80 void setMarkerBit();
81 void setTimestamp(struct timeval framePresentationTime);
82 void setSpecialHeaderWord(unsigned word, /* 32 bits, in host order */
83 unsigned wordPosition = 0);
84 void setSpecialHeaderBytes(unsigned char const* bytes, unsigned numBytes,
85 unsigned bytePosition = 0);
86 void setFrameSpecificHeaderWord(unsigned word, /* 32 bits, in host order */
87 unsigned wordPosition = 0);
88 void setFrameSpecificHeaderBytes(unsigned char const* bytes, unsigned numBytes,
89 unsigned bytePosition = 0);
90 void setFramePadding(unsigned numPaddingBytes);
91 unsigned numFramesUsedSoFar() const { return fNumFramesUsedSoFar; }
92 unsigned ourMaxPacketSize() const { return fOurMaxPacketSize; }
93
94public: // redefined virtual functions:
95 virtual void stopPlaying();
96
97protected: // redefined virtual functions:
98 virtual Boolean continuePlaying();
99
100private:
101 void buildAndSendPacket(Boolean isFirstPacket);
102 void packFrame();
103 void sendPacketIfNecessary();
104 static void sendNext(void* firstArg);
105 friend void sendNext(void*);
106
107 static void afterGettingFrame(void* clientData,
108 unsigned numBytesRead, unsigned numTruncatedBytes,
109 struct timeval presentationTime,
110 unsigned durationInMicroseconds);
111 void afterGettingFrame1(unsigned numBytesRead, unsigned numTruncatedBytes,
112 struct timeval presentationTime,
113 unsigned durationInMicroseconds);
114 Boolean isTooBigForAPacket(unsigned numBytes) const;
115
116 static void ourHandleClosure(void* clientData);
117
118private:
119 OutPacketBuffer* fOutBuf;
120
121 Boolean fNoFramesLeft;
122 unsigned fNumFramesUsedSoFar;
123 unsigned fCurFragmentationOffset;
124 Boolean fPreviousFrameEndedFragmentation;
125
126 Boolean fIsFirstPacket;
127 struct timeval fNextSendTime;
128 unsigned fTimestampPosition;
129 unsigned fSpecialHeaderPosition;
130 unsigned fSpecialHeaderSize; // size in bytes of any special header used
131 unsigned fCurFrameSpecificHeaderPosition;
132 unsigned fCurFrameSpecificHeaderSize; // size in bytes of cur frame-specific header
133 unsigned fTotalFrameSpecificHeaderSizes; // size of all frame-specific hdrs in pkt
134 unsigned fOurMaxPacketSize;
135
136 onSendErrorFunc* fOnSendErrorFunc;
137 void* fOnSendErrorData;
138};
139
140#endif
141