blob: b39043af6d11ccbc118bc307aff4cfda83a33c6c [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"
hclam@chromium.org806dc3b2013-04-09 19:54:10 +000017#include "trace_event.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018#include "critical_section_wrapper.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000019#include "rtcp_utility.h"
20#include "rtp_rtcp_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000021
22namespace
23{
24 const float FRAC = 4.294967296E9;
25}
26
27namespace webrtc {
28using namespace RTCPUtility;
29using namespace RTCPHelp;
30
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000031// The number of RTCP time intervals needed to trigger a timeout.
32const int kRrTimeoutIntervals = 3;
33
pbos@webrtc.org2f446732013-04-08 11:08:41 +000034RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock,
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000035 ModuleRtpRtcpImpl* owner)
36 : TMMBRHelp(),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000037 _id(id),
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000038 _clock(clock),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000039 _method(kRtcpOff),
40 _lastReceived(0),
41 _rtpRtcp(*owner),
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +000042 _criticalSectionFeedbacks(
43 CriticalSectionWrapper::CreateCriticalSection()),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000044 _cbRtcpFeedback(NULL),
45 _cbRtcpBandwidthObserver(NULL),
46 _cbRtcpIntraFrameObserver(NULL),
47 _criticalSectionRTCPReceiver(
48 CriticalSectionWrapper::CreateCriticalSection()),
49 _SSRC(0),
50 _remoteSSRC(0),
51 _remoteSenderInfo(),
52 _lastReceivedSRNTPsecs(0),
53 _lastReceivedSRNTPfrac(0),
54 _receivedInfoMap(),
55 _packetTimeOutMS(0),
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000056 _lastReceivedRrMs(0),
stefan@webrtc.orgccd4b2a2013-04-23 15:58:23 +000057 _lastIncreasedSequenceNumberMs(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 +0000213int32_t
214RTCPReceiver::NTP(uint32_t *ReceivedNTPsecs,
215 uint32_t *ReceivedNTPfrac,
216 uint32_t *RTCPArrivalTimeSecs,
217 uint32_t *RTCPArrivalTimeFrac,
218 uint32_t *rtcp_timestamp) const
niklase@google.com470e71d2011-07-07 08:21:25 +0000219{
220 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
221 if(ReceivedNTPsecs)
222 {
223 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
224 }
225 if(ReceivedNTPfrac)
226 {
227 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
228 }
229 if(RTCPArrivalTimeFrac)
230 {
231 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we received a RTCP packet with a send block
232 }
233 if(RTCPArrivalTimeSecs)
234 {
235 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
236 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000237 if (rtcp_timestamp) {
238 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
239 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 return 0;
241}
242
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000243int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000244RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const
245{
246 if(senderInfo == NULL)
247 {
248 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "%s invalid argument", __FUNCTION__);
249 return -1;
250 }
251 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
252 if(_lastReceivedSRNTPsecs == 0)
253 {
254 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s No received SR", __FUNCTION__);
255 return -1;
256 }
257 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
258 return 0;
259}
260
261// statistics
262// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000263int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000264 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000265 assert(receiveBlocks);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000266 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
267
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000268 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000269 _receivedReportBlockMap.begin();
270
271 while (it != _receivedReportBlockMap.end()) {
272 receiveBlocks->push_back(it->second->remoteReceiveBlock);
273 it++;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000274 }
275 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000276}
277
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000278int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000279RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
280 RTCPUtility::RTCPParserV2* rtcpParser)
281{
282 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
283
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000284 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000285
286 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
287 while (pktType != RTCPUtility::kRtcpNotValidCode)
288 {
289 // Each "case" is responsible for iterate the parser to the
290 // next top level packet.
291 switch (pktType)
292 {
293 case RTCPUtility::kRtcpSrCode:
294 case RTCPUtility::kRtcpRrCode:
295 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
296 break;
297 case RTCPUtility::kRtcpSdesCode:
298 HandleSDES(*rtcpParser);
299 break;
300 case RTCPUtility::kRtcpXrVoipMetricCode:
301 HandleXRVOIPMetric(*rtcpParser, rtcpPacketInformation);
302 break;
303 case RTCPUtility::kRtcpByeCode:
304 HandleBYE(*rtcpParser);
305 break;
306 case RTCPUtility::kRtcpRtpfbNackCode:
307 HandleNACK(*rtcpParser, rtcpPacketInformation);
308 break;
309 case RTCPUtility::kRtcpRtpfbTmmbrCode:
310 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
311 break;
312 case RTCPUtility::kRtcpRtpfbTmmbnCode:
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000313 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000314 break;
315 case RTCPUtility::kRtcpRtpfbSrReqCode:
316 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
317 break;
318 case RTCPUtility::kRtcpPsfbPliCode:
319 HandlePLI(*rtcpParser, rtcpPacketInformation);
320 break;
321 case RTCPUtility::kRtcpPsfbSliCode:
322 HandleSLI(*rtcpParser, rtcpPacketInformation);
323 break;
324 case RTCPUtility::kRtcpPsfbRpsiCode:
325 HandleRPSI(*rtcpParser, rtcpPacketInformation);
326 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000327 case RTCPUtility::kRtcpExtendedIjCode:
328 HandleIJ(*rtcpParser, rtcpPacketInformation);
329 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000330 case RTCPUtility::kRtcpPsfbFirCode:
331 HandleFIR(*rtcpParser, rtcpPacketInformation);
332 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000333 case RTCPUtility::kRtcpPsfbAppCode:
334 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
335 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000336 case RTCPUtility::kRtcpAppCode:
337 // generic application messages
338 HandleAPP(*rtcpParser, rtcpPacketInformation);
339 break;
340 case RTCPUtility::kRtcpAppItemCode:
341 // generic application messages
342 HandleAPPItem(*rtcpParser, rtcpPacketInformation);
343 break;
344 default:
345 rtcpParser->Iterate();
346 break;
347 }
348 pktType = rtcpParser->PacketType();
349 }
350 return 0;
351}
352
353// no need for critsect we have _criticalSectionRTCPReceiver
354void
355RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
356 RTCPPacketInformation& rtcpPacketInformation)
357{
358 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
359 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
360
361 assert((rtcpPacketType == RTCPUtility::kRtcpRrCode) || (rtcpPacketType == RTCPUtility::kRtcpSrCode));
362
363 // SR.SenderSSRC
364 // The synchronization source identifier for the originator of this SR packet
365
366 // rtcpPacket.RR.SenderSSRC
367 // The source of the packet sender, same as of SR? or is this a CE?
368
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000369 const uint32_t remoteSSRC = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.SenderSSRC:rtcpPacket.SR.SenderSSRC;
370 const uint8_t numberOfReportBlocks = (rtcpPacketType == RTCPUtility::kRtcpRrCode) ? rtcpPacket.RR.NumberOfReportBlocks:rtcpPacket.SR.NumberOfReportBlocks;
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
372 rtcpPacketInformation.remoteSSRC = remoteSSRC;
373
374 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
375 if (!ptrReceiveInfo)
376 {
377 rtcpParser.Iterate();
378 return;
379 }
380
381 if (rtcpPacketType == RTCPUtility::kRtcpSrCode)
382 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000383 TRACE_EVENT_INSTANT2("webrtc_rtp", "SR",
384 "remote_ssrc", remoteSSRC,
385 "ssrc", _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000386
387 if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
388 {
389 // only signal that we have received a SR when we accept one
390 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
391
stefan@webrtc.org976a7e62012-09-21 13:20:21 +0000392 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
393 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
394 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
395
niklase@google.com470e71d2011-07-07 08:21:25 +0000396 // We will only store the send report from one source, but
397 // we will store all the receive block
398
399 // Save the NTP time of this report
400 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
401 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
402 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
403 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
404 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
405
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000406 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 }
408 else
409 {
410 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
411 }
412 } else
413 {
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000414 TRACE_EVENT_INSTANT2("webrtc_rtp", "RR",
415 "remote_ssrc", remoteSSRC,
416 "ssrc", _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
418 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
419 }
420 UpdateReceiveInformation(*ptrReceiveInfo);
421
422 rtcpPacketType = rtcpParser.Iterate();
423
424 while (rtcpPacketType == RTCPUtility::kRtcpReportBlockItemCode)
425 {
426 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC, numberOfReportBlocks);
427 rtcpPacketType = rtcpParser.Iterate();
428 }
429}
430
431// no need for critsect we have _criticalSectionRTCPReceiver
432void
433RTCPReceiver::HandleReportBlock(const RTCPUtility::RTCPPacket& rtcpPacket,
434 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000435 const uint32_t remoteSSRC,
436 const uint8_t numberOfReportBlocks) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000437 // This will be called once per report block in the RTCP packet.
438 // We filter out all report blocks that are not for us.
439 // Each packet has max 31 RR blocks.
440 //
441 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000442
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000443 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
444 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000445
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000446 // Filter out all report blocks that are not for us.
447 if (rtcpPacket.ReportBlockItem.SSRC != _SSRC) {
448 // This block is not for us ignore it.
449 return;
450 }
451
452 // To avoid problem with acquiring _criticalSectionRTCPSender while holding
453 // _criticalSectionRTCPReceiver.
454 _criticalSectionRTCPReceiver->Leave();
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000455 uint32_t sendTimeMS =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000456 _rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);
457 _criticalSectionRTCPReceiver->Enter();
458
459 RTCPReportBlockInformation* reportBlock =
460 CreateReportBlockInformation(remoteSSRC);
461 if (reportBlock == NULL) {
462 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
463 "\tfailed to CreateReportBlockInformation(%u)", remoteSSRC);
464 return;
465 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000466
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000467 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000468 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000469 TRACE_COUNTER_ID1("webrtc_rtp", "RRFractionLost", rb.SSRC, rb.FractionLost);
470 TRACE_COUNTER_ID1("webrtc_rtp", "RRCumulativeNumOfPacketLost",
471 rb.SSRC, rb.CumulativeNumOfPacketsLost);
472 TRACE_COUNTER_ID1("webrtc_rtp", "RRJitter", rb.SSRC, rb.Jitter);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000473 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
474 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
475 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
476 reportBlock->remoteReceiveBlock.cumulativeLost =
477 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000478 if (rb.ExtendedHighestSequenceNumber >
479 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
480 // We have successfully delivered new RTP packets to the remote side after
481 // the last RR was sent from the remote side.
482 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000483 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000484 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
485 rb.ExtendedHighestSequenceNumber;
486 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
487 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
488 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
489
490 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
491 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
492 }
493
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000494 uint32_t delaySinceLastSendReport =
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000495 rtcpPacket.ReportBlockItem.DelayLastSR;
496
497 // local NTP time when we received this
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000498 uint32_t lastReceivedRRNTPsecs = 0;
499 uint32_t lastReceivedRRNTPfrac = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000500
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000501 _clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000502
503 // time when we received this in MS
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000504 uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
505 lastReceivedRRNTPfrac);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000506
507 // Estimate RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000508 uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000509 d /= 65536;
510 d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;
511
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000512 int32_t RTT = 0;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000513
514 if (sendTimeMS > 0) {
515 RTT = receiveTimeMS - d - sendTimeMS;
516 if (RTT <= 0) {
517 RTT = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000518 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000519 if (RTT > reportBlock->maxRTT) {
520 // store max RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000521 reportBlock->maxRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000522 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000523 if (reportBlock->minRTT == 0) {
524 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000525 reportBlock->minRTT = (uint16_t) RTT;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000526 } else if (RTT < reportBlock->minRTT) {
527 // Store min RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000528 reportBlock->minRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000530 // store last RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000531 reportBlock->RTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000533 // store average RTT
534 if (reportBlock->numAverageCalcs != 0) {
535 float ac = static_cast<float> (reportBlock->numAverageCalcs);
536 float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT)
537 + ((1 / (ac + 1)) * RTT);
538 reportBlock->avgRTT = static_cast<int> (newAverage + 0.5f);
539 } else {
540 // first RTT
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000541 reportBlock->avgRTT = (uint16_t) RTT;
niklase@google.com470e71d2011-07-07 08:21:25 +0000542 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000543 reportBlock->numAverageCalcs++;
544 }
545
hclam@chromium.org806dc3b2013-04-09 19:54:10 +0000546 TRACE_COUNTER_ID1("webrtc_rtp", "RR_RTT", rb.SSRC, RTT);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000547
548 // rtcpPacketInformation
549 rtcpPacketInformation.AddReportInfo(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000550 reportBlock->remoteReceiveBlock.fractionLost, (uint16_t) RTT,
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000551 reportBlock->remoteReceiveBlock.extendedHighSeqNum,
552 reportBlock->remoteReceiveBlock.jitter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553}
554
555RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000556RTCPReceiver::CreateReportBlockInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000557 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000559 std::map<uint32_t, RTCPReportBlockInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000560 _receivedReportBlockMap.find(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000561
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000562 RTCPReportBlockInformation* ptrReportBlockInfo = NULL;
563 if (it != _receivedReportBlockMap.end()) {
564 ptrReportBlockInfo = it->second;
565 } else {
566 ptrReportBlockInfo = new RTCPReportBlockInformation;
567 _receivedReportBlockMap[remoteSSRC] = ptrReportBlockInfo;
568 }
569 return ptrReportBlockInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000570}
571
572RTCPReportBlockInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000573RTCPReceiver::GetReportBlockInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000574 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000576 std::map<uint32_t, RTCPReportBlockInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000577 _receivedReportBlockMap.find(remoteSSRC);
578
579 if (it == _receivedReportBlockMap.end()) {
580 return NULL;
581 }
582 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000583}
584
585RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000586RTCPReceiver::CreateCnameInformation(uint32_t remoteSSRC) {
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, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000590 _receivedCnameMap.find(remoteSSRC);
591
592 if (it != _receivedCnameMap.end()) {
593 return it->second;
594 }
595 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000596 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 _receivedCnameMap[remoteSSRC] = cnameInfo;
598 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000599}
600
601RTCPCnameInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000602RTCPReceiver::GetCnameInformation(uint32_t remoteSSRC) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000603 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000604
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000605 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000606 _receivedCnameMap.find(remoteSSRC);
607
608 if (it == _receivedCnameMap.end()) {
609 return NULL;
610 }
611 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000612}
613
614RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000615RTCPReceiver::CreateReceiveInformation(uint32_t remoteSSRC) {
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, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000619 _receivedInfoMap.find(remoteSSRC);
620
621 if (it != _receivedInfoMap.end()) {
622 return it->second;
623 }
624 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
625 _receivedInfoMap[remoteSSRC] = receiveInfo;
626 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000627}
628
629RTCPReceiveInformation*
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000630RTCPReceiver::GetReceiveInformation(uint32_t remoteSSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000631 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000633 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000634 _receivedInfoMap.find(remoteSSRC);
635 if (it == _receivedInfoMap.end()) {
636 return NULL;
637 }
638 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000639}
640
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641void RTCPReceiver::UpdateReceiveInformation(
642 RTCPReceiveInformation& receiveInformation) {
643 // Update that this remote is alive
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000644 receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000645}
646
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000647bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
648 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
649 if (_lastReceivedRrMs == 0)
650 return false;
651
652 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000653 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000654 // Reset the timer to only trigger one log.
655 _lastReceivedRrMs = 0;
656 return true;
657 }
658 return false;
659}
660
661bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
662 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
663 if (_lastIncreasedSequenceNumberMs == 0)
664 return false;
665
666 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000667 if (_clock->TimeInMilliseconds() > _lastIncreasedSequenceNumberMs +
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000668 time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000669 // Reset the timer to only trigger one log.
670 _lastIncreasedSequenceNumberMs = 0;
671 return true;
672 }
673 return false;
674}
675
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000676bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
677 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000678
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000679 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000680 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000681
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000682 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000683 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000684
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000685 while (receiveInfoIt != _receivedInfoMap.end()) {
686 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
687 if (receiveInfo == NULL) {
688 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000689 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 // time since last received rtcp packet
691 // when we dont have a lastTimeReceived and the object is marked
692 // readyForDelete it's removed from the map
693 if (receiveInfo->lastTimeReceived) {
694 /// use audio define since we don't know what interval the remote peer is
695 // using
696 if ((timeNow - receiveInfo->lastTimeReceived) >
697 5 * RTCP_INTERVAL_AUDIO_MS) {
698 // no rtcp packet for the last five regular intervals, reset limitations
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000699 receiveInfo->TmmbrSet.clearSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000700 // prevent that we call this over and over again
701 receiveInfo->lastTimeReceived = 0;
702 // send new TMMBN to all channels using the default codec
703 updateBoundingSet = true;
704 }
705 receiveInfoIt++;
706 } else if (receiveInfo->readyForDelete) {
707 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000708 std::map<uint32_t, RTCPReceiveInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709 receiveInfoItemToBeErased = receiveInfoIt;
710 receiveInfoIt++;
711 delete receiveInfoItemToBeErased->second;
712 _receivedInfoMap.erase(receiveInfoItemToBeErased);
713 } else {
714 receiveInfoIt++;
715 }
716 }
717 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000718}
719
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000720int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000721 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000722
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000723 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000724 _receivedInfoMap.find(_remoteSSRC);
725
726 if (receiveInfoIt == _receivedInfoMap.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000727 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000728 }
729 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
730 if (receiveInfo == NULL) {
731 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
732 "%s failed to get RTCPReceiveInformation",
733 __FUNCTION__);
734 return -1;
735 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000736 if (receiveInfo->TmmbnBoundingSet.lengthOfSet() > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000737 boundingSetRec->VerifyAndAllocateSet(
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000738 receiveInfo->TmmbnBoundingSet.lengthOfSet() + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739 for(uint32_t i=0; i< receiveInfo->TmmbnBoundingSet.lengthOfSet();
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000740 i++) {
741 if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == _SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000742 // owner of bounding set
743 tmmbrOwner = true;
744 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000745 boundingSetRec->SetEntry(i,
746 receiveInfo->TmmbnBoundingSet.Tmmbr(i),
747 receiveInfo->TmmbnBoundingSet.PacketOH(i),
748 receiveInfo->TmmbnBoundingSet.Ssrc(i));
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000749 }
750 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +0000751 return receiveInfo->TmmbnBoundingSet.lengthOfSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000752}
753
754// no need for critsect we have _criticalSectionRTCPReceiver
755void
756RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser)
757{
758 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
759 while (pktType == RTCPUtility::kRtcpSdesChunkCode)
760 {
761 HandleSDESChunk(rtcpParser);
762 pktType = rtcpParser.Iterate();
763 }
764}
765
766// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000767void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
768 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
769 RTCPCnameInformation* cnameInfo =
770 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
771 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000772
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000773 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
774 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000775}
776
777// no need for critsect we have _criticalSectionRTCPReceiver
778void
779RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
780 RTCPPacketInformation& rtcpPacketInformation)
781{
782 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000783 if (_SSRC != rtcpPacket.NACK.MediaSSRC)
784 {
785 // Not to us.
786 rtcpParser.Iterate();
787 return;
788 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000789 rtcpPacketInformation.ResetNACKPacketIdArray();
790
791 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
792 while (pktType == RTCPUtility::kRtcpRtpfbNackItemCode)
793 {
794 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
795 pktType = rtcpParser.Iterate();
796 }
797}
798
799// no need for critsect we have _criticalSectionRTCPReceiver
800void
801RTCPReceiver::HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket,
802 RTCPPacketInformation& rtcpPacketInformation)
803{
804 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
805
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000806 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
niklase@google.com470e71d2011-07-07 08:21:25 +0000807 if(bitMask)
808 {
809 for(int i=1; i <= 16; ++i)
810 {
811 if(bitMask & 0x01)
812 {
813 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
814 }
815 bitMask = bitMask >>1;
816 }
817 }
818
819 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
820}
821
822// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000823void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
824 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000825
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000826 // clear our lists
827 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000828 std::map<uint32_t, RTCPReportBlockInformation*>::iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000829 reportBlockInfoIt = _receivedReportBlockMap.find(
830 rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000831
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000832 if (reportBlockInfoIt != _receivedReportBlockMap.end()) {
833 delete reportBlockInfoIt->second;
834 _receivedReportBlockMap.erase(reportBlockInfoIt);
835 }
836 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000837 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000838 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000839
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000840 if (receiveInfoIt != _receivedInfoMap.end()) {
841 receiveInfoIt->second->readyForDelete = true;
842 }
843
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000844 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000845 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
846
847 if (cnameInfoIt != _receivedCnameMap.end()) {
848 delete cnameInfoIt->second;
849 _receivedCnameMap.erase(cnameInfoIt);
850 }
851 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000852}
853
854// no need for critsect we have _criticalSectionRTCPReceiver
855void
856RTCPReceiver::HandleXRVOIPMetric(RTCPUtility::RTCPParserV2& rtcpParser,
857 RTCPPacketInformation& rtcpPacketInformation)
858{
859 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
860
861 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
862
863 if(rtcpPacket.XRVOIPMetricItem.SSRC == _SSRC)
864 {
865 // Store VoIP metrics block if it's about me
866 // from OriginatorSSRC do we filter it?
867 // rtcpPacket.XR.OriginatorSSRC;
868
869 RTCPVoIPMetric receivedVoIPMetrics;
870 receivedVoIPMetrics.burstDensity = rtcpPacket.XRVOIPMetricItem.burstDensity;
871 receivedVoIPMetrics.burstDuration = rtcpPacket.XRVOIPMetricItem.burstDuration;
872 receivedVoIPMetrics.discardRate = rtcpPacket.XRVOIPMetricItem.discardRate;
873 receivedVoIPMetrics.endSystemDelay = rtcpPacket.XRVOIPMetricItem.endSystemDelay;
874 receivedVoIPMetrics.extRfactor = rtcpPacket.XRVOIPMetricItem.extRfactor;
875 receivedVoIPMetrics.gapDensity = rtcpPacket.XRVOIPMetricItem.gapDensity;
876 receivedVoIPMetrics.gapDuration = rtcpPacket.XRVOIPMetricItem.gapDuration;
877 receivedVoIPMetrics.Gmin = rtcpPacket.XRVOIPMetricItem.Gmin;
878 receivedVoIPMetrics.JBabsMax = rtcpPacket.XRVOIPMetricItem.JBabsMax;
879 receivedVoIPMetrics.JBmax = rtcpPacket.XRVOIPMetricItem.JBmax;
880 receivedVoIPMetrics.JBnominal = rtcpPacket.XRVOIPMetricItem.JBnominal;
881 receivedVoIPMetrics.lossRate = rtcpPacket.XRVOIPMetricItem.lossRate;
882 receivedVoIPMetrics.MOSCQ = rtcpPacket.XRVOIPMetricItem.MOSCQ;
883 receivedVoIPMetrics.MOSLQ = rtcpPacket.XRVOIPMetricItem.MOSLQ;
884 receivedVoIPMetrics.noiseLevel = rtcpPacket.XRVOIPMetricItem.noiseLevel;
885 receivedVoIPMetrics.RERL = rtcpPacket.XRVOIPMetricItem.RERL;
886 receivedVoIPMetrics.Rfactor = rtcpPacket.XRVOIPMetricItem.Rfactor;
887 receivedVoIPMetrics.roundTripDelay = rtcpPacket.XRVOIPMetricItem.roundTripDelay;
888 receivedVoIPMetrics.RXconfig = rtcpPacket.XRVOIPMetricItem.RXconfig;
889 receivedVoIPMetrics.signalLevel = rtcpPacket.XRVOIPMetricItem.signalLevel;
890
891 rtcpPacketInformation.AddVoIPMetric(&receivedVoIPMetrics);
892
893 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrVoipMetric; // received signal
894 }
895 rtcpParser.Iterate();
896}
897
898// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000899void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
900 RTCPPacketInformation& rtcpPacketInformation) {
901 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
902 if (_SSRC == rtcpPacket.PLI.MediaSSRC) {
903 // Received a signal that we need to send a new key frame.
904 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
905 }
906 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000907}
908
909// no need for critsect we have _criticalSectionRTCPReceiver
910void
911RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
912 RTCPPacketInformation& rtcpPacketInformation)
913{
914 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
915
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000916 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000917 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
918 if (ptrReceiveInfo == NULL)
919 {
920 // This remote SSRC must be saved before.
921 rtcpParser.Iterate();
922 return;
923 }
924 if(rtcpPacket.TMMBR.MediaSSRC)
925 {
926 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
927 // in relay mode this is a valid number
928 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
929 }
930
931 // Use packet length to calc max number of TMMBR blocks
932 // each TMMBR block is 8 bytes
933 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
934
935 // sanity
936 if(maxNumOfTMMBRBlocks > 200) // we can't have more than what's in one packet
937 {
938 assert(false);
939 rtcpParser.Iterate();
940 return;
941 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000942 ptrReceiveInfo->VerifyAndAllocateTMMBRSet((uint32_t)maxNumOfTMMBRBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +0000943
944 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
945 while (pktType == RTCPUtility::kRtcpRtpfbTmmbrItemCode)
946 {
947 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation, senderSSRC);
948 pktType = rtcpParser.Iterate();
949 }
950}
951
952// no need for critsect we have _criticalSectionRTCPReceiver
953void
954RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
955 const RTCPUtility::RTCPPacket& rtcpPacket,
956 RTCPPacketInformation& rtcpPacketInformation,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000957 const uint32_t senderSSRC)
niklase@google.com470e71d2011-07-07 08:21:25 +0000958{
959 if (_SSRC == rtcpPacket.TMMBRItem.SSRC &&
960 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0)
961 {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000962 receiveInfo.InsertTMMBRItem(senderSSRC, rtcpPacket.TMMBRItem,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000963 _clock->TimeInMilliseconds());
niklase@google.com470e71d2011-07-07 08:21:25 +0000964 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
965 }
966}
967
968// no need for critsect we have _criticalSectionRTCPReceiver
969void
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000970RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
971 RTCPPacketInformation& rtcpPacketInformation)
niklase@google.com470e71d2011-07-07 08:21:25 +0000972{
973 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
974 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
975 if (ptrReceiveInfo == NULL)
976 {
977 // This remote SSRC must be saved before.
978 rtcpParser.Iterate();
979 return;
980 }
hta@webrtc.org9d54cd12012-04-30 08:24:55 +0000981 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000982 // Use packet length to calc max number of TMMBN blocks
983 // each TMMBN block is 8 bytes
984 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
985
986 // sanity
987 if(maxNumOfTMMBNBlocks > 200) // we cant have more than what's in one packet
988 {
989 assert(false);
990 rtcpParser.Iterate();
991 return;
992 }
993
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000994 ptrReceiveInfo->VerifyAndAllocateBoundingSet((uint32_t)maxNumOfTMMBNBlocks);
niklase@google.com470e71d2011-07-07 08:21:25 +0000995
996 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
997 while (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode)
998 {
999 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
1000 pktType = rtcpParser.Iterate();
1001 }
1002}
1003
1004// no need for critsect we have _criticalSectionRTCPReceiver
1005void
1006RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
1007 RTCPPacketInformation& rtcpPacketInformation)
1008{
1009 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
1010 rtcpParser.Iterate();
1011}
1012
1013// no need for critsect we have _criticalSectionRTCPReceiver
1014void
1015RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
1016 const RTCPUtility::RTCPPacket& rtcpPacket)
1017{
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001018 receiveInfo.TmmbnBoundingSet.AddEntry(
1019 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate,
1020 rtcpPacket.TMMBNItem.MeasuredOverhead,
1021 rtcpPacket.TMMBNItem.SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001022}
1023
1024// no need for critsect we have _criticalSectionRTCPReceiver
1025void
1026RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1027 RTCPPacketInformation& rtcpPacketInformation)
1028{
1029 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001030 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1031 while (pktType == RTCPUtility::kRtcpPsfbSliItemCode)
1032 {
1033 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1034 pktType = rtcpParser.Iterate();
1035 }
1036}
1037
1038// no need for critsect we have _criticalSectionRTCPReceiver
1039void
1040RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1041 RTCPPacketInformation& rtcpPacketInformation)
1042{
1043 // in theory there could be multiple slices lost
1044 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli; // received signal that we need to refresh a slice
1045 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
1046}
1047
1048void
1049RTCPReceiver::HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser,
1050 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation)
1051{
1052 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001053 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1054 if(pktType == RTCPUtility::kRtcpPsfbRpsiCode)
1055 {
1056 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi; // received signal that we have a confirmed reference picture
1057 if(rtcpPacket.RPSI.NumberOfValidBits%8 != 0)
1058 {
1059 // to us unknown
1060 // continue
1061 rtcpParser.Iterate();
1062 return;
1063 }
1064 rtcpPacketInformation.rpsiPictureId = 0;
1065
1066 // convert NativeBitString to rpsiPictureId
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001067 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits /8;
1068 for(uint8_t n = 0; n < (numberOfBytes-1); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001069 {
1070 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1071 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1072 }
1073 rtcpPacketInformation.rpsiPictureId += (rtcpPacket.RPSI.NativeBitString[numberOfBytes-1] & 0x7f);
1074 }
1075}
1076
1077// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001078void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1079 RTCPPacketInformation& rtcpPacketInformation) {
1080 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1081 if (pktType == RTCPUtility::kRtcpPsfbRembCode) {
1082 pktType = rtcpParser.Iterate();
1083 if (pktType == RTCPUtility::kRtcpPsfbRembItemCode) {
1084 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1085 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001086 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001087 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001088}
1089
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +00001090// no need for critsect we have _criticalSectionRTCPReceiver
1091void
1092RTCPReceiver::HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser,
1093 RTCPPacketInformation& rtcpPacketInformation)
1094{
1095 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1096
1097 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1098 while (pktType == RTCPUtility::kRtcpExtendedIjItemCode)
1099 {
1100 HandleIJItem(rtcpPacket, rtcpPacketInformation);
1101 pktType = rtcpParser.Iterate();
1102 }
1103}
1104
1105void
1106RTCPReceiver::HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1107 RTCPPacketInformation& rtcpPacketInformation)
1108{
1109 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1110 rtcpPacketInformation.interArrivalJitter =
1111 rtcpPacket.ExtendedJitterReportItem.Jitter;
1112}
1113
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001114void RTCPReceiver::HandleREMBItem(
1115 RTCPUtility::RTCPParserV2& rtcpParser,
1116 RTCPPacketInformation& rtcpPacketInformation) {
1117 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1118 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1119 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1120 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001121}
1122
1123// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001124void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1125 RTCPPacketInformation& rtcpPacketInformation) {
1126 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1127 RTCPReceiveInformation* ptrReceiveInfo =
1128 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001129
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001130 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1131 while (pktType == RTCPUtility::kRtcpPsfbFirItemCode) {
1132 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1133 pktType = rtcpParser.Iterate();
1134 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001135}
1136
1137// no need for critsect we have _criticalSectionRTCPReceiver
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001138void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1139 const RTCPUtility::RTCPPacket& rtcpPacket,
1140 RTCPPacketInformation& rtcpPacketInformation) {
1141 // Is it our sender that is requested to generate a new keyframe
1142 if (_SSRC != rtcpPacket.FIRItem.SSRC) {
1143 return;
1144 }
1145 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1146 // we don't know who this originate from
1147 if (receiveInfo) {
1148 // check if we have reported this FIRSequenceNumber before
1149 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
1150 receiveInfo->lastFIRSequenceNumber) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001151 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001152 // sanity; don't go crazy with the callbacks
1153 if ((now - receiveInfo->lastFIRRequest) > RTCP_MIN_FRAME_LENGTH_MS) {
1154 receiveInfo->lastFIRRequest = now;
1155 receiveInfo->lastFIRSequenceNumber =
1156 rtcpPacket.FIRItem.CommandSequenceNumber;
1157 // received signal that we need to send a new key frame
1158 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1159 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001160 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001161 } else {
1162 // received signal that we need to send a new key frame
1163 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1164 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001165}
1166
1167void
1168RTCPReceiver::HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser,
1169 RTCPPacketInformation& rtcpPacketInformation)
1170{
1171 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1172
1173 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpApp;
1174 rtcpPacketInformation.applicationSubType = rtcpPacket.APP.SubType;
1175 rtcpPacketInformation.applicationName = rtcpPacket.APP.Name;
1176
1177 rtcpParser.Iterate();
1178}
1179
1180void
1181RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser,
1182 RTCPPacketInformation& rtcpPacketInformation)
1183{
1184 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1185
1186 rtcpPacketInformation.AddApplicationData(rtcpPacket.APP.Data, rtcpPacket.APP.Size);
1187
1188 rtcpParser.Iterate();
1189}
1190
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001191int32_t RTCPReceiver::UpdateTMMBR() {
1192 int32_t numBoundingSet = 0;
1193 uint32_t bitrate = 0;
1194 uint32_t accNumCandidates = 0;
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001195
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001196 int32_t size = TMMBRReceived(0, 0, NULL);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001197 if (size > 0) {
1198 TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size);
1199 // Get candidate set from receiver.
1200 accNumCandidates = TMMBRReceived(size, accNumCandidates, candidateSet);
1201 } else {
1202 // Candidate set empty.
1203 VerifyAndAllocateCandidateSet(0); // resets candidate set
1204 }
1205 // Find bounding set
1206 TMMBRSet* boundingSet = NULL;
1207 numBoundingSet = FindTMMBRBoundingSet(boundingSet);
1208 if (numBoundingSet == -1) {
1209 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
1210 "Failed to find TMMBR bounding set.");
1211 return -1;
1212 }
1213 // Set bounding set
1214 // Inform remote clients about the new bandwidth
1215 // inform the remote client
1216 _rtpRtcp.SetTMMBN(boundingSet);
1217
1218 // might trigger a TMMBN
1219 if (numBoundingSet == 0) {
1220 // owner of max bitrate request has timed out
1221 // empty bounding set has been sent
1222 return 0;
1223 }
1224 // Get net bitrate from bounding set depending on sent packet rate
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001225 if (CalcMinBitRate(&bitrate)) {
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001226 // we have a new bandwidth estimate on this channel
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001227 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1228 if (_cbRtcpBandwidthObserver) {
1229 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate * 1000);
1230 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id,
1231 "Set TMMBR request:%d kbps", bitrate);
1232 }
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001233 }
1234 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001235}
1236
1237// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001238void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001239 RTCPPacketInformation& rtcpPacketInformation) {
1240 // Process TMMBR and REMB first to avoid multiple callbacks
1241 // to OnNetworkChanged.
1242 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
1243 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1244 "SIG [RTCP] Incoming TMMBR to id:%d", _id);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001245
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001246 // Might trigger a OnReceivedBandwidthEstimateUpdate.
1247 UpdateTMMBR();
1248 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001249 unsigned int local_ssrc = 0;
1250 {
1251 // We don't want to hold this critsect when triggering the callbacks below.
1252 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1253 local_ssrc = _SSRC;
1254 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001255 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq) {
1256 _rtpRtcp.OnRequestSendReport();
1257 }
1258 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001259 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001260 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1261 "SIG [RTCP] Incoming NACK length:%d",
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001262 rtcpPacketInformation.nackSequenceNumbers.size());
1263 _rtpRtcp.OnReceivedNACK(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001264 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001265 }
1266 {
1267 CriticalSectionScoped lock(_criticalSectionFeedbacks);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001268
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001269 // We need feedback that we have received a report block(s) so that we
1270 // can generate a new packet in a conference relay scenario, one received
1271 // report can generate several RTCP packets, based on number relayed/mixed
1272 // a send report block should go out to all receivers.
1273 if (_cbRtcpIntraFrameObserver) {
1274 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1275 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1276 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
1277 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1278 "SIG [RTCP] Incoming PLI from SSRC:0x%x",
1279 rtcpPacketInformation.remoteSSRC);
1280 } else {
1281 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1282 "SIG [RTCP] Incoming FIR from SSRC:0x%x",
1283 rtcpPacketInformation.remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001284 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001285 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001286 }
1287 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1288 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001289 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001290 }
1291 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1292 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001293 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001294 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001295 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001296 if (_cbRtcpBandwidthObserver) {
1297 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
1298 WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id,
1299 "SIG [RTCP] Incoming REMB:%d",
1300 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1301 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1302 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1303 }
1304 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr ||
1305 rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr) &&
1306 rtcpPacketInformation.reportBlock) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001307 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001308 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
1309 rtcpPacketInformation.remoteSSRC,
1310 rtcpPacketInformation.fractionLost,
1311 rtcpPacketInformation.roundTripTime,
1312 rtcpPacketInformation.lastReceivedExtendedHighSeqNum,
1313 now);
1314 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001315 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001316 if(_cbRtcpFeedback) {
1317 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) {
1318 _cbRtcpFeedback->OnSendReportReceived(_id,
stefan@webrtc.org976a7e62012-09-21 13:20:21 +00001319 rtcpPacketInformation.remoteSSRC,
1320 rtcpPacketInformation.ntp_secs,
1321 rtcpPacketInformation.ntp_frac,
1322 rtcpPacketInformation.rtp_timestamp);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001323 } else {
1324 _cbRtcpFeedback->OnReceiveReportReceived(_id,
1325 rtcpPacketInformation.remoteSSRC);
1326 }
1327 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1328 _cbRtcpFeedback->OnXRVoIPMetricReceived(_id,
1329 rtcpPacketInformation.VoIPMetric);
1330 }
1331 if(rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpApp) {
1332 _cbRtcpFeedback->OnApplicationDataReceived(_id,
1333 rtcpPacketInformation.applicationSubType,
1334 rtcpPacketInformation.applicationName,
1335 rtcpPacketInformation.applicationLength,
1336 rtcpPacketInformation.applicationData);
1337 }
1338 }
1339 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001340}
1341
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001342int32_t RTCPReceiver::CNAME(const uint32_t remoteSSRC,
1343 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001344 assert(cName);
1345
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001346 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1347 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001348 if (cnameInfo == NULL) {
1349 return -1;
1350 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001351 cName[RTCP_CNAME_SIZE - 1] = 0;
1352 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1353 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001354}
1355
1356// no callbacks allowed inside this function
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001357int32_t RTCPReceiver::TMMBRReceived(const uint32_t size,
1358 const uint32_t accNumCandidates,
1359 TMMBRSet* candidateSet) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001360 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +00001361
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001362 std::map<uint32_t, RTCPReceiveInformation*>::const_iterator
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001363 receiveInfoIt = _receivedInfoMap.begin();
1364 if (receiveInfoIt == _receivedInfoMap.end()) {
1365 return -1;
1366 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001367 uint32_t num = accNumCandidates;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001368 if (candidateSet) {
1369 while( num < size && receiveInfoIt != _receivedInfoMap.end()) {
1370 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1371 if (receiveInfo == NULL) {
1372 return 0;
1373 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001374 for (uint32_t i = 0;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001375 (num < size) && (i < receiveInfo->TmmbrSet.lengthOfSet()); i++) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001376 if (receiveInfo->GetTMMBRSet(i, num, candidateSet,
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +00001377 _clock->TimeInMilliseconds()) == 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001378 num++;
1379 }
1380 }
1381 receiveInfoIt++;
1382 }
1383 } else {
1384 while (receiveInfoIt != _receivedInfoMap.end()) {
1385 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
1386 if(receiveInfo == NULL) {
1387 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
1388 "%s failed to get RTCPReceiveInformation",
1389 __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +00001390 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001391 }
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001392 num += receiveInfo->TmmbrSet.lengthOfSet();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001393 receiveInfoIt++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001394 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001395 }
1396 return num;
niklase@google.com470e71d2011-07-07 08:21:25 +00001397}
1398
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001399int32_t
1400RTCPReceiver::SetPacketTimeout(const uint32_t timeoutMS)
niklase@google.com470e71d2011-07-07 08:21:25 +00001401{
1402 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1403 _packetTimeOutMS = timeoutMS;
1404 return 0;
1405}
1406
1407void RTCPReceiver::PacketTimeout()
1408{
1409 if(_packetTimeOutMS == 0)
1410 {
1411 // not configured
1412 return;
1413 }
1414
1415 bool packetTimeOut = false;
1416 {
1417 CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
1418 if(_lastReceived == 0)
1419 {
1420 // not active
1421 return;
1422 }
1423
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001424 int64_t now = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +00001425 if(now - _lastReceived > _packetTimeOutMS)
1426 {
1427 packetTimeOut = true;
1428 _lastReceived = 0; // only one callback
1429 }
1430 }
1431 CriticalSectionScoped lock(_criticalSectionFeedbacks);
1432 if(packetTimeOut && _cbRtcpFeedback)
1433 {
1434 _cbRtcpFeedback->OnRTCPPacketTimeout(_id);
1435 }
1436}
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001437
niklase@google.com470e71d2011-07-07 08:21:25 +00001438} // namespace webrtc