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// Implementation
21
22#include "MultiFramedRTPSink.hh"
23#include "GroupsockHelper.hh"
24
25////////// MultiFramedRTPSink //////////
26
27void MultiFramedRTPSink::setPacketSizes(unsigned preferredPacketSize,
28 unsigned maxPacketSize) {
29 if (preferredPacketSize > maxPacketSize || preferredPacketSize == 0) return;
30 // sanity check
31
32 delete fOutBuf;
33 fOutBuf = new OutPacketBuffer(preferredPacketSize, maxPacketSize);
34 fOurMaxPacketSize = maxPacketSize; // save value, in case subclasses need it
35}
36
37#ifndef RTP_PAYLOAD_MAX_SIZE
38#define RTP_PAYLOAD_MAX_SIZE 1456
39 // Default max packet size (1500, minus allowance for IP, UDP, UMTP headers)
40 // (Also, make it a multiple of 4 bytes, just in case that matters.)
41#endif
42#ifndef RTP_PAYLOAD_PREFERRED_SIZE
43#define RTP_PAYLOAD_PREFERRED_SIZE ((RTP_PAYLOAD_MAX_SIZE) < 1000 ? (RTP_PAYLOAD_MAX_SIZE) : 1000)
44#endif
45
46MultiFramedRTPSink::MultiFramedRTPSink(UsageEnvironment& env,
47 Groupsock* rtpGS,
48 unsigned char rtpPayloadType,
49 unsigned rtpTimestampFrequency,
50 char const* rtpPayloadFormatName,
51 unsigned numChannels)
52 : RTPSink(env, rtpGS, rtpPayloadType, rtpTimestampFrequency,
53 rtpPayloadFormatName, numChannels),
54 fOutBuf(NULL), fCurFragmentationOffset(0), fPreviousFrameEndedFragmentation(False),
55 fOnSendErrorFunc(NULL), fOnSendErrorData(NULL) {
56 setPacketSizes((RTP_PAYLOAD_PREFERRED_SIZE), (RTP_PAYLOAD_MAX_SIZE));
57}
58
59MultiFramedRTPSink::~MultiFramedRTPSink() {
60 delete fOutBuf;
61}
62
63void MultiFramedRTPSink
64::doSpecialFrameHandling(unsigned /*fragmentationOffset*/,
65 unsigned char* /*frameStart*/,
66 unsigned /*numBytesInFrame*/,
67 struct timeval framePresentationTime,
68 unsigned /*numRemainingBytes*/) {
69 // default implementation: If this is the first frame in the packet,
70 // use its presentationTime for the RTP timestamp:
71 if (isFirstFrameInPacket()) {
72 setTimestamp(framePresentationTime);
73 }
74}
75
76Boolean MultiFramedRTPSink::allowFragmentationAfterStart() const {
77 return False; // by default
78}
79
80Boolean MultiFramedRTPSink::allowOtherFramesAfterLastFragment() const {
81 return False; // by default
82}
83
84Boolean MultiFramedRTPSink
85::frameCanAppearAfterPacketStart(unsigned char const* /*frameStart*/,
86 unsigned /*numBytesInFrame*/) const {
87 return True; // by default
88}
89
90unsigned MultiFramedRTPSink::specialHeaderSize() const {
91 // default implementation: Assume no special header:
92 return 0;
93}
94
95unsigned MultiFramedRTPSink::frameSpecificHeaderSize() const {
96 // default implementation: Assume no frame-specific header:
97 return 0;
98}
99
100unsigned MultiFramedRTPSink::computeOverflowForNewFrame(unsigned newFrameSize) const {
101 // default implementation: Just call numOverflowBytes()
102 return fOutBuf->numOverflowBytes(newFrameSize);
103}
104
105void MultiFramedRTPSink::setMarkerBit() {
106 unsigned rtpHdr = fOutBuf->extractWord(0);
107 rtpHdr |= 0x00800000;
108 fOutBuf->insertWord(rtpHdr, 0);
109}
110
111void MultiFramedRTPSink::setTimestamp(struct timeval framePresentationTime) {
112 // First, convert the presentation time to a 32-bit RTP timestamp:
113 fCurrentTimestamp = convertToRTPTimestamp(framePresentationTime);
114
115 // Then, insert it into the RTP packet:
116 fOutBuf->insertWord(fCurrentTimestamp, fTimestampPosition);
117}
118
119void MultiFramedRTPSink::setSpecialHeaderWord(unsigned word,
120 unsigned wordPosition) {
121 fOutBuf->insertWord(word, fSpecialHeaderPosition + 4*wordPosition);
122}
123
124void MultiFramedRTPSink::setSpecialHeaderBytes(unsigned char const* bytes,
125 unsigned numBytes,
126 unsigned bytePosition) {
127 fOutBuf->insert(bytes, numBytes, fSpecialHeaderPosition + bytePosition);
128}
129
130void MultiFramedRTPSink::setFrameSpecificHeaderWord(unsigned word,
131 unsigned wordPosition) {
132 fOutBuf->insertWord(word, fCurFrameSpecificHeaderPosition + 4*wordPosition);
133}
134
135void MultiFramedRTPSink::setFrameSpecificHeaderBytes(unsigned char const* bytes,
136 unsigned numBytes,
137 unsigned bytePosition) {
138 fOutBuf->insert(bytes, numBytes, fCurFrameSpecificHeaderPosition + bytePosition);
139}
140
141void MultiFramedRTPSink::setFramePadding(unsigned numPaddingBytes) {
142 if (numPaddingBytes > 0) {
143 // Add the padding bytes (with the last one being the padding size):
144 unsigned char paddingBuffer[255]; //max padding
145 memset(paddingBuffer, 0, numPaddingBytes);
146 paddingBuffer[numPaddingBytes-1] = numPaddingBytes;
147 fOutBuf->enqueue(paddingBuffer, numPaddingBytes);
148
149 // Set the RTP padding bit:
150 unsigned rtpHdr = fOutBuf->extractWord(0);
151 rtpHdr |= 0x20000000;
152 fOutBuf->insertWord(rtpHdr, 0);
153 }
154}
155
156Boolean MultiFramedRTPSink::continuePlaying() {
157 // Send the first packet.
158 // (This will also schedule any future sends.)
159 buildAndSendPacket(True);
160 return True;
161}
162
163void MultiFramedRTPSink::stopPlaying() {
164 fOutBuf->resetPacketStart();
165 fOutBuf->resetOffset();
166 fOutBuf->resetOverflowData();
167
168 // Then call the default "stopPlaying()" function:
169 MediaSink::stopPlaying();
170}
171
172void MultiFramedRTPSink::buildAndSendPacket(Boolean isFirstPacket) {
173 nextTask() = NULL;
174 fIsFirstPacket = isFirstPacket;
175
176 // Set up the RTP header:
177 unsigned rtpHdr = 0x80000000; // RTP version 2; marker ('M') bit not set (by default; it can be set later)
178 rtpHdr |= (fRTPPayloadType<<16);
179 rtpHdr |= fSeqNo; // sequence number
180 fOutBuf->enqueueWord(rtpHdr);
181
182 // Note where the RTP timestamp will go.
183 // (We can't fill this in until we start packing payload frames.)
184 fTimestampPosition = fOutBuf->curPacketSize();
185 fOutBuf->skipBytes(4); // leave a hole for the timestamp
186
187 fOutBuf->enqueueWord(SSRC());
188
189 // Allow for a special, payload-format-specific header following the
190 // RTP header:
191 fSpecialHeaderPosition = fOutBuf->curPacketSize();
192 fSpecialHeaderSize = specialHeaderSize();
193 fOutBuf->skipBytes(fSpecialHeaderSize);
194
195 // Begin packing as many (complete) frames into the packet as we can:
196 fTotalFrameSpecificHeaderSizes = 0;
197 fNoFramesLeft = False;
198 fNumFramesUsedSoFar = 0;
199 packFrame();
200}
201
202void MultiFramedRTPSink::packFrame() {
203 // Get the next frame.
204
205 // First, skip over the space we'll use for any frame-specific header:
206 fCurFrameSpecificHeaderPosition = fOutBuf->curPacketSize();
207 fCurFrameSpecificHeaderSize = frameSpecificHeaderSize();
208 fOutBuf->skipBytes(fCurFrameSpecificHeaderSize);
209 fTotalFrameSpecificHeaderSizes += fCurFrameSpecificHeaderSize;
210
211 // See if we have an overflow frame that was too big for the last pkt
212 if (fOutBuf->haveOverflowData()) {
213 // Use this frame before reading a new one from the source
214 unsigned frameSize = fOutBuf->overflowDataSize();
215 struct timeval presentationTime = fOutBuf->overflowPresentationTime();
216 unsigned durationInMicroseconds = fOutBuf->overflowDurationInMicroseconds();
217 fOutBuf->useOverflowData();
218
219 afterGettingFrame1(frameSize, 0, presentationTime, durationInMicroseconds);
220 } else {
221 // Normal case: we need to read a new frame from the source
222 if (fSource == NULL) return;
223 fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(),
224 afterGettingFrame, this, ourHandleClosure, this);
225 }
226}
227
228void MultiFramedRTPSink
229::afterGettingFrame(void* clientData, unsigned numBytesRead,
230 unsigned numTruncatedBytes,
231 struct timeval presentationTime,
232 unsigned durationInMicroseconds) {
233 MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;
234 sink->afterGettingFrame1(numBytesRead, numTruncatedBytes,
235 presentationTime, durationInMicroseconds);
236}
237
238void MultiFramedRTPSink
239::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
240 struct timeval presentationTime,
241 unsigned durationInMicroseconds) {
242 if (fIsFirstPacket) {
243 // Record the fact that we're starting to play now:
244 gettimeofday(&fNextSendTime, NULL);
245 }
246
247 fMostRecentPresentationTime = presentationTime;
248 if (fInitialPresentationTime.tv_sec == 0 && fInitialPresentationTime.tv_usec == 0) {
249 fInitialPresentationTime = presentationTime;
250 }
251
252 if (numTruncatedBytes > 0) {
253 unsigned const bufferSize = fOutBuf->totalBytesAvailable();
254 envir() << "MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size ("
255 << bufferSize << "). "
256 << numTruncatedBytes << " bytes of trailing data was dropped! Correct this by increasing \"OutPacketBuffer::maxSize\" to at least "
257 << OutPacketBuffer::maxSize + numTruncatedBytes << ", *before* creating this 'RTPSink'. (Current value is "
258 << OutPacketBuffer::maxSize << ".)\n";
259 }
260 unsigned curFragmentationOffset = fCurFragmentationOffset;
261 unsigned numFrameBytesToUse = frameSize;
262 unsigned overflowBytes = 0;
263
264 // If we have already packed one or more frames into this packet,
265 // check whether this new frame is eligible to be packed after them.
266 // (This is independent of whether the packet has enough room for this
267 // new frame; that check comes later.)
268 if (fNumFramesUsedSoFar > 0) {
269 if ((fPreviousFrameEndedFragmentation
270 && !allowOtherFramesAfterLastFragment())
271 || !frameCanAppearAfterPacketStart(fOutBuf->curPtr(), frameSize)) {
272 // Save away this frame for next time:
273 numFrameBytesToUse = 0;
274 fOutBuf->setOverflowData(fOutBuf->curPacketSize(), frameSize,
275 presentationTime, durationInMicroseconds);
276 }
277 }
278 fPreviousFrameEndedFragmentation = False;
279
280 if (numFrameBytesToUse > 0) {
281 // Check whether this frame overflows the packet
282 if (fOutBuf->wouldOverflow(frameSize)) {
283 // Don't use this frame now; instead, save it as overflow data, and
284 // send it in the next packet instead. However, if the frame is too
285 // big to fit in a packet by itself, then we need to fragment it (and
286 // use some of it in this packet, if the payload format permits this.)
287 if (isTooBigForAPacket(frameSize)
288 && (fNumFramesUsedSoFar == 0 || allowFragmentationAfterStart())) {
289 // We need to fragment this frame, and use some of it now:
290 overflowBytes = computeOverflowForNewFrame(frameSize);
291 numFrameBytesToUse -= overflowBytes;
292 fCurFragmentationOffset += numFrameBytesToUse;
293 } else {
294 // We don't use any of this frame now:
295 overflowBytes = frameSize;
296 numFrameBytesToUse = 0;
297 }
298 fOutBuf->setOverflowData(fOutBuf->curPacketSize() + numFrameBytesToUse,
299 overflowBytes, presentationTime, durationInMicroseconds);
300 } else if (fCurFragmentationOffset > 0) {
301 // This is the last fragment of a frame that was fragmented over
302 // more than one packet. Do any special handling for this case:
303 fCurFragmentationOffset = 0;
304 fPreviousFrameEndedFragmentation = True;
305 }
306 }
307
308 if (numFrameBytesToUse == 0 && frameSize > 0) {
309 // Send our packet now, because we have filled it up:
310 sendPacketIfNecessary();
311 } else {
312 // Use this frame in our outgoing packet:
313 unsigned char* frameStart = fOutBuf->curPtr();
314 fOutBuf->increment(numFrameBytesToUse);
315 // do this now, in case "doSpecialFrameHandling()" calls "setFramePadding()" to append padding bytes
316
317 // Here's where any payload format specific processing gets done:
318 doSpecialFrameHandling(curFragmentationOffset, frameStart,
319 numFrameBytesToUse, presentationTime,
320 overflowBytes);
321
322 ++fNumFramesUsedSoFar;
323
324 // Update the time at which the next packet should be sent, based
325 // on the duration of the frame that we just packed into it.
326 // However, if this frame has overflow data remaining, then don't
327 // count its duration yet.
328 if (overflowBytes == 0) {
329 fNextSendTime.tv_usec += durationInMicroseconds;
330 fNextSendTime.tv_sec += fNextSendTime.tv_usec/1000000;
331 fNextSendTime.tv_usec %= 1000000;
332 }
333
334 // Send our packet now if (i) it's already at our preferred size, or
335 // (ii) (heuristic) another frame of the same size as the one we just
336 // read would overflow the packet, or
337 // (iii) it contains the last fragment of a fragmented frame, and we
338 // don't allow anything else to follow this or
339 // (iv) only one frame per packet is allowed:
340 if (fOutBuf->isPreferredSize()
341 || fOutBuf->wouldOverflow(numFrameBytesToUse)
342 || (fPreviousFrameEndedFragmentation &&
343 !allowOtherFramesAfterLastFragment())
344 || !frameCanAppearAfterPacketStart(fOutBuf->curPtr() - frameSize,
345 frameSize) ) {
346 // The packet is ready to be sent now
347 sendPacketIfNecessary();
348 } else {
349 // There's room for more frames; try getting another:
350 packFrame();
351 }
352 }
353}
354
355static unsigned const rtpHeaderSize = 12;
356
357Boolean MultiFramedRTPSink::isTooBigForAPacket(unsigned numBytes) const {
358 // Check whether a 'numBytes'-byte frame - together with a RTP header and
359 // (possible) special headers - would be too big for an output packet:
360 // (Later allow for RTP extension header!) #####
361 numBytes += rtpHeaderSize + specialHeaderSize() + frameSpecificHeaderSize();
362 return fOutBuf->isTooBigForAPacket(numBytes);
363}
364
365void MultiFramedRTPSink::sendPacketIfNecessary() {
366 if (fNumFramesUsedSoFar > 0) {
367 // Send the packet:
368#ifdef TEST_LOSS
369 if ((our_random()%10) != 0) // simulate 10% packet loss #####
370#endif
371 if (!fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize())) {
372 // if failure handler has been specified, call it
373 if (fOnSendErrorFunc != NULL) (*fOnSendErrorFunc)(fOnSendErrorData);
374 }
375 ++fPacketCount;
376 fTotalOctetCount += fOutBuf->curPacketSize();
377 fOctetCount += fOutBuf->curPacketSize()
378 - rtpHeaderSize - fSpecialHeaderSize - fTotalFrameSpecificHeaderSizes;
379
380 ++fSeqNo; // for next time
381 }
382
383 if (fOutBuf->haveOverflowData()
384 && fOutBuf->totalBytesAvailable() > fOutBuf->totalBufferSize()/2) {
385 // Efficiency hack: Reset the packet start pointer to just in front of
386 // the overflow data (allowing for the RTP header and special headers),
387 // so that we probably don't have to "memmove()" the overflow data
388 // into place when building the next packet:
389 unsigned newPacketStart = fOutBuf->curPacketSize()
390 - (rtpHeaderSize + fSpecialHeaderSize + frameSpecificHeaderSize());
391 fOutBuf->adjustPacketStart(newPacketStart);
392 } else {
393 // Normal case: Reset the packet start pointer back to the start:
394 fOutBuf->resetPacketStart();
395 }
396 fOutBuf->resetOffset();
397 fNumFramesUsedSoFar = 0;
398
399 if (fNoFramesLeft) {
400 // We're done:
401 onSourceClosure();
402 } else {
403 // We have more frames left to send. Figure out when the next frame
404 // is due to start playing, then make sure that we wait this long before
405 // sending the next packet.
406 struct timeval timeNow;
407 gettimeofday(&timeNow, NULL);
408 int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
409 int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
410 if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that the time-to-delay is non-negative:
411 uSecondsToGo = 0;
412 }
413
414 // Delay this amount of time:
415 nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this);
416 }
417}
418
419// The following is called after each delay between packet sends:
420void MultiFramedRTPSink::sendNext(void* firstArg) {
421 MultiFramedRTPSink* sink = (MultiFramedRTPSink*)firstArg;
422 sink->buildAndSendPacket(False);
423}
424
425void MultiFramedRTPSink::ourHandleClosure(void* clientData) {
426 MultiFramedRTPSink* sink = (MultiFramedRTPSink*)clientData;
427 // There are no frames left, but we may have a partially built packet
428 // to send
429 sink->fNoFramesLeft = True;
430 sink->sendPacketIfNecessary();
431}
432