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 Sources
19// Implementation
20
21#include "RTPSource.hh"
22#include "GroupsockHelper.hh"
23
24////////// RTPSource //////////
25
26Boolean RTPSource::lookupByName(UsageEnvironment& env,
27 char const* sourceName,
28 RTPSource*& resultSource) {
29 resultSource = NULL; // unless we succeed
30
31 MediaSource* source;
32 if (!MediaSource::lookupByName(env, sourceName, source)) return False;
33
34 if (!source->isRTPSource()) {
35 env.setResultMsg(sourceName, " is not a RTP source");
36 return False;
37 }
38
39 resultSource = (RTPSource*)source;
40 return True;
41}
42
43Boolean RTPSource::hasBeenSynchronizedUsingRTCP() {
44 return fCurPacketHasBeenSynchronizedUsingRTCP;
45}
46
47Boolean RTPSource::isRTPSource() const {
48 return True;
49}
50
51RTPSource::RTPSource(UsageEnvironment& env, Groupsock* RTPgs,
52 unsigned char rtpPayloadFormat,
53 u_int32_t rtpTimestampFrequency)
54 : FramedSource(env),
55 fRTPInterface(this, RTPgs),
56 fCurPacketHasBeenSynchronizedUsingRTCP(False), fLastReceivedSSRC(0),
57 fRTCPInstanceForMultiplexedRTCPPackets(NULL),
58 fRTPPayloadFormat(rtpPayloadFormat), fTimestampFrequency(rtpTimestampFrequency),
59 fSSRC(our_random32()), fEnableRTCPReports(True) {
60 fReceptionStatsDB = new RTPReceptionStatsDB();
61}
62
63RTPSource::~RTPSource() {
64 delete fReceptionStatsDB;
65}
66
67void RTPSource::getAttributes() const {
68 envir().setResultMsg(""); // Fix later to get attributes from header #####
69}
70
71
72////////// RTPReceptionStatsDB //////////
73
74RTPReceptionStatsDB::RTPReceptionStatsDB()
75 : fTable(HashTable::create(ONE_WORD_HASH_KEYS)), fTotNumPacketsReceived(0) {
76 reset();
77}
78
79void RTPReceptionStatsDB::reset() {
80 fNumActiveSourcesSinceLastReset = 0;
81
82 Iterator iter(*this);
83 RTPReceptionStats* stats;
84 while ((stats = iter.next()) != NULL) {
85 stats->reset();
86 }
87}
88
89RTPReceptionStatsDB::~RTPReceptionStatsDB() {
90 // First, remove and delete all stats records from the table:
91 RTPReceptionStats* stats;
92 while ((stats = (RTPReceptionStats*)fTable->RemoveNext()) != NULL) {
93 delete stats;
94 }
95
96 // Then, delete the table itself:
97 delete fTable;
98}
99
100void RTPReceptionStatsDB
101::noteIncomingPacket(u_int32_t SSRC, u_int16_t seqNum,
102 u_int32_t rtpTimestamp, unsigned timestampFrequency,
103 Boolean useForJitterCalculation,
104 struct timeval& resultPresentationTime,
105 Boolean& resultHasBeenSyncedUsingRTCP,
106 unsigned packetSize) {
107 ++fTotNumPacketsReceived;
108 RTPReceptionStats* stats = lookup(SSRC);
109 if (stats == NULL) {
110 // This is the first time we've heard from this SSRC.
111 // Create a new record for it:
112 stats = new RTPReceptionStats(SSRC, seqNum);
113 if (stats == NULL) return;
114 add(SSRC, stats);
115 }
116
117 if (stats->numPacketsReceivedSinceLastReset() == 0) {
118 ++fNumActiveSourcesSinceLastReset;
119 }
120
121 stats->noteIncomingPacket(seqNum, rtpTimestamp, timestampFrequency,
122 useForJitterCalculation,
123 resultPresentationTime,
124 resultHasBeenSyncedUsingRTCP, packetSize);
125}
126
127void RTPReceptionStatsDB
128::noteIncomingSR(u_int32_t SSRC,
129 u_int32_t ntpTimestampMSW, u_int32_t ntpTimestampLSW,
130 u_int32_t rtpTimestamp) {
131 RTPReceptionStats* stats = lookup(SSRC);
132 if (stats == NULL) {
133 // This is the first time we've heard of this SSRC.
134 // Create a new record for it:
135 stats = new RTPReceptionStats(SSRC);
136 if (stats == NULL) return;
137 add(SSRC, stats);
138 }
139
140 stats->noteIncomingSR(ntpTimestampMSW, ntpTimestampLSW, rtpTimestamp);
141}
142
143void RTPReceptionStatsDB::removeRecord(u_int32_t SSRC) {
144 RTPReceptionStats* stats = lookup(SSRC);
145 if (stats != NULL) {
146 long SSRC_long = (long)SSRC;
147 fTable->Remove((char const*)SSRC_long);
148 delete stats;
149 }
150}
151
152RTPReceptionStatsDB::Iterator
153::Iterator(RTPReceptionStatsDB& receptionStatsDB)
154 : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {
155}
156
157RTPReceptionStatsDB::Iterator::~Iterator() {
158 delete fIter;
159}
160
161RTPReceptionStats*
162RTPReceptionStatsDB::Iterator::next(Boolean includeInactiveSources) {
163 char const* key; // dummy
164
165 // If asked, skip over any sources that haven't been active
166 // since the last reset:
167 RTPReceptionStats* stats;
168 do {
169 stats = (RTPReceptionStats*)(fIter->next(key));
170 } while (stats != NULL && !includeInactiveSources
171 && stats->numPacketsReceivedSinceLastReset() == 0);
172
173 return stats;
174}
175
176RTPReceptionStats* RTPReceptionStatsDB::lookup(u_int32_t SSRC) const {
177 long SSRC_long = (long)SSRC;
178 return (RTPReceptionStats*)(fTable->Lookup((char const*)SSRC_long));
179}
180
181void RTPReceptionStatsDB::add(u_int32_t SSRC, RTPReceptionStats* stats) {
182 long SSRC_long = (long)SSRC;
183 fTable->Add((char const*)SSRC_long, stats);
184}
185
186////////// RTPReceptionStats //////////
187
188RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC, u_int16_t initialSeqNum) {
189 initSeqNum(initialSeqNum);
190 init(SSRC);
191}
192
193RTPReceptionStats::RTPReceptionStats(u_int32_t SSRC) {
194 init(SSRC);
195}
196
197RTPReceptionStats::~RTPReceptionStats() {
198}
199
200void RTPReceptionStats::init(u_int32_t SSRC) {
201 fSSRC = SSRC;
202 fTotNumPacketsReceived = 0;
203 fTotBytesReceived_hi = fTotBytesReceived_lo = 0;
204 fBaseExtSeqNumReceived = 0;
205 fHighestExtSeqNumReceived = 0;
206 fHaveSeenInitialSequenceNumber = False;
207 fLastTransit = ~0;
208 fPreviousPacketRTPTimestamp = 0;
209 fJitter = 0.0;
210 fLastReceivedSR_NTPmsw = fLastReceivedSR_NTPlsw = 0;
211 fLastReceivedSR_time.tv_sec = fLastReceivedSR_time.tv_usec = 0;
212 fLastPacketReceptionTime.tv_sec = fLastPacketReceptionTime.tv_usec = 0;
213 fMinInterPacketGapUS = 0x7FFFFFFF;
214 fMaxInterPacketGapUS = 0;
215 fTotalInterPacketGaps.tv_sec = fTotalInterPacketGaps.tv_usec = 0;
216 fHasBeenSynchronized = False;
217 fSyncTime.tv_sec = fSyncTime.tv_usec = 0;
218 reset();
219}
220
221void RTPReceptionStats::initSeqNum(u_int16_t initialSeqNum) {
222 fBaseExtSeqNumReceived = 0x10000 | initialSeqNum;
223 fHighestExtSeqNumReceived = 0x10000 | initialSeqNum;
224 fHaveSeenInitialSequenceNumber = True;
225}
226
227#ifndef MILLION
228#define MILLION 1000000
229#endif
230
231void RTPReceptionStats
232::noteIncomingPacket(u_int16_t seqNum, u_int32_t rtpTimestamp,
233 unsigned timestampFrequency,
234 Boolean useForJitterCalculation,
235 struct timeval& resultPresentationTime,
236 Boolean& resultHasBeenSyncedUsingRTCP,
237 unsigned packetSize) {
238 if (!fHaveSeenInitialSequenceNumber) initSeqNum(seqNum);
239
240 ++fNumPacketsReceivedSinceLastReset;
241 ++fTotNumPacketsReceived;
242 u_int32_t prevTotBytesReceived_lo = fTotBytesReceived_lo;
243 fTotBytesReceived_lo += packetSize;
244 if (fTotBytesReceived_lo < prevTotBytesReceived_lo) { // wrap-around
245 ++fTotBytesReceived_hi;
246 }
247
248 // Check whether the new sequence number is the highest yet seen:
249 unsigned oldSeqNum = (fHighestExtSeqNumReceived&0xFFFF);
250 unsigned seqNumCycle = (fHighestExtSeqNumReceived&0xFFFF0000);
251 unsigned seqNumDifference = (unsigned)((int)seqNum-(int)oldSeqNum);
252 unsigned newSeqNum = 0;
253 if (seqNumLT((u_int16_t)oldSeqNum, seqNum)) {
254 // This packet was not an old packet received out of order, so check it:
255
256 if (seqNumDifference >= 0x8000) {
257 // The sequence number wrapped around, so start a new cycle:
258 seqNumCycle += 0x10000;
259 }
260
261 newSeqNum = seqNumCycle|seqNum;
262 if (newSeqNum > fHighestExtSeqNumReceived) {
263 fHighestExtSeqNumReceived = newSeqNum;
264 }
265 } else if (fTotNumPacketsReceived > 1) {
266 // This packet was an old packet received out of order
267
268 if ((int)seqNumDifference >= 0x8000) {
269 // The sequence number wrapped around, so switch to an old cycle:
270 seqNumCycle -= 0x10000;
271 }
272
273 newSeqNum = seqNumCycle|seqNum;
274 if (newSeqNum < fBaseExtSeqNumReceived) {
275 fBaseExtSeqNumReceived = newSeqNum;
276 }
277 }
278
279 // Record the inter-packet delay
280 struct timeval timeNow;
281 gettimeofday(&timeNow, NULL);
282 if (fLastPacketReceptionTime.tv_sec != 0
283 || fLastPacketReceptionTime.tv_usec != 0) {
284 unsigned gap
285 = (timeNow.tv_sec - fLastPacketReceptionTime.tv_sec)*MILLION
286 + timeNow.tv_usec - fLastPacketReceptionTime.tv_usec;
287 if (gap > fMaxInterPacketGapUS) {
288 fMaxInterPacketGapUS = gap;
289 }
290 if (gap < fMinInterPacketGapUS) {
291 fMinInterPacketGapUS = gap;
292 }
293 fTotalInterPacketGaps.tv_usec += gap;
294 if (fTotalInterPacketGaps.tv_usec >= MILLION) {
295 ++fTotalInterPacketGaps.tv_sec;
296 fTotalInterPacketGaps.tv_usec -= MILLION;
297 }
298 }
299 fLastPacketReceptionTime = timeNow;
300
301 // Compute the current 'jitter' using the received packet's RTP timestamp,
302 // and the RTP timestamp that would correspond to the current time.
303 // (Use the code from appendix A.8 in the RTP spec.)
304 // Note, however, that we don't use this packet if its timestamp is
305 // the same as that of the previous packet (this indicates a multi-packet
306 // fragment), or if we've been explicitly told not to use this packet.
307 if (useForJitterCalculation
308 && rtpTimestamp != fPreviousPacketRTPTimestamp) {
309 unsigned arrival = (timestampFrequency*timeNow.tv_sec);
310 arrival += (unsigned)
311 ((2.0*timestampFrequency*timeNow.tv_usec + 1000000.0)/2000000);
312 // note: rounding
313 int transit = arrival - rtpTimestamp;
314 if (fLastTransit == (~0)) fLastTransit = transit; // hack for first time
315 int d = transit - fLastTransit;
316 fLastTransit = transit;
317 if (d < 0) d = -d;
318 fJitter += (1.0/16.0) * ((double)d - fJitter);
319 }
320
321 // Return the 'presentation time' that corresponds to "rtpTimestamp":
322 if (fSyncTime.tv_sec == 0 && fSyncTime.tv_usec == 0) {
323 // This is the first timestamp that we've seen, so use the current
324 // 'wall clock' time as the synchronization time. (This will be
325 // corrected later when we receive RTCP SRs.)
326 fSyncTimestamp = rtpTimestamp;
327 fSyncTime = timeNow;
328 }
329
330 int timestampDiff = rtpTimestamp - fSyncTimestamp;
331 // Note: This works even if the timestamp wraps around
332 // (as long as "int" is 32 bits)
333
334 // Divide this by the timestamp frequency to get real time:
335 double timeDiff = timestampDiff/(double)timestampFrequency;
336
337 // Add this to the 'sync time' to get our result:
338 unsigned const million = 1000000;
339 unsigned seconds, uSeconds;
340 if (timeDiff >= 0.0) {
341 seconds = fSyncTime.tv_sec + (unsigned)(timeDiff);
342 uSeconds = fSyncTime.tv_usec
343 + (unsigned)((timeDiff - (unsigned)timeDiff)*million);
344 if (uSeconds >= million) {
345 uSeconds -= million;
346 ++seconds;
347 }
348 } else {
349 timeDiff = -timeDiff;
350 seconds = fSyncTime.tv_sec - (unsigned)(timeDiff);
351 uSeconds = fSyncTime.tv_usec
352 - (unsigned)((timeDiff - (unsigned)timeDiff)*million);
353 if ((int)uSeconds < 0) {
354 uSeconds += million;
355 --seconds;
356 }
357 }
358 resultPresentationTime.tv_sec = seconds;
359 resultPresentationTime.tv_usec = uSeconds;
360 resultHasBeenSyncedUsingRTCP = fHasBeenSynchronized;
361
362 // Save these as the new synchronization timestamp & time:
363 fSyncTimestamp = rtpTimestamp;
364 fSyncTime = resultPresentationTime;
365
366 fPreviousPacketRTPTimestamp = rtpTimestamp;
367}
368
369void RTPReceptionStats::noteIncomingSR(u_int32_t ntpTimestampMSW,
370 u_int32_t ntpTimestampLSW,
371 u_int32_t rtpTimestamp) {
372 fLastReceivedSR_NTPmsw = ntpTimestampMSW;
373 fLastReceivedSR_NTPlsw = ntpTimestampLSW;
374
375 gettimeofday(&fLastReceivedSR_time, NULL);
376
377 // Use this SR to update time synchronization information:
378 fSyncTimestamp = rtpTimestamp;
379 fSyncTime.tv_sec = ntpTimestampMSW - 0x83AA7E80; // 1/1/1900 -> 1/1/1970
380 double microseconds = (ntpTimestampLSW*15625.0)/0x04000000; // 10^6/2^32
381 fSyncTime.tv_usec = (unsigned)(microseconds+0.5);
382 fHasBeenSynchronized = True;
383}
384
385double RTPReceptionStats::totNumKBytesReceived() const {
386 double const hiMultiplier = 0x20000000/125.0; // == (2^32)/(10^3)
387 return fTotBytesReceived_hi*hiMultiplier + fTotBytesReceived_lo/1000.0;
388}
389
390unsigned RTPReceptionStats::jitter() const {
391 return (unsigned)fJitter;
392}
393
394void RTPReceptionStats::reset() {
395 fNumPacketsReceivedSinceLastReset = 0;
396 fLastResetExtSeqNumReceived = fHighestExtSeqNumReceived;
397}
398
399Boolean seqNumLT(u_int16_t s1, u_int16_t s2) {
400 // a 'less-than' on 16-bit sequence numbers
401 int diff = s2-s1;
402 if (diff > 0) {
403 return (diff < 0x8000);
404 } else if (diff < 0) {
405 return (diff < -0x8000);
406 } else { // diff == 0
407 return False;
408 }
409}
410