blob: ddd8e337b80d116af8cceb2c14cc949a914d8b23 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "rtcp_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
13#include <string.h> //memset
14#include <cassert> //assert
15
16#include "trace.h"
17#include "critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000018#include "rtcp_utility.h"
19#include "rtp_rtcp_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
21namespace
22{
23 const float FRAC = 4.294967296E9;
24}
25
26namespace webrtc {
27using namespace RTCPUtility;
28using namespace RTCPHelp;
29
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000030// The number of RTCP time intervals needed to trigger a timeout.
31const int kRrTimeoutIntervals = 3;
32
pbos@webrtc.org2f446732013-04-08 11:08:41 +000033RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock,
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000034 ModuleRtpRtcpImpl* owner)
35 : TMMBRHelp(),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000036 _id(id),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000037 _clock(clock),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000038 _method(kRtcpOff),
39 _lastReceived(0),
40 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000041 _criticalSectionFeedbacks(
42 CriticalSectionWrapper::CreateCriticalSection()),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000043 _cbRtcpFeedback(NULL),
44 _cbRtcpBandwidthObserver(NULL),
45 _cbRtcpIntraFrameObserver(NULL),
46 _criticalSectionRTCPReceiver(
47 CriticalSectionWrapper::CreateCriticalSection()),
48 _SSRC(0),
49 _remoteSSRC(0),
50 _remoteSenderInfo(),
51 _lastReceivedSRNTPsecs(0),
52 _lastReceivedSRNTPfrac(0),
53 _receivedInfoMap(),
54 _packetTimeOutMS(0),
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000055 _lastReceivedRrMs(0),
56 _lastIncreasedSequenceNumberMs(0),
57 _rtt(0) {
niklase@google.com470e71d2011-07-07 08:21:25 +000058 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
59 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
60}
61
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000062RTCPReceiver::~RTCPReceiver() {
63 delete _criticalSectionRTCPReceiver;
64 delete _criticalSectionFeedbacks;
niklase@google.com470e71d2011-07-07 08:21:25 +000065
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000066 while (!_receivedReportBlockMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000067 std::map<uint32_t, RTCPReportBlockInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000068 _receivedReportBlockMap.begin();
69 delete first->second;
70 _receivedReportBlockMap.erase(first);
71 }
72 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000073 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000074 _receivedInfoMap.begin();
75 delete first->second;
76 _receivedInfoMap.erase(first);
77 }
78 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000079 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000080 _receivedCnameMap.begin();
81 delete first->second;
82 _receivedCnameMap.erase(first);
83 }
84 WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id,
85 "%s deleted", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +000086}
87
88void
pbos@webrtc.org2f446732013-04-08 11:08:41 +000089RTCPReceiver::ChangeUniqueId(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000090{
91 _id = id;
92}
93
94RTCPMethod
95RTCPReceiver::Status() const
96{
97 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
98 return _method;
99}
100
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000101int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000102RTCPReceiver::SetRTCPStatus(const RTCPMethod method)
103{
104 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
105 _method = method;
106 return 0;
107}
108
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000109int64_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000110RTCPReceiver::LastReceived()
111{
112 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
113 return _lastReceived;
114}
115
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000116int64_t
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000117RTCPReceiver::LastReceivedReceiverReport() const {
118 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000119 int64_t last_received_rr = -1;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000120 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
121 it != _receivedInfoMap.end(); ++it) {
122 if (it->second->lastTimeReceived > last_received_rr) {
123 last_received_rr = it->second->lastTimeReceived;
124 }
125 }
126 return last_received_rr;
127}
128
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000129int32_t
130RTCPReceiver::SetRemoteSSRC( const uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000131{
132 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
133
134 // new SSRC reset old reports
135 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
136 _lastReceivedSRNTPsecs = 0;
137 _lastReceivedSRNTPfrac = 0;
138
139 _remoteSSRC = ssrc;
140 return 0;
141}
142
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000143void RTCPReceiver::RegisterRtcpObservers(
144 RtcpIntraFrameObserver* intra_frame_callback,
145 RtcpBandwidthObserver* bandwidth_callback,
146 RtcpFeedback* feedback_callback) {
147 CriticalSectionScoped lock(_criticalSectionFeedbacks);
148 _cbRtcpIntraFrameObserver = intra_frame_callback;
149 _cbRtcpBandwidthObserver = bandwidth_callback;
150 _cbRtcpFeedback = feedback_callback;
niklase@google.com470e71d2011-07-07 08:21:25 +0000151}
152
niklase@google.com470e71d2011-07-07 08:21:25 +0000153
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000154void RTCPReceiver::SetSSRC(const uint32_t ssrc) {
155 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000156 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000158 old_ssrc = _SSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000159 _SSRC = ssrc;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000160 }
161 {
162 CriticalSectionScoped lock(_criticalSectionFeedbacks);
163 if (_cbRtcpIntraFrameObserver && old_ssrc != ssrc) {
164 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, ssrc);
165 }
166 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000167}
168
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000169int32_t RTCPReceiver::ResetRTT(const uint32_t remoteSSRC) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000170 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
171 RTCPReportBlockInformation* reportBlock =
172 GetReportBlockInformation(remoteSSRC);
173 if (reportBlock == NULL) {
174 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
175 "\tfailed to GetReportBlockInformation(%u)", remoteSSRC);
176 return -1;
177 }
178 reportBlock->RTT = 0;
179 reportBlock->avgRTT = 0;
180 reportBlock->minRTT = 0;
181 reportBlock->maxRTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000182 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183}
184
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000185int32_t RTCPReceiver::RTT(const uint32_t remoteSSRC,
186 uint16_t* RTT,
187 uint16_t* avgRTT,
188 uint16_t* minRTT,
189 uint16_t* maxRTT) const {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000190 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000191
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000192 RTCPReportBlockInformation* reportBlock =
193 GetReportBlockInformation(remoteSSRC);
194
195 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000196 return -1;
197 }
198 if (RTT) {
199 *RTT = reportBlock->RTT;
200 }
201 if (avgRTT) {
202 *avgRTT = reportBlock->avgRTT;
203 }
204 if (minRTT) {
205 *minRTT = reportBlock->minRTT;
206 }
207 if (maxRTT) {
208 *maxRTT = reportBlock->maxRTT;
209 }
210 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
212
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000213uint16_t RTCPReceiver::RTT() const {
mflodman@webrtc.orgd7d46882012-02-14 12:49:59 +0000214 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
215 if (!_receivedReportBlockMap.empty()) {
216 return 0;
217 }
218 return _rtt;
219}
220
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000221int RTCPReceiver::SetRTT(uint16_t rtt) {
mflodman@webrtc.orgd7d46882012-02-14 12:49:59 +0000222 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
223 if (!_receivedReportBlockMap.empty()) {
224 return -1;
225 }
226 _rtt = rtt;
227 return 0;
228}
229
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000230int32_t
231RTCPReceiver::NTP(uint32_t *ReceivedNTPsecs,
232 uint32_t *ReceivedNTPfrac,
233 uint32_t *RTCPArrivalTimeSecs,
234 uint32_t *RTCPArrivalTimeFrac,
235 uint32_t *rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000236{
237 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
238 if(ReceivedNTPsecs)
239 {
240 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
241 }
242 if(ReceivedNTPfrac)
243 {
244 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
245 }
246 if(RTCPArrivalTimeFrac)
247 {
248 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
249 }
250 if(RTCPArrivalTimeSecs)
251 {
252 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
253 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000254 if (rtcp_timestamp) {
255 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
256 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 return 0;
258}
259
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000260int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000261RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
262{
263 if(senderInfo == NULL)
264 {
265 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
266 return -1;
267 }
268 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
269 if(_lastReceivedSRNTPsecs == 0)
270 {
271 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
272 return -1;
273 }
274 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
275 return 0;
276}
277
278// statistics
279// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000280int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000281 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000282 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000283 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
284
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000285 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000286 _receivedReportBlockMap.begin();
287
288 while (it != _receivedReportBlockMap.end()) {
289 receiveBlocks->push_back(it->second->remoteReceiveBlock);
290 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000291 }
292 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000293}
294
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000295int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000296RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
297 RTCPUtility::RTCPParserV2* rtcpParser)
298{
299 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
300
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000301 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000302
303 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
304 while (pktType != RTCPUtility::kRtcpNotValidCode)
305 {
306 // Each "case" is responsible for iterate the parser to the
307 // next top level packet.
308 switch (pktType)
309 {
310 case RTCPUtility::kRtcpSrCode:
311 case RTCPUtility::kRtcpRrCode:
312 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
313 break;
314 case RTCPUtility::kRtcpSdesCode:
315 HandleSDES(*rtcpParser);
316 break;
317 case RTCPUtility::kRtcpXrVoipMetricCode:
318 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
319 break;
320 case RTCPUtility::kRtcpByeCode:
321 HandleBYE(*rtcpParser);
322 break;
323 case RTCPUtility::kRtcpRtpfbNackCode:
324 HandleNACK(*rtcpParser, rtcpPacketInformation);
325 break;
326 case RTCPUtility::kRtcpRtpfbTmmbrCode:
327 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
328 break;
329 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000330 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000331 break;
332 case RTCPUtility::kRtcpRtpfbSrReqCode:
333 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
334 break;
335 case RTCPUtility::kRtcpPsfbPliCode:
336 HandlePLI(*rtcpParser, rtcpPacketInformation);
337 break;
338 case RTCPUtility::kRtcpPsfbSliCode:
339 HandleSLI(*rtcpParser, rtcpPacketInformation);
340 break;
341 case RTCPUtility::kRtcpPsfbRpsiCode:
342 HandleRPSI(*rtcpParser, rtcpPacketInformation);
343 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000344 case RTCPUtility::kRtcpExtendedIjCode:
345 HandleIJ(*rtcpParser, rtcpPacketInformation);
346 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347 case RTCPUtility::kRtcpPsfbFirCode:
348 HandleFIR(*rtcpParser, rtcpPacketInformation);
349 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000350 case RTCPUtility::kRtcpPsfbAppCode:
351 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
352 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000353 case RTCPUtility::kRtcpAppCode:
354 // generic application messages
355 HandleAPP(*rtcpParser, rtcpPacketInformation);
356 break;
357 case RTCPUtility::kRtcpAppItemCode:
358 // generic application messages
359 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
360 break;
361 default:
362 rtcpParser->Iterate();
363 break;
364 }
365 pktType = rtcpParser->PacketType();
366 }
367 return 0;
368}
369
370// no need for critsect we have _criticalSectionRTCPReceiver
371void
372RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
373 RTCPPacketInformation& rtcpPacketInformation)
374{
375 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
376 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
377
378 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
379
380 // SR.SenderSSRC
381 // The synchronization source identifier for the originator of this SR packet
382
383 // rtcpPacket.RR.SenderSSRC
384 // The source of the packet sender, same as of SR? or is this a CE?
385
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000386 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
387 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
389 rtcpPacketInformation.remoteSSRC = remoteSSRC;
390
391 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
392 if (!ptrReceiveInfo)
393 {
394 rtcpParser.Iterate();
395 return;
396 }
397
398 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
399 {
400 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
401 "Received SR(%d). SSRC:0x%x, from SSRC:0x%x, to us %d.", _id, _SSRC, remoteSSRC, (_remoteSSRC == remoteSSRC)?1:0);
402
403 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
404 {
405 // only signal that we have received a SR when we accept one
406 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
407
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000408 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
409 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
410 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
411
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 // We will only store the send report from one source, but
413 // we will store all the receive block
414
415 // Save the NTP time of this report
416 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
417 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
418 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
419 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
420 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
421
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000422 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 }
424 else
425 {
426 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
427 }
428 } else
429 {
430 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
431 "Received RR(%d). SSRC:0x%x, from SSRC:0x%x", _id, _SSRC, remoteSSRC);
432
433 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
434 }
435 UpdateReceiveInformation(*ptrReceiveInfo);
436
437 rtcpPacketType = rtcpParser.Iterate();
438
439 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
440 {
441 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
442 rtcpPacketType = rtcpParser.Iterate();
443 }
444}
445
446// no need for critsect we have _criticalSectionRTCPReceiver
447void
448RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
449 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000450 const uint32_t remoteSSRC,
451 const uint8_t numberOfReportBlocks) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000452 // This will be called once per report block in the RTCP packet.
453 // We filter out all report blocks that are not for us.
454 // Each packet has max 31 RR blocks.
455 //
456 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000457
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000458 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
459 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000460
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000461 // Filter out all report blocks that are not for us.
462 if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
463 // This block is not for us ignore it.
464 return;
465 }
466
467 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
468 // _criticalSectionRTCPReceiver.
469 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000470 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000471 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
472 _criticalSectionRTCPReceiver->Enter();
473
474 RTCPReportBlockInformation* reportBlock =
475 CreateReportBlockInformation(remoteSSRC);
476 if (reportBlock == NULL) {
477 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
478 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
479 return;
480 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000481
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000482 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000483 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
484 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
485 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
486 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
487 reportBlock->remoteReceiveBlock.cumulativeLost =
488 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000489 if (rb.ExtendedHighestSequenceNumber >
490 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
491 // We have successfully delivered new RTP packets to the remote side after
492 // the last RR was sent from the remote side.
493 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000494 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000495 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
496 rb.ExtendedHighestSequenceNumber;
497 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
498 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
499 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
500
501 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
502 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
503 }
504
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000505 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000506 rtcpPacket.ReportBlockItem.DelayLastSR;
507
508 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000509 uint32_t lastReceivedRRNTPsecs = 0;
510 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000511
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000512 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000513
514 // time when we received this in MS
stefan@webrtc.orgafcc6102013-04-09 13:37:40 +0000515 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
516 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000517
518 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000519 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000520 d /= 65536;
521 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
522
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000523 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000524
525 if (sendTimeMS > 0) {
526 RTT = receiveTimeMS - d - sendTimeMS;
527 if (RTT <= 0) {
528 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000530 if (RTT > reportBlock->maxRTT) {
531 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000532 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000533 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000534 if (reportBlock->minRTT == 0) {
535 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000536 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000537 } else if (RTT < reportBlock->minRTT) {
538 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000539 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000540 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000541 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000542 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000543
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000544 // store average RTT
545 if (reportBlock->numAverageCalcs != 0) {
546 float ac = static_cast<float> (reportBlock->numAverageCalcs);
547 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
548 + ((1 / (ac + 1)) * RTT);
549 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
550 } else {
551 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000552 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000553 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000554 reportBlock->numAverageCalcs++;
555 }
556
557 WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id,
558 " -> Received report block(%d), from SSRC:0x%x, RTT:%d, loss:%d",
559 _id, remoteSSRC, RTT, rtcpPacket.ReportBlockItem.FractionLost);
560
561 // rtcpPacketInformation
562 rtcpPacketInformation.AddReportInfo(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000563 reportBlock->remoteReceiveBlock.fractionLost, (uint16_t) RTT,
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000564 reportBlock->remoteReceiveBlock.extendedHighSeqNum,
565 reportBlock->remoteReceiveBlock.jitter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000566}
567
568RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000569RTCPReceiver::CreateReportBlockInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000570 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000572 std::map<uint32_t, RTCPReportBlockInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000575 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
576 if (it != _receivedReportBlockMap.end()) {
577 ptrReportBlockInfo = it->second;
578 } else {
579 ptrReportBlockInfo = new RTCPReportBlockInformation;
580 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
581 }
582 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
585RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000586RTCPReceiver::GetReportBlockInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000587 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000588
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000589 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000590 _receivedReportBlockMap.find(remoteSSRC);
591
592 if (it == _receivedReportBlockMap.end()) {
593 return NULL;
594 }
595 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000596}
597
598RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000599RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000600 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000602 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000603 _receivedCnameMap.find(remoteSSRC);
604
605 if (it != _receivedCnameMap.end()) {
606 return it->second;
607 }
608 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000609 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000610 _receivedCnameMap[remoteSSRC] = cnameInfo;
611 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000612}
613
614RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000615RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000616 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000617
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000618 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000619 _receivedCnameMap.find(remoteSSRC);
620
621 if (it == _receivedCnameMap.end()) {
622 return NULL;
623 }
624 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000625}
626
627RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000628RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000629 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000631 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000632 _receivedInfoMap.find(remoteSSRC);
633
634 if (it != _receivedInfoMap.end()) {
635 return it->second;
636 }
637 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
638 _receivedInfoMap[remoteSSRC] = receiveInfo;
639 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000640}
641
642RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000643RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000644 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000645
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000646 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000647 _receivedInfoMap.find(remoteSSRC);
648 if (it == _receivedInfoMap.end()) {
649 return NULL;
650 }
651 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000652}
653
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000654void RTCPReceiver::UpdateReceiveInformation(
655 RTCPReceiveInformation& receiveInformation) {
656 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000657 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000658}
659
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000660bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
661 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
662 if (_lastReceivedRrMs == 0)
663 return false;
664
665 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000666 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000667 // Reset the timer to only trigger one log.
668 _lastReceivedRrMs = 0;
669 return true;
670 }
671 return false;
672}
673
674bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
675 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
676 if (_lastIncreasedSequenceNumberMs == 0)
677 return false;
678
679 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000680 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000681 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000682 // Reset the timer to only trigger one log.
683 _lastIncreasedSequenceNumberMs = 0;
684 return true;
685 }
686 return false;
687}
688
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000689bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
690 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000691
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000693 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000694
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000695 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000696 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000697
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000698 while (receiveInfoIt != _receivedInfoMap.end()) {
699 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
700 if (receiveInfo == NULL) {
701 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000702 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000703 // time since last received rtcp packet
704 // when we dont have a lastTimeReceived and the object is marked
705 // readyForDelete it's removed from the map
706 if (receiveInfo->lastTimeReceived) {
707 /// use audio define since we don't know what interval the remote peer is
708 // using
709 if ((timeNow - receiveInfo->lastTimeReceived) >
710 5 * RTCP_INTERVAL_AUDIO_MS) {
711 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000712 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000713 // prevent that we call this over and over again
714 receiveInfo->lastTimeReceived = 0;
715 // send new TMMBN to all channels using the default codec
716 updateBoundingSet = true;
717 }
718 receiveInfoIt++;
719 } else if (receiveInfo->readyForDelete) {
720 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000721 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000722 receiveInfoItemToBeErased = receiveInfoIt;
723 receiveInfoIt++;
724 delete receiveInfoItemToBeErased->second;
725 _receivedInfoMap.erase(receiveInfoItemToBeErased);
726 } else {
727 receiveInfoIt++;
728 }
729 }
730 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000731}
732
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000733int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000734 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000735
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000736 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000737 _receivedInfoMap.find(_remoteSSRC);
738
739 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000740 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000741 }
742 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
743 if (receiveInfo == NULL) {
744 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
745 "%s failed to get RTCPReceiveInformation",
746 __FUNCTION__);
747 return -1;
748 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000749 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000750 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000751 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000752 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000753 i++) {
754 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000755 // owner of bounding set
756 tmmbrOwner = true;
757 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000758 boundingSetRec->SetEntry(i,
759 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
760 receiveInfo->TmmbnBoundingSet.PacketOH(i),
761 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000762 }
763 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000764 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000765}
766
767// no need for critsect we have _criticalSectionRTCPReceiver
768void
769RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
770{
771 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
772 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
773 {
774 HandleSDESChunk(rtcpParser);
775 pktType = rtcpParser.Iterate();
776 }
777}
778
779// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000780void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
781 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
782 RTCPCnameInformation* cnameInfo =
783 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
784 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000785
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000786 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
787 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000788}
789
790// no need for critsect we have _criticalSectionRTCPReceiver
791void
792RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
793 RTCPPacketInformation& rtcpPacketInformation)
794{
795 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000796 if (_SSRC != rtcpPacket.NACK.MediaSSRC)
797 {
798 // Not to us.
799 rtcpParser.Iterate();
800 return;
801 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000802 rtcpPacketInformation.ResetNACKPacketIdArray();
803
804 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
805 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
806 {
807 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
808 pktType = rtcpParser.Iterate();
809 }
810}
811
812// no need for critsect we have _criticalSectionRTCPReceiver
813void
814RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
815 RTCPPacketInformation& rtcpPacketInformation)
816{
817 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
818
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000819 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000820 if(bitMask)
821 {
822 for(int i=1; i <= 16; ++i)
823 {
824 if(bitMask & 0x01)
825 {
826 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
827 }
828 bitMask = bitMask >>1;
829 }
830 }
831
832 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
833}
834
835// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000836void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
837 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000838
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000839 // clear our lists
840 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000841 std::map<uint32_t, RTCPReportBlockInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000842 reportBlockInfoIt = _receivedReportBlockMap.find(
843 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000844
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000845 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
846 delete reportBlockInfoIt->second;
847 _receivedReportBlockMap.erase(reportBlockInfoIt);
848 }
849 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000850 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000851 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000852
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000853 if (receiveInfoIt != _receivedInfoMap.end()) {
854 receiveInfoIt->second->readyForDelete = true;
855 }
856
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000857 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000858 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
859
860 if (cnameInfoIt != _receivedCnameMap.end()) {
861 delete cnameInfoIt->second;
862 _receivedCnameMap.erase(cnameInfoIt);
863 }
864 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000865}
866
867// no need for critsect we have _criticalSectionRTCPReceiver
868void
869RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
870 RTCPPacketInformation& rtcpPacketInformation)
871{
872 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
873
874 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
875
876 if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
877 {
878 // Store VoIP metrics block if it's about me
879 // from OriginatorSSRC do we filter it?
880 // rtcpPacket.XR.OriginatorSSRC;
881
882 RTCPVoIPMetric receivedVoIPMetrics;
883 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
884 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
885 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
886 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
887 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
888 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
889 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
890 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
891 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
892 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
893 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
894 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
895 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
896 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
897 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
898 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
899 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
900 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
901 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
902 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
903
904 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
905
906 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
907 }
908 rtcpParser.Iterate();
909}
910
911// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000912void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
913 RTCPPacketInformation& rtcpPacketInformation) {
914 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
915 if (_SSRC == rtcpPacket.PLI.MediaSSRC) {
916 // Received a signal that we need to send a new key frame.
917 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
918 }
919 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000920}
921
922// no need for critsect we have _criticalSectionRTCPReceiver
923void
924RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
925 RTCPPacketInformation& rtcpPacketInformation)
926{
927 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
928
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000929 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000930 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
931 if (ptrReceiveInfo == NULL)
932 {
933 // This remote SSRC must be saved before.
934 rtcpParser.Iterate();
935 return;
936 }
937 if(rtcpPacket.TMMBR.MediaSSRC)
938 {
939 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
940 // in relay mode this is a valid number
941 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
942 }
943
944 // Use packet length to calc max number of TMMBR blocks
945 // each TMMBR block is 8 bytes
946 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
947
948 // sanity
949 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
950 {
951 assert(false);
952 rtcpParser.Iterate();
953 return;
954 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000955 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +0000956
957 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
958 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
959 {
960 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
961 pktType = rtcpParser.Iterate();
962 }
963}
964
965// no need for critsect we have _criticalSectionRTCPReceiver
966void
967RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
968 const RTCPUtility::RTCPPacket& rtcpPacket,
969 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000970 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000971{
972 if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
973 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
974 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000975 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000976 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +0000977 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
978 }
979}
980
981// no need for critsect we have _criticalSectionRTCPReceiver
982void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000983RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
984 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +0000985{
986 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
987 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
988 if (ptrReceiveInfo == NULL)
989 {
990 // This remote SSRC must be saved before.
991 rtcpParser.Iterate();
992 return;
993 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000994 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000995 // Use packet length to calc max number of TMMBN blocks
996 // each TMMBN block is 8 bytes
997 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
998
999 // sanity
1000 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
1001 {
1002 assert(false);
1003 rtcpParser.Iterate();
1004 return;
1005 }
1006
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001007 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +00001008
1009 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1010 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
1011 {
1012 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1013 pktType = rtcpParser.Iterate();
1014 }
1015}
1016
1017// no need for critsect we have _criticalSectionRTCPReceiver
1018void
1019RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1020 RTCPPacketInformation& rtcpPacketInformation)
1021{
1022 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1023 rtcpParser.Iterate();
1024}
1025
1026// no need for critsect we have _criticalSectionRTCPReceiver
1027void
1028RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1029 const RTCPUtility::RTCPPacket& rtcpPacket)
1030{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001031 receiveInfo.TmmbnBoundingSet.AddEntry(
1032 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1033 rtcpPacket.TMMBNItem.MeasuredOverhead,
1034 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001035}
1036
1037// no need for critsect we have _criticalSectionRTCPReceiver
1038void
1039RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1040 RTCPPacketInformation& rtcpPacketInformation)
1041{
1042 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001043 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1044 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1045 {
1046 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1047 pktType = rtcpParser.Iterate();
1048 }
1049}
1050
1051// no need for critsect we have _criticalSectionRTCPReceiver
1052void
1053RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1054 RTCPPacketInformation& rtcpPacketInformation)
1055{
1056 // in theory there could be multiple slices lost
1057 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1058 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1059}
1060
1061void
1062RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1063 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1064{
1065 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001066 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1067 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1068 {
1069 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1070 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1071 {
1072 // to us unknown
1073 // continue
1074 rtcpParser.Iterate();
1075 return;
1076 }
1077 rtcpPacketInformation.rpsiPictureId = 0;
1078
1079 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001080 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1081 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001082 {
1083 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1084 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1085 }
1086 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1087 }
1088}
1089
1090// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001091void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1092 RTCPPacketInformation& rtcpPacketInformation) {
1093 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1094 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1095 pktType = rtcpParser.Iterate();
1096 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1097 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1098 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001099 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001100 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001101}
1102
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001103// no need for critsect we have _criticalSectionRTCPReceiver
1104void
1105RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1106 RTCPPacketInformation& rtcpPacketInformation)
1107{
1108 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1109
1110 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1111 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1112 {
1113 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1114 pktType = rtcpParser.Iterate();
1115 }
1116}
1117
1118void
1119RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1120 RTCPPacketInformation& rtcpPacketInformation)
1121{
1122 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1123 rtcpPacketInformation.interArrivalJitter =
1124 rtcpPacket.ExtendedJitterReportItem.Jitter;
1125}
1126
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001127void RTCPReceiver::HandleREMBItem(
1128 RTCPUtility::RTCPParserV2& rtcpParser,
1129 RTCPPacketInformation& rtcpPacketInformation) {
1130 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1131 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1132 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1133 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001134}
1135
1136// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001137void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1138 RTCPPacketInformation& rtcpPacketInformation) {
1139 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1140 RTCPReceiveInformation* ptrReceiveInfo =
1141 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001142
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001143 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1144 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1145 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1146 pktType = rtcpParser.Iterate();
1147 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001148}
1149
1150// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001151void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1152 const RTCPUtility::RTCPPacket& rtcpPacket,
1153 RTCPPacketInformation& rtcpPacketInformation) {
1154 // Is it our sender that is requested to generate a new keyframe
1155 if (_SSRC != rtcpPacket.FIRItem.SSRC) {
1156 return;
1157 }
1158 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1159 // we don't know who this originate from
1160 if (receiveInfo) {
1161 // check if we have reported this FIRSequenceNumber before
1162 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1163 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001164 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001165 // sanity; don't go crazy with the callbacks
1166 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1167 receiveInfo->lastFIRRequest = now;
1168 receiveInfo->lastFIRSequenceNumber =
1169 rtcpPacket.FIRItem.CommandSequenceNumber;
1170 // received signal that we need to send a new key frame
1171 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1172 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001173 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001174 } else {
1175 // received signal that we need to send a new key frame
1176 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1177 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001178}
1179
1180void
1181RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1182 RTCPPacketInformation& rtcpPacketInformation)
1183{
1184 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1185
1186 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1187 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1188 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1189
1190 rtcpParser.Iterate();
1191}
1192
1193void
1194RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1195 RTCPPacketInformation& rtcpPacketInformation)
1196{
1197 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1198
1199 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1200
1201 rtcpParser.Iterate();
1202}
1203
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001204int32_t RTCPReceiver::UpdateTMMBR() {
1205 int32_t numBoundingSet = 0;
1206 uint32_t bitrate = 0;
1207 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001208
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001209 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001210 if (size > 0) {
1211 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1212 // Get candidate set from receiver.
1213 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1214 } else {
1215 // Candidate set empty.
1216 VerifyAndAllocateCandidateSet(0); // resets candidate set
1217 }
1218 // Find bounding set
1219 TMMBRSet* boundingSet = NULL;
1220 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1221 if (numBoundingSet == -1) {
1222 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1223 "Failed to find TMMBR bounding set.");
1224 return -1;
1225 }
1226 // Set bounding set
1227 // Inform remote clients about the new bandwidth
1228 // inform the remote client
1229 _rtpRtcp.SetTMMBN(boundingSet);
1230
1231 // might trigger a TMMBN
1232 if (numBoundingSet == 0) {
1233 // owner of max bitrate request has timed out
1234 // empty bounding set has been sent
1235 return 0;
1236 }
1237 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001238 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001239 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001240 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1241 if (_cbRtcpBandwidthObserver) {
1242 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1243 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1244 "Set TMMBR request:%d kbps", bitrate);
1245 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001246 }
1247 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001248}
1249
1250// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001251void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001252 RTCPPacketInformation& rtcpPacketInformation) {
1253 // Process TMMBR and REMB first to avoid multiple callbacks
1254 // to OnNetworkChanged.
1255 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1256 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1257 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001258
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001259 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1260 UpdateTMMBR();
1261 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001262 unsigned int local_ssrc = 0;
1263 {
1264 // We don't want to hold this critsect when triggering the callbacks below.
1265 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1266 local_ssrc = _SSRC;
1267 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001268 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1269 _rtpRtcp.OnRequestSendReport();
1270 }
1271 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001272 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001273 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1274 "SIG [RTCP] Incoming NACK length:%d",
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001275 rtcpPacketInformation.nackSequenceNumbers.size());
1276 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001277 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001278 }
1279 {
1280 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001281
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001282 // We need feedback that we have received a report block(s) so that we
1283 // can generate a new packet in a conference relay scenario, one received
1284 // report can generate several RTCP packets, based on number relayed/mixed
1285 // a send report block should go out to all receivers.
1286 if (_cbRtcpIntraFrameObserver) {
1287 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1288 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1289 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1290 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1291 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1292 rtcpPacketInformation.remoteSSRC);
1293 } else {
1294 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1295 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1296 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001297 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001298 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001299 }
1300 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1301 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001302 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001303 }
1304 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1305 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001306 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001307 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001308 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001309 if (_cbRtcpBandwidthObserver) {
1310 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1311 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1312 "SIG [RTCP] Incoming REMB:%d",
1313 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1314 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1315 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1316 }
1317 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1318 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) &&
1319 rtcpPacketInformation.reportBlock) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001320 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001321 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
1322 rtcpPacketInformation.remoteSSRC,
1323 rtcpPacketInformation.fractionLost,
1324 rtcpPacketInformation.roundTripTime,
1325 rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
1326 now);
1327 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001328 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001329 if(_cbRtcpFeedback) {
1330 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) {
1331 _cbRtcpFeedback->OnSendReportReceived(_id,
stefan@webrtc.org976a7e62012-09-21 13:20:21 +00001332 rtcpPacketInformation.remoteSSRC,
1333 rtcpPacketInformation.ntp_secs,
1334 rtcpPacketInformation.ntp_frac,
1335 rtcpPacketInformation.rtp_timestamp);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001336 } else {
1337 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1338 rtcpPacketInformation.remoteSSRC);
1339 }
1340 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1341 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1342 rtcpPacketInformation.VoIPMetric);
1343 }
1344 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1345 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1346 rtcpPacketInformation.applicationSubType,
1347 rtcpPacketInformation.applicationName,
1348 rtcpPacketInformation.applicationLength,
1349 rtcpPacketInformation.applicationData);
1350 }
1351 }
1352 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001353}
1354
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001355int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1356 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001357 assert(cName);
1358
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001359 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1360 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001361 if (cnameInfo == NULL) {
1362 return -1;
1363 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001364 cName[RTCP_CNAME_SIZE - 1] = 0;
1365 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1366 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001367}
1368
1369// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001370int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1371 const uint32_t accNumCandidates,
1372 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001373 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001374
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001375 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001376 receiveInfoIt = _receivedInfoMap.begin();
1377 if (receiveInfoIt == _receivedInfoMap.end()) {
1378 return -1;
1379 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001380 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001381 if (candidateSet) {
1382 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1383 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1384 if (receiveInfo == NULL) {
1385 return 0;
1386 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001387 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001388 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001389 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001390 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001391 num++;
1392 }
1393 }
1394 receiveInfoIt++;
1395 }
1396 } else {
1397 while (receiveInfoIt != _receivedInfoMap.end()) {
1398 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1399 if(receiveInfo == NULL) {
1400 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1401 "%s failed to get RTCPReceiveInformation",
1402 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001403 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001404 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001405 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001406 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001407 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001408 }
1409 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001410}
1411
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001412int32_t
1413RTCPReceiver::SetPacketTimeout(const uint32_t timeoutMS)
niklase@google.com470e71d2011-07-07 08:21:25 +00001414{
1415 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1416 _packetTimeOutMS = timeoutMS;
1417 return 0;
1418}
1419
1420void RTCPReceiver::PacketTimeout()
1421{
1422 if(_packetTimeOutMS == 0)
1423 {
1424 // not configured
1425 return;
1426 }
1427
1428 bool packetTimeOut = false;
1429 {
1430 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1431 if(_lastReceived == 0)
1432 {
1433 // not active
1434 return;
1435 }
1436
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001437 int64_t now = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +00001438 if(now - _lastReceived > _packetTimeOutMS)
1439 {
1440 packetTimeOut = true;
1441 _lastReceived = 0; // only one callback
1442 }
1443 }
1444 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1445 if(packetTimeOut && _cbRtcpFeedback)
1446 {
1447 _cbRtcpFeedback->OnRTCPPacketTimeout(_id);
1448 }
1449}
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001450
niklase@google.com470e71d2011-07-07 08:21:25 +00001451} // namespace webrtc