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 Sinks
19// Implementation
20
21#include "RTPSink.hh"
22#include "GroupsockHelper.hh"
23
24////////// RTPSink //////////
25
26Boolean RTPSink::lookupByName(UsageEnvironment& env, char const* sinkName,
27 RTPSink*& resultSink) {
28 resultSink = NULL; // unless we succeed
29
30 MediaSink* sink;
31 if (!MediaSink::lookupByName(env, sinkName, sink)) return False;
32
33 if (!sink->isRTPSink()) {
34 env.setResultMsg(sinkName, " is not a RTP sink");
35 return False;
36 }
37
38 resultSink = (RTPSink*)sink;
39 return True;
40}
41
42Boolean RTPSink::isRTPSink() const {
43 return True;
44}
45
46RTPSink::RTPSink(UsageEnvironment& env,
47 Groupsock* rtpGS, unsigned char rtpPayloadType,
48 unsigned rtpTimestampFrequency,
49 char const* rtpPayloadFormatName,
50 unsigned numChannels)
51 : MediaSink(env), fRTPInterface(this, rtpGS),
52 fRTPPayloadType(rtpPayloadType),
53 fPacketCount(0), fOctetCount(0), fTotalOctetCount(0),
54 fTimestampFrequency(rtpTimestampFrequency), fNextTimestampHasBeenPreset(False), fEnableRTCPReports(True),
55 fNumChannels(numChannels), fEstimatedBitrate(0) {
56 fRTPPayloadFormatName
57 = strDup(rtpPayloadFormatName == NULL ? "???" : rtpPayloadFormatName);
58 gettimeofday(&fCreationTime, NULL);
59 fTotalOctetCountStartTime = fCreationTime;
60 resetPresentationTimes();
61
62 fSeqNo = (u_int16_t)our_random();
63 fSSRC = our_random32();
64 fTimestampBase = our_random32();
65
66 fTransmissionStatsDB = new RTPTransmissionStatsDB(*this);
67}
68
69RTPSink::~RTPSink() {
70 delete fTransmissionStatsDB;
71 delete[] (char*)fRTPPayloadFormatName;
72 fRTPInterface.forgetOurGroupsock();
73 // so that the "fRTCPInterface" destructor doesn't turn off background read handling (in case
74 // its 'groupsock' is being shared with something else that does background read handling).
75}
76
77u_int32_t RTPSink::convertToRTPTimestamp(struct timeval tv) {
78 // Begin by converting from "struct timeval" units to RTP timestamp units:
79 u_int32_t timestampIncrement = (fTimestampFrequency*tv.tv_sec);
80 timestampIncrement += (u_int32_t)(fTimestampFrequency*(tv.tv_usec/1000000.0) + 0.5); // note: rounding
81
82 // Then add this to our 'timestamp base':
83 if (fNextTimestampHasBeenPreset) {
84 // Make the returned timestamp the same as the current "fTimestampBase",
85 // so that timestamps begin with the value that was previously preset:
86 fTimestampBase -= timestampIncrement;
87 fNextTimestampHasBeenPreset = False;
88 }
89
90 u_int32_t const rtpTimestamp = fTimestampBase + timestampIncrement;
91#ifdef DEBUG_TIMESTAMPS
92 fprintf(stderr, "fTimestampBase: 0x%08x, tv: %lu.%06ld\n\t=> RTP timestamp: 0x%08x\n",
93 fTimestampBase, tv.tv_sec, tv.tv_usec, rtpTimestamp);
94 fflush(stderr);
95#endif
96
97 return rtpTimestamp;
98}
99
100u_int32_t RTPSink::presetNextTimestamp() {
101 struct timeval timeNow;
102 gettimeofday(&timeNow, NULL);
103
104 u_int32_t tsNow = convertToRTPTimestamp(timeNow);
105 if (!groupsockBeingUsed().hasMultipleDestinations()) {
106 // Don't adjust the timestamp stream if we already have another destination ongoing
107 fTimestampBase = tsNow;
108 fNextTimestampHasBeenPreset = True;
109 }
110
111 return tsNow;
112}
113
114void RTPSink::getTotalBitrate(unsigned& outNumBytes, double& outElapsedTime) {
115 struct timeval timeNow;
116 gettimeofday(&timeNow, NULL);
117
118 outNumBytes = fTotalOctetCount;
119 outElapsedTime = (double)(timeNow.tv_sec-fTotalOctetCountStartTime.tv_sec)
120 + (timeNow.tv_usec-fTotalOctetCountStartTime.tv_usec)/1000000.0;
121
122 fTotalOctetCount = 0;
123 fTotalOctetCountStartTime = timeNow;
124}
125
126void RTPSink::resetPresentationTimes() {
127 fInitialPresentationTime.tv_sec = fMostRecentPresentationTime.tv_sec = 0;
128 fInitialPresentationTime.tv_usec = fMostRecentPresentationTime.tv_usec = 0;
129}
130
131char const* RTPSink::sdpMediaType() const {
132 return "data";
133 // default SDP media (m=) type, unless redefined by subclasses
134}
135
136char* RTPSink::rtpmapLine() const {
137 if (rtpPayloadType() >= 96) { // the payload format type is dynamic
138 char* encodingParamsPart;
139 if (numChannels() != 1) {
140 encodingParamsPart = new char[1 + 20 /* max int len */];
141 sprintf(encodingParamsPart, "/%d", numChannels());
142 } else {
143 encodingParamsPart = strDup("");
144 }
145 char const* const rtpmapFmt = "a=rtpmap:%d %s/%d%s\r\n";
146 unsigned rtpmapFmtSize = strlen(rtpmapFmt)
147 + 3 /* max char len */ + strlen(rtpPayloadFormatName())
148 + 20 /* max int len */ + strlen(encodingParamsPart);
149 char* rtpmapLine = new char[rtpmapFmtSize];
150 sprintf(rtpmapLine, rtpmapFmt,
151 rtpPayloadType(), rtpPayloadFormatName(),
152 rtpTimestampFrequency(), encodingParamsPart);
153 delete[] encodingParamsPart;
154
155 return rtpmapLine;
156 } else {
157 // The payload format is staic, so there's no "a=rtpmap:" line:
158 return strDup("");
159 }
160}
161
162char const* RTPSink::auxSDPLine() {
163 return NULL; // by default
164}
165
166
167////////// RTPTransmissionStatsDB //////////
168
169RTPTransmissionStatsDB::RTPTransmissionStatsDB(RTPSink& rtpSink)
170 : fOurRTPSink(rtpSink),
171 fTable(HashTable::create(ONE_WORD_HASH_KEYS)) {
172 fNumReceivers=0;
173}
174
175RTPTransmissionStatsDB::~RTPTransmissionStatsDB() {
176 // First, remove and delete all stats records from the table:
177 RTPTransmissionStats* stats;
178 while ((stats = (RTPTransmissionStats*)fTable->RemoveNext()) != NULL) {
179 delete stats;
180 }
181
182 // Then, delete the table itself:
183 delete fTable;
184}
185
186void RTPTransmissionStatsDB
187::noteIncomingRR(u_int32_t SSRC, struct sockaddr_in const& lastFromAddress,
188 unsigned lossStats, unsigned lastPacketNumReceived,
189 unsigned jitter, unsigned lastSRTime, unsigned diffSR_RRTime) {
190 RTPTransmissionStats* stats = lookup(SSRC);
191 if (stats == NULL) {
192 // This is the first time we've heard of this SSRC.
193 // Create a new record for it:
194 stats = new RTPTransmissionStats(fOurRTPSink, SSRC);
195 if (stats == NULL) return;
196 add(SSRC, stats);
197#ifdef DEBUG_RR
198 fprintf(stderr, "Adding new entry for SSRC %x in RTPTransmissionStatsDB\n", SSRC);
199#endif
200 }
201
202 stats->noteIncomingRR(lastFromAddress,
203 lossStats, lastPacketNumReceived, jitter,
204 lastSRTime, diffSR_RRTime);
205}
206
207void RTPTransmissionStatsDB::removeRecord(u_int32_t SSRC) {
208 RTPTransmissionStats* stats = lookup(SSRC);
209 if (stats != NULL) {
210 long SSRC_long = (long)SSRC;
211 fTable->Remove((char const*)SSRC_long);
212 --fNumReceivers;
213 delete stats;
214 }
215}
216
217RTPTransmissionStatsDB::Iterator
218::Iterator(RTPTransmissionStatsDB& receptionStatsDB)
219 : fIter(HashTable::Iterator::create(*(receptionStatsDB.fTable))) {
220}
221
222RTPTransmissionStatsDB::Iterator::~Iterator() {
223 delete fIter;
224}
225
226RTPTransmissionStats*
227RTPTransmissionStatsDB::Iterator::next() {
228 char const* key; // dummy
229
230 return (RTPTransmissionStats*)(fIter->next(key));
231}
232
233RTPTransmissionStats* RTPTransmissionStatsDB::lookup(u_int32_t SSRC) const {
234 long SSRC_long = (long)SSRC;
235 return (RTPTransmissionStats*)(fTable->Lookup((char const*)SSRC_long));
236}
237
238void RTPTransmissionStatsDB::add(u_int32_t SSRC, RTPTransmissionStats* stats) {
239 long SSRC_long = (long)SSRC;
240 fTable->Add((char const*)SSRC_long, stats);
241 ++fNumReceivers;
242}
243
244
245////////// RTPTransmissionStats //////////
246
247RTPTransmissionStats::RTPTransmissionStats(RTPSink& rtpSink, u_int32_t SSRC)
248 : fOurRTPSink(rtpSink), fSSRC(SSRC), fLastPacketNumReceived(0),
249 fPacketLossRatio(0), fTotNumPacketsLost(0), fJitter(0),
250 fLastSRTime(0), fDiffSR_RRTime(0), fAtLeastTwoRRsHaveBeenReceived(False), fFirstPacket(True),
251 fTotalOctetCount_hi(0), fTotalOctetCount_lo(0),
252 fTotalPacketCount_hi(0), fTotalPacketCount_lo(0) {
253 gettimeofday(&fTimeCreated, NULL);
254
255 fLastOctetCount = rtpSink.octetCount();
256 fLastPacketCount = rtpSink.packetCount();
257}
258
259RTPTransmissionStats::~RTPTransmissionStats() {}
260
261void RTPTransmissionStats
262::noteIncomingRR(struct sockaddr_in const& lastFromAddress,
263 unsigned lossStats, unsigned lastPacketNumReceived,
264 unsigned jitter, unsigned lastSRTime,
265 unsigned diffSR_RRTime) {
266 if (fFirstPacket) {
267 fFirstPacket = False;
268 fFirstPacketNumReported = lastPacketNumReceived;
269 } else {
270 fAtLeastTwoRRsHaveBeenReceived = True;
271 fOldLastPacketNumReceived = fLastPacketNumReceived;
272 fOldTotNumPacketsLost = fTotNumPacketsLost;
273 }
274 gettimeofday(&fTimeReceived, NULL);
275
276 fLastFromAddress = lastFromAddress;
277 fPacketLossRatio = lossStats>>24;
278 fTotNumPacketsLost = lossStats&0xFFFFFF;
279 fLastPacketNumReceived = lastPacketNumReceived;
280 fJitter = jitter;
281 fLastSRTime = lastSRTime;
282 fDiffSR_RRTime = diffSR_RRTime;
283#ifdef DEBUG_RR
284 fprintf(stderr, "RTCP RR data (received at %lu.%06ld): lossStats 0x%08x, lastPacketNumReceived 0x%08x, jitter 0x%08x, lastSRTime 0x%08x, diffSR_RRTime 0x%08x\n",
285 fTimeReceived.tv_sec, fTimeReceived.tv_usec, lossStats, lastPacketNumReceived, jitter, lastSRTime, diffSR_RRTime);
286 unsigned rtd = roundTripDelay();
287 fprintf(stderr, "=> round-trip delay: 0x%04x (== %f seconds)\n", rtd, rtd/65536.0);
288#endif
289
290 // Update our counts of the total number of octets and packets sent towards
291 // this receiver:
292 u_int32_t newOctetCount = fOurRTPSink.octetCount();
293 u_int32_t octetCountDiff = newOctetCount - fLastOctetCount;
294 fLastOctetCount = newOctetCount;
295 u_int32_t prevTotalOctetCount_lo = fTotalOctetCount_lo;
296 fTotalOctetCount_lo += octetCountDiff;
297 if (fTotalOctetCount_lo < prevTotalOctetCount_lo) { // wrap around
298 ++fTotalOctetCount_hi;
299 }
300
301 u_int32_t newPacketCount = fOurRTPSink.packetCount();
302 u_int32_t packetCountDiff = newPacketCount - fLastPacketCount;
303 fLastPacketCount = newPacketCount;
304 u_int32_t prevTotalPacketCount_lo = fTotalPacketCount_lo;
305 fTotalPacketCount_lo += packetCountDiff;
306 if (fTotalPacketCount_lo < prevTotalPacketCount_lo) { // wrap around
307 ++fTotalPacketCount_hi;
308 }
309}
310
311unsigned RTPTransmissionStats::roundTripDelay() const {
312 // Compute the round-trip delay that was indicated by the most recently-received
313 // RTCP RR packet. Use the method noted in the RTP/RTCP specification (RFC 3350).
314
315 if (fLastSRTime == 0) {
316 // Either no RTCP RR packet has been received yet, or else the
317 // reporting receiver has not yet received any RTCP SR packets from us:
318 return 0;
319 }
320
321 // First, convert the time that we received the last RTCP RR packet to NTP format,
322 // in units of 1/65536 (2^-16) seconds:
323 unsigned lastReceivedTimeNTP_high
324 = fTimeReceived.tv_sec + 0x83AA7E80; // 1970 epoch -> 1900 epoch
325 double fractionalPart = (fTimeReceived.tv_usec*0x0400)/15625.0; // 2^16/10^6
326 unsigned lastReceivedTimeNTP
327 = (unsigned)((lastReceivedTimeNTP_high<<16) + fractionalPart + 0.5);
328
329 int rawResult = lastReceivedTimeNTP - fLastSRTime - fDiffSR_RRTime;
330 if (rawResult < 0) {
331 // This can happen if there's clock drift between the sender and receiver,
332 // and if the round-trip time was very small.
333 rawResult = 0;
334 }
335 return (unsigned)rawResult;
336}
337
338void RTPTransmissionStats::getTotalOctetCount(u_int32_t& hi, u_int32_t& lo) {
339 hi = fTotalOctetCount_hi;
340 lo = fTotalOctetCount_lo;
341}
342
343void RTPTransmissionStats::getTotalPacketCount(u_int32_t& hi, u_int32_t& lo) {
344 hi = fTotalPacketCount_hi;
345 lo = fTotalPacketCount_lo;
346}
347
348unsigned RTPTransmissionStats::packetsReceivedSinceLastRR() const {
349 if (!fAtLeastTwoRRsHaveBeenReceived) return 0;
350
351 return fLastPacketNumReceived-fOldLastPacketNumReceived;
352}
353
354int RTPTransmissionStats::packetsLostBetweenRR() const {
355 if (!fAtLeastTwoRRsHaveBeenReceived) return 0;
356
357 return fTotNumPacketsLost - fOldTotNumPacketsLost;
358}
359